Merge "Allow setting lock task features without setting packages" into udc-dev
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 3312294..9e59ee4 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2547,7 +2547,7 @@
.setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
new AppOpInfo.Builder(OP_TURN_SCREEN_ON, OPSTR_TURN_SCREEN_ON, "TURN_SCREEN_ON")
.setPermission(Manifest.permission.TURN_SCREEN_ON)
- .setDefaultMode(AppOpsManager.MODE_ERRORED).build(),
+ .setDefaultMode(AppOpsManager.MODE_DEFAULT).build(),
new AppOpInfo.Builder(OP_GET_ACCOUNTS, OPSTR_GET_ACCOUNTS, "GET_ACCOUNTS")
.setPermission(Manifest.permission.GET_ACCOUNTS)
.setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 746dcb6..d8cedb8 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -44,6 +44,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -246,6 +247,7 @@
private boolean mBypassDnd;
private int mLockscreenVisibility = DEFAULT_VISIBILITY;
private Uri mSound = Settings.System.DEFAULT_NOTIFICATION_URI;
+ private boolean mSoundRestored = false;
private boolean mLights;
private int mLightColor = DEFAULT_LIGHT_COLOR;
private long[] mVibration;
@@ -929,8 +931,9 @@
/**
* @hide
*/
- public void populateFromXmlForRestore(XmlPullParser parser, Context context) {
- populateFromXml(XmlUtils.makeTyped(parser), true, context);
+ public void populateFromXmlForRestore(XmlPullParser parser, boolean pkgInstalled,
+ Context context) {
+ populateFromXml(XmlUtils.makeTyped(parser), true, pkgInstalled, context);
}
/**
@@ -938,14 +941,14 @@
*/
@SystemApi
public void populateFromXml(XmlPullParser parser) {
- populateFromXml(XmlUtils.makeTyped(parser), false, null);
+ populateFromXml(XmlUtils.makeTyped(parser), false, true, null);
}
/**
* If {@param forRestore} is true, {@param Context} MUST be non-null.
*/
private void populateFromXml(TypedXmlPullParser parser, boolean forRestore,
- @Nullable Context context) {
+ boolean pkgInstalled, @Nullable Context context) {
Preconditions.checkArgument(!forRestore || context != null,
"forRestore is true but got null context");
@@ -956,7 +959,8 @@
setLockscreenVisibility(safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY));
Uri sound = safeUri(parser, ATT_SOUND);
- setSound(forRestore ? restoreSoundUri(context, sound) : sound, safeAudioAttributes(parser));
+ setSound(forRestore ? restoreSoundUri(context, sound, pkgInstalled) : sound,
+ safeAudioAttributes(parser));
enableLights(safeBool(parser, ATT_LIGHTS, false));
setLightColor(safeInt(parser, ATT_LIGHT_COLOR, DEFAULT_LIGHT_COLOR));
@@ -978,8 +982,58 @@
setImportantConversation(safeBool(parser, ATT_IMP_CONVERSATION, false));
}
+ /**
+ * Returns whether the sound for this channel was successfully restored
+ * from backup.
+ * @return false if the sound was not restored successfully. true otherwise (default value)
+ * @hide
+ */
+ public boolean isSoundRestored() {
+ return mSoundRestored;
+ }
+
@Nullable
- private Uri restoreSoundUri(Context context, @Nullable Uri uri) {
+ private Uri getCanonicalizedSoundUri(ContentResolver contentResolver, @NonNull Uri uri) {
+ if (Settings.System.DEFAULT_NOTIFICATION_URI.equals(uri)) {
+ return uri;
+ }
+
+ if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())) {
+ try {
+ contentResolver.getResourceId(uri);
+ return uri;
+ } catch (FileNotFoundException e) {
+ return null;
+ }
+ }
+
+ if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
+ return uri;
+ }
+
+ return contentResolver.canonicalize(uri);
+ }
+
+ @Nullable
+ private Uri getUncanonicalizedSoundUri(ContentResolver contentResolver, @NonNull Uri uri) {
+ if (Settings.System.DEFAULT_NOTIFICATION_URI.equals(uri)
+ || ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())
+ || ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
+ return uri;
+ }
+ return contentResolver.uncanonicalize(uri);
+ }
+
+ /**
+ * Restore/validate sound Uri from backup
+ * @param context The Context
+ * @param uri The sound Uri to restore
+ * @param pkgInstalled If the parent package is installed
+ * @return restored and validated Uri
+ * @hide
+ */
+ @Nullable
+ public Uri restoreSoundUri(Context context, @Nullable Uri uri, boolean pkgInstalled) {
if (uri == null || Uri.EMPTY.equals(uri)) {
return null;
}
@@ -991,12 +1045,22 @@
// the uri and in the case of not having the resource we end up with the default - better
// than broken. As a side effect we'll canonicalize already canonicalized uris, this is fine
// according to the docs because canonicalize method has to handle canonical uris as well.
- Uri canonicalizedUri = contentResolver.canonicalize(uri);
+ Uri canonicalizedUri = getCanonicalizedSoundUri(contentResolver, uri);
if (canonicalizedUri == null) {
- // We got a null because the uri in the backup does not exist here, so we return default
- return Settings.System.DEFAULT_NOTIFICATION_URI;
+ // Uri failed to restore with package installed
+ if (!mSoundRestored && pkgInstalled) {
+ mSoundRestored = true;
+ // We got a null because the uri in the backup does not exist here, so we return
+ // default
+ return Settings.System.DEFAULT_NOTIFICATION_URI;
+ } else {
+ // Flag as unrestored and try again later (on package install)
+ mSoundRestored = false;
+ return uri;
+ }
}
- return contentResolver.uncanonicalize(canonicalizedUri);
+ mSoundRestored = true;
+ return getUncanonicalizedSoundUri(contentResolver, canonicalizedUri);
}
/**
@@ -1019,7 +1083,7 @@
if (sound == null || Uri.EMPTY.equals(sound)) {
return null;
}
- Uri canonicalSound = context.getContentResolver().canonicalize(sound);
+ Uri canonicalSound = getCanonicalizedSoundUri(context.getContentResolver(), sound);
if (canonicalSound == null) {
// The content provider does not support canonical uris so we backup the default
return Settings.System.DEFAULT_NOTIFICATION_URI;
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 30fd77c..de66f05 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -3554,6 +3554,18 @@
}
/**
+ * @return the path to the validated base APK for this session, which may point at an
+ * APK inside the session (when the session defines the base), or it may
+ * point at the existing base APK (when adding splits to an existing app).
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.READ_INSTALLED_SESSION_PATHS)
+ public @Nullable String getResolvedBaseApkPath() {
+ return resolvedBaseCodePath;
+ }
+
+ /**
* Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}.
*
* @hide
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index ed6a88f..70b72c8 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -304,7 +304,9 @@
return;
}
case DO_SET_STYLUS_WINDOW_IDLE_TIMEOUT: {
- inputMethod.setStylusWindowIdleTimeoutForTest((long) msg.obj);
+ if (isValid(inputMethod, target, "DO_SET_STYLUS_WINDOW_IDLE_TIMEOUT")) {
+ inputMethod.setStylusWindowIdleTimeoutForTest((long) msg.obj);
+ }
return;
}
}
diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java
index 82571db..e9bb28c 100644
--- a/core/java/android/service/dreams/DreamManagerInternal.java
+++ b/core/java/android/service/dreams/DreamManagerInternal.java
@@ -84,6 +84,19 @@
*
* @param keepDreaming True if the current dream should continue when undocking.
*/
- void onKeepDreamingWhenUnpluggingChanged(boolean keepDreaming);
+ default void onKeepDreamingWhenUnpluggingChanged(boolean keepDreaming) {
+ }
+
+ /**
+ * Called when dreaming has started.
+ */
+ default void onDreamingStarted() {
+ }
+
+ /**
+ * Called when dreaming has stopped.
+ */
+ default void onDreamingStopped() {
+ }
}
}
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 24c96ea..91c350a 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -1334,13 +1334,7 @@
@Override
public void destroy() {
synchronized (mLock) {
- if (mAvailability == STATE_KEYPHRASE_ENROLLED) {
- try {
- stopRecognition();
- } catch (Exception e) {
- Log.i(TAG, "failed to stopRecognition in destroy", e);
- }
- }
+ detachSessionLocked();
mAvailability = STATE_INVALID;
mIsAvailabilityOverriddenByTestApi = false;
@@ -1349,6 +1343,17 @@
super.destroy();
}
+ private void detachSessionLocked() {
+ try {
+ if (DBG) Slog.d(TAG, "detachSessionLocked() " + mSoundTriggerSession);
+ if (mSoundTriggerSession != null) {
+ mSoundTriggerSession.detach();
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index f2373fb..e31adcf 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -341,9 +341,6 @@
@Nullable
public DisplayShape displayShape;
- /**
- * Refresh rate range limitation based on the current device layout
- */
@Nullable
public SurfaceControl.RefreshRateRange layoutLimitedRefreshRate;
@@ -357,7 +354,7 @@
* RefreshRateRange limitation for @Temperature.ThrottlingStatus
*/
@NonNull
- public SparseArray<SurfaceControl.RefreshRateRange> thermalRefreshRateThrottling =
+ public SparseArray<SurfaceControl.RefreshRateRange> refreshRateThermalThrottling =
new SparseArray<>();
public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
@@ -437,7 +434,7 @@
&& Objects.equals(displayShape, other.displayShape)
&& Objects.equals(layoutLimitedRefreshRate, other.layoutLimitedRefreshRate)
&& BrightnessSynchronizer.floatEquals(hdrSdrRatio, other.hdrSdrRatio)
- && thermalRefreshRateThrottling.contentEquals(other.thermalRefreshRateThrottling);
+ && refreshRateThermalThrottling.contentEquals(other.refreshRateThermalThrottling);
}
@Override
@@ -494,7 +491,7 @@
displayShape = other.displayShape;
layoutLimitedRefreshRate = other.layoutLimitedRefreshRate;
hdrSdrRatio = other.hdrSdrRatio;
- thermalRefreshRateThrottling = other.thermalRefreshRateThrottling;
+ refreshRateThermalThrottling = other.refreshRateThermalThrottling;
}
public void readFromParcel(Parcel source) {
@@ -557,7 +554,7 @@
displayShape = source.readTypedObject(DisplayShape.CREATOR);
layoutLimitedRefreshRate = source.readTypedObject(SurfaceControl.RefreshRateRange.CREATOR);
hdrSdrRatio = source.readFloat();
- thermalRefreshRateThrottling = source.readSparseArray(null,
+ refreshRateThermalThrottling = source.readSparseArray(null,
SurfaceControl.RefreshRateRange.class);
}
@@ -619,7 +616,7 @@
dest.writeTypedObject(displayShape, flags);
dest.writeTypedObject(layoutLimitedRefreshRate, flags);
dest.writeFloat(hdrSdrRatio);
- dest.writeSparseArray(thermalRefreshRateThrottling);
+ dest.writeSparseArray(refreshRateThermalThrottling);
}
@Override
@@ -887,8 +884,8 @@
} else {
sb.append(hdrSdrRatio);
}
- sb.append(", thermalRefreshRateThrottling ");
- sb.append(thermalRefreshRateThrottling);
+ sb.append(", refreshRateThermalThrottling ");
+ sb.append(refreshRateThermalThrottling);
sb.append("}");
return sb.toString();
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index bc6a3b5..99deac4 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -220,6 +220,7 @@
long newParentNativeObject);
private static native void nativeSetBuffer(long transactionObj, long nativeObject,
HardwareBuffer buffer, long fencePtr, Consumer<SyncFence> releaseCallback);
+ private static native void nativeUnsetBuffer(long transactionObj, long nativeObject);
private static native void nativeSetBufferTransform(long transactionObj, long nativeObject,
int transform);
private static native void nativeSetDataSpace(long transactionObj, long nativeObject,
@@ -3664,6 +3665,22 @@
}
/**
+ * Unsets the buffer for the SurfaceControl in the current Transaction. This will not clear
+ * the buffer being rendered, but resets the buffer state in the Transaction only. The call
+ * will also invoke the release callback.
+ *
+ * Note, this call is different from passing a null buffer to
+ * {@link SurfaceControl.Transaction#setBuffer} which will release the last displayed
+ * buffer.
+ *
+ * @hide
+ */
+ public Transaction unsetBuffer(SurfaceControl sc) {
+ nativeUnsetBuffer(mNativeObject, sc.mNativeObject);
+ return this;
+ }
+
+ /**
* Updates the HardwareBuffer displayed for the SurfaceControl.
*
* Note that the buffer must be allocated with {@link HardwareBuffer#USAGE_COMPOSER_OVERLAY}
@@ -3682,7 +3699,8 @@
* until all presentation fences have signaled, ensuring the transaction remains consistent.
*
* @param sc The SurfaceControl to update
- * @param buffer The buffer to be displayed
+ * @param buffer The buffer to be displayed. Pass in a null buffer to release the last
+ * displayed buffer.
* @param fence The presentation fence. If null or invalid, this is equivalent to
* {@link #setBuffer(SurfaceControl, HardwareBuffer)}
* @return this
@@ -3846,14 +3864,14 @@
* 100 nits and a max display brightness of 200 nits, this should
* be set to 2.0f.
*
- * Default value is 1.0f.
+ * <p>Default value is 1.0f.
*
- * Transfer functions that encode their own brightness ranges,
+ * <p>Transfer functions that encode their own brightness ranges,
* such as HLG or PQ, should also set this to 1.0f and instead
* communicate extended content brightness information via
* metadata such as CTA861_3 or SMPTE2086.
*
- * Must be finite && >= 1.0f
+ * <p>Must be finite && >= 1.0f
*
* @param desiredRatio The desired hdr/sdr ratio. This can be used to communicate the max
* desired brightness range. This is similar to the "max luminance"
@@ -3862,13 +3880,17 @@
* may not be able to, or may choose not to, deliver the
* requested range.
*
- * If unspecified, the system will attempt to provide the best range
- * it can for the given ambient conditions & device state. However,
- * voluntarily reducing the requested range can help improve battery
- * life as well as can improve quality by ensuring greater bit depth
- * is allocated to the luminance range in use.
+ * <p>While requesting a large desired ratio will result in the most
+ * dynamic range, voluntarily reducing the requested range can help
+ * improve battery life as well as can improve quality by ensuring
+ * greater bit depth is allocated to the luminance range in use.
*
- * Must be finite && >= 1.0f
+ * <p>Default value is 1.0f and indicates that extended range brightness
+ * is not being used, so the resulting SDR or HDR behavior will be
+ * determined entirely by the dataspace being used (ie, typically SDR
+ * however PQ or HLG transfer functions will still result in HDR)
+ *
+ * <p>Must be finite && >= 1.0f
* @return this
**/
public @NonNull Transaction setExtendedRangeBrightness(@NonNull SurfaceControl sc,
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6bd9538..c0ac04c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -647,11 +647,18 @@
boolean mForceNextWindowRelayout;
CountDownLatch mWindowDrawCountDown;
- // Whether we have used applyTransactionOnDraw to schedule an RT
- // frame callback consuming a passed in transaction. In this case
- // we also need to schedule a commit callback so we can observe
- // if the draw was skipped, and the BBQ pending transactions.
+ /**
+ * Value to indicate whether someone has called {@link #applyTransactionOnDraw}before the
+ * traversal. This is used to determine whether a RT frame callback needs to be registered to
+ * merge the transaction with the next frame. The value is cleared after the VRI has run a
+ * traversal pass.
+ */
boolean mHasPendingTransactions;
+ /**
+ * The combined transactions passed in from {@link #applyTransactionOnDraw}
+ */
+ private Transaction mPendingTransaction = new Transaction();
+
boolean mIsDrawing;
int mLastSystemUiVisibility;
@@ -4548,9 +4555,13 @@
}
private void registerCallbackForPendingTransactions() {
+ Transaction t = new Transaction();
+ t.merge(mPendingTransaction);
+
registerRtFrameCallback(new FrameDrawingCallback() {
@Override
public HardwareRenderer.FrameCommitCallback onFrameDraw(int syncResult, long frame) {
+ mergeWithNextTransaction(t, frame);
if ((syncResult
& (SYNC_LOST_SURFACE_REWARD_IF_FOUND | SYNC_CONTEXT_IS_STOPPED)) != 0) {
mBlastBufferQueue.applyPendingTransactions(frame);
@@ -8780,6 +8791,9 @@
mActiveSurfaceSyncGroup.markSyncReady();
mActiveSurfaceSyncGroup = null;
}
+ if (mHasPendingTransactions) {
+ mPendingTransaction.apply();
+ }
WindowManagerGlobal.getInstance().doRemoveView(this);
}
@@ -11114,12 +11128,11 @@
} else {
// Copy and clear the passed in transaction for thread safety. The new transaction is
// accessed on the render thread.
- var localTransaction = new Transaction();
- localTransaction.merge(t);
+ mPendingTransaction.merge(t);
mHasPendingTransactions = true;
- registerRtFrameCallback(frame -> {
- mergeWithNextTransaction(localTransaction, frame);
- });
+ // Schedule the traversal to ensure there's an attempt to draw a frame and apply the
+ // pending transactions. This is also where the registerFrameCallback will be scheduled.
+ scheduleTraversals();
}
return true;
}
@@ -11260,6 +11273,10 @@
if (DEBUG_BLAST) {
Log.d(mTag, "registerCallbacksForSync syncBuffer=" + syncBuffer);
}
+
+ Transaction t = new Transaction();
+ t.merge(mPendingTransaction);
+
mAttachInfo.mThreadedRenderer.registerRtFrameCallback(new FrameDrawingCallback() {
@Override
public void onFrameDraw(long frame) {
@@ -11273,6 +11290,7 @@
+ frame + ".");
}
+ mergeWithNextTransaction(t, frame);
// If the syncResults are SYNC_LOST_SURFACE_REWARD_IF_FOUND or
// SYNC_CONTEXT_IS_STOPPED it means nothing will draw. There's no need to set up
// any blast sync or commit callback, and the code should directly call
diff --git a/core/java/com/android/internal/app/IVoiceInteractionSoundTriggerSession.aidl b/core/java/com/android/internal/app/IVoiceInteractionSoundTriggerSession.aidl
index 1ccc71a..23de50c 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionSoundTriggerSession.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionSoundTriggerSession.aidl
@@ -94,4 +94,9 @@
*/
@nullable SoundTrigger.ModelParamRange queryParameter(int keyphraseId,
in ModelParams modelParam);
+ /**
+ * Invalidates the sound trigger session and clears any associated resources. Subsequent calls
+ * to this object will throw IllegalStateException.
+ */
+ void detach();
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 8e96ac1..193099b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -616,6 +616,12 @@
genReleaseCallback(env, releaseCallback));
}
+static void nativeUnsetBuffer(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+ transaction->unsetBuffer(ctrl);
+}
+
static void nativeSetBufferTransform(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint transform) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -2198,6 +2204,8 @@
(void*)nativeSetGeometry },
{"nativeSetBuffer", "(JJLandroid/hardware/HardwareBuffer;JLjava/util/function/Consumer;)V",
(void*)nativeSetBuffer },
+ {"nativeUnsetBuffer", "(JJ)V", (void*)nativeUnsetBuffer },
+
{"nativeSetBufferTransform", "(JJI)V", (void*) nativeSetBufferTransform},
{"nativeSetDataSpace", "(JJI)V",
(void*)nativeSetDataSpace },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 11fcd1e..31220b4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2542,7 +2542,7 @@
<permission android:name="android.permission.TURN_SCREEN_ON"
android:label="@string/permlab_turnScreenOn"
android:description="@string/permdesc_turnScreenOn"
- android:protectionLevel="normal|appop" />
+ android:protectionLevel="signature|privileged|appop" />
<!-- ==================================================== -->
<!-- Permissions related to changing audio settings -->
@@ -5418,6 +5418,15 @@
<permission android:name="android.permission.INSTALL_DPC_PACKAGES"
android:protectionLevel="signature|role" />
+ <!-- Allows an application to read resolved paths to the APKs (Base and any splits)
+ of a session based install.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS"
+ android:protectionLevel="signature|installer" />
+ <uses-permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS" />
+
<!-- Allows an application to use System Data Loaders.
<p>Not for use by third-party applications.
@hide
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index a57a051..fd74185 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -133,6 +133,10 @@
<string name="config_pointing_ui_package" translatable="false"></string>
<java-symbol type="string" name="config_pointing_ui_package" />
+ <!-- Telephony pointing UI class name to be launched. -->
+ <string name="config_pointing_ui_class" translatable="false"></string>
+ <java-symbol type="string" name="config_pointing_ui_class" />
+
<!-- Telephony resends received satellite datagram to listener
if ack is not received within this timeout -->
<integer name="config_timeout_to_receive_delivered_ack_millis">300000</integer>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 549ac58..596f351 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -307,6 +307,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
+ "-1828118576": {
+ "message": "SyncGroup %d: Started %sfor listener: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_SYNC_ENGINE",
+ "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
+ },
"-1824578273": {
"message": "Reporting new frame to %s: %s",
"level": "VERBOSE",
@@ -1489,6 +1495,12 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-741766551": {
+ "message": "Content Recording: Ignoring session on invalid virtual display",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_CONTENT_RECORDING",
+ "at": "com\/android\/server\/wm\/ContentRecordingController.java"
+ },
"-732715767": {
"message": "Unable to retrieve window container to start recording for display %d",
"level": "VERBOSE",
@@ -2893,12 +2905,6 @@
"group": "WM_DEBUG_BOOT",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "550717438": {
- "message": "SyncGroup %d: Started for listener: %s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_SYNC_ENGINE",
- "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
- },
"556758086": {
"message": "Applying new update lock state '%s' for %s",
"level": "DEBUG",
@@ -4129,6 +4135,12 @@
"group": "WM_DEBUG_ANIM",
"at": "com\/android\/server\/wm\/WindowStateAnimator.java"
},
+ "1820873642": {
+ "message": "SyncGroup %d: Unfinished dependencies: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_SYNC_ENGINE",
+ "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
+ },
"1822314934": {
"message": "Expected target rootTask=%s to restored behind rootTask=%s but it is behind rootTask=%s",
"level": "WARN",
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 88373e8..cb3b64c 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -261,8 +261,9 @@
/**
* Compressed JPEG format that includes an embedded recovery map.
*
- * <p>JPEG compressed main image along with XMP embedded recovery map
- * following ISO TBD.</p>
+ * <p>JPEG compressed main image along with embedded recovery map following the
+ * <a href="https://developer.android.com/guide/topics/media/hdr-image-format">Ultra HDR
+ * Image format specification</a>.</p>
*/
public static final int JPEG_R = 0x1005;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index ceef373..cca63ef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -2419,12 +2419,13 @@
}
}
}
- // If the size of dismissStages > 0, the task is closed without prepare pending
+ // If the size of dismissStages == 1, one of the task is closed without prepare pending
// transition, which could happen if all activities were finished after finish top
// activity in a task, so the trigger task is null when handleRequest.
+ // Note if the size of dismissStages == 2, it's starting a new task, so don't handle it.
final ArraySet<StageTaskListener> dismissStages = record.getShouldDismissedStage();
if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0
- || dismissStages.size() > 0) {
+ || dismissStages.size() == 1) {
Log.e(TAG, "Somehow removed the last task in a stage outside of a proper "
+ "transition.");
final WindowContainerTransaction wct = new WindowContainerTransaction();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 619e963..f9fdd83 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -17,17 +17,12 @@
package com.android.wm.shell.windowdecor;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.res.ColorStateList;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Region;
@@ -39,11 +34,6 @@
import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewConfiguration;
-import android.widget.Button;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.window.SurfaceSyncGroup;
import android.window.WindowContainerTransaction;
import com.android.launcher3.icons.IconProvider;
@@ -90,6 +80,7 @@
private AdditionalWindow mHandleMenuAppInfoPill;
private AdditionalWindow mHandleMenuWindowingPill;
private AdditionalWindow mHandleMenuMoreActionsPill;
+ private HandleMenu mHandleMenu;
private Drawable mAppIcon;
private CharSequence mAppName;
@@ -122,29 +113,6 @@
mSyncQueue = syncQueue;
loadAppInfo();
- loadHandleMenuDimensions();
- }
-
- private void loadHandleMenuDimensions() {
- final Resources resources = mDecorWindowContext.getResources();
- mMenuWidth = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_width);
- mMarginMenuTop = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_margin_top);
- mMarginMenuStart = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_margin_start);
- mMarginMenuSpacing = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_pill_spacing_margin);
- mAppInfoPillHeight = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_app_info_pill_height);
- mWindowingPillHeight = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_windowing_pill_height);
- mShadowRadius = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_shadow_radius);
- mCornerRadius = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_corner_radius);
- mMoreActionsPillHeight = loadDimensionPixelSize(resources,
- R.dimen.desktop_mode_handle_menu_more_actions_pill_height);
}
@Override
@@ -197,20 +165,8 @@
taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM;
final boolean isDragResizeable = isFreeform && taskInfo.isResizeable;
- if (mHandleMenuAppInfoPill != null) {
- updateHandleMenuPillPositions();
- startT.setPosition(mHandleMenuAppInfoPill.mWindowSurface,
- mHandleMenuAppInfoPillPosition.x, mHandleMenuAppInfoPillPosition.y);
-
- // Only show windowing buttons in proto2. Proto1 uses a system-level mode only.
- final boolean shouldShowWindowingPill = DesktopModeStatus.isProto2Enabled();
- if (shouldShowWindowingPill) {
- startT.setPosition(mHandleMenuWindowingPill.mWindowSurface,
- mHandleMenuWindowingPillPosition.x, mHandleMenuWindowingPillPosition.y);
- }
-
- startT.setPosition(mHandleMenuMoreActionsPill.mWindowSurface,
- mHandleMenuMoreActionsPillPosition.x, mHandleMenuMoreActionsPillPosition.y);
+ if (isHandleMenuActive()) {
+ mHandleMenu.relayout(startT);
}
final WindowDecorLinearLayout oldRootView = mResult.mRootView;
@@ -297,7 +253,7 @@
}
boolean isHandleMenuActive() {
- return mHandleMenuAppInfoPill != null;
+ return mHandleMenu != null;
}
private void loadAppInfo() {
@@ -327,136 +283,16 @@
* Create and display handle menu window
*/
void createHandleMenu() {
- final SurfaceSyncGroup ssg = new SurfaceSyncGroup(TAG);
- final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- updateHandleMenuPillPositions();
-
- createAppInfoPill(t, ssg);
-
- // Only show windowing buttons in proto2. Proto1 uses a system-level mode only.
- final boolean shouldShowWindowingPill = DesktopModeStatus.isProto2Enabled();
- if (shouldShowWindowingPill) {
- createWindowingPill(t, ssg);
- }
-
- createMoreActionsPill(t, ssg);
-
- ssg.addTransaction(t);
- ssg.markSyncReady();
- setupHandleMenu(shouldShowWindowingPill);
- }
-
- private void createAppInfoPill(SurfaceControl.Transaction t, SurfaceSyncGroup ssg) {
- final int x = (int) mHandleMenuAppInfoPillPosition.x;
- final int y = (int) mHandleMenuAppInfoPillPosition.y;
- mHandleMenuAppInfoPill = addWindow(
- R.layout.desktop_mode_window_decor_handle_menu_app_info_pill,
- "Menu's app info pill",
- t, ssg, x, y, mMenuWidth, mAppInfoPillHeight, mShadowRadius, mCornerRadius);
- }
-
- private void createWindowingPill(SurfaceControl.Transaction t, SurfaceSyncGroup ssg) {
- final int x = (int) mHandleMenuWindowingPillPosition.x;
- final int y = (int) mHandleMenuWindowingPillPosition.y;
- mHandleMenuWindowingPill = addWindow(
- R.layout.desktop_mode_window_decor_handle_menu_windowing_pill,
- "Menu's windowing pill",
- t, ssg, x, y, mMenuWidth, mWindowingPillHeight, mShadowRadius, mCornerRadius);
- }
-
- private void createMoreActionsPill(SurfaceControl.Transaction t, SurfaceSyncGroup ssg) {
- final int x = (int) mHandleMenuMoreActionsPillPosition.x;
- final int y = (int) mHandleMenuMoreActionsPillPosition.y;
- mHandleMenuMoreActionsPill = addWindow(
- R.layout.desktop_mode_window_decor_handle_menu_more_actions_pill,
- "Menu's more actions pill",
- t, ssg, x, y, mMenuWidth, mMoreActionsPillHeight, mShadowRadius, mCornerRadius);
- }
-
- private void setupHandleMenu(boolean windowingPillShown) {
- // App Info pill setup.
- final View appInfoPillView = mHandleMenuAppInfoPill.mWindowViewHost.getView();
- final ImageButton collapseBtn = appInfoPillView.findViewById(R.id.collapse_menu_button);
- final ImageView appIcon = appInfoPillView.findViewById(R.id.application_icon);
- final TextView appName = appInfoPillView.findViewById(R.id.application_name);
- collapseBtn.setOnClickListener(mOnCaptionButtonClickListener);
- appInfoPillView.setOnTouchListener(mOnCaptionTouchListener);
- appIcon.setImageDrawable(mAppIcon);
- appName.setText(mAppName);
-
- // Windowing pill setup.
- if (windowingPillShown) {
- final View windowingPillView = mHandleMenuWindowingPill.mWindowViewHost.getView();
- final ImageButton fullscreenBtn = windowingPillView.findViewById(
- R.id.fullscreen_button);
- final ImageButton splitscreenBtn = windowingPillView.findViewById(
- R.id.split_screen_button);
- final ImageButton floatingBtn = windowingPillView.findViewById(R.id.floating_button);
- final ImageButton desktopBtn = windowingPillView.findViewById(R.id.desktop_button);
- fullscreenBtn.setOnClickListener(mOnCaptionButtonClickListener);
- splitscreenBtn.setOnClickListener(mOnCaptionButtonClickListener);
- floatingBtn.setOnClickListener(mOnCaptionButtonClickListener);
- desktopBtn.setOnClickListener(mOnCaptionButtonClickListener);
- // The button corresponding to the windowing mode that the task is currently in uses a
- // different color than the others.
- final ColorStateList activeColorStateList = ColorStateList.valueOf(
- mContext.getColor(R.color.desktop_mode_caption_menu_buttons_color_active));
- final ColorStateList inActiveColorStateList = ColorStateList.valueOf(
- mContext.getColor(R.color.desktop_mode_caption_menu_buttons_color_inactive));
- fullscreenBtn.setImageTintList(
- mTaskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
- ? activeColorStateList : inActiveColorStateList);
- splitscreenBtn.setImageTintList(
- mTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
- ? activeColorStateList : inActiveColorStateList);
- floatingBtn.setImageTintList(mTaskInfo.getWindowingMode() == WINDOWING_MODE_PINNED
- ? activeColorStateList : inActiveColorStateList);
- desktopBtn.setImageTintList(mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
- ? activeColorStateList : inActiveColorStateList);
- }
-
- // More Actions pill setup.
- final View moreActionsPillView = mHandleMenuMoreActionsPill.mWindowViewHost.getView();
- final Button closeBtn = moreActionsPillView.findViewById(R.id.close_button);
- closeBtn.setOnClickListener(mOnCaptionButtonClickListener);
- }
-
- /**
- * Updates the handle menu pills' position variables to reflect their next positions
- */
- private void updateHandleMenuPillPositions() {
- final int menuX, menuY;
- final int captionWidth = mTaskInfo.getConfiguration()
- .windowConfiguration.getBounds().width();
- if (mRelayoutParams.mLayoutResId
- == R.layout.desktop_mode_app_controls_window_decor) {
- // Align the handle menu to the left of the caption.
- menuX = mRelayoutParams.mCaptionX + mMarginMenuStart;
- menuY = mRelayoutParams.mCaptionY + mMarginMenuTop;
- } else {
- // Position the handle menu at the center of the caption.
- menuX = mRelayoutParams.mCaptionX + (captionWidth / 2) - (mMenuWidth / 2);
- menuY = mRelayoutParams.mCaptionY + mMarginMenuStart;
- }
-
- // App Info pill setup.
- final int appInfoPillY = menuY;
- mHandleMenuAppInfoPillPosition.set(menuX, appInfoPillY);
-
- // Only show windowing buttons in proto2. Proto1 uses a system-level mode only.
- final boolean shouldShowWindowingPill = DesktopModeStatus.isProto2Enabled();
-
- final int windowingPillY, moreActionsPillY;
- if (shouldShowWindowingPill) {
- windowingPillY = appInfoPillY + mAppInfoPillHeight + mMarginMenuSpacing;
- mHandleMenuWindowingPillPosition.set(menuX, windowingPillY);
- moreActionsPillY = windowingPillY + mWindowingPillHeight + mMarginMenuSpacing;
- mHandleMenuMoreActionsPillPosition.set(menuX, moreActionsPillY);
- } else {
- // Just start after the end of the app info pill + margins.
- moreActionsPillY = appInfoPillY + mAppInfoPillHeight + mMarginMenuSpacing;
- mHandleMenuMoreActionsPillPosition.set(menuX, moreActionsPillY);
- }
+ mHandleMenu = new HandleMenu.Builder(this)
+ .setAppIcon(mAppIcon)
+ .setAppName(mAppName)
+ .setOnClickListener(mOnCaptionButtonClickListener)
+ .setOnTouchListener(mOnCaptionTouchListener)
+ .setLayoutId(mRelayoutParams.mLayoutResId)
+ .setCaptionPosition(mRelayoutParams.mCaptionX, mRelayoutParams.mCaptionY)
+ .setWindowingButtonsVisible(DesktopModeStatus.isProto2Enabled())
+ .build();
+ mHandleMenu.show();
}
/**
@@ -464,14 +300,8 @@
*/
void closeHandleMenu() {
if (!isHandleMenuActive()) return;
- mHandleMenuAppInfoPill.releaseView();
- mHandleMenuAppInfoPill = null;
- if (mHandleMenuWindowingPill != null) {
- mHandleMenuWindowingPill.releaseView();
- mHandleMenuWindowingPill = null;
- }
- mHandleMenuMoreActionsPill.releaseView();
- mHandleMenuMoreActionsPill = null;
+ mHandleMenu.close();
+ mHandleMenu = null;
}
@Override
@@ -488,10 +318,6 @@
void closeHandleMenuIfNeeded(MotionEvent ev) {
if (!isHandleMenuActive()) return;
- // When this is called before the layout is fully inflated, width will be 0.
- // Menu is not visible in this scenario, so skip the check if that is the case.
- if (mHandleMenuAppInfoPill.mWindowViewHost.getView().getWidth() == 0) return;
-
PointF inputPoint = offsetCaptionLocation(ev);
// If this is called before open_menu_button's onClick, we don't want to close
@@ -501,22 +327,7 @@
inputPoint.x,
inputPoint.y);
- final boolean pointInAppInfoPill = pointInView(
- mHandleMenuAppInfoPill.mWindowViewHost.getView(),
- inputPoint.x - mHandleMenuAppInfoPillPosition.x,
- inputPoint.y - mHandleMenuAppInfoPillPosition.y);
- boolean pointInWindowingPill = false;
- if (mHandleMenuWindowingPill != null) {
- pointInWindowingPill = pointInView(mHandleMenuWindowingPill.mWindowViewHost.getView(),
- inputPoint.x - mHandleMenuWindowingPillPosition.x,
- inputPoint.y - mHandleMenuWindowingPillPosition.y);
- }
- final boolean pointInMoreActionsPill = pointInView(
- mHandleMenuMoreActionsPill.mWindowViewHost.getView(),
- inputPoint.x - mHandleMenuMoreActionsPillPosition.x,
- inputPoint.y - mHandleMenuMoreActionsPillPosition.y);
- if (!pointInAppInfoPill && !pointInWindowingPill
- && !pointInMoreActionsPill && !pointInOpenMenuButton) {
+ if (!mHandleMenu.isValidMenuInput(inputPoint) && !pointInOpenMenuButton) {
closeHandleMenu();
}
}
@@ -573,13 +384,7 @@
final View handle = caption.findViewById(R.id.caption_handle);
clickIfPointInView(new PointF(ev.getX(), ev.getY()), handle);
} else {
- final View appInfoPill = mHandleMenuAppInfoPill.mWindowViewHost.getView();
- final ImageButton collapse = appInfoPill.findViewById(R.id.collapse_menu_button);
- // Translate the input point from display coordinates to the same space as the collapse
- // button, meaning its parent (app info pill view).
- final PointF inputPoint = new PointF(ev.getX() - mHandleMenuAppInfoPillPosition.x,
- ev.getY() - mHandleMenuAppInfoPillPosition.y);
- clickIfPointInView(inputPoint, collapse);
+ mHandleMenu.checkClickEvent(ev);
}
}
@@ -591,7 +396,7 @@
return false;
}
- private boolean pointInView(View v, float x, float y) {
+ boolean pointInView(View v, float x, float y) {
return v != null && v.getLeft() <= x && v.getRight() >= x
&& v.getTop() <= y && v.getBottom() >= y;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
new file mode 100644
index 0000000..ed3cca0
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
@@ -0,0 +1,402 @@
+/*
+ * 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.wm.shell.windowdecor;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.PointF;
+import android.graphics.drawable.Drawable;
+import android.view.MotionEvent;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.window.SurfaceSyncGroup;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.desktopmode.DesktopModeStatus;
+
+/**
+ * Handle menu opened when the appropriate button is clicked on.
+ *
+ * Displays up to 3 pills that show the following:
+ * App Info: App name, app icon, and collapse button to close the menu.
+ * Windowing Options(Proto 2 only): Buttons to change windowing modes.
+ * Additional Options: Miscellaneous functions including screenshot and closing task.
+ */
+class HandleMenu {
+ private static final String TAG = "HandleMenu";
+ private final Context mContext;
+ private final WindowDecoration mParentDecor;
+ private WindowDecoration.AdditionalWindow mAppInfoPill;
+ private WindowDecoration.AdditionalWindow mWindowingPill;
+ private WindowDecoration.AdditionalWindow mMoreActionsPill;
+ private final PointF mAppInfoPillPosition = new PointF();
+ private final PointF mWindowingPillPosition = new PointF();
+ private final PointF mMoreActionsPillPosition = new PointF();
+ private final boolean mShouldShowWindowingPill;
+ private final Drawable mAppIcon;
+ private final CharSequence mAppName;
+ private final View.OnClickListener mOnClickListener;
+ private final View.OnTouchListener mOnTouchListener;
+ private final RunningTaskInfo mTaskInfo;
+ private final int mLayoutResId;
+ private final int mCaptionX;
+ private final int mCaptionY;
+ private int mMarginMenuTop;
+ private int mMarginMenuStart;
+ private int mMarginMenuSpacing;
+ private int mMenuWidth;
+ private int mAppInfoPillHeight;
+ private int mWindowingPillHeight;
+ private int mMoreActionsPillHeight;
+ private int mShadowRadius;
+ private int mCornerRadius;
+
+
+ HandleMenu(WindowDecoration parentDecor, int layoutResId, int captionX, int captionY,
+ View.OnClickListener onClickListener, View.OnTouchListener onTouchListener,
+ Drawable appIcon, CharSequence appName, boolean shouldShowWindowingPill) {
+ mParentDecor = parentDecor;
+ mContext = mParentDecor.mDecorWindowContext;
+ mTaskInfo = mParentDecor.mTaskInfo;
+ mLayoutResId = layoutResId;
+ mCaptionX = captionX;
+ mCaptionY = captionY;
+ mOnClickListener = onClickListener;
+ mOnTouchListener = onTouchListener;
+ mAppIcon = appIcon;
+ mAppName = appName;
+ mShouldShowWindowingPill = shouldShowWindowingPill;
+ loadHandleMenuDimensions();
+ updateHandleMenuPillPositions();
+ }
+
+ void show() {
+ final SurfaceSyncGroup ssg = new SurfaceSyncGroup(TAG);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+
+ createAppInfoPill(t, ssg);
+ if (mShouldShowWindowingPill) {
+ createWindowingPill(t, ssg);
+ }
+ createMoreActionsPill(t, ssg);
+ ssg.addTransaction(t);
+ ssg.markSyncReady();
+ setupHandleMenu();
+ }
+
+ private void createAppInfoPill(SurfaceControl.Transaction t, SurfaceSyncGroup ssg) {
+ final int x = (int) mAppInfoPillPosition.x;
+ final int y = (int) mAppInfoPillPosition.y;
+ mAppInfoPill = mParentDecor.addWindow(
+ R.layout.desktop_mode_window_decor_handle_menu_app_info_pill,
+ "Menu's app info pill",
+ t, ssg, x, y, mMenuWidth, mAppInfoPillHeight, mShadowRadius, mCornerRadius);
+ }
+
+ private void createWindowingPill(SurfaceControl.Transaction t, SurfaceSyncGroup ssg) {
+ final int x = (int) mWindowingPillPosition.x;
+ final int y = (int) mWindowingPillPosition.y;
+ mWindowingPill = mParentDecor.addWindow(
+ R.layout.desktop_mode_window_decor_handle_menu_windowing_pill,
+ "Menu's windowing pill",
+ t, ssg, x, y, mMenuWidth, mWindowingPillHeight, mShadowRadius, mCornerRadius);
+ }
+
+ private void createMoreActionsPill(SurfaceControl.Transaction t, SurfaceSyncGroup ssg) {
+ final int x = (int) mMoreActionsPillPosition.x;
+ final int y = (int) mMoreActionsPillPosition.y;
+ mMoreActionsPill = mParentDecor.addWindow(
+ R.layout.desktop_mode_window_decor_handle_menu_more_actions_pill,
+ "Menu's more actions pill",
+ t, ssg, x, y, mMenuWidth, mMoreActionsPillHeight, mShadowRadius, mCornerRadius);
+ }
+
+ /**
+ * Set up interactive elements and color of this handle menu
+ */
+ private void setupHandleMenu() {
+ // App Info pill setup.
+ final View appInfoPillView = mAppInfoPill.mWindowViewHost.getView();
+ final ImageButton collapseBtn = appInfoPillView.findViewById(R.id.collapse_menu_button);
+ final ImageView appIcon = appInfoPillView.findViewById(R.id.application_icon);
+ final TextView appName = appInfoPillView.findViewById(R.id.application_name);
+ collapseBtn.setOnClickListener(mOnClickListener);
+ appInfoPillView.setOnTouchListener(mOnTouchListener);
+ appIcon.setImageDrawable(mAppIcon);
+ appName.setText(mAppName);
+
+ // Windowing pill setup.
+ if (mShouldShowWindowingPill) {
+ final View windowingPillView = mWindowingPill.mWindowViewHost.getView();
+ final ImageButton fullscreenBtn = windowingPillView.findViewById(
+ R.id.fullscreen_button);
+ final ImageButton splitscreenBtn = windowingPillView.findViewById(
+ R.id.split_screen_button);
+ final ImageButton floatingBtn = windowingPillView.findViewById(R.id.floating_button);
+ final ImageButton desktopBtn = windowingPillView.findViewById(R.id.desktop_button);
+ fullscreenBtn.setOnClickListener(mOnClickListener);
+ splitscreenBtn.setOnClickListener(mOnClickListener);
+ floatingBtn.setOnClickListener(mOnClickListener);
+ desktopBtn.setOnClickListener(mOnClickListener);
+ // The button corresponding to the windowing mode that the task is currently in uses a
+ // different color than the others.
+ final ColorStateList activeColorStateList = ColorStateList.valueOf(
+ mContext.getColor(R.color.desktop_mode_caption_menu_buttons_color_active));
+ final ColorStateList inActiveColorStateList = ColorStateList.valueOf(
+ mContext.getColor(R.color.desktop_mode_caption_menu_buttons_color_inactive));
+ fullscreenBtn.setImageTintList(
+ mTaskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+ ? activeColorStateList : inActiveColorStateList);
+ splitscreenBtn.setImageTintList(
+ mTaskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
+ ? activeColorStateList : inActiveColorStateList);
+ floatingBtn.setImageTintList(mTaskInfo.getWindowingMode() == WINDOWING_MODE_PINNED
+ ? activeColorStateList : inActiveColorStateList);
+ desktopBtn.setImageTintList(mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
+ ? activeColorStateList : inActiveColorStateList);
+ }
+
+ // More Actions pill setup.
+ final View moreActionsPillView = mMoreActionsPill.mWindowViewHost.getView();
+ final Button closeBtn = moreActionsPillView.findViewById(R.id.close_button);
+ closeBtn.setOnClickListener(mOnClickListener);
+ }
+
+ /**
+ * Updates the handle menu pills' position variables to reflect their next positions
+ */
+ private void updateHandleMenuPillPositions() {
+ final int menuX, menuY;
+ final int captionWidth = mTaskInfo.getConfiguration()
+ .windowConfiguration.getBounds().width();
+ if (mLayoutResId
+ == R.layout.desktop_mode_app_controls_window_decor) {
+ // Align the handle menu to the left of the caption.
+ menuX = mCaptionX + mMarginMenuStart;
+ menuY = mCaptionY + mMarginMenuTop;
+ } else {
+ // Position the handle menu at the center of the caption.
+ menuX = mCaptionX + (captionWidth / 2) - (mMenuWidth / 2);
+ menuY = mCaptionY + mMarginMenuStart;
+ }
+
+ // App Info pill setup.
+ final int appInfoPillY = menuY;
+ mAppInfoPillPosition.set(menuX, appInfoPillY);
+
+ final int windowingPillY, moreActionsPillY;
+ if (mShouldShowWindowingPill) {
+ windowingPillY = appInfoPillY + mAppInfoPillHeight + mMarginMenuSpacing;
+ mWindowingPillPosition.set(menuX, windowingPillY);
+ moreActionsPillY = windowingPillY + mWindowingPillHeight + mMarginMenuSpacing;
+ mMoreActionsPillPosition.set(menuX, moreActionsPillY);
+ } else {
+ // Just start after the end of the app info pill + margins.
+ moreActionsPillY = appInfoPillY + mAppInfoPillHeight + mMarginMenuSpacing;
+ mMoreActionsPillPosition.set(menuX, moreActionsPillY);
+ }
+ }
+
+ /**
+ * Update pill layout, in case task changes have caused positioning to change.
+ * @param t
+ */
+ void relayout(SurfaceControl.Transaction t) {
+ if (mAppInfoPill != null) {
+ updateHandleMenuPillPositions();
+ t.setPosition(mAppInfoPill.mWindowSurface,
+ mAppInfoPillPosition.x, mAppInfoPillPosition.y);
+ // Only show windowing buttons in proto2. Proto1 uses a system-level mode only.
+ final boolean shouldShowWindowingPill = DesktopModeStatus.isProto2Enabled();
+ if (shouldShowWindowingPill) {
+ t.setPosition(mWindowingPill.mWindowSurface,
+ mWindowingPillPosition.x, mWindowingPillPosition.y);
+ }
+ t.setPosition(mMoreActionsPill.mWindowSurface,
+ mMoreActionsPillPosition.x, mMoreActionsPillPosition.y);
+ }
+ }
+ /**
+ * Check a passed MotionEvent if a click has occurred on any button on this caption
+ * Note this should only be called when a regular onClick is not possible
+ * (i.e. the button was clicked through status bar layer)
+ * @param ev the MotionEvent to compare against.
+ */
+ void checkClickEvent(MotionEvent ev) {
+ final View appInfoPill = mAppInfoPill.mWindowViewHost.getView();
+ final ImageButton collapse = appInfoPill.findViewById(R.id.collapse_menu_button);
+ // Translate the input point from display coordinates to the same space as the collapse
+ // button, meaning its parent (app info pill view).
+ final PointF inputPoint = new PointF(ev.getX() - mAppInfoPillPosition.x,
+ ev.getY() - mAppInfoPillPosition.y);
+ if (pointInView(collapse, inputPoint.x, inputPoint.y)) {
+ mOnClickListener.onClick(collapse);
+ }
+ }
+
+ /**
+ * A valid menu input is one of the following:
+ * An input that happens in the menu views.
+ * Any input before the views have been laid out.
+ * @param inputPoint the input to compare against.
+ */
+ boolean isValidMenuInput(PointF inputPoint) {
+ if (!viewsLaidOut()) return true;
+ final boolean pointInAppInfoPill = pointInView(
+ mAppInfoPill.mWindowViewHost.getView(),
+ inputPoint.x - mAppInfoPillPosition.x,
+ inputPoint.y - mAppInfoPillPosition.y);
+ boolean pointInWindowingPill = false;
+ if (mWindowingPill != null) {
+ pointInWindowingPill = pointInView(
+ mWindowingPill.mWindowViewHost.getView(),
+ inputPoint.x - mWindowingPillPosition.x,
+ inputPoint.y - mWindowingPillPosition.y);
+ }
+ final boolean pointInMoreActionsPill = pointInView(
+ mMoreActionsPill.mWindowViewHost.getView(),
+ inputPoint.x - mMoreActionsPillPosition.x,
+ inputPoint.y - mMoreActionsPillPosition.y);
+
+ return pointInAppInfoPill || pointInWindowingPill || pointInMoreActionsPill;
+ }
+
+ private boolean pointInView(View v, float x, float y) {
+ return v != null && v.getLeft() <= x && v.getRight() >= x
+ && v.getTop() <= y && v.getBottom() >= y;
+ }
+
+ /**
+ * Check if the views for handle menu can be seen.
+ * @return
+ */
+ private boolean viewsLaidOut() {
+ return mAppInfoPill.mWindowViewHost.getView().isLaidOut();
+ }
+
+
+ private void loadHandleMenuDimensions() {
+ final Resources resources = mContext.getResources();
+ mMenuWidth = loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_width);
+ mMarginMenuTop = loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_margin_top);
+ mMarginMenuStart = loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_margin_start);
+ mMarginMenuSpacing = loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_pill_spacing_margin);
+ mAppInfoPillHeight = loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_app_info_pill_height);
+ mWindowingPillHeight = loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_windowing_pill_height);
+ mMoreActionsPillHeight = loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_more_actions_pill_height);
+ mShadowRadius = loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_shadow_radius);
+ mCornerRadius = loadDimensionPixelSize(resources,
+ R.dimen.desktop_mode_handle_menu_corner_radius);
+ }
+
+ private int loadDimensionPixelSize(Resources resources, int resourceId) {
+ if (resourceId == Resources.ID_NULL) {
+ return 0;
+ }
+ return resources.getDimensionPixelSize(resourceId);
+ }
+
+ void close() {
+ mAppInfoPill.releaseView();
+ mAppInfoPill = null;
+ if (mWindowingPill != null) {
+ mWindowingPill.releaseView();
+ mWindowingPill = null;
+ }
+ mMoreActionsPill.releaseView();
+ mMoreActionsPill = null;
+ }
+
+ static final class Builder {
+ private final WindowDecoration mParent;
+ private CharSequence mName;
+ private Drawable mAppIcon;
+ private View.OnClickListener mOnClickListener;
+ private View.OnTouchListener mOnTouchListener;
+ private int mLayoutId;
+ private int mCaptionX;
+ private int mCaptionY;
+ private boolean mShowWindowingPill;
+
+
+ Builder(@NonNull WindowDecoration parent) {
+ mParent = parent;
+ }
+
+ Builder setAppName(@Nullable CharSequence name) {
+ mName = name;
+ return this;
+ }
+
+ Builder setAppIcon(@Nullable Drawable appIcon) {
+ mAppIcon = appIcon;
+ return this;
+ }
+
+ Builder setOnClickListener(@Nullable View.OnClickListener onClickListener) {
+ mOnClickListener = onClickListener;
+ return this;
+ }
+
+ Builder setOnTouchListener(@Nullable View.OnTouchListener onTouchListener) {
+ mOnTouchListener = onTouchListener;
+ return this;
+ }
+
+ Builder setLayoutId(int layoutId) {
+ mLayoutId = layoutId;
+ return this;
+ }
+
+ Builder setCaptionPosition(int captionX, int captionY) {
+ mCaptionX = captionX;
+ mCaptionY = captionY;
+ return this;
+ }
+
+ Builder setWindowingButtonsVisible(boolean windowingButtonsVisible) {
+ mShowWindowingPill = windowingButtonsVisible;
+ return this;
+ }
+
+ HandleMenu build() {
+ return new HandleMenu(mParent, mLayoutId, mCaptionX, mCaptionY, mOnClickListener,
+ mOnTouchListener, mAppIcon, mName, mShowWindowingPill);
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 9a1b4ff..e772fc2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -458,7 +458,7 @@
SurfaceControlViewHost mWindowViewHost;
Supplier<SurfaceControl.Transaction> mTransactionSupplier;
- private AdditionalWindow(SurfaceControl surfaceControl,
+ AdditionalWindow(SurfaceControl surfaceControl,
SurfaceControlViewHost surfaceControlViewHost,
Supplier<SurfaceControl.Transaction> transactionSupplier) {
mWindowSurface = surfaceControl;
diff --git a/media/java/android/media/projection/IMediaProjectionManager.aidl b/media/java/android/media/projection/IMediaProjectionManager.aidl
index 835e4c3..a3cd623 100644
--- a/media/java/android/media/projection/IMediaProjectionManager.aidl
+++ b/media/java/android/media/projection/IMediaProjectionManager.aidl
@@ -20,11 +20,23 @@
import android.media.projection.IMediaProjectionCallback;
import android.media.projection.IMediaProjectionWatcherCallback;
import android.media.projection.MediaProjectionInfo;
+import android.media.projection.ReviewGrantedConsentResult;
import android.os.IBinder;
import android.view.ContentRecordingSession;
/** {@hide} */
interface IMediaProjectionManager {
+ /**
+ * Intent extra indicating if user must review access to the consent token already granted.
+ */
+ const String EXTRA_USER_REVIEW_GRANTED_CONSENT = "extra_media_projection_user_consent_required";
+
+ /**
+ * Intent extra indicating the package attempting to re-use granted consent.
+ */
+ const String EXTRA_PACKAGE_REUSING_GRANTED_CONSENT =
+ "extra_media_projection_package_reusing_consent";
+
@UnsupportedAppUsage
boolean hasProjectionPermission(int uid, String packageName);
@@ -37,6 +49,21 @@
boolean permanentGrant);
/**
+ * Returns the current {@link IMediaProjection} instance associated with the given
+ * package, or {@code null} if it is not possible to re-use the current projection.
+ *
+ * <p>Should only be invoked when the user has reviewed consent for a re-used projection token.
+ * Requires that there is a prior session waiting for the user to review consent, and the given
+ * package details match those on the current projection.
+ *
+ * @see {@link #isCurrentProjection}
+ */
+ @EnforcePermission("android.Manifest.permission.MANAGE_MEDIA_PROJECTION")
+ @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ + ".permission.MANAGE_MEDIA_PROJECTION)")
+ IMediaProjection getProjection(int uid, String packageName);
+
+ /**
* Returns {@code true} if the given {@link IMediaProjection} corresponds to the current
* projection, or {@code false} otherwise.
*/
@@ -58,7 +85,7 @@
*/
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ ".permission.MANAGE_MEDIA_PROJECTION)")
- void requestConsentForInvalidProjection(IMediaProjection projection);
+ void requestConsentForInvalidProjection(in IMediaProjection projection);
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ ".permission.MANAGE_MEDIA_PROJECTION)")
@@ -94,9 +121,32 @@
*
* @param incomingSession the nullable incoming content recording session
* @param projection the non-null projection the session describes
+ * @throws SecurityException If the provided projection is not current.
*/
@JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ ".permission.MANAGE_MEDIA_PROJECTION)")
boolean setContentRecordingSession(in ContentRecordingSession incomingSession,
in IMediaProjection projection);
+
+ /**
+ * Sets the result of the user reviewing the recording permission, when the host app is re-using
+ * the consent token.
+ *
+ * <p>Ignores the provided result if the given projection is not the current projection.
+ *
+ * <p>Based on the given result:
+ * <ul>
+ * <li>If UNKNOWN or RECORD_CANCEL, then tear down the recording.</li>
+ * <li>If RECORD_CONTENT_DISPLAY, then record the default display.</li>
+ * <li>If RECORD_CONTENT_TASK, record the task indicated by
+ * {@link IMediaProjection#getLaunchCookie}.</li>
+ * </ul>
+ * @param projection The projection associated with the consent result. Must be the current
+ * projection instance, unless the given result is RECORD_CANCEL.
+ */
+ @EnforcePermission("android.Manifest.permission.MANAGE_MEDIA_PROJECTION")
+ @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
+ + ".permission.MANAGE_MEDIA_PROJECTION)")
+ void setUserReviewGrantedConsentResult(ReviewGrantedConsentResult consentResult,
+ in @nullable IMediaProjection projection);
}
diff --git a/media/java/android/media/projection/ReviewGrantedConsentResult.aidl b/media/java/android/media/projection/ReviewGrantedConsentResult.aidl
new file mode 100644
index 0000000..4f25be7
--- /dev/null
+++ b/media/java/android/media/projection/ReviewGrantedConsentResult.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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.media.projection;
+
+/**
+ * Indicates result of user interacting with consent dialog, when their review is required due to
+ * app re-using the token.
+
+ * @hide
+ */
+@Backing(type="int")
+enum ReviewGrantedConsentResult {
+ UNKNOWN = -1,
+ RECORD_CANCEL = 0,
+ RECORD_CONTENT_DISPLAY = 1,
+ RECORD_CONTENT_TASK = 2,
+}
diff --git a/media/java/android/media/soundtrigger/TEST_MAPPING b/media/java/android/media/soundtrigger/TEST_MAPPING
new file mode 100644
index 0000000..3d73795
--- /dev/null
+++ b/media/java/android/media/soundtrigger/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsSoundTriggerTestCases"
+ }
+ ]
+}
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 80a3e70..d749b91 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -223,7 +223,8 @@
break;
}
case DO_TIME_SHIFT_SET_MODE: {
- mTvInputSessionImpl.timeShiftSetMode((Integer) msg.obj);
+ mTvInputSessionImpl.timeShiftSetMode(msg.arg1);
+ break;
}
case DO_TIME_SHIFT_ENABLE_POSITION_TRACKING: {
mTvInputSessionImpl.timeShiftEnablePositionTracking((Boolean) msg.obj);
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index 9a995a0..a396b7e 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -396,6 +396,12 @@
}
}
+ // For testing purposes only.
+ /** @hide */
+ public TvInputManager.SessionCallback getSessionCallback() {
+ return mSessionCallback;
+ }
+
/**
* Callback used to receive various status updates on the
* {@link android.media.tv.TvInputService.RecordingSession}
diff --git a/packages/PackageInstaller/Android.bp b/packages/PackageInstaller/Android.bp
index fd982f5..6ecd328 100644
--- a/packages/PackageInstaller/Android.bp
+++ b/packages/PackageInstaller/Android.bp
@@ -39,8 +39,7 @@
certificate: "platform",
privileged: true,
- platform_apis: false,
- sdk_version: "system_current",
+ platform_apis: true,
rename_resources_package: false,
static_libs: [
"xz-java",
@@ -57,8 +56,7 @@
certificate: "platform",
privileged: true,
- platform_apis: false,
- sdk_version: "system_current",
+ platform_apis: true,
rename_resources_package: false,
overrides: ["PackageInstaller"],
@@ -77,8 +75,7 @@
certificate: "platform",
privileged: true,
- platform_apis: false,
- sdk_version: "system_current",
+ platform_apis: true,
rename_resources_package: false,
overrides: ["PackageInstaller"],
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 9ee6fbd..6ccebfd 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -9,6 +9,7 @@
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<uses-permission android:name="android.permission.READ_INSTALL_SESSIONS" />
+ <uses-permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" />
<uses-permission android:name="android.permission.USE_RESERVED_DISK" />
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index c81e75b..3ba2acb 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -375,16 +375,15 @@
final int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID,
-1 /* defaultValue */);
final SessionInfo info = mInstaller.getSessionInfo(sessionId);
- final String resolvedBaseCodePath = intent.getStringExtra(
- PackageInstaller.EXTRA_RESOLVED_BASE_PATH);
- if (info == null || !info.isSealed() || resolvedBaseCodePath == null) {
+ String resolvedPath = info.getResolvedBaseApkPath();
+ if (info == null || !info.isSealed() || resolvedPath == null) {
Log.w(TAG, "Session " + mSessionId + " in funky state; ignoring");
finish();
return;
}
mSessionId = sessionId;
- packageSource = Uri.fromFile(new File(resolvedBaseCodePath));
+ packageSource = Uri.fromFile(new File(resolvedPath));
mOriginatingURI = null;
mReferrerURI = null;
mPendingUserActionReason = info.getPendingUserActionReason();
diff --git a/packages/SettingsLib/Spa/build.gradle b/packages/SettingsLib/Spa/build.gradle
index 4fd2b5d..e68ef85 100644
--- a/packages/SettingsLib/Spa/build.gradle
+++ b/packages/SettingsLib/Spa/build.gradle
@@ -14,17 +14,27 @@
* limitations under the License.
*/
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
buildscript {
ext {
BUILD_TOOLS_VERSION = "30.0.3"
MIN_SDK = 21
TARGET_SDK = 33
jetpack_compose_version = '1.4.0-beta01'
- jetpack_compose_compiler_version = '1.4.0'
+ jetpack_compose_compiler_version = '1.4.4'
}
}
plugins {
- id 'com.android.application' version '8.0.0-beta05' apply false
- id 'com.android.library' version '8.0.0-beta05' apply false
- id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
+ id 'com.android.application' version '8.0.0' apply false
+ id 'com.android.library' version '8.0.0' apply false
+ id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
+}
+subprojects {
+ tasks.withType(KotlinCompile).configureEach {
+ kotlinOptions {
+ jvmTarget = "17"
+ freeCompilerArgs = ["-Xjvm-default=all"]
+ }
+ }
}
diff --git a/packages/SettingsLib/Spa/gallery/build.gradle b/packages/SettingsLib/Spa/gallery/build.gradle
index 416a403..212aa7b 100644
--- a/packages/SettingsLib/Spa/gallery/build.gradle
+++ b/packages/SettingsLib/Spa/gallery/build.gradle
@@ -42,12 +42,8 @@
}
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_11
- targetCompatibility JavaVersion.VERSION_11
- }
- kotlinOptions {
- jvmTarget = '11'
- freeCompilerArgs = ["-Xjvm-default=all"]
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
}
buildFeatures {
compose true
diff --git a/packages/SettingsLib/Spa/spa/build.gradle b/packages/SettingsLib/Spa/spa/build.gradle
index 9962c93..fb945a3 100644
--- a/packages/SettingsLib/Spa/spa/build.gradle
+++ b/packages/SettingsLib/Spa/spa/build.gradle
@@ -51,10 +51,6 @@
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
- kotlinOptions {
- jvmTarget = '17'
- freeCompilerArgs = ["-Xjvm-default=all"]
- }
buildFeatures {
compose true
}
@@ -79,7 +75,7 @@
api "androidx.compose.ui:ui-tooling-preview:$jetpack_compose_version"
api "androidx.lifecycle:lifecycle-livedata-ktx"
api "androidx.lifecycle:lifecycle-runtime-compose"
- api "androidx.navigation:navigation-compose:2.6.0-alpha07"
+ api "androidx.navigation:navigation-compose:2.6.0-alpha08"
api "com.github.PhilJay:MPAndroidChart:v3.1.0-alpha"
api "com.google.android.material:material:1.7.0-alpha03"
debugApi "androidx.compose.ui:ui-tooling:$jetpack_compose_version"
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
index f0df9a6..8cbf7cc 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
@@ -19,7 +19,6 @@
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.material.icons.Icons
@@ -40,7 +39,6 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.framework.theme.SettingsTheme
@@ -60,13 +58,17 @@
Box(
modifier = Modifier
- .padding(SettingsDimension.itemPadding)
+ .padding(
+ start = SettingsDimension.itemPaddingStart,
+ top = SettingsDimension.itemPaddingAround,
+ end = SettingsDimension.itemPaddingEnd,
+ bottom = SettingsDimension.itemPaddingAround,
+ )
.selectableGroup(),
) {
val contentPadding = PaddingValues(horizontal = SettingsDimension.itemPaddingEnd)
Button(
onClick = { expanded = true },
- modifier = Modifier.height(36.dp),
colors = ButtonDefaults.buttonColors(
containerColor = SettingsTheme.colorScheme.spinnerHeaderContainer,
contentColor = SettingsTheme.colorScheme.onSpinnerHeaderContainer,
@@ -86,7 +88,6 @@
expanded = expanded,
onDismissRequest = { expanded = false },
modifier = Modifier.background(SettingsTheme.colorScheme.spinnerItemContainer),
- offset = DpOffset(x = 0.dp, y = 4.dp),
) {
for (option in options) {
DropdownMenuItem(
@@ -116,7 +117,9 @@
) {
Text(
text = option?.text ?: "",
- modifier = modifier.padding(end = SettingsDimension.itemPaddingEnd),
+ modifier = modifier
+ .padding(end = SettingsDimension.itemPaddingEnd)
+ .padding(vertical = SettingsDimension.itemPaddingAround),
color = color,
style = MaterialTheme.typography.labelLarge,
)
diff --git a/packages/SettingsLib/Spa/testutils/build.gradle b/packages/SettingsLib/Spa/testutils/build.gradle
index e7f7db2..23a9add 100644
--- a/packages/SettingsLib/Spa/testutils/build.gradle
+++ b/packages/SettingsLib/Spa/testutils/build.gradle
@@ -41,10 +41,6 @@
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
- kotlinOptions {
- jvmTarget = '17'
- freeCompilerArgs = ["-Xjvm-default=all"]
- }
buildFeatures {
compose true
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverLogging.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverLogging.java
index 5326e73..daa3616 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverLogging.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverLogging.java
@@ -32,9 +32,13 @@
public static final String EXTRA_POWER_SAVE_MODE_MANUAL_ENABLED_REASON =
"extra_power_save_mode_manual_enabled_reason";
+ /** Record the event while enabling power save mode manually. */
+ public static final String EXTRA_POWER_SAVE_MODE_MANUAL_ENABLED =
+ "extra_power_save_mode_manual_enabled";
+
/** Broadcast action to record battery saver manual enabled reason. */
- public static final String ACTION_SAVER_MANUAL_ENABLED_REASON =
- "com.android.settingslib.fuelgauge.ACTION_SAVER_MANUAL_ENABLED_REASON";
+ public static final String ACTION_SAVER_STATE_MANUAL_UPDATE =
+ "com.android.settingslib.fuelgauge.ACTION_SAVER_STATE_MANUAL_UPDATE";
/** An interface for the battery saver manual enable reason. */
@Retention(RetentionPolicy.SOURCE)
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
index e28ada4..c9540c7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -16,7 +16,8 @@
package com.android.settingslib.fuelgauge;
-import static com.android.settingslib.fuelgauge.BatterySaverLogging.ACTION_SAVER_MANUAL_ENABLED_REASON;
+import static com.android.settingslib.fuelgauge.BatterySaverLogging.ACTION_SAVER_STATE_MANUAL_UPDATE;
+import static com.android.settingslib.fuelgauge.BatterySaverLogging.EXTRA_POWER_SAVE_MODE_MANUAL_ENABLED;
import static com.android.settingslib.fuelgauge.BatterySaverLogging.EXTRA_POWER_SAVE_MODE_MANUAL_ENABLED_REASON;
import static com.android.settingslib.fuelgauge.BatterySaverLogging.SaverManualEnabledReason;
@@ -152,9 +153,8 @@
sendSystemUiBroadcast(context, ACTION_SHOW_AUTO_SAVER_SUGGESTION,
confirmationExtras);
}
- recordBatterySaverEnabledReason(context, reason);
}
-
+ recordBatterySaverEnabledReason(context, enable, reason);
return true;
}
return false;
@@ -185,11 +185,12 @@
return true;
}
- private static void recordBatterySaverEnabledReason(Context context,
+ private static void recordBatterySaverEnabledReason(Context context, boolean enable,
@SaverManualEnabledReason int reason) {
- final Bundle enabledReasonExtras = new Bundle(1);
+ final Bundle enabledReasonExtras = new Bundle(2);
enabledReasonExtras.putInt(EXTRA_POWER_SAVE_MODE_MANUAL_ENABLED_REASON, reason);
- sendSystemUiBroadcast(context, ACTION_SAVER_MANUAL_ENABLED_REASON, enabledReasonExtras);
+ enabledReasonExtras.putBoolean(EXTRA_POWER_SAVE_MODE_MANUAL_ENABLED, enable);
+ sendSystemUiBroadcast(context, ACTION_SAVER_STATE_MANUAL_UPDATE, enabledReasonExtras);
}
private static void sendSystemUiBroadcast(Context context, String action, Bundle extras) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
index 7a26f76..80301c0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
@@ -16,14 +16,16 @@
package com.android.settingslib.fuelgauge;
+import static com.android.settingslib.fuelgauge.BatterySaverLogging.ACTION_SAVER_STATE_MANUAL_UPDATE;
import static com.android.settingslib.fuelgauge.BatterySaverLogging.SAVER_ENABLED_UNKNOWN;
+import static com.android.settingslib.fuelgauge.BatterySaverUtils.ACTION_SHOW_AUTO_SAVER_SUGGESTION;
+import static com.android.settingslib.fuelgauge.BatterySaverUtils.ACTION_SHOW_START_SAVER_CONFIRMATION;
import static com.android.settingslib.fuelgauge.BatterySaverUtils.KEY_NO_SCHEDULE;
import static com.android.settingslib.fuelgauge.BatterySaverUtils.KEY_PERCENTAGE;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
@@ -40,10 +42,13 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import java.util.List;
+
@RunWith(RobolectricTestRunner.class)
public class BatterySaverUtilsTest {
private static final int BATTERY_SAVER_THRESHOLD_1 = 15;
@@ -68,7 +73,7 @@
}
@Test
- public void testSetPowerSaveMode_enable_firstCall_needWarning() {
+ public void testSetPowerSaveMode_enableWithWarning_firstCall_needConfirmationWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
@@ -76,9 +81,12 @@
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true,
SAVER_ENABLED_UNKNOWN)).isFalse();
- verify(mMockContext, times(1)).sendBroadcast(any(Intent.class));
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext, times(1)).sendBroadcast(intentCaptor.capture());
verify(mMockPowerManager, times(0)).setPowerSaveModeEnabled(anyBoolean());
+ assertThat(intentCaptor.getValue().getAction()).isEqualTo(
+ ACTION_SHOW_START_SAVER_CONFIRMATION);
// They shouldn't have changed.
assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(-1,
@@ -88,7 +96,7 @@
}
@Test
- public void testSetPowerSaveMode_enable_secondCall_needWarning() {
+ public void testSetPowerSaveMode_enableWithWarning_secondCall_expectUpdateIntent() {
// Already acked.
Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
Secure.putInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1);
@@ -97,8 +105,12 @@
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true,
SAVER_ENABLED_UNKNOWN)).isTrue();
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext, times(1)).sendBroadcast(intentCaptor.capture());
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
+ assertThat(intentCaptor.getValue().getAction()).isEqualTo(
+ ACTION_SAVER_STATE_MANUAL_UPDATE);
assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(1,
Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
@@ -107,7 +119,7 @@
}
@Test
- public void testSetPowerSaveMode_enable_thridCall_needWarning() {
+ public void testSetPowerSaveMode_enableWithWarning_thirdCall_expectUpdateIntent() {
// Already acked.
Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
Secure.putInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1);
@@ -116,8 +128,12 @@
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true,
SAVER_ENABLED_UNKNOWN)).isTrue();
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext, times(1)).sendBroadcast(intentCaptor.capture());
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
+ assertThat(intentCaptor.getValue().getAction()).isEqualTo(
+ ACTION_SAVER_STATE_MANUAL_UPDATE);
assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(1,
Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
@@ -126,7 +142,31 @@
}
@Test
- public void testSetPowerSaveMode_enable_firstCall_noWarning() {
+ public void testSetPowerSaveMode_enableWithWarning_5thCall_needAutoSuggestionWarning() {
+ // Already acked.
+ Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
+ Secure.putInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, 1);
+ Secure.putInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, 3);
+
+ assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true,
+ SAVER_ENABLED_UNKNOWN)).isTrue();
+
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext, times(2)).sendBroadcast(intentCaptor.capture());
+ verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
+
+ List<Intent> values = intentCaptor.getAllValues();
+ assertThat(values.get(0).getAction()).isEqualTo(ACTION_SHOW_AUTO_SAVER_SUGGESTION);
+ assertThat(values.get(1).getAction()).isEqualTo(ACTION_SAVER_STATE_MANUAL_UPDATE);
+ assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(4,
+ Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+ }
+
+ @Test
+ public void testSetPowerSaveMode_enableWithoutWarning_expectUpdateIntent() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
@@ -134,8 +174,12 @@
assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, false,
SAVER_ENABLED_UNKNOWN)).isTrue();
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext, times(1)).sendBroadcast(intentCaptor.capture());
verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(true));
+ assertThat(intentCaptor.getValue().getAction()).isEqualTo(
+ ACTION_SAVER_STATE_MANUAL_UPDATE);
assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
assertEquals(1,
Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
@@ -143,43 +187,13 @@
}
@Test
- public void testSetPowerSaveMode_disable_firstCall_noWarning() {
- Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
- Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
- Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
-
- // When disabling, needFirstTimeWarning doesn't matter.
- assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, false, false,
- SAVER_ENABLED_UNKNOWN)).isTrue();
-
- verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
- verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(false));
-
- assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
- assertEquals(-1,
- Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
- assertEquals(-2,
- Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+ public void testSetPowerSaveMode_disableWithoutWarning_expectUpdateIntent() {
+ verifyDisablePowerSaveMode(/* needFirstTimeWarning= */ false);
}
@Test
- public void testSetPowerSaveMode_disable_firstCall_needWarning() {
- Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
- Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
- Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
-
- // When disabling, needFirstTimeWarning doesn't matter.
- assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, false, true,
- SAVER_ENABLED_UNKNOWN)).isTrue();
-
- verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
- verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(false));
-
- assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
- assertEquals(-1,
- Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
- assertEquals(-2,
- Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+ public void testSetPowerSaveMode_disableWithWarning_expectUpdateIntent() {
+ verifyDisablePowerSaveMode(/* needFirstTimeWarning= */ true);
}
@Test
@@ -256,4 +270,26 @@
.isEqualTo(20);
}
+
+ private void verifyDisablePowerSaveMode(boolean needFirstTimeWarning) {
+ Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+ Secure.putString(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+ Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
+
+ // When disabling, needFirstTimeWarning doesn't matter.
+ assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, false, needFirstTimeWarning,
+ SAVER_ENABLED_UNKNOWN)).isTrue();
+
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mMockContext, times(1)).sendBroadcast(intentCaptor.capture());
+ verify(mMockPowerManager, times(1)).setPowerSaveModeEnabled(eq(false));
+
+ assertThat(intentCaptor.getValue().getAction()).isEqualTo(
+ ACTION_SAVER_STATE_MANUAL_UPDATE);
+ assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(-1,
+ Secure.getInt(mMockResolver, Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+ assertEquals(-2,
+ Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+ }
}
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 865b0df..b95a149 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -228,26 +228,33 @@
filegroup {
name: "SystemUI-tests-robolectric-pilots",
srcs: [
+ /* Keyguard converted tests */
// data
"tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt",
"tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt",
- "tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt",
"tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt",
"tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt",
"tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt",
"tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt",
"tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt",
+ "tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt",
"tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt",
"tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt",
+ "tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt",
+ "tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt",
+ "tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt",
+ "tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt",
+ "tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt",
"tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt",
"tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt",
+ "tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt",
+ "tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt",
// domain
"tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt",
- "tests/src/com/android/systemui/keyguard/domain/quickaffordance/FakeKeyguardQuickAffordanceRegistry.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt",
// ui
"tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt",
@@ -256,8 +263,13 @@
"tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt",
"tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt",
"tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt",
+ // Keyguard helper
+ "tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt",
+ "tests/src/com/android/systemui/dump/LogBufferHelper.kt",
+ "tests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java",
+ "tests/src/com/android/systemui/keyguard/domain/quickaffordance/FakeKeyguardQuickAffordanceRegistry.kt",
- // Biometric
+ /* Biometric converted tests */
"tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt",
"tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt",
"tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt",
diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp
index 5b5871f..8eb012d 100644
--- a/packages/SystemUI/animation/Android.bp
+++ b/packages/SystemUI/animation/Android.bp
@@ -43,6 +43,7 @@
"androidx.core_core-ktx",
"androidx.annotation_annotation",
"SystemUIShaderLib",
+ "animationlib",
],
manifest: "AndroidManifest.xml",
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 296c2ae..2e80379 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -39,9 +39,9 @@
import android.view.animation.PathInterpolator
import androidx.annotation.BinderThread
import androidx.annotation.UiThread
+import com.android.app.animation.Interpolators
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.policy.ScreenDecorationsUtils
-import java.lang.IllegalArgumentException
import kotlin.math.roundToInt
private const val TAG = "ActivityLaunchAnimator"
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index 42a8636..48dd08f 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -33,10 +33,10 @@
import android.view.WindowManager
import android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
import android.widget.FrameLayout
+import com.android.app.animation.Interpolators
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.jank.InteractionJankMonitor.CujType
import com.android.systemui.util.registerAnimationOnBackInvoked
-import java.lang.IllegalArgumentException
import kotlin.math.roundToInt
private const val TAG = "DialogLaunchAnimator"
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java b/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
deleted file mode 100644
index 9dbb920..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.animation;
-
-import android.graphics.Path;
-import android.util.MathUtils;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.BounceInterpolator;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-import android.view.animation.PathInterpolator;
-
-/**
- * Utility class to receive interpolators from.
- *
- * Make sure that changes made to this class are also reflected in {@link InterpolatorsAndroidX}.
- * Please consider using the androidx dependencies featuring better testability altogether.
- */
-public class Interpolators {
-
- /*
- * ============================================================================================
- * Emphasized interpolators.
- * ============================================================================================
- */
-
- /**
- * The default emphasized interpolator. Used for hero / emphasized movement of content.
- */
- public static final Interpolator EMPHASIZED = createEmphasizedInterpolator();
-
- /**
- * The accelerated emphasized interpolator. Used for hero / emphasized movement of content that
- * is disappearing e.g. when moving off screen.
- */
- public static final Interpolator EMPHASIZED_ACCELERATE = new PathInterpolator(
- 0.3f, 0f, 0.8f, 0.15f);
-
- /**
- * The decelerating emphasized interpolator. Used for hero / emphasized movement of content that
- * is appearing e.g. when coming from off screen
- */
- public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
- 0.05f, 0.7f, 0.1f, 1f);
-
-
- /*
- * ============================================================================================
- * Standard interpolators.
- * ============================================================================================
- */
-
- /**
- * The standard interpolator that should be used on every normal animation
- */
- public static final Interpolator STANDARD = new PathInterpolator(
- 0.2f, 0f, 0f, 1f);
-
- /**
- * The standard accelerating interpolator that should be used on every regular movement of
- * content that is disappearing e.g. when moving off screen.
- */
- public static final Interpolator STANDARD_ACCELERATE = new PathInterpolator(
- 0.3f, 0f, 1f, 1f);
-
- /**
- * The standard decelerating interpolator that should be used on every regular movement of
- * content that is appearing e.g. when coming from off screen.
- */
- public static final Interpolator STANDARD_DECELERATE = new PathInterpolator(
- 0f, 0f, 0f, 1f);
-
- /*
- * ============================================================================================
- * Legacy
- * ============================================================================================
- */
-
- /**
- * The default legacy interpolator as defined in Material 1. Also known as FAST_OUT_SLOW_IN.
- */
- public static final Interpolator LEGACY = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
-
- /**
- * The default legacy accelerating interpolator as defined in Material 1.
- * Also known as FAST_OUT_LINEAR_IN.
- */
- public static final Interpolator LEGACY_ACCELERATE = new PathInterpolator(0.4f, 0f, 1f, 1f);
-
- /**
- * The default legacy decelerating interpolator as defined in Material 1.
- * Also known as LINEAR_OUT_SLOW_IN.
- */
- public static final Interpolator LEGACY_DECELERATE = new PathInterpolator(0f, 0f, 0.2f, 1f);
-
- /**
- * Linear interpolator. Often used if the interpolator is for different properties who need
- * different interpolations.
- */
- public static final Interpolator LINEAR = new LinearInterpolator();
-
- /*
- * ============================================================================================
- * Custom interpolators
- * ============================================================================================
- */
-
- public static final Interpolator FAST_OUT_SLOW_IN = LEGACY;
- public static final Interpolator FAST_OUT_LINEAR_IN = LEGACY_ACCELERATE;
- public static final Interpolator LINEAR_OUT_SLOW_IN = LEGACY_DECELERATE;
-
- /**
- * Like {@link #FAST_OUT_SLOW_IN}, but used in case the animation is played in reverse (i.e. t
- * goes from 1 to 0 instead of 0 to 1).
- */
- public static final Interpolator FAST_OUT_SLOW_IN_REVERSE =
- new PathInterpolator(0.8f, 0f, 0.6f, 1f);
- public static final Interpolator SLOW_OUT_LINEAR_IN = new PathInterpolator(0.8f, 0f, 1f, 1f);
- public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
- public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
- public static final Interpolator ACCELERATE = new AccelerateInterpolator();
- public static final Interpolator ACCELERATE_DECELERATE = new AccelerateDecelerateInterpolator();
- public static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f);
- public static final Interpolator CUSTOM_40_40 = new PathInterpolator(0.4f, 0f, 0.6f, 1f);
- public static final Interpolator ICON_OVERSHOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f);
- public static final Interpolator ICON_OVERSHOT_LESS = new PathInterpolator(0.4f, 0f, 0.2f,
- 1.1f);
- public static final Interpolator PANEL_CLOSE_ACCELERATED = new PathInterpolator(0.3f, 0, 0.5f,
- 1);
- public static final Interpolator BOUNCE = new BounceInterpolator();
- /**
- * For state transitions on the control panel that lives in GlobalActions.
- */
- public static final Interpolator CONTROL_STATE = new PathInterpolator(0.4f, 0f, 0.2f,
- 1.0f);
-
- /**
- * Interpolator to be used when animating a move based on a click. Pair with enough duration.
- */
- public static final Interpolator TOUCH_RESPONSE =
- new PathInterpolator(0.3f, 0f, 0.1f, 1f);
-
- /**
- * Like {@link #TOUCH_RESPONSE}, but used in case the animation is played in reverse (i.e. t
- * goes from 1 to 0 instead of 0 to 1).
- */
- public static final Interpolator TOUCH_RESPONSE_REVERSE =
- new PathInterpolator(0.9f, 0f, 0.7f, 1f);
-
- /*
- * ============================================================================================
- * Functions / Utilities
- * ============================================================================================
- */
-
- /**
- * Calculate the amount of overshoot using an exponential falloff function with desired
- * properties, where the overshoot smoothly transitions at the 1.0f boundary into the
- * overshoot, retaining its acceleration.
- *
- * @param progress a progress value going from 0 to 1
- * @param overshootAmount the amount > 0 of overshoot desired. A value of 0.1 means the max
- * value of the overall progress will be at 1.1.
- * @param overshootStart the point in (0,1] where the result should reach 1
- * @return the interpolated overshoot
- */
- public static float getOvershootInterpolation(float progress, float overshootAmount,
- float overshootStart) {
- if (overshootAmount == 0.0f || overshootStart == 0.0f) {
- throw new IllegalArgumentException("Invalid values for overshoot");
- }
- float b = MathUtils.log((overshootAmount + 1) / (overshootAmount)) / overshootStart;
- return MathUtils.max(0.0f,
- (float) (1.0f - Math.exp(-b * progress)) * (overshootAmount + 1.0f));
- }
-
- /**
- * Similar to {@link #getOvershootInterpolation(float, float, float)} but the overshoot
- * starts immediately here, instead of first having a section of non-overshooting
- *
- * @param progress a progress value going from 0 to 1
- */
- public static float getOvershootInterpolation(float progress) {
- return MathUtils.max(0.0f, (float) (1.0f - Math.exp(-4 * progress)));
- }
-
- // Create the default emphasized interpolator
- private static PathInterpolator createEmphasizedInterpolator() {
- Path path = new Path();
- // Doing the same as fast_out_extra_slow_in
- path.moveTo(0f, 0f);
- path.cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f);
- path.cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f);
- return new PathInterpolator(path);
- }
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/InterpolatorsAndroidX.java b/packages/SystemUI/animation/src/com/android/systemui/animation/InterpolatorsAndroidX.java
deleted file mode 100644
index 8da87feb..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/InterpolatorsAndroidX.java
+++ /dev/null
@@ -1,219 +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.animation;
-
-import android.graphics.Path;
-import android.util.MathUtils;
-
-import androidx.core.animation.AccelerateDecelerateInterpolator;
-import androidx.core.animation.AccelerateInterpolator;
-import androidx.core.animation.BounceInterpolator;
-import androidx.core.animation.DecelerateInterpolator;
-import androidx.core.animation.Interpolator;
-import androidx.core.animation.LinearInterpolator;
-import androidx.core.animation.PathInterpolator;
-
-/**
- * Utility class to receive interpolators from. (androidx compatible version)
- *
- * This is the androidx compatible version of {@link Interpolators}. Make sure that changes made to
- * this class are also reflected in {@link Interpolators}.
- *
- * Using the androidx versions of {@link androidx.core.animation.ValueAnimator} or
- * {@link androidx.core.animation.ObjectAnimator} improves animation testability. This file provides
- * the androidx compatible versions of the interpolators defined in {@link Interpolators}.
- * AnimatorTestRule can be used in Tests to manipulate the animation under test (e.g. artificially
- * advancing the time).
- */
-public class InterpolatorsAndroidX {
-
- /*
- * ============================================================================================
- * Emphasized interpolators.
- * ============================================================================================
- */
-
- /**
- * The default emphasized interpolator. Used for hero / emphasized movement of content.
- */
- public static final Interpolator EMPHASIZED = createEmphasizedInterpolator();
-
- /**
- * The accelerated emphasized interpolator. Used for hero / emphasized movement of content that
- * is disappearing e.g. when moving off screen.
- */
- public static final Interpolator EMPHASIZED_ACCELERATE = new PathInterpolator(
- 0.3f, 0f, 0.8f, 0.15f);
-
- /**
- * The decelerating emphasized interpolator. Used for hero / emphasized movement of content that
- * is appearing e.g. when coming from off screen
- */
- public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
- 0.05f, 0.7f, 0.1f, 1f);
-
-
- /*
- * ============================================================================================
- * Standard interpolators.
- * ============================================================================================
- */
-
- /**
- * The standard interpolator that should be used on every normal animation
- */
- public static final Interpolator STANDARD = new PathInterpolator(
- 0.2f, 0f, 0f, 1f);
-
- /**
- * The standard accelerating interpolator that should be used on every regular movement of
- * content that is disappearing e.g. when moving off screen.
- */
- public static final Interpolator STANDARD_ACCELERATE = new PathInterpolator(
- 0.3f, 0f, 1f, 1f);
-
- /**
- * The standard decelerating interpolator that should be used on every regular movement of
- * content that is appearing e.g. when coming from off screen.
- */
- public static final Interpolator STANDARD_DECELERATE = new PathInterpolator(
- 0f, 0f, 0f, 1f);
-
- /*
- * ============================================================================================
- * Legacy
- * ============================================================================================
- */
-
- /**
- * The default legacy interpolator as defined in Material 1. Also known as FAST_OUT_SLOW_IN.
- */
- public static final Interpolator LEGACY = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
-
- /**
- * The default legacy accelerating interpolator as defined in Material 1.
- * Also known as FAST_OUT_LINEAR_IN.
- */
- public static final Interpolator LEGACY_ACCELERATE = new PathInterpolator(0.4f, 0f, 1f, 1f);
-
- /**
- * The default legacy decelerating interpolator as defined in Material 1.
- * Also known as LINEAR_OUT_SLOW_IN.
- */
- public static final Interpolator LEGACY_DECELERATE = new PathInterpolator(0f, 0f, 0.2f, 1f);
-
- /**
- * Linear interpolator. Often used if the interpolator is for different properties who need
- * different interpolations.
- */
- public static final Interpolator LINEAR = new LinearInterpolator();
-
- /*
- * ============================================================================================
- * Custom interpolators
- * ============================================================================================
- */
-
- public static final Interpolator FAST_OUT_SLOW_IN = LEGACY;
- public static final Interpolator FAST_OUT_LINEAR_IN = LEGACY_ACCELERATE;
- public static final Interpolator LINEAR_OUT_SLOW_IN = LEGACY_DECELERATE;
-
- /**
- * Like {@link #FAST_OUT_SLOW_IN}, but used in case the animation is played in reverse (i.e. t
- * goes from 1 to 0 instead of 0 to 1).
- */
- public static final Interpolator FAST_OUT_SLOW_IN_REVERSE =
- new PathInterpolator(0.8f, 0f, 0.6f, 1f);
- public static final Interpolator SLOW_OUT_LINEAR_IN = new PathInterpolator(0.8f, 0f, 1f, 1f);
- public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
- public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
- public static final Interpolator ACCELERATE = new AccelerateInterpolator();
- public static final Interpolator ACCELERATE_DECELERATE = new AccelerateDecelerateInterpolator();
- public static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f);
- public static final Interpolator CUSTOM_40_40 = new PathInterpolator(0.4f, 0f, 0.6f, 1f);
- public static final Interpolator ICON_OVERSHOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f);
- public static final Interpolator ICON_OVERSHOT_LESS = new PathInterpolator(0.4f, 0f, 0.2f,
- 1.1f);
- public static final Interpolator PANEL_CLOSE_ACCELERATED = new PathInterpolator(0.3f, 0, 0.5f,
- 1);
- public static final Interpolator BOUNCE = new BounceInterpolator();
- /**
- * For state transitions on the control panel that lives in GlobalActions.
- */
- public static final Interpolator CONTROL_STATE = new PathInterpolator(0.4f, 0f, 0.2f,
- 1.0f);
-
- /**
- * Interpolator to be used when animating a move based on a click. Pair with enough duration.
- */
- public static final Interpolator TOUCH_RESPONSE =
- new PathInterpolator(0.3f, 0f, 0.1f, 1f);
-
- /**
- * Like {@link #TOUCH_RESPONSE}, but used in case the animation is played in reverse (i.e. t
- * goes from 1 to 0 instead of 0 to 1).
- */
- public static final Interpolator TOUCH_RESPONSE_REVERSE =
- new PathInterpolator(0.9f, 0f, 0.7f, 1f);
-
- /*
- * ============================================================================================
- * Functions / Utilities
- * ============================================================================================
- */
-
- /**
- * Calculate the amount of overshoot using an exponential falloff function with desired
- * properties, where the overshoot smoothly transitions at the 1.0f boundary into the
- * overshoot, retaining its acceleration.
- *
- * @param progress a progress value going from 0 to 1
- * @param overshootAmount the amount > 0 of overshoot desired. A value of 0.1 means the max
- * value of the overall progress will be at 1.1.
- * @param overshootStart the point in (0,1] where the result should reach 1
- * @return the interpolated overshoot
- */
- public static float getOvershootInterpolation(float progress, float overshootAmount,
- float overshootStart) {
- if (overshootAmount == 0.0f || overshootStart == 0.0f) {
- throw new IllegalArgumentException("Invalid values for overshoot");
- }
- float b = MathUtils.log((overshootAmount + 1) / (overshootAmount)) / overshootStart;
- return MathUtils.max(0.0f,
- (float) (1.0f - Math.exp(-b * progress)) * (overshootAmount + 1.0f));
- }
-
- /**
- * Similar to {@link #getOvershootInterpolation(float, float, float)} but the overshoot
- * starts immediately here, instead of first having a section of non-overshooting
- *
- * @param progress a progress value going from 0 to 1
- */
- public static float getOvershootInterpolation(float progress) {
- return MathUtils.max(0.0f, (float) (1.0f - Math.exp(-4 * progress)));
- }
-
- // Create the default emphasized interpolator
- private static PathInterpolator createEmphasizedInterpolator() {
- Path path = new Path();
- // Doing the same as fast_out_extra_slow_in
- path.moveTo(0f, 0f);
- path.cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f);
- path.cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f);
- return new PathInterpolator(path);
- }
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
index 3417ffd..142fd21 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
@@ -28,7 +28,7 @@
import android.view.View
import android.view.ViewGroup
import android.view.animation.Interpolator
-import com.android.systemui.animation.Interpolators.LINEAR
+import com.android.app.animation.Interpolators.LINEAR
import kotlin.math.roundToInt
private const val TAG = "LaunchAnimator"
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
index 3ee97be..9346a2f 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
@@ -24,12 +24,30 @@
import android.graphics.Typeface
import android.graphics.fonts.Font
import android.text.Layout
+import android.text.TextPaint
import android.util.LruCache
private const val DEFAULT_ANIMATION_DURATION: Long = 300
private const val TYPEFACE_CACHE_MAX_ENTRIES = 5
typealias GlyphCallback = (TextAnimator.PositionedGlyph, Float) -> Unit
+
+interface TypefaceVariantCache {
+ fun getTypefaceForVariant(fvar: String, targetPaint: TextPaint): Typeface?
+}
+
+class TypefaceVariantCacheImpl() : TypefaceVariantCache {
+ private val cache = LruCache<String, Typeface>(TYPEFACE_CACHE_MAX_ENTRIES)
+ override fun getTypefaceForVariant(fvar: String, targetPaint: TextPaint): Typeface? {
+ cache.get(fvar)?.let {
+ return it
+ }
+
+ targetPaint.fontVariationSettings = fvar
+ return targetPaint.typeface?.also { cache.put(fvar, it) }
+ }
+}
+
/**
* This class provides text animation between two styles.
*
@@ -56,9 +74,19 @@
* ```
* </code> </pre>
*/
-class TextAnimator(layout: Layout, private val invalidateCallback: () -> Unit) {
+class TextAnimator(
+ layout: Layout,
+ private val invalidateCallback: () -> Unit,
+) {
+ var typefaceCache: TypefaceVariantCache = TypefaceVariantCacheImpl()
+ get() = field
+ set(value) {
+ field = value
+ textInterpolator.typefaceCache = value
+ }
+
// Following two members are for mutable for testing purposes.
- public var textInterpolator: TextInterpolator = TextInterpolator(layout)
+ public var textInterpolator: TextInterpolator = TextInterpolator(layout, typefaceCache)
public var animator: ValueAnimator =
ValueAnimator.ofFloat(1f).apply {
duration = DEFAULT_ANIMATION_DURATION
@@ -68,9 +96,7 @@
}
addListener(
object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator?) {
- textInterpolator.rebase()
- }
+ override fun onAnimationEnd(animation: Animator?) = textInterpolator.rebase()
override fun onAnimationCancel(animation: Animator?) = textInterpolator.rebase()
}
)
@@ -116,8 +142,6 @@
private val fontVariationUtils = FontVariationUtils()
- private val typefaceCache = LruCache<String, Typeface>(TYPEFACE_CACHE_MAX_ENTRIES)
-
fun updateLayout(layout: Layout) {
textInterpolator.layout = layout
}
@@ -220,12 +244,8 @@
}
if (!fvar.isNullOrBlank()) {
- textInterpolator.targetPaint.typeface = typefaceCache.get(fvar) ?: run {
- textInterpolator.targetPaint.fontVariationSettings = fvar
- textInterpolator.targetPaint.typeface?.also {
- typefaceCache.put(fvar, textInterpolator.targetPaint.typeface)
- }
- }
+ textInterpolator.targetPaint.typeface =
+ typefaceCache.getTypefaceForVariant(fvar, textInterpolator.targetPaint)
}
if (color != null) {
@@ -304,7 +324,8 @@
weight = weight,
width = width,
opticalSize = opticalSize,
- roundness = roundness,)
+ roundness = roundness,
+ )
setTextStyle(
fvar = fvar,
textSize = textSize,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
index 23f16f2..a041926 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
@@ -28,8 +28,10 @@
import java.lang.Math.max
/** Provide text style linear interpolation for plain text. */
-class TextInterpolator(layout: Layout) {
-
+class TextInterpolator(
+ layout: Layout,
+ var typefaceCache: TypefaceVariantCache,
+) {
/**
* Returns base paint used for interpolation.
*
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
index 58ffef2..8e79e3c 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
@@ -25,6 +25,7 @@
import android.view.View
import android.view.ViewGroup
import android.view.animation.Interpolator
+import com.android.app.animation.Interpolators
import kotlin.math.max
import kotlin.math.min
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt
index f3d8b17..dd32851 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/back/BackAnimationSpec.kt
@@ -19,7 +19,7 @@
import android.util.DisplayMetrics
import android.view.animation.Interpolator
import android.window.BackEvent
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.util.dpToPx
/** Used to convert [BackEvent] into a [BackTransformation]. */
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
index 9d1dd1b..3688f9e 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
@@ -29,9 +29,9 @@
import android.util.AttributeSet
import android.util.MathUtils
import android.widget.TextView
+import com.android.app.animation.Interpolators
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.animation.GlyphCallback
-import com.android.systemui.animation.Interpolators
import com.android.systemui.animation.TextAnimator
import com.android.systemui.customization.R
import com.android.systemui.plugins.log.LogBuffer
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardQuickAffordancePreviewConstants.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardPreviewConstants.kt
similarity index 86%
rename from packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardQuickAffordancePreviewConstants.kt
rename to packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardPreviewConstants.kt
index bf922bc..08ee602 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardQuickAffordancePreviewConstants.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/shared/model/KeyguardPreviewConstants.kt
@@ -17,7 +17,9 @@
package com.android.systemui.shared.quickaffordance.shared.model
-object KeyguardQuickAffordancePreviewConstants {
+object KeyguardPreviewConstants {
+ const val MESSAGE_ID_HIDE_SMART_SPACE = 1111
+ const val KEY_HIDE_SMART_SPACE = "hide_smart_space"
const val MESSAGE_ID_SLOT_SELECTED = 1337
const val KEY_SLOT_ID = "slot_id"
const val KEY_INITIALLY_SELECTED_SLOT_ID = "initially_selected_slot_id"
diff --git a/packages/SystemUI/res/drawable/keyguard_settings_popup_menu_background.xml b/packages/SystemUI/res/drawable/keyguard_settings_popup_menu_background.xml
index a0ceb81..fe76ba7 100644
--- a/packages/SystemUI/res/drawable/keyguard_settings_popup_menu_background.xml
+++ b/packages/SystemUI/res/drawable/keyguard_settings_popup_menu_background.xml
@@ -26,7 +26,7 @@
</item>
<item>
<shape android:shape="rectangle">
- <solid android:color="?androidprv:attr/materialColorOnBackground" />
+ <solid android:color="?androidprv:attr/materialColorSecondaryFixed" />
<corners android:radius="@dimen/keyguard_affordance_fixed_radius" />
</shape>
</item>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 9cb8aa0..a2eba81 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -389,7 +389,7 @@
<dimen name="navigation_key_width">70dp</dimen>
<!-- The width/height of the icon of a navigation button -->
- <dimen name="navigation_icon_size">32dp</dimen>
+ <dimen name="navigation_icon_size">24dp</dimen>
<!-- The padding on the side of the navigation bar. Must be greater than or equal to
navigation_extra_key_width -->
diff --git a/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt b/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt
index f59bf8e..64d766d 100644
--- a/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt
+++ b/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt
@@ -26,8 +26,8 @@
import android.graphics.Color
import android.util.AttributeSet
import android.view.View
+import com.android.app.animation.Interpolators
import com.android.settingslib.Utils
-import com.android.systemui.animation.Interpolators
/** Displays security messages for the keyguard bouncer. */
open class BouncerKeyguardMessageArea(context: Context?, attrs: AttributeSet?) :
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index a6c782d..a30cae9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -15,9 +15,9 @@
import androidx.annotation.IntDef;
import androidx.annotation.VisibleForTesting;
+import com.android.app.animation.Interpolators;
import com.android.keyguard.dagger.KeyguardStatusViewScope;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.ClockController;
import com.android.systemui.plugins.log.LogBuffer;
import com.android.systemui.plugins.log.LogLevel;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index 0394754..0982030 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -32,9 +32,9 @@
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
+import com.android.app.animation.Interpolators;
import com.android.settingslib.animation.DisappearAnimationUtils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt;
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 33bea02..1d7c35d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -45,11 +45,11 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.TextViewInputDisabler;
import com.android.systemui.DejankUtils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
/**
* Displays an alphanumeric (latin-1) key entry for the user to enter
* an unlock password
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 0a91150..b4ddc9a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -34,9 +34,9 @@
import android.view.KeyEvent;
import android.view.View;
+import com.android.app.animation.Interpolators;
import com.android.internal.widget.LockscreenCredential;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index ba5a8c9..78021ad 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -32,7 +32,7 @@
import static androidx.constraintlayout.widget.ConstraintSet.TOP;
import static androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT;
-import static com.android.systemui.animation.InterpolatorsAndroidX.DECELERATE_QUINT;
+import static com.android.app.animation.InterpolatorsAndroidX.DECELERATE_QUINT;
import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY;
import static java.lang.Integer.max;
@@ -86,6 +86,7 @@
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringAnimation;
+import com.android.app.animation.Interpolators;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
@@ -96,7 +97,6 @@
import com.android.settingslib.drawable.CircleFramedDrawable;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.classifier.FalsingA11yDelegate;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.shared.system.SysUiStatsLog;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewTransition.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewTransition.kt
index c9128e5..96ac8ad 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewTransition.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewTransition.kt
@@ -26,9 +26,9 @@
import android.view.View
import android.view.ViewGroup
import android.view.animation.AnimationUtils
+import com.android.app.animation.Interpolators
import com.android.internal.R.interpolator.fast_out_extra_slow_in
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
/** Animates constraint layout changes for the security view. */
class KeyguardSecurityViewTransition : Transition() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 65a7166..b4f124a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -44,11 +44,11 @@
import androidx.slice.widget.RowContent;
import androidx.slice.widget.SliceContent;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index edfcb8d..89e7e17 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -40,11 +40,11 @@
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
+import com.android.app.animation.Interpolators;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.keyguard.KeyguardClockSwitch.ClockSize;
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.ClockController;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 9573913..2c669bb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -396,7 +396,6 @@
private int mFaceRunningState = BIOMETRIC_STATE_STOPPED;
private boolean mIsDreaming;
private boolean mLogoutEnabled;
- private boolean mIsFaceEnrolled;
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private int mPostureState = DEVICE_POSTURE_UNKNOWN;
private FingerprintInteractiveToAuthProvider mFingerprintInteractiveToAuthProvider;
@@ -2573,16 +2572,6 @@
}
}
- private void updateFaceEnrolled(int userId) {
- final Boolean isFaceEnrolled = isFaceSupported()
- && mBiometricEnabledForUser.get(userId)
- && mAuthController.isFaceAuthEnrolled(userId);
- if (mIsFaceEnrolled != isFaceEnrolled) {
- mLogger.logFaceEnrolledUpdated(mIsFaceEnrolled, isFaceEnrolled);
- }
- mIsFaceEnrolled = isFaceEnrolled;
- }
-
private boolean isFaceSupported() {
return mFaceManager != null && !mFaceSensorProperties.isEmpty();
}
@@ -2622,10 +2611,17 @@
}
/**
- * @return true if there's at least one face enrolled
+ * @return true if there's at least one face enrolled for the given user
+ */
+ private boolean isFaceEnrolled(int userId) {
+ return mAuthController.isFaceAuthEnrolled(userId);
+ }
+
+ /**
+ * @return true if there's at least one face enrolled for the current user
*/
public boolean isFaceEnrolled() {
- return mIsFaceEnrolled;
+ return isFaceEnrolled(getCurrentUser());
}
private final UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() {
@@ -3284,14 +3280,13 @@
@SuppressLint("MissingPermission")
@VisibleForTesting
boolean isUnlockWithFingerprintPossible(int userId) {
- // TODO (b/242022358), make this rely on onEnrollmentChanged event and update it only once.
- boolean newFpEnrolled = isFingerprintSupported()
- && !isFingerprintDisabled(userId) && mFpm.hasEnrolledTemplates(userId);
- Boolean oldFpEnrolled = mIsUnlockWithFingerprintPossible.getOrDefault(userId, false);
- if (oldFpEnrolled != newFpEnrolled) {
- mLogger.logFpEnrolledUpdated(userId, oldFpEnrolled, newFpEnrolled);
+ boolean newFpPossible = isFingerprintSupported()
+ && !isFingerprintDisabled(userId) && mAuthController.isFingerprintEnrolled(userId);
+ Boolean oldFpPossible = mIsUnlockWithFingerprintPossible.getOrDefault(userId, false);
+ if (oldFpPossible != newFpPossible) {
+ mLogger.logFpPossibleUpdated(userId, oldFpPossible, newFpPossible);
}
- mIsUnlockWithFingerprintPossible.put(userId, newFpEnrolled);
+ mIsUnlockWithFingerprintPossible.put(userId, newFpPossible);
return mIsUnlockWithFingerprintPossible.get(userId);
}
@@ -3306,24 +3301,13 @@
/**
* @deprecated This is being migrated to use modern architecture.
*/
+ @VisibleForTesting
@Deprecated
- private boolean isUnlockWithFacePossible(int userId) {
+ public boolean isUnlockWithFacePossible(int userId) {
if (isFaceAuthInteractorEnabled()) {
return getFaceAuthInteractor().canFaceAuthRun();
}
- return isFaceAuthEnabledForUser(userId) && !isFaceDisabled(userId);
- }
-
- /**
- * If face hardware is available, user has enrolled and enabled auth via setting.
- *
- * @deprecated This is being migrated to use modern architecture.
- */
- @Deprecated
- public boolean isFaceAuthEnabledForUser(int userId) {
- // TODO (b/242022358), make this rely on onEnrollmentChanged event and update it only once.
- updateFaceEnrolled(userId);
- return mIsFaceEnrolled;
+ return isFaceSupported() && isFaceEnrolled(userId) && !isFaceDisabled(userId);
}
private void stopListeningForFingerprint() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
index 651c979..aa652fa 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
@@ -21,7 +21,7 @@
import android.util.Property;
import android.view.View;
-import com.android.systemui.animation.Interpolators;
+import com.android.app.animation.Interpolators;
import com.android.systemui.plugins.log.LogBuffer;
import com.android.systemui.plugins.log.LogLevel;
import com.android.systemui.statusbar.StatusBarState;
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
index ad66909..e761123 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
@@ -30,7 +30,7 @@
import androidx.annotation.StyleRes;
-import com.android.systemui.animation.Interpolators;
+import com.android.app.animation.Interpolators;
/**
* Provides background color and radius animations for key pad buttons.
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
index 14810d9..c4ecb39 100644
--- a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
@@ -35,9 +35,9 @@
import androidx.core.graphics.drawable.DrawableCompat;
+import com.android.app.animation.Interpolators;
import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
/**
* This class contains implementation for methods that will be used when user has set a
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index 1661806..fe40145 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -630,7 +630,7 @@
)
}
- fun logFpEnrolledUpdated(userId: Int, oldValue: Boolean, newValue: Boolean) {
+ fun logFpPossibleUpdated(userId: Int, oldValue: Boolean, newValue: Boolean) {
logBuffer.log(
TAG,
DEBUG,
@@ -639,7 +639,7 @@
bool1 = oldValue
bool2 = newValue
},
- { "Fp enrolled state changed for userId: $int1 old: $bool1, new: $bool2" }
+ { "Fp possible state changed for userId: $int1 old: $bool1, new: $bool2" }
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
index 12dd8f0..4c16d41c 100644
--- a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
@@ -16,6 +16,7 @@
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.util.AttributeSet;
@@ -23,21 +24,29 @@
import android.view.View;
import android.widget.FrameLayout;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* Custom {@link FrameLayout} that re-inflates when changes to {@link Configuration} happen.
* Currently supports changes to density, asset path, and locale.
*/
-public class AutoReinflateContainer extends FrameLayout implements
- ConfigurationController.ConfigurationListener {
+public class AutoReinflateContainer extends FrameLayout {
+
+ private static final Set<Integer> SUPPORTED_CHANGES = Set.of(
+ ActivityInfo.CONFIG_LOCALE,
+ ActivityInfo.CONFIG_UI_MODE,
+ ActivityInfo.CONFIG_ASSETS_PATHS,
+ ActivityInfo.CONFIG_DENSITY,
+ ActivityInfo.CONFIG_FONT_SCALE
+ );
private final List<InflateListener> mInflateListeners = new ArrayList<>();
private final int mLayout;
+ private final Configuration mLastConfig = new Configuration();
+
public AutoReinflateContainer(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -51,15 +60,14 @@
}
@Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- Dependency.get(ConfigurationController.class).addCallback(this);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- Dependency.get(ConfigurationController.class).removeCallback(this);
+ protected void onConfigurationChanged(Configuration newConfig) {
+ int diff = mLastConfig.updateFrom(newConfig);
+ for (int change: SUPPORTED_CHANGES) {
+ if ((diff & change) != 0) {
+ inflateLayout();
+ return;
+ }
+ }
}
protected void inflateLayoutImpl() {
@@ -80,26 +88,6 @@
listener.onInflated(getChildAt(0));
}
- @Override
- public void onDensityOrFontScaleChanged() {
- inflateLayout();
- }
-
- @Override
- public void onThemeChanged() {
- inflateLayout();
- }
-
- @Override
- public void onUiModeChanged() {
- inflateLayout();
- }
-
- @Override
- public void onLocaleListChanged() {
- inflateLayout();
- }
-
public interface InflateListener {
/**
* Called whenever a new view is inflated.
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index ef16a3a..aade71a 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -106,7 +106,6 @@
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.ExtensionController;
@@ -134,14 +133,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.
@@ -270,7 +269,6 @@
@Inject Lazy<NotificationShadeWindowController> mNotificationShadeWindowController;
@Inject Lazy<StatusBarWindowController> mTempStatusBarWindowController;
@Inject Lazy<DarkIconDispatcher> mDarkIconDispatcher;
- @Inject Lazy<ConfigurationController> mConfigurationController;
@Inject Lazy<StatusBarIconController> mStatusBarIconController;
@Inject Lazy<ScreenLifecycle> mScreenLifecycle;
@Inject Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
@@ -441,8 +439,6 @@
mProviders.put(DarkIconDispatcher.class, mDarkIconDispatcher::get);
- mProviders.put(ConfigurationController.class, mConfigurationController::get);
-
mProviders.put(StatusBarIconController.class, mStatusBarIconController::get);
mProviders.put(ScreenLifecycle.class, mScreenLifecycle::get);
diff --git a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
index de82ca0..c1871e0 100644
--- a/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
+++ b/packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
@@ -36,7 +36,7 @@
import android.view.View
import androidx.annotation.VisibleForTesting
import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.util.asIndenting
import java.io.PrintWriter
diff --git a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
index a3e7d71..e72ad82 100644
--- a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
@@ -34,7 +34,7 @@
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.settingslib.Utils
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.biometrics.AuthController
import com.android.systemui.log.ScreenDecorationsLogger
import com.android.systemui.plugins.statusbar.StatusBarStateController
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 2503520..99d4662 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -43,8 +43,8 @@
import androidx.annotation.VisibleForTesting;
+import com.android.app.animation.Interpolators;
import com.android.internal.dynamicanimation.animation.SpringForce;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.FalsingManager;
@@ -374,11 +374,10 @@
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
final boolean captured = (mIsSwiping || mLongPressSent || mMenuRowIntercepting);
- mIsSwiping = false;
- mTouchedView = null;
mLongPressSent = false;
mCallback.onLongPressSent(null);
mMenuRowIntercepting = false;
+ resetSwipeState();
cancelLongPress();
if (captured) return true;
break;
@@ -491,7 +490,7 @@
}
if (!mCancelled || wasRemoved) {
mCallback.onChildDismissed(animView);
- resetSwipeState();
+ resetSwipeOfView(animView);
}
if (endAction != null) {
endAction.accept(mCancelled);
@@ -546,7 +545,7 @@
if (!cancelled) {
updateSwipeProgressFromOffset(animView, canBeDismissed);
- resetSwipeState();
+ resetSwipeOfView(animView);
}
onChildSnappedBack(animView, targetLeft);
});
@@ -806,9 +805,20 @@
return mIsSwiping ? mTouchedView : null;
}
+ protected void resetSwipeOfView(View view) {
+ if (getSwipedView() == view) {
+ resetSwipeState();
+ }
+ }
+
public void resetSwipeState() {
+ View swipedView = getSwipedView();
mTouchedView = null;
mIsSwiping = false;
+ if (swipedView != null) {
+ snapChildIfNeeded(swipedView, false, 0);
+ onChildSnappedBack(swipedView, 0);
+ }
}
private float getTouchSlop(MotionEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
index d6f0b59..d491975 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
@@ -32,8 +32,8 @@
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
+import com.android.app.animation.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
/**
* Visually discloses that contextual data was provided to an assistant.
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 0002ae9..2aac056 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -45,9 +45,9 @@
import androidx.annotation.StyleRes;
import androidx.annotation.VisibleForTesting;
+import com.android.app.animation.Interpolators;
import com.android.systemui.DualToneHandler;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.policy.BatteryController;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index aeebb01..be585ed 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -59,11 +59,11 @@
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.biometrics.AuthController.ScaleFactorProvider;
import com.android.systemui.biometrics.domain.interactor.BiometricPromptCredentialInteractor;
import com.android.systemui.biometrics.ui.CredentialView;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index d0ac296..782a10b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -32,7 +32,7 @@
import com.android.settingslib.udfps.UdfpsOverlayParams
import com.android.systemui.CoreStartable
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index b007134..5ede16d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -28,7 +28,7 @@
import android.view.View
import android.view.animation.PathInterpolator
import com.android.internal.graphics.ColorUtils
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.surfaceeffects.ripple.RippleShader
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt
index ef7dcb7..1dbafc6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt
@@ -19,7 +19,7 @@
import android.graphics.PointF
import android.graphics.RectF
import com.android.systemui.Dumpable
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.ShadeExpansionListener
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
index ba8e60a..52db4ab 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
@@ -40,9 +40,9 @@
import androidx.annotation.Nullable;
import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
+import com.android.app.animation.Interpolators;
import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieProperty;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
index 3b50bbc..eaab75a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
@@ -23,11 +23,11 @@
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.animation.Interpolators
import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.R
import com.android.systemui.animation.ActivityLaunchAnimator
-import com.android.systemui.animation.Interpolators
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
index 9847c10..baf8d74 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
@@ -22,9 +22,7 @@
import com.android.systemui.biometrics.EllipseOverlapDetectorParams
import com.android.systemui.dagger.SysUISingleton
import kotlin.math.cos
-import kotlin.math.pow
import kotlin.math.sin
-import kotlin.math.sqrt
private enum class SensorPixelPosition {
OUTSIDE, // Pixel that falls outside of sensor circle
@@ -42,8 +40,8 @@
@SysUISingleton
class EllipseOverlapDetector(private val params: EllipseOverlapDetectorParams) : OverlapDetector {
override fun isGoodOverlap(touchData: NormalizedTouchData, nativeSensorBounds: Rect): Boolean {
- // First, check if entire ellipse is within the sensor
- if (isEllipseWithinSensor(touchData, nativeSensorBounds)) {
+ // First, check if touch is within bounding box,
+ if (nativeSensorBounds.contains(touchData.x.toInt(), touchData.y.toInt())) {
return true
}
@@ -119,28 +117,4 @@
return result <= 1
}
-
- /** Returns whether the entire ellipse is contained within the sensor area */
- private fun isEllipseWithinSensor(
- touchData: NormalizedTouchData,
- nativeSensorBounds: Rect
- ): Boolean {
- val a2 = (touchData.minor / 2.0).pow(2.0)
- val b2 = (touchData.major / 2.0).pow(2.0)
-
- val sin2a = sin(touchData.orientation.toDouble()).pow(2.0)
- val cos2a = cos(touchData.orientation.toDouble()).pow(2.0)
-
- val cx = sqrt(a2 * cos2a + b2 * sin2a)
- val cy = sqrt(a2 * sin2a + b2 * cos2a)
-
- val ellipseRect =
- Rect(
- (-cx + touchData.x).toInt(),
- (-cy + touchData.y).toInt(),
- (cx + touchData.x).toInt(),
- (cy + touchData.y).toInt()
- )
- return nativeSensorBounds.contains(ellipseRect)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialViewBinder.kt
index e2d36dc..9292bd7 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialViewBinder.kt
@@ -6,8 +6,8 @@
import android.widget.TextView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.animation.Interpolators
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
import com.android.systemui.biometrics.AuthDialog
import com.android.systemui.biometrics.AuthPanelController
import com.android.systemui.biometrics.ui.CredentialPasswordView
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index 11ef749..7bf8f4d 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -30,9 +30,9 @@
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.app.animation.Interpolators;
import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.surfaceeffects.ripple.RippleShader;
import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape;
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java
index 1fa9ac5..1ffbe32 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java
@@ -72,7 +72,7 @@
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Package not found: " + mClipboardManager.getPrimaryClipSource(), e);
}
- mEditText.setText(clip.getItemAt(0).getText());
+ mEditText.setText(clip.getItemAt(0).getText().toString());
mEditText.requestFocus();
mEditText.setSelection(0);
mSensitive = clip.getDescription().getExtras() != null
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt
index 8d0edf8..b447d66 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt
@@ -32,7 +32,7 @@
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.controls.ui.ControlsUiController
object ControlsAnimations {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
index 6a9aaf8..e6361f4 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
@@ -50,7 +50,7 @@
import androidx.annotation.VisibleForTesting
import com.android.internal.graphics.ColorUtils
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.controls.ControlsMetricsLogger
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.util.concurrency.DelayableExecutor
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
index fa36eee..1461135 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
@@ -38,7 +38,7 @@
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.controls.ui.ControlViewHolder.Companion.MAX_LEVEL
import com.android.systemui.controls.ui.ControlViewHolder.Companion.MIN_LEVEL
import java.util.IllegalFormatException
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index 0dcba50..f6435a7 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -278,7 +278,6 @@
@Provides
@Singleton
- @Nullable
static IVrManager provideIVrManager() {
return IVrManager.Stub.asInterface(ServiceManager.getService(Context.VR_SERVICE));
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index 5b56c04..83f39b5 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -24,8 +24,8 @@
import androidx.core.animation.doOnEnd
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.animation.Interpolators
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
import com.android.systemui.complication.ComplicationHostViewController
import com.android.systemui.complication.ComplicationLayoutParams
import com.android.systemui.complication.ComplicationLayoutParams.POSITION_BOTTOM
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index 15a32d2..c22019e 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -33,9 +33,9 @@
import androidx.annotation.NonNull;
+import com.android.app.animation.Interpolators;
import com.android.dream.lowlight.LowLightTransitionCoordinator;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.complication.ComplicationHostViewController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java b/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
index 5bbfbda..3ef19b7 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
@@ -16,12 +16,9 @@
package com.android.systemui.dreams.conditions;
import android.app.DreamManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.text.TextUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.shared.condition.Condition;
import javax.inject.Inject;
@@ -30,48 +27,33 @@
* {@link DreamCondition} provides a signal when a dream begins and ends.
*/
public class DreamCondition extends Condition {
- private final Context mContext;
private final DreamManager mDreamManager;
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- processIntent(intent);
- }
- };
+ private final KeyguardUpdateMonitor mUpdateMonitor;
+
+
+ private final KeyguardUpdateMonitorCallback mUpdateCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onDreamingStateChanged(boolean dreaming) {
+ updateCondition(dreaming);
+ }
+ };
@Inject
- public DreamCondition(Context context,
- DreamManager dreamManager) {
- mContext = context;
+ public DreamCondition(DreamManager dreamManager, KeyguardUpdateMonitor monitor) {
mDreamManager = dreamManager;
- }
-
- private void processIntent(Intent intent) {
- // In the case of a non-existent sticky broadcast, ignore when there is no intent.
- if (intent == null) {
- return;
- }
- if (TextUtils.equals(intent.getAction(), Intent.ACTION_DREAMING_STARTED)) {
- updateCondition(true);
- } else if (TextUtils.equals(intent.getAction(), Intent.ACTION_DREAMING_STOPPED)) {
- updateCondition(false);
- } else {
- throw new IllegalStateException("unexpected intent:" + intent);
- }
+ mUpdateMonitor = monitor;
}
@Override
protected void start() {
- final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_DREAMING_STARTED);
- filter.addAction(Intent.ACTION_DREAMING_STOPPED);
- mContext.registerReceiver(mReceiver, filter);
+ mUpdateMonitor.registerCallback(mUpdateCallback);
updateCondition(mDreamManager.isDreaming());
}
@Override
protected void stop() {
- mContext.unregisterReceiver(mReceiver);
+ mUpdateMonitor.removeCallback(mUpdateCallback);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 05153b6..2ecb0a0 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -110,7 +110,7 @@
// TODO(b/275694445): Tracking Bug
@JvmField
- val LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING = unreleasedFlag(208,
+ val LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING = releasedFlag(208,
"lockscreen_without_secure_lock_when_dreaming")
/**
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index d3b6fc2..5189944 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -97,6 +97,7 @@
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
+import com.android.app.animation.Interpolators;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.colorextraction.ColorExtractor;
@@ -116,7 +117,6 @@
import com.android.systemui.animation.DialogCuj;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.animation.Expandable;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.Background;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index 2d1b7ae..9844ca0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -36,7 +36,7 @@
import com.android.internal.R
import com.android.keyguard.KeyguardClockSwitchController
import com.android.keyguard.KeyguardViewController
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
@@ -792,7 +792,8 @@
// Translate up from the bottom.
surfaceBehindMatrix.setTranslate(
surfaceBehindRemoteAnimationTarget.localBounds.left.toFloat(),
- surfaceHeight * SURFACE_BEHIND_START_TRANSLATION_Y * (1f - amount)
+ surfaceBehindRemoteAnimationTarget.localBounds.top.toFloat() +
+ surfaceHeight * SURFACE_BEHIND_START_TRANSLATION_Y * (1f - amount)
)
// Scale up from a point at the center-bottom of the surface.
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 93ddfba..99a9bed5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -98,6 +98,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import com.android.app.animation.Interpolators;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.jank.InteractionJankMonitor.Configuration;
import com.android.internal.policy.IKeyguardDismissCallback;
@@ -121,7 +122,6 @@
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.LaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingCollector;
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 e6568f2..cde67f9 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
@@ -17,7 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index c2d139c..7e9cbc1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -17,7 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index 86f65dde..aca4019 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -17,7 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index 3beac0b..fc7bfb4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -17,7 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
index b5bcd45..39c630b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
@@ -17,7 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index 87f3164..0505d37 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -17,7 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
index 1fbfff9..944adba 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
@@ -17,7 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
index 94961cb..d4af381 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
@@ -17,10 +17,10 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
+import com.android.app.animation.Interpolators
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Password
import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
index 38b9d50..9d7477c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlow.kt
@@ -16,7 +16,7 @@
package com.android.systemui.keyguard.ui
import android.view.animation.Interpolator
-import com.android.systemui.animation.Interpolators.LINEAR
+import com.android.app.animation.Interpolators.LINEAR
import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
index d96609c..c8d37a1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
@@ -32,11 +32,11 @@
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.animation.Interpolators
import com.android.settingslib.Utils
import com.android.systemui.R
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.animation.Expandable
-import com.android.systemui.animation.Interpolators
import com.android.systemui.animation.view.LaunchableLinearLayout
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.ui.binder.IconViewBinder
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 9aecb5d..85fb565 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
@@ -39,7 +39,8 @@
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel
import com.android.systemui.shared.clocks.ClockRegistry
import com.android.systemui.shared.clocks.shared.model.ClockPreviewConstants
-import com.android.systemui.shared.quickaffordance.shared.model.KeyguardQuickAffordancePreviewConstants
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants
+import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
@@ -59,6 +60,7 @@
private val clockController: ClockEventController,
private val clockRegistry: ClockRegistry,
private val broadcastDispatcher: BroadcastDispatcher,
+ private val lockscreenSmartspaceController: LockscreenSmartspaceController,
@Assisted bundle: Bundle,
) {
@@ -67,7 +69,7 @@
private val height: Int = bundle.getInt(KEY_VIEW_HEIGHT)
private val shouldHighlightSelectedAffordance: Boolean =
bundle.getBoolean(
- KeyguardQuickAffordancePreviewConstants.KEY_HIGHLIGHT_QUICK_AFFORDANCES,
+ KeyguardPreviewConstants.KEY_HIGHLIGHT_QUICK_AFFORDANCES,
false,
)
private val shouldHideClock: Boolean =
@@ -79,6 +81,7 @@
get() = host.surfacePackage
private var clockView: View? = null
+ private var smartSpaceView: View? = null
private val disposables = mutableSetOf<DisposableHandle>()
private var isDestroyed = false
@@ -87,7 +90,7 @@
bottomAreaViewModel.enablePreviewMode(
initiallySelectedSlotId =
bundle.getString(
- KeyguardQuickAffordancePreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID,
+ KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID,
),
shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance,
)
@@ -108,9 +111,10 @@
val rootView = FrameLayout(context)
setUpBottomArea(rootView)
- if (!shouldHideClock) {
- setUpClock(rootView)
- }
+
+ setupSmartspace(rootView)
+
+ setUpClock(rootView)
rootView.measure(
View.MeasureSpec.makeMeasureSpec(
@@ -147,9 +151,62 @@
fun destroy() {
isDestroyed = true
+ lockscreenSmartspaceController.disconnect()
disposables.forEach { it.dispose() }
}
+ fun hideSmartspace(hide: Boolean) {
+ smartSpaceView?.visibility = if (hide) View.INVISIBLE else View.VISIBLE
+ }
+
+ /**
+ * This sets up and shows a non-interactive smart space
+ *
+ * The top padding is as follows:
+ * Status bar height + clock top margin + keyguard smart space top offset
+ *
+ * The start padding is as follows:
+ * Clock padding start + Below clock padding start
+ *
+ * The end padding is as follows:
+ * Below clock padding end
+ */
+ private fun setupSmartspace(parentView: ViewGroup) {
+ if (!lockscreenSmartspaceController.isEnabled() ||
+ !lockscreenSmartspaceController.isDateWeatherDecoupled()) {
+ return
+ }
+
+ smartSpaceView = lockscreenSmartspaceController.buildAndConnectDateView(parentView)
+
+ val topPadding: Int = with(context.resources) {
+ getDimensionPixelSize(R.dimen.status_bar_header_height_keyguard) +
+ getDimensionPixelSize(R.dimen.keyguard_smartspace_top_offset) +
+ getDimensionPixelSize(R.dimen.keyguard_clock_top_margin)
+ }
+
+ val startPadding: Int = with(context.resources) {
+ getDimensionPixelSize(R.dimen.clock_padding_start) +
+ getDimensionPixelSize(R.dimen.below_clock_padding_start)
+ }
+
+ val endPadding: Int = context.resources
+ .getDimensionPixelSize(R.dimen.below_clock_padding_end)
+
+ smartSpaceView?.let {
+ it.setPaddingRelative(startPadding, topPadding, endPadding, 0)
+ it.isClickable = false
+
+ parentView.addView(
+ it,
+ FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ ),
+ )
+ }
+ }
+
private fun setUpBottomArea(parentView: ViewGroup) {
val bottomAreaView =
LayoutInflater.from(context)
@@ -202,22 +259,48 @@
disposables.add(DisposableHandle { broadcastDispatcher.unregisterReceiver(receiver) })
onClockChanged(parentView)
+
+ updateSmartspaceWithSetupClock()
}
private fun onClockChanged(parentView: ViewGroup) {
clockController.clock = clockRegistry.createCurrentClock()
- clockController.clock
- ?.largeClock
- ?.events
- ?.onTargetRegionChanged(KeyguardClockSwitch.getLargeClockRegion(parentView))
- clockView?.let { parentView.removeView(it) }
- clockView =
- clockController.clock?.largeClock?.view?.apply {
+
+ if (!shouldHideClock) {
+ val largeClock = clockController.clock?.largeClock
+
+ largeClock
+ ?.events
+ ?.onTargetRegionChanged(KeyguardClockSwitch.getLargeClockRegion(parentView))
+
+ clockView?.let { parentView.removeView(it) }
+ clockView = largeClock?.view?.apply {
if (shouldHighlightSelectedAffordance) {
alpha = DIM_ALPHA
}
parentView.addView(this)
+ visibility = View.VISIBLE
}
+ } else {
+ clockView?.visibility = View.GONE
+ }
+ }
+
+ /**
+ * Updates smart space after clock is set up. Used to show or hide smartspace with the right
+ * opacity based on the clock after setup.
+ */
+ private fun updateSmartspaceWithSetupClock() {
+ val hasCustomWeatherDataDisplay =
+ clockController
+ .clock
+ ?.largeClock
+ ?.config
+ ?.hasCustomWeatherDataDisplay == true
+
+ hideSmartspace(hasCustomWeatherDataDisplay)
+
+ smartSpaceView?.alpha = if (shouldHighlightSelectedAffordance) DIM_ALPHA else 1.0f
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
index 6d95882..3869b23 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
@@ -29,7 +29,7 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.shared.quickaffordance.shared.model.KeyguardQuickAffordancePreviewConstants
+import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
@@ -114,13 +114,18 @@
}
when (message.what) {
- KeyguardQuickAffordancePreviewConstants.MESSAGE_ID_SLOT_SELECTED -> {
+ KeyguardPreviewConstants.MESSAGE_ID_SLOT_SELECTED -> {
message.data
.getString(
- KeyguardQuickAffordancePreviewConstants.KEY_SLOT_ID,
+ KeyguardPreviewConstants.KEY_SLOT_ID,
)
?.let { slotId -> renderer.onSlotSelected(slotId = slotId) }
}
+ KeyguardPreviewConstants.MESSAGE_ID_HIDE_SMART_SPACE -> {
+ message.data
+ .getBoolean(KeyguardPreviewConstants.KEY_HIDE_SMART_SPACE)
+ .let { hide -> renderer.hideSmartspace(hide) }
+ }
else -> requestDestruction(this)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
index 8d6545a4..2c9a9b3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
@@ -16,8 +16,8 @@
package com.android.systemui.keyguard.ui.viewmodel
-import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
-import com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE
+import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt
index f16827d..c135786 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModel.kt
@@ -16,7 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
-import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromGoneTransitionInteractor.Companion.TO_DREAMING_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
index bc9dc4f..c6187dd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModel.kt
@@ -16,7 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
-import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_DREAMING_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
index a60665a..d3ea89c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModel.kt
@@ -16,7 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
-import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_OCCLUDED_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
index ddce516..6845c55 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
@@ -16,7 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
-import com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE
+import com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromOccludedTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
index df93d23..68810f9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
@@ -16,7 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
-import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_GONE_DURATION
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
index 52d4171..0860c20 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
@@ -20,7 +20,10 @@
import android.content.res.Configuration
import android.content.res.Resources
import android.media.projection.IMediaProjection
+import android.media.projection.IMediaProjectionManager.EXTRA_USER_REVIEW_GRANTED_CONSENT
import android.media.projection.MediaProjectionManager.EXTRA_MEDIA_PROJECTION
+import android.media.projection.ReviewGrantedConsentResult.RECORD_CANCEL
+import android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_TASK
import android.os.Binder
import android.os.Bundle
import android.os.IBinder
@@ -67,6 +70,11 @@
private lateinit var controller: MediaProjectionAppSelectorController
private lateinit var recentsViewController: MediaProjectionRecentsViewController
private lateinit var component: MediaProjectionAppSelectorComponent
+ // Indicate if we are under the media projection security flow
+ // i.e. when a host app reuses consent token, review the permission and update it to the service
+ private var reviewGrantedConsentRequired = false
+ // If an app is selected, set to true so that we don't send RECORD_CANCEL in onDestroy
+ private var taskSelected = false
override fun getLayoutResource() = R.layout.media_projection_app_selector
@@ -85,6 +93,9 @@
component.personalProfileUserHandle
)
+ reviewGrantedConsentRequired =
+ intent.getBooleanExtra(EXTRA_USER_REVIEW_GRANTED_CONSENT, false)
+
super.onCreate(bundle)
controller.init()
}
@@ -149,6 +160,16 @@
}
override fun onDestroy() {
+ // onDestroy is also called when an app is selected, in that case we only want to send
+ // RECORD_CONTENT_TASK but not RECORD_CANCEL
+ if (!taskSelected) {
+ // TODO(b/272010156): Return result to PermissionActivity and update service there
+ MediaProjectionServiceHelper.setReviewedConsentIfNeeded(
+ RECORD_CANCEL,
+ reviewGrantedConsentRequired,
+ /* projection= */ null
+ )
+ }
activityLauncher.destroy()
controller.destroy()
super.onDestroy()
@@ -163,6 +184,7 @@
}
override fun returnSelectedApp(launchCookie: IBinder) {
+ taskSelected = true
if (intent.hasExtra(EXTRA_CAPTURE_REGION_RESULT_RECEIVER)) {
// The client requested to return the result in the result receiver instead of
// activity result, let's send the media projection to the result receiver
@@ -174,7 +196,11 @@
val captureRegion = MediaProjectionCaptureTarget(launchCookie)
val data = Bundle().apply { putParcelable(KEY_CAPTURE_TARGET, captureRegion) }
resultReceiver.send(RESULT_OK, data)
+ // TODO(b/279175710): Ensure consent result is always set here. Skipping this for now
+ // in ScreenMediaRecorder, since we know the permission grant (projection) is never
+ // reused in that scenario.
} else {
+ // TODO(b/272010156): Return result to PermissionActivity and update service there
// Return the media projection instance as activity result
val mediaProjectionBinder = intent.getIBinderExtra(EXTRA_MEDIA_PROJECTION)
val projection = IMediaProjection.Stub.asInterface(mediaProjectionBinder)
@@ -185,6 +211,11 @@
intent.putExtra(EXTRA_MEDIA_PROJECTION, projection.asBinder())
setResult(RESULT_OK, intent)
setForceSendResultForMediaProjection()
+ MediaProjectionServiceHelper.setReviewedConsentIfNeeded(
+ RECORD_CONTENT_TASK,
+ reviewGrantedConsentRequired,
+ projection
+ )
}
finish()
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index ccddd1d..e217e36 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -16,11 +16,16 @@
package com.android.systemui.media;
+import static android.media.projection.IMediaProjectionManager.EXTRA_PACKAGE_REUSING_GRANTED_CONSENT;
+import static android.media.projection.IMediaProjectionManager.EXTRA_USER_REVIEW_GRANTED_CONSENT;
+import static android.media.projection.ReviewGrantedConsentResult.RECORD_CANCEL;
+import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_DISPLAY;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static com.android.systemui.screenrecord.ScreenShareOptionKt.ENTIRE_SCREEN;
import static com.android.systemui.screenrecord.ScreenShareOptionKt.SINGLE_APP;
+import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
@@ -30,12 +35,10 @@
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.media.projection.IMediaProjection;
-import android.media.projection.IMediaProjectionManager;
import android.media.projection.MediaProjectionManager;
+import android.media.projection.ReviewGrantedConsentResult;
import android.os.Bundle;
-import android.os.IBinder;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.text.BidiFormatter;
import android.text.SpannableString;
@@ -55,10 +58,10 @@
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.util.Utils;
-import javax.inject.Inject;
-
import dagger.Lazy;
+import javax.inject.Inject;
+
public class MediaProjectionPermissionActivity extends Activity
implements DialogInterface.OnClickListener {
private static final String TAG = "MediaProjectionPermissionActivity";
@@ -70,10 +73,13 @@
private String mPackageName;
private int mUid;
- private IMediaProjectionManager mService;
private AlertDialog mDialog;
+ // Indicates if user must review already-granted consent that the MediaProjection app is
+ // attempting to re-use.
+ private boolean mReviewGrantedConsentRequired = false;
+
@Inject
public MediaProjectionPermissionActivity(FeatureFlags featureFlags,
Lazy<ScreenCaptureDevicePolicyResolver> screenCaptureDevicePolicyResolver) {
@@ -85,13 +91,23 @@
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- mPackageName = getCallingPackage();
- IBinder b = ServiceManager.getService(MEDIA_PROJECTION_SERVICE);
- mService = IMediaProjectionManager.Stub.asInterface(b);
+ final Intent launchingIntent = getIntent();
+ mReviewGrantedConsentRequired = launchingIntent.getBooleanExtra(
+ EXTRA_USER_REVIEW_GRANTED_CONSENT, false);
+ mPackageName = getCallingPackage();
+
+ // This activity is launched directly by an app, or system server. System server provides
+ // the package name through the intent if so.
if (mPackageName == null) {
- finish();
- return;
+ if (launchingIntent.hasExtra(EXTRA_PACKAGE_REUSING_GRANTED_CONSENT)) {
+ mPackageName = launchingIntent.getStringExtra(
+ EXTRA_PACKAGE_REUSING_GRANTED_CONSENT);
+ } else {
+ setResult(RESULT_CANCELED);
+ finish(RECORD_CANCEL, /* projection= */ null);
+ return;
+ }
}
PackageManager packageManager = getPackageManager();
@@ -100,25 +116,36 @@
aInfo = packageManager.getApplicationInfo(mPackageName, 0);
mUid = aInfo.uid;
} catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "unable to look up package name", e);
- finish();
+ Log.e(TAG, "Unable to look up package name", e);
+ setResult(RESULT_CANCELED);
+ finish(RECORD_CANCEL, /* projection= */ null);
return;
}
try {
- if (mService.hasProjectionPermission(mUid, mPackageName)) {
- setResult(RESULT_OK, getMediaProjectionIntent(mUid, mPackageName));
- finish();
+ if (MediaProjectionServiceHelper.hasProjectionPermission(mUid, mPackageName)) {
+ final IMediaProjection projection =
+ MediaProjectionServiceHelper.createOrReuseProjection(mUid, mPackageName,
+ mReviewGrantedConsentRequired);
+ // Automatically grant consent if a system-privileged component is recording.
+ final Intent intent = new Intent();
+ intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
+ projection.asBinder());
+ setResult(RESULT_OK, intent);
+ finish(RECORD_CONTENT_DISPLAY, projection);
return;
}
} catch (RemoteException e) {
Log.e(TAG, "Error checking projection permissions", e);
- finish();
+ setResult(RESULT_CANCELED);
+ finish(RECORD_CANCEL, /* projection= */ null);
return;
}
if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)) {
if (showScreenCaptureDisabledDialogIfNeeded()) {
+ setResult(RESULT_CANCELED);
+ finish(RECORD_CANCEL, /* projection= */ null);
return;
}
}
@@ -178,7 +205,7 @@
ScreenShareOption selectedOption =
((MediaProjectionPermissionDialog) mDialog).getSelectedScreenShareOption();
grantMediaProjectionPermission(selectedOption.getMode());
- }, appName);
+ }, () -> finish(RECORD_CANCEL, /* projection= */ null), appName);
} else {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this,
R.style.Theme_SystemUI_Dialog)
@@ -191,7 +218,6 @@
}
setUpDialog(mDialog);
-
mDialog.show();
}
@@ -207,6 +233,12 @@
public void onClick(DialogInterface dialog, int which) {
if (which == AlertDialog.BUTTON_POSITIVE) {
grantMediaProjectionPermission(ENTIRE_SCREEN);
+ } else {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ setResult(RESULT_CANCELED);
+ finish(RECORD_CANCEL, /* projection= */ null);
}
}
@@ -240,15 +272,25 @@
private void grantMediaProjectionPermission(int screenShareMode) {
try {
if (screenShareMode == ENTIRE_SCREEN) {
- setResult(RESULT_OK, getMediaProjectionIntent(mUid, mPackageName));
+ final IMediaProjection projection =
+ MediaProjectionServiceHelper.createOrReuseProjection(mUid, mPackageName,
+ mReviewGrantedConsentRequired);
+ final Intent intent = new Intent();
+ intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
+ projection.asBinder());
+ setResult(RESULT_OK, intent);
+ finish(RECORD_CONTENT_DISPLAY, projection);
}
if (isPartialScreenSharingEnabled() && screenShareMode == SINGLE_APP) {
- IMediaProjection projection = createProjection(mUid, mPackageName);
- final Intent intent = new Intent(this, MediaProjectionAppSelectorActivity.class);
+ IMediaProjection projection = MediaProjectionServiceHelper.createOrReuseProjection(
+ mUid, mPackageName, mReviewGrantedConsentRequired);
+ final Intent intent = new Intent(this,
+ MediaProjectionAppSelectorActivity.class);
intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
projection.asBinder());
intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
getHostUserHandle());
+ intent.putExtra(EXTRA_USER_REVIEW_GRANTED_CONSENT, mReviewGrantedConsentRequired);
intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
// Start activity from the current foreground user to avoid creating a separate
@@ -259,11 +301,11 @@
} catch (RemoteException e) {
Log.e(TAG, "Error granting projection permission", e);
setResult(RESULT_CANCELED);
+ finish(RECORD_CANCEL, /* projection= */ null);
} finally {
if (mDialog != null) {
mDialog.dismiss();
}
- finish();
}
}
@@ -271,22 +313,22 @@
return UserHandle.getUserHandleForUid(getLaunchedFromUid());
}
- private IMediaProjection createProjection(int uid, String packageName) throws RemoteException {
- return mService.createProjection(uid, packageName,
- MediaProjectionManager.TYPE_SCREEN_CAPTURE, false /* permanentGrant */);
+ @Override
+ public void finish() {
+ // Default to cancelling recording when user needs to review consent.
+ finish(RECORD_CANCEL, /* projection= */ null);
}
- private Intent getMediaProjectionIntent(int uid, String packageName)
- throws RemoteException {
- IMediaProjection projection = createProjection(uid, packageName);
- Intent intent = new Intent();
- intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION, projection.asBinder());
- return intent;
+ private void finish(@ReviewGrantedConsentResult int consentResult,
+ @Nullable IMediaProjection projection) {
+ MediaProjectionServiceHelper.setReviewedConsentIfNeeded(
+ consentResult, mReviewGrantedConsentRequired, projection);
+ super.finish();
}
private void onDialogDismissedOrCancelled(DialogInterface dialogInterface) {
if (!isFinishing()) {
- finish();
+ finish(RECORD_CANCEL, /* projection= */ null);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionServiceHelper.kt b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionServiceHelper.kt
new file mode 100644
index 0000000..9e616e2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionServiceHelper.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.media
+
+import android.content.Context
+import android.media.projection.IMediaProjection
+import android.media.projection.IMediaProjectionManager
+import android.media.projection.MediaProjectionManager
+import android.media.projection.ReviewGrantedConsentResult
+import android.os.RemoteException
+import android.os.ServiceManager
+import android.util.Log
+
+/**
+ * Helper class that handles the media projection service related actions. It simplifies invoking
+ * the MediaProjectionManagerService and updating the permission consent.
+ */
+class MediaProjectionServiceHelper {
+ companion object {
+ private const val TAG = "MediaProjectionServiceHelper"
+ private val service =
+ IMediaProjectionManager.Stub.asInterface(
+ ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE)
+ )
+
+ @JvmStatic
+ @Throws(RemoteException::class)
+ fun hasProjectionPermission(uid: Int, packageName: String) =
+ service.hasProjectionPermission(uid, packageName)
+
+ @JvmStatic
+ @Throws(RemoteException::class)
+ fun createOrReuseProjection(
+ uid: Int,
+ packageName: String,
+ reviewGrantedConsentRequired: Boolean
+ ): IMediaProjection {
+ val existingProjection =
+ if (reviewGrantedConsentRequired) service.getProjection(uid, packageName) else null
+ return existingProjection
+ ?: service.createProjection(
+ uid,
+ packageName,
+ MediaProjectionManager.TYPE_SCREEN_CAPTURE,
+ false /* permanentGrant */
+ )
+ }
+
+ /**
+ * This method is called when a host app reuses the consent token. If the token is being
+ * used more than once, ask the user to review their consent and send the reviewed result.
+ *
+ * @param consentResult consent result to update
+ * @param reviewGrantedConsentRequired if user must review already-granted consent that the
+ * host app is attempting to reuse
+ * @param projection projection token associated with the consent result, or null if the
+ * result is for cancelling.
+ */
+ @JvmStatic
+ fun setReviewedConsentIfNeeded(
+ @ReviewGrantedConsentResult consentResult: Int,
+ reviewGrantedConsentRequired: Boolean,
+ projection: IMediaProjection?
+ ) {
+ // Only send the result to the server, when the user needed to review the re-used
+ // consent token.
+ if (
+ reviewGrantedConsentRequired && consentResult != ReviewGrantedConsentResult.UNKNOWN
+ ) {
+ try {
+ service.setUserReviewGrantedConsentResult(consentResult, projection)
+ } catch (e: RemoteException) {
+ // If we are unable to pass back the result, capture continues with blank frames
+ Log.e(TAG, "Unable to set required consent result for token re-use", e)
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarObserver.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarObserver.kt
index 37d956b..e38abc2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarObserver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/player/SeekBarObserver.kt
@@ -21,9 +21,9 @@
import android.text.format.DateUtils
import androidx.annotation.UiThread
import androidx.lifecycle.Observer
+import com.android.app.animation.Interpolators
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
import com.android.systemui.media.controls.ui.SquigglyProgress
/**
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
index 3669493..b46ebb2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
@@ -34,10 +34,10 @@
import android.util.MathUtils
import android.view.View
import androidx.annotation.Keep
+import com.android.app.animation.Interpolators
import com.android.internal.graphics.ColorUtils
import com.android.internal.graphics.ColorUtils.blendARGB
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
import org.xmlpull.v1.XmlPullParser
private const val BACKGROUND_ANIM_DURATION = 370L
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/LightSourceDrawable.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/LightSourceDrawable.kt
index dd5c2bf..937a618 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/LightSourceDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/LightSourceDrawable.kt
@@ -35,9 +35,9 @@
import android.util.AttributeSet
import android.util.MathUtils.lerp
import androidx.annotation.Keep
+import com.android.app.animation.Interpolators
import com.android.internal.graphics.ColorUtils
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
import org.xmlpull.v1.XmlPullParser
private const val RIPPLE_ANIM_DURATION = 800L
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index ab39442..0aa4349 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -166,6 +166,7 @@
}
}
+ /** Whether the media card currently has the "expanded" layout */
@VisibleForTesting
var currentlyExpanded = true
set(value) {
@@ -501,6 +502,7 @@
mediaHostStatesManager.addCallback(
object : MediaHostStatesManager.Callback {
override fun onHostStateChanged(location: Int, mediaHostState: MediaHostState) {
+ updateUserVisibility()
if (location == desiredLocation) {
onDesiredLocationChanged(desiredLocation, mediaHostState, animate = false)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index 40027a1..f9d3094 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -72,6 +72,7 @@
import androidx.annotation.UiThread;
import androidx.constraintlayout.widget.ConstraintSet;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.jank.InteractionJankMonitor;
@@ -82,7 +83,6 @@
import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.GhostedViewLaunchAnimatorController;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.bluetooth.BroadcastDialogController;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.dagger.qualifiers.Background;
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
index 54237ce..fe8ebaf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
@@ -33,9 +33,9 @@
import android.view.ViewGroup
import android.view.ViewGroupOverlay
import androidx.annotation.VisibleForTesting
+import com.android.app.animation.Interpolators
import com.android.keyguard.KeyguardViewController
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dreams.DreamOverlayStateController
@@ -257,7 +257,7 @@
if (value && (isLockScreenShadeVisibleToUser() || isHomeScreenShadeVisibleToUser())) {
mediaCarouselController.logSmartspaceImpression(value)
}
- mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = isVisibleToUser()
+ updateUserVisibility()
}
/**
@@ -460,8 +460,7 @@
) {
mediaCarouselController.logSmartspaceImpression(qsExpanded)
}
- mediaCarouselController.mediaCarouselScrollHandler.visibleToUser =
- isVisibleToUser()
+ updateUserVisibility()
}
override fun onDozeAmountChanged(linear: Float, eased: Float) {
@@ -480,8 +479,7 @@
qsExpanded = false
closeGuts()
}
- mediaCarouselController.mediaCarouselScrollHandler.visibleToUser =
- isVisibleToUser()
+ updateUserVisibility()
}
override fun onExpandedChanged(isExpanded: Boolean) {
@@ -489,8 +487,7 @@
if (isHomeScreenShadeVisibleToUser()) {
mediaCarouselController.logSmartspaceImpression(qsExpanded)
}
- mediaCarouselController.mediaCarouselScrollHandler.visibleToUser =
- isVisibleToUser()
+ updateUserVisibility()
}
}
)
@@ -532,9 +529,7 @@
}
)
- mediaCarouselController.updateUserVisibility = {
- mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = isVisibleToUser()
- }
+ mediaCarouselController.updateUserVisibility = this::updateUserVisibility
mediaCarouselController.updateHostVisibility = {
mediaHosts.forEach { it?.updateViewVisibility() }
}
@@ -1180,11 +1175,15 @@
return isCrossFadeAnimatorRunning
}
- /** Returns true when the media card could be visible to the user if existed. */
- private fun isVisibleToUser(): Boolean {
- return isLockScreenVisibleToUser() ||
- isLockScreenShadeVisibleToUser() ||
- isHomeScreenShadeVisibleToUser()
+ /** Update whether or not the media carousel could be visible to the user */
+ private fun updateUserVisibility() {
+ val shadeVisible =
+ isLockScreenVisibleToUser() ||
+ isLockScreenShadeVisibleToUser() ||
+ isHomeScreenShadeVisibleToUser()
+ val mediaVisible = qsExpanded || hasActiveMediaOrRecommendation
+ mediaCarouselController.mediaCarouselScrollHandler.visibleToUser =
+ shadeVisible && mediaVisible
}
private fun isLockScreenVisibleToUser(): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/SquigglyProgress.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/SquigglyProgress.kt
index e9b2cf2..583c626 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/SquigglyProgress.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/SquigglyProgress.kt
@@ -31,8 +31,8 @@
import android.util.MathUtils.lerpInv
import android.util.MathUtils.lerpInvSat
import androidx.annotation.VisibleForTesting
+import com.android.app.animation.Interpolators
import com.android.internal.graphics.ColorUtils
-import com.android.systemui.animation.Interpolators
import kotlin.math.abs
import kotlin.math.cos
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
index 78082c3..77ff036 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
@@ -36,7 +36,7 @@
import android.view.View.ACCESSIBILITY_LIVE_REGION_NONE
import com.android.internal.widget.CachingIconView
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.ui.binder.TintedIconViewBinder
import com.android.systemui.dagger.SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskLabelLoader.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskLabelLoader.kt
index eadcb93..1be8b70 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskLabelLoader.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskLabelLoader.kt
@@ -20,6 +20,7 @@
import android.content.ComponentName
import android.content.pm.PackageManager
import android.os.UserHandle
+import android.util.Log
import com.android.systemui.dagger.qualifiers.Background
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -36,18 +37,27 @@
private val packageManager: PackageManager
) : RecentTaskLabelLoader {
+ private val TAG = "RecentTaskLabelLoader"
+
override suspend fun loadLabel(
@UserIdInt userId: Int,
componentName: ComponentName
): CharSequence? =
withContext(coroutineDispatcher) {
- val userHandle = UserHandle(userId)
- val appInfo =
- packageManager.getApplicationInfo(
- componentName.packageName,
- PackageManager.ApplicationInfoFlags.of(0 /* no flags */)
- )
- val label = packageManager.getApplicationLabel(appInfo)
- return@withContext packageManager.getUserBadgedLabel(label, userHandle)
+ var badgedLabel: CharSequence? = null
+ try {
+ val appInfo =
+ packageManager.getApplicationInfoAsUser(
+ componentName.packageName,
+ PackageManager.ApplicationInfoFlags.of(0 /* no flags */),
+ userId
+ )
+ val label = packageManager.getApplicationLabel(appInfo)
+ val userHandle = UserHandle(userId)
+ badgedLabel = packageManager.getUserBadgedLabel(label, userHandle)
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.e(TAG, "Unable to get application info", e)
+ }
+ return@withContext badgedLabel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTaskViewHolder.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTaskViewHolder.kt
index 64f97f2..2d75359 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTaskViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTaskViewHolder.kt
@@ -68,7 +68,7 @@
}
launch {
val label = labelLoader.loadLabel(task.userId, component)
- root.contentDescription = label
+ root.contentDescription = label ?: root.context.getString(R.string.unknown)
}
}
launch {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 94f01b8..146b5f5 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -58,11 +58,11 @@
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.Utils;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
import com.android.systemui.navigationbar.buttons.ContextualButton;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
index 0218016..10084bd 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
@@ -16,7 +16,7 @@
package com.android.systemui.navigationbar.buttons;
-import static com.android.systemui.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.LINEAR;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -24,9 +24,6 @@
import android.view.View;
import android.view.View.AccessibilityDelegate;
-import com.android.systemui.Dependency;
-import com.android.systemui.assist.AssistManager;
-
import java.util.ArrayList;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
index 590efbb..ff22398 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
@@ -48,10 +48,10 @@
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
+import com.android.app.animation.Interpolators;
import com.android.internal.util.LatencyTracker;
import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.plugins.NavigationEdgeBackPlugin;
import com.android.systemui.settings.DisplayTracker;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index a7aac5a..463c79c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -26,7 +26,7 @@
import androidx.annotation.Nullable;
-import com.android.systemui.animation.Interpolators;
+import com.android.app.animation.Interpolators;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.qs.QSTile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 584d27f8..09cc2c5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -18,9 +18,10 @@
import static com.android.systemui.media.dagger.MediaModule.QS_PANEL;
import static com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL;
-import static com.android.systemui.statusbar.disableflags.DisableFlagsLogger.DisableState;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED;
+import static com.android.systemui.statusbar.disableflags.DisableFlagsLogger.DisableState;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.res.Configuration;
@@ -43,10 +44,10 @@
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
+import com.android.app.animation.Interpolators;
import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.compose.ComposeFacade;
import com.android.systemui.dump.DumpManager;
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt
index db0052a..f63bf07 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt
@@ -43,6 +43,7 @@
) : SystemUIDialog(context), AdapterView.OnItemSelectedListener {
private lateinit var dialogTitle: TextView
private lateinit var startButton: TextView
+ private lateinit var cancelButton: TextView
private lateinit var warning: TextView
private lateinit var screenShareModeSpinner: Spinner
var selectedScreenShareOption: ScreenShareOption = screenShareOptions.first()
@@ -57,7 +58,7 @@
dialogTitle = findViewById(R.id.screen_share_dialog_title)
warning = findViewById(R.id.text_warning)
startButton = findViewById(R.id.button_start)
- findViewById<TextView>(R.id.button_cancel).setOnClickListener { dismiss() }
+ cancelButton = findViewById(R.id.button_cancel)
updateIcon()
initScreenShareOptions()
createOptionsView(getOptionsViewLayoutId())
@@ -117,6 +118,10 @@
startButton.setOnClickListener(listener)
}
+ protected fun setCancelButtonOnClickListener(listener: View.OnClickListener?) {
+ cancelButton.setOnClickListener(listener)
+ }
+
// Create additional options that is shown under the share mode spinner
// Eg. the audio and tap toggles in SysUI Recorder
@LayoutRes protected open fun getOptionsViewLayoutId(): Int? = null
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt
index c5a82ce1..201557c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt
@@ -23,6 +23,7 @@
class MediaProjectionPermissionDialog(
context: Context?,
private val onStartRecordingClicked: Runnable,
+ private val onCancelClicked: Runnable,
private val appName: String?
) : BaseScreenSharePermissionDialog(context, createOptionList(appName), appName) {
override fun onCreate(savedInstanceState: Bundle?) {
@@ -39,6 +40,10 @@
onStartRecordingClicked.run()
dismiss()
}
+ setCancelButtonOnClickListener {
+ onCancelClicked.run()
+ dismiss()
+ }
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
index b445000..5850a84 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
@@ -47,19 +47,36 @@
viewsIdToTranslate =
setOf(
ViewIdToTranslate(R.id.quick_settings_panel, START, filterShade),
- ViewIdToTranslate(R.id.notification_stack_scroller, END, filterShade),
- ViewIdToTranslate(R.id.statusIcons, END, filterShade),
- ViewIdToTranslate(R.id.privacy_container, END, filterShade),
- ViewIdToTranslate(R.id.batteryRemainingIcon, END, filterShade),
- ViewIdToTranslate(R.id.carrier_group, END, filterShade),
- ViewIdToTranslate(R.id.clock, START, filterShade),
- ViewIdToTranslate(R.id.date, START, filterShade)),
+ ViewIdToTranslate(R.id.notification_stack_scroller, END, filterShade)),
progressProvider = progressProvider)
}
+ private val translateAnimatorStatusBar by lazy {
+ UnfoldConstantTranslateAnimator(
+ viewsIdToTranslate =
+ setOf(
+ ViewIdToTranslate(R.id.statusIcons, END, filterShade),
+ ViewIdToTranslate(R.id.privacy_container, END, filterShade),
+ ViewIdToTranslate(R.id.batteryRemainingIcon, END, filterShade),
+ ViewIdToTranslate(R.id.carrier_group, END, filterShade),
+ ViewIdToTranslate(R.id.clock, START, filterShade),
+ ViewIdToTranslate(R.id.date, START, filterShade)
+ ),
+ progressProvider = progressProvider
+ )
+ }
+
fun setup(root: ViewGroup) {
val translationMax =
context.resources.getDimensionPixelSize(R.dimen.notification_side_paddings).toFloat()
translateAnimator.init(root, translationMax)
+ val splitShadeStatusBarViewGroup: ViewGroup? =
+ root.findViewById(R.id.split_shade_status_bar)
+ if (splitShadeStatusBarViewGroup != null) {
+ translateAnimatorStatusBar.init(
+ splitShadeStatusBarViewGroup,
+ translationMax
+ )
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index d28ccff..be92bd4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -22,10 +22,10 @@
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
+import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
import static com.android.keyguard.KeyguardClockSwitch.SMALL;
-import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
-import static com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE;
import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK;
import static com.android.systemui.classifier.Classifier.GENERIC;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
@@ -59,8 +59,6 @@
import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.Region;
-import android.hardware.biometrics.SensorLocationInternal;
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
@@ -90,6 +88,7 @@
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
@@ -113,7 +112,6 @@
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.LaunchAnimator;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.classifier.Classifier;
@@ -224,8 +222,6 @@
import com.android.systemui.util.time.SystemClock;
import com.android.wm.shell.animation.FlingAnimationUtils;
-import kotlin.Unit;
-
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
@@ -236,6 +232,8 @@
import javax.inject.Inject;
import javax.inject.Provider;
+import kotlin.Unit;
+
import kotlinx.coroutines.CoroutineDispatcher;
@CentralSurfacesComponent.CentralSurfacesScope
@@ -410,7 +408,8 @@
private int mDisplayRightInset = 0; // in pixels
private int mDisplayLeftInset = 0; // in pixels
- private final KeyguardClockPositionAlgorithm
+ @VisibleForTesting
+ KeyguardClockPositionAlgorithm
mClockPositionAlgorithm =
new KeyguardClockPositionAlgorithm();
private final KeyguardClockPositionAlgorithm.Result
@@ -1493,11 +1492,9 @@
? 1.0f : mInterpolatedDarkAmount;
float udfpsAodTopLocation = -1f;
- if (mUpdateMonitor.isUdfpsEnrolled() && mAuthController.getUdfpsProps().size() > 0) {
- FingerprintSensorPropertiesInternal props = mAuthController.getUdfpsProps().get(0);
- final SensorLocationInternal location = props.getLocation();
- udfpsAodTopLocation = location.sensorLocationY - location.sensorRadius
- - mUdfpsMaxYBurnInOffset;
+ if (mUpdateMonitor.isUdfpsEnrolled() && mAuthController.getUdfpsLocation() != null) {
+ udfpsAodTopLocation = mAuthController.getUdfpsLocation().y
+ - mAuthController.getUdfpsRadius() - mUdfpsMaxYBurnInOffset;
}
mClockPositionAlgorithm.setup(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index ef14d1c..7a79e85 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -50,6 +50,7 @@
import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
@@ -59,7 +60,6 @@
import com.android.keyguard.FaceAuthApiRequestReason;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index f0815e9..4131e7d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -34,10 +34,10 @@
import android.widget.TextView
import androidx.annotation.VisibleForTesting
import androidx.constraintlayout.motion.widget.MotionLayout
+import com.android.app.animation.Interpolators
import com.android.settingslib.Utils
import com.android.systemui.Dumpable
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
index 63179da..c1ebf12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
@@ -18,8 +18,8 @@
import android.view.View;
+import com.android.app.animation.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 54b341f..1a32d70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -38,8 +38,8 @@
import android.view.animation.Interpolator;
import android.widget.ImageView;
+import com.android.app.animation.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.wm.shell.animation.FlingAnimationUtils;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
index 9421524..823bb35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
@@ -16,7 +16,7 @@
import android.util.MathUtils.lerp
import android.view.View
import android.view.animation.PathInterpolator
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.statusbar.LightRevealEffect.Companion.getPercentPastThreshold
import com.android.systemui.util.getColorWithAlpha
import com.android.systemui.util.leak.RotationUtils
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index faf592e..2258968 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -18,7 +18,7 @@
import com.android.systemui.ExpandHelper
import com.android.systemui.Gefingerpoken
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.biometrics.UdfpsKeyguardViewController
import com.android.systemui.classifier.Classifier
import com.android.systemui.classifier.FalsingCollector
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 72ae16e..fb88a96 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -44,9 +44,9 @@
import android.view.View;
import android.widget.ImageView;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 8dc7842..d37cbcc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -33,7 +33,7 @@
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
import com.android.systemui.Dumpable
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 7eb63da..5c3bacc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -35,10 +35,10 @@
import androidx.annotation.NonNull;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index 976924a..f9d4f1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -31,7 +31,7 @@
import com.android.systemui.Dumpable
import com.android.systemui.Gefingerpoken
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScroller.kt b/packages/SystemUI/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScroller.kt
index 575f354..f1e51e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScroller.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScroller.kt
@@ -4,7 +4,7 @@
import android.content.res.Configuration
import android.util.MathUtils
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.policy.ConfigurationController
import dagger.assisted.Assisted
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt b/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt
index 572c0e0..3d574ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt
@@ -8,7 +8,7 @@
import android.view.animation.PathInterpolator
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.qs.QS
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 7755003..91c08a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -52,10 +52,10 @@
import androidx.core.graphics.ColorUtils;
+import com.android.app.animation.Interpolators;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.notification.NotificationIconDozeHelper;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.util.drawable.DrawableSize;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 79d01b4a..d6a14604 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -42,6 +42,7 @@
import androidx.annotation.NonNull;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
@@ -49,7 +50,6 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.DejankUtils;
import com.android.systemui.Dumpable;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
index 2fa27ee..67ab060 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
@@ -25,8 +25,8 @@
import android.view.ViewGroup;
import android.view.animation.Interpolator;
+import com.android.app.animation.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.notification.TransformState;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
index bfc4e9c..eddb683 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
@@ -26,7 +26,7 @@
import android.widget.FrameLayout
import com.android.internal.annotations.GuardedBy
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.statusbar.StatusBarStateController
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
index 0446165..b09b9f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
@@ -21,8 +21,8 @@
import android.view.View;
import android.widget.ImageView;
+import com.android.app.animation.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.row.HybridNotificationView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
index c22dbf6..785e65d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
@@ -3,7 +3,7 @@
import android.util.MathUtils
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.animation.ActivityLaunchAnimator
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.animation.LaunchAnimator
import kotlin.math.min
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
index c22cd1b..5a14200 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
@@ -23,13 +23,13 @@
import android.view.ViewGroup;
import android.widget.TextView;
+import com.android.app.animation.Interpolators;
import com.android.internal.widget.IMessagingLayout;
import com.android.internal.widget.MessagingGroup;
import com.android.internal.widget.MessagingImageMessage;
import com.android.internal.widget.MessagingLinearLayout;
import com.android.internal.widget.MessagingMessage;
import com.android.internal.widget.MessagingPropertyAnimator;
-import com.android.systemui.animation.Interpolators;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
index 3fc7b13..a045698 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
@@ -24,8 +24,8 @@
import android.view.View;
import android.widget.ImageView;
+import com.android.app.animation.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import java.util.function.Consumer;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index fe0b28d..9ba2199 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -21,8 +21,8 @@
import androidx.annotation.VisibleForTesting
import androidx.core.animation.ObjectAnimator
import com.android.systemui.Dumpable
-import com.android.systemui.animation.Interpolators
-import com.android.systemui.animation.InterpolatorsAndroidX
+import com.android.app.animation.Interpolators
+import com.android.app.animation.InterpolatorsAndroidX
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
index 5d07cac..57d20246 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
@@ -24,7 +24,7 @@
import android.view.View;
import android.view.animation.Interpolator;
-import com.android.systemui.animation.Interpolators;
+import com.android.app.animation.Interpolators;
import com.android.systemui.statusbar.notification.stack.AnimationFilter;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ViewState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 9f9fba4..90eb630 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -23,11 +23,11 @@
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.android.app.animation.Interpolators;
import com.android.internal.widget.MessagingImageMessage;
import com.android.internal.widget.MessagingPropertyAnimator;
import com.android.internal.widget.ViewClippingUtil;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.ViewTransformationHelper;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ViewGroupFadeHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ViewGroupFadeHelper.kt
index dc16274..16f1a45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ViewGroupFadeHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ViewGroupFadeHelper.kt
@@ -22,7 +22,7 @@
import android.view.View
import android.view.ViewGroup
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
/**
* Class to help with fading of view groups without fading one subview
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 766ad88..f70d5e6 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
@@ -31,12 +31,12 @@
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
+import com.android.app.animation.Interpolators;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.jank.InteractionJankMonitor.Configuration;
import com.android.settingslib.Utils;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationUtils;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index e468a59..2695410 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -64,6 +64,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -72,7 +73,6 @@
import com.android.internal.widget.CachingIconView;
import com.android.internal.widget.CallLayout;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java
index b56bae1..7a2bee9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java
@@ -45,10 +45,10 @@
import androidx.annotation.VisibleForTesting;
+import com.android.app.animation.Interpolators;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.InstanceIdSequence;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.logging.NotificationPanelLogger;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 5edff5f..9dbbc58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -32,9 +32,9 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.Roundable;
import com.android.systemui.statusbar.notification.RoundableState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index f21db0b..9bc0333 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -25,7 +25,7 @@
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
-import static com.android.systemui.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
import static java.lang.annotation.RetentionPolicy.SOURCE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index 596bdc0..047db20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -33,9 +33,9 @@
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 8a50f2f..99a7755 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -20,7 +20,7 @@
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
-import static com.android.systemui.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
import static java.lang.annotation.RetentionPolicy.SOURCE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index bafc474..5a129fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -39,9 +39,9 @@
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.AlphaOptimizedImageView;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
index 5f4c926..d5d7f75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
@@ -45,11 +45,11 @@
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
index 5aaf63f..b24cec1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
@@ -23,8 +23,8 @@
import android.view.View;
import android.view.animation.Interpolator;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.animation.Interpolators;
import java.util.function.Consumer;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 9a777ea..84fe9ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -34,10 +34,10 @@
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.internal.widget.CachingIconView;
import com.android.internal.widget.NotificationExpandButton;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.ViewTransformationHelper;
import com.android.systemui.statusbar.notification.CustomInterpolatorTransformation;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java
index 7f3381c..d73bbeb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ExpandableViewState.java
@@ -22,8 +22,8 @@
import android.animation.ValueAnimator;
import android.view.View;
+import com.android.app.animation.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
index 0b435fe..9a33a94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
@@ -26,7 +26,7 @@
import android.view.View;
import android.view.animation.Interpolator;
-import com.android.systemui.animation.Interpolators;
+import com.android.app.animation.Interpolators;
import com.android.systemui.statusbar.notification.ShadeViewRefactor;
import com.android.systemui.statusbar.notification.row.ExpandableView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 5c322d7..82608b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -75,6 +75,7 @@
import android.widget.OverScroller;
import android.widget.ScrollView;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.jank.InteractionJankMonitor;
@@ -86,7 +87,6 @@
import com.android.systemui.Dumpable;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
@@ -4189,10 +4189,7 @@
mCentralSurfaces.resetUserExpandedStates();
clearTemporaryViews();
clearUserLockedViews();
- if (mSwipeHelper.isSwiping()) {
- mSwipeHelper.resetSwipeState();
- updateContinuousShadowDrawing();
- }
+ cancelActiveSwipe();
}
}
@@ -4264,6 +4261,9 @@
if (!mIsExpanded) {
mGroupExpansionManager.collapseGroups();
mExpandHelper.cancelImmediately();
+ if (!mIsExpansionChanging) {
+ cancelActiveSwipe();
+ }
}
updateNotificationAnimationStates();
updateChronometers();
@@ -6113,7 +6113,11 @@
}
}
- @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
+ private void cancelActiveSwipe() {
+ mSwipeHelper.resetSwipeState();
+ updateContinuousShadowDrawing();
+ }
+
void updateContinuousShadowDrawing() {
boolean continuousShadowUpdate = mAnimationRunning
|| mSwipeHelper.isSwiping();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index ee72943..f07dd00 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -22,9 +22,9 @@
import android.util.Property;
import android.view.View;
+import com.android.app.animation.Interpolators;
import com.android.keyguard.KeyguardSliceView;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.shared.clocks.AnimatableClockView;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index d07da38..f4605be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -26,9 +26,9 @@
import android.view.View;
import android.view.animation.Interpolator;
+import com.android.app.animation.Interpolators;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.NotificationFadeAware.FadeOptimizedNotification;
import com.android.systemui.statusbar.notification.PropertyAnimator;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 9dce332..4590712 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -33,9 +33,9 @@
import android.util.Log;
import android.view.View;
+import com.android.app.animation.Interpolators;
import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
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 5654772..e1c8064 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -1637,10 +1637,7 @@
private void inflateStatusBarWindow() {
if (mCentralSurfacesComponent != null) {
- // Tear down
- for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) {
- s.stop();
- }
+ Log.e(TAG, "CentralSurfacesComponent being recreated; this is unexpected.");
}
mCentralSurfacesComponent = mCentralSurfacesComponentFactory.create();
mFragmentService.addFragmentInstantiationProvider(
@@ -1682,11 +1679,6 @@
mCentralSurfacesComponent.getCentralSurfacesCommandQueueCallbacks();
// Connect in to the status bar manager service
mCommandQueue.addCallback(mCommandQueueCallbacks);
-
- // Perform all other initialization for CentralSurfacesScope
- for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) {
- s.start();
- }
}
protected void startKeyguard() {
@@ -3648,9 +3640,6 @@
/* wakingUp= */ true,
mShouldDelayWakeUpAnimation);
- if (!mKeyguardBypassController.getBypassEnabled()) {
- mHeadsUpManager.releaseAllImmediately();
- }
updateVisibleToUser();
updateIsKeyguard();
mDozeServiceHost.stopDozing();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 90a6d0f..c1859b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -23,10 +23,10 @@
import android.content.res.Resources;
import android.util.MathUtils;
+import com.android.app.animation.Interpolators;
import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherListView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
index 9d30cb4..61c1cc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -30,9 +30,9 @@
import androidx.annotation.StyleRes;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.keyguard.KeyguardIndication;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index 74ab47f..c17366a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -115,9 +115,7 @@
val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible &&
!statusBarStateController.isDozing
- val userId = KeyguardUpdateMonitor.getCurrentUser()
- val isFaceEnabled = keyguardUpdateMonitor.isFaceAuthEnabledForUser(userId)
- val shouldListen = (onKeyguard || bouncerVisible) && isFaceEnabled
+ val shouldListen = (onKeyguard || bouncerVisible) && keyguardUpdateMonitor.isFaceEnrolled
if (shouldListen != isListening) {
isListening = shouldListen
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 13566ef..720eeba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -43,9 +43,9 @@
import androidx.annotation.VisibleForTesting;
+import com.android.app.animation.Interpolators;
import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index e835c5ce..5232fb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -37,12 +37,12 @@
import androidx.core.animation.AnimatorListenerAdapter;
import androidx.core.animation.ValueAnimator;
+import com.android.app.animation.InterpolatorsAndroidX;
import com.android.keyguard.CarrierTextController;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.logging.KeyguardLogger;
import com.android.systemui.R;
-import com.android.systemui.animation.InterpolatorsAndroidX;
import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.log.LogLevel;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 6bf5443..7bc4fc3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -24,21 +24,21 @@
import android.util.MathUtils;
import android.util.TimeUtils;
+import com.android.app.animation.Interpolators;
import com.android.systemui.Dumpable;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-
import dagger.assisted.Assisted;
import dagger.assisted.AssistedFactory;
import dagger.assisted.AssistedInject;
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+
/**
* Class to control all aspects about light bar changes.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index cc4f901..46a2457 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -31,9 +31,9 @@
import android.util.SparseArray;
import android.view.ViewTreeObserver.OnPreDrawListener;
+import com.android.app.animation.Interpolators;
import com.android.internal.graphics.ColorUtils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 55dc188..560ea8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -15,11 +15,11 @@
import androidx.annotation.VisibleForTesting;
import androidx.collection.ArrayMap;
+import com.android.app.animation.Interpolators;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.ContrastColorUtil;
import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 006a029d..bef422c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -36,10 +36,10 @@
import androidx.annotation.VisibleForTesting;
import androidx.collection.ArrayMap;
+import com.android.app.animation.Interpolators;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.settingslib.Utils;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.stack.AnimationFilter;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
index 5e5317d7..07a6d0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
@@ -29,7 +29,7 @@
import android.view.animation.AnimationUtils;
import android.widget.Button;
-import com.android.systemui.animation.Interpolators;
+import com.android.app.animation.Interpolators;
import com.android.systemui.statusbar.AlphaOptimizedImageView;
public class SettingsButton extends AlphaOptimizedImageView {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index 8fa803e..cdf6652 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -15,7 +15,7 @@
import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF
import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD
import com.android.systemui.DejankUtils
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.KeyguardViewMediator
import com.android.systemui.keyguard.WakefulnessLifecycle
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
index b16d16a..ddb6d93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
@@ -45,7 +45,6 @@
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
-import java.util.Set;
import javax.inject.Named;
import javax.inject.Scope;
@@ -60,7 +59,6 @@
* outside the component. Should more items be moved *into* this component to avoid so many getters?
*/
@Subcomponent(modules = {
- CentralSurfacesStartableModule.class,
NotificationStackScrollLayoutListContainerModule.class,
StatusBarViewModule.class,
StatusBarNotificationActivityStarterModule.class,
@@ -85,14 +83,6 @@
@interface CentralSurfacesScope {}
/**
- * Performs initialization logic after {@link CentralSurfacesComponent} has been constructed.
- */
- interface Startable {
- void start();
- void stop();
- }
-
- /**
* Creates a {@link NotificationShadeWindowView}.
*/
NotificationShadeWindowView getNotificationShadeWindowView();
@@ -143,11 +133,6 @@
@Named(STATUS_BAR_FRAGMENT)
CollapsedStatusBarFragment createCollapsedStatusBarFragment();
- /**
- * Set of startables to be run after a CentralSurfacesComponent has been constructed.
- */
- Set<Startable> getStartables();
-
NotificationActivityStarter getNotificationActivityStarter();
NotificationPresenter getNotificationPresenter();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesStartableModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesStartableModule.java
deleted file mode 100644
index 7ded90f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesStartableModule.java
+++ /dev/null
@@ -1,28 +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.phone.dagger;
-
-import dagger.Module;
-import dagger.multibindings.Multibinds;
-
-import java.util.Set;
-
-@Module
-interface CentralSurfacesStartableModule {
- @Multibinds
- Set<CentralSurfacesComponent.Startable> multibindStartables();
-}
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 453dd1b..831d402 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
@@ -44,10 +44,10 @@
import androidx.annotation.VisibleForTesting;
import androidx.core.animation.Animator;
+import com.android.app.animation.Interpolators;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index 673819b..3d811cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -240,7 +240,7 @@
|| (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB && mDebugUnlocked);
boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user);
- boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(user);
+ boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceEnrolled();
boolean changed = secure != mSecure || canDismissLockScreen != mCanDismissLockScreen
|| trustManaged != mTrustManaged || mTrusted != trusted
|| mFaceAuthEnabled != faceAuthEnabled;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserDetailItemView.java
index 4dd63be..e1ec94f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserDetailItemView.java
@@ -24,9 +24,9 @@
import androidx.core.graphics.ColorUtils;
+import com.android.app.animation.Interpolators;
import com.android.keyguard.KeyguardConstants;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.qs.tiles.UserDetailItemView;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
index 928e011..66b5256 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
@@ -31,6 +31,7 @@
import android.view.View;
import android.view.ViewGroup;
+import com.android.app.animation.Interpolators;
import com.android.keyguard.KeyguardConstants;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
@@ -38,7 +39,6 @@
import com.android.keyguard.dagger.KeyguardUserSwitcherScope;
import com.android.settingslib.drawable.CircleFramedDrawable;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java
index 850a4b4..363b06a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java
@@ -21,11 +21,11 @@
import android.util.Log;
import android.view.View;
+import com.android.app.animation.Interpolators;
import com.android.keyguard.AlphaOptimizedLinearLayout;
import com.android.keyguard.KeyguardConstants;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
-import com.android.systemui.animation.Interpolators;
/**
* The container for the user switcher on Keyguard.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 403a7e8..e311bad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -73,6 +73,7 @@
import androidx.core.animation.ObjectAnimator;
import androidx.core.animation.ValueAnimator;
+import com.android.app.animation.InterpolatorsAndroidX;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.logging.UiEvent;
@@ -80,7 +81,6 @@
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.animation.InterpolatorsAndroidX;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
index 1612388..46954b5 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
@@ -18,7 +18,7 @@
import android.view.View
import android.view.ViewGroup
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
import com.android.systemui.animation.ViewHierarchyAnimator
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.util.children
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
index e819f94..4fbbc89 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
@@ -34,10 +34,10 @@
import androidx.annotation.DimenRes
import androidx.annotation.IdRes
import androidx.annotation.VisibleForTesting
+import com.android.app.animation.Interpolators
import com.android.internal.widget.CachingIconView
import com.android.systemui.Gefingerpoken
import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription
import com.android.systemui.common.shared.model.Text.Companion.loadText
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt b/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
index 5d80292..db4ab7e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
@@ -19,7 +19,7 @@
import android.animation.ValueAnimator
import android.graphics.PointF
import android.util.MathUtils
-import com.android.systemui.animation.Interpolators
+import com.android.app.animation.Interpolators
/**
* The fraction after which we start fading in when going from a gone widget to a visible one
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 77210b7..91078dc 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -109,6 +109,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.app.animation.Interpolators;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
@@ -119,7 +120,6 @@
import com.android.systemui.Dumpable;
import com.android.systemui.Prefs;
import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.plugins.ActivityStarter;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 2962c14..71246c9 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -383,6 +383,7 @@
}
private void setupFingerprintAuth(boolean isClass3) throws RemoteException {
+ when(mAuthController.isFingerprintEnrolled(anyInt())).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
mFingerprintSensorProperties = List.of(
@@ -2692,33 +2693,42 @@
}
@Test
public void testFingerprintSensorProperties() throws RemoteException {
+ // GIVEN no fingerprint sensor properties
+ when(mAuthController.isFingerprintEnrolled(anyInt())).thenReturn(true);
mFingerprintAuthenticatorsRegisteredCallback.onAllAuthenticatorsRegistered(
new ArrayList<>());
+ // THEN fingerprint is not possible
assertThat(mKeyguardUpdateMonitor.isUnlockWithFingerprintPossible(
KeyguardUpdateMonitor.getCurrentUser())).isFalse();
+ // WHEN there are fingerprint sensor properties
mFingerprintAuthenticatorsRegisteredCallback
.onAllAuthenticatorsRegistered(mFingerprintSensorProperties);
- verifyFingerprintAuthenticateCall();
+ // THEN unlock with fp is possible & fingerprint starts listening
assertThat(mKeyguardUpdateMonitor.isUnlockWithFingerprintPossible(
KeyguardUpdateMonitor.getCurrentUser())).isTrue();
+ verifyFingerprintAuthenticateCall();
}
@Test
public void testFaceSensorProperties() throws RemoteException {
+ // GIVEN no face sensor properties
+ when(mAuthController.isFaceAuthEnrolled(anyInt())).thenReturn(true);
mFaceAuthenticatorsRegisteredCallback.onAllAuthenticatorsRegistered(new ArrayList<>());
- assertThat(mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(
+ // THEN face is not possible
+ assertThat(mKeyguardUpdateMonitor.isUnlockWithFacePossible(
KeyguardUpdateMonitor.getCurrentUser())).isFalse();
+ // WHEN there are face sensor properties
mFaceAuthenticatorsRegisteredCallback.onAllAuthenticatorsRegistered(mFaceSensorProperties);
- biometricsEnabledForCurrentUser();
+ // THEN face is possible but face does NOT start listening immediately
+ assertThat(mKeyguardUpdateMonitor.isUnlockWithFacePossible(
+ KeyguardUpdateMonitor.getCurrentUser())).isTrue();
verifyFaceAuthenticateNeverCalled();
verifyFaceDetectNeverCalled();
- assertThat(mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(
- KeyguardUpdateMonitor.getCurrentUser())).isTrue();
}
@Test
@@ -2791,9 +2801,6 @@
}
private void mockCanBypassLockscreen(boolean canBypass) {
- // force update the isFaceEnrolled cache:
- mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(getCurrentUser());
-
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
when(mKeyguardBypassController.canBypass()).thenReturn(canBypass);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/InterpolatorsAndroidXTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/InterpolatorsAndroidXTest.kt
deleted file mode 100644
index 2c680be..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/InterpolatorsAndroidXTest.kt
+++ /dev/null
@@ -1,55 +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.animation
-
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import java.lang.reflect.Modifier
-import junit.framework.Assert.assertEquals
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@SmallTest
-@RunWith(JUnit4::class)
-class InterpolatorsAndroidXTest : SysuiTestCase() {
-
- @Test
- fun testInterpolatorsAndInterpolatorsAndroidXPublicMethodsAreEqual() {
- assertEquals(
- Interpolators::class.java.getPublicMethods(),
- InterpolatorsAndroidX::class.java.getPublicMethods()
- )
- }
-
- @Test
- fun testInterpolatorsAndInterpolatorsAndroidXPublicFieldsAreEqual() {
- assertEquals(
- Interpolators::class.java.getPublicFields(),
- InterpolatorsAndroidX::class.java.getPublicFields()
- )
- }
-
- private fun <T> Class<T>.getPublicMethods() =
- declaredMethods
- .filter { Modifier.isPublic(it.modifiers) }
- .map { it.toString().replace(name, "") }
- .toSet()
-
- private fun <T> Class<T>.getPublicFields() =
- fields.filter { Modifier.isPublic(it.modifiers) }.map { it.name }.toSet()
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt
index 02d4ecd..063757a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt
@@ -31,6 +31,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.io.File
@@ -64,6 +65,7 @@
@RunWith(AndroidTestingRunner::class)
@SmallTest
class TextInterpolatorTest : SysuiTestCase() {
+ lateinit var typefaceCache: TypefaceVariantCache
private fun makeLayout(
text: String,
@@ -75,11 +77,16 @@
.setTextDirection(dir).build()
}
+ @Before
+ fun setup() {
+ typefaceCache = TypefaceVariantCacheImpl()
+ }
+
@Test
fun testStartState() {
val layout = makeLayout(TEXT, PAINT)
- val interp = TextInterpolator(layout)
+ val interp = TextInterpolator(layout, typefaceCache)
interp.basePaint.set(START_PAINT)
interp.onBasePaintModified()
@@ -98,7 +105,7 @@
fun testEndState() {
val layout = makeLayout(TEXT, PAINT)
- val interp = TextInterpolator(layout)
+ val interp = TextInterpolator(layout, typefaceCache)
interp.basePaint.set(START_PAINT)
interp.onBasePaintModified()
@@ -116,7 +123,7 @@
fun testMiddleState() {
val layout = makeLayout(TEXT, PAINT)
- val interp = TextInterpolator(layout)
+ val interp = TextInterpolator(layout, typefaceCache)
interp.basePaint.set(START_PAINT)
interp.onBasePaintModified()
@@ -138,7 +145,7 @@
fun testRebase() {
val layout = makeLayout(TEXT, PAINT)
- val interp = TextInterpolator(layout)
+ val interp = TextInterpolator(layout, typefaceCache)
interp.basePaint.set(START_PAINT)
interp.onBasePaintModified()
@@ -160,7 +167,7 @@
fun testBidi_LTR() {
val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.LTR)
- val interp = TextInterpolator(layout)
+ val interp = TextInterpolator(layout, typefaceCache)
interp.basePaint.set(START_PAINT)
interp.onBasePaintModified()
@@ -180,7 +187,7 @@
fun testBidi_RTL() {
val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL)
- val interp = TextInterpolator(layout)
+ val interp = TextInterpolator(layout, typefaceCache)
interp.basePaint.set(START_PAINT)
interp.onBasePaintModified()
@@ -200,7 +207,7 @@
fun testGlyphCallback_Empty() {
val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL)
- val interp = TextInterpolator(layout).apply {
+ val interp = TextInterpolator(layout, typefaceCache).apply {
glyphFilter = { glyph, progress ->
}
}
@@ -222,7 +229,7 @@
fun testGlyphCallback_Xcoordinate() {
val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL)
- val interp = TextInterpolator(layout).apply {
+ val interp = TextInterpolator(layout, typefaceCache).apply {
glyphFilter = { glyph, progress ->
glyph.x += 30f
}
@@ -247,7 +254,7 @@
fun testGlyphCallback_Ycoordinate() {
val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL)
- val interp = TextInterpolator(layout).apply {
+ val interp = TextInterpolator(layout, typefaceCache).apply {
glyphFilter = { glyph, progress ->
glyph.y += 30f
}
@@ -272,7 +279,7 @@
fun testGlyphCallback_TextSize() {
val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL)
- val interp = TextInterpolator(layout).apply {
+ val interp = TextInterpolator(layout, typefaceCache).apply {
glyphFilter = { glyph, progress ->
glyph.textSize += 10f
}
@@ -297,7 +304,7 @@
fun testGlyphCallback_Color() {
val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL)
- val interp = TextInterpolator(layout).apply {
+ val interp = TextInterpolator(layout, typefaceCache).apply {
glyphFilter = { glyph, progress ->
glyph.color = Color.RED
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
index 6ab54a3..da9ceb4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
@@ -19,6 +19,7 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import com.android.app.animation.Interpolators
@SmallTest
@RunWith(AndroidTestingRunner::class)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
index f4dacab..213dc87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
@@ -26,6 +26,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.R
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.After
@@ -43,6 +44,7 @@
@RunWith(AndroidJUnit4::class)
@RunWithLooper(setAsMainLooper = true)
@SmallTest
+@RoboPilotTest
class AuthBiometricFingerprintAndFaceViewTest : SysuiTestCase() {
@JvmField
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
index 9f789e4..22ebc7e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
@@ -23,6 +23,7 @@
import android.view.View
import androidx.test.filters.SmallTest
import com.android.systemui.R
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.After
@@ -40,6 +41,7 @@
@RunWith(AndroidJUnit4::class)
@RunWithLooper(setAsMainLooper = true)
@SmallTest
+@RoboPilotTest
class AuthBiometricFingerprintViewTest : SysuiTestCase() {
@JvmField
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 0f20ace..4f24b3a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -89,6 +89,7 @@
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.widget.LockPatternUtils;
import com.android.settingslib.udfps.UdfpsUtils;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.domain.interactor.BiometricPromptCredentialInteractor;
import com.android.systemui.biometrics.domain.interactor.LogContextInteractor;
@@ -120,6 +121,7 @@
@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/BiometricDisplayListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java
index 24a13a5..c6315cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java
@@ -41,6 +41,7 @@
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;
@@ -55,6 +56,7 @@
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 88b6c39..ad9fc95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt
@@ -19,6 +19,7 @@
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
@@ -33,6 +34,7 @@
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 c554af6..e6334cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -52,6 +52,7 @@
import androidx.test.filters.SmallTest
import com.airbnb.lottie.LottieAnimationView
import com.android.systemui.R
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestableContext
import com.android.systemui.dump.DumpManager
@@ -90,6 +91,7 @@
private const val SENSOR_ID = 1
@SmallTest
+@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class SideFpsControllerTest : 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 1faad80..2747e83 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -40,6 +40,7 @@
import com.android.settingslib.udfps.UdfpsOverlayParams
import com.android.settingslib.udfps.UdfpsUtils
import com.android.systemui.R
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.dump.DumpManager
@@ -80,6 +81,7 @@
private const val SENSOR_HEIGHT = 60
@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 8d8b190..da71188 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -76,6 +76,7 @@
import com.android.settingslib.udfps.UdfpsOverlayParams;
import com.android.settingslib.udfps.UdfpsUtils;
import com.android.systemui.R;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.biometrics.udfps.InteractionEvent;
@@ -125,6 +126,7 @@
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 cd9189b..280bfdf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java
@@ -27,6 +27,7 @@
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;
@@ -37,6 +38,7 @@
@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 5239966..1afb223 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDisplayModeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDisplayModeTest.java
@@ -30,6 +30,7 @@
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;
@@ -40,6 +41,7 @@
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/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index af3a06b..b5515d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -33,6 +33,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.systemui.RoboPilotTest;
import com.android.systemui.shade.ShadeExpansionListener;
import com.android.systemui.statusbar.StatusBarState;
@@ -40,6 +41,7 @@
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/UdfpsKeyguardViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
index fea9d2d5..8bf32cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
@@ -34,6 +34,7 @@
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.RoboPilotTest
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -55,6 +56,7 @@
@RunWith(AndroidJUnit4::class)
@SmallTest
+@RoboPilotTest
@TestableLooper.RunWithLooper
@kotlinx.coroutines.ExperimentalCoroutinesApi
class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControllerBaseTest() {
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 8b374ae..6d55254 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsShellTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsShellTest.kt
@@ -21,6 +21,7 @@
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
@@ -39,6 +40,7 @@
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 f075967..d11c965 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
@@ -27,6 +27,7 @@
import androidx.test.filters.SmallTest
import com.android.settingslib.udfps.UdfpsOverlayParams
import com.android.systemui.R
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
@@ -49,6 +50,7 @@
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/biometrics/udfps/EllipseOverlapDetectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetectorTest.kt
index 4b41537..fb3c185 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetectorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetectorTest.kt
@@ -61,7 +61,7 @@
@JvmStatic
fun data(): List<TestCase> =
listOf(
- genTestCases(
+ genPositiveTestCases(
innerXs = listOf(SENSOR.left, SENSOR.right, SENSOR.centerX()),
innerYs = listOf(SENSOR.top, SENSOR.bottom, SENSOR.centerY()),
outerXs = listOf(SENSOR.left - 1, SENSOR.right + 1),
@@ -70,9 +70,7 @@
major = 300f,
expected = true
),
- genTestCases(
- innerXs = listOf(SENSOR.left, SENSOR.right),
- innerYs = listOf(SENSOR.top, SENSOR.bottom),
+ genNegativeTestCase(
outerXs = listOf(SENSOR.left - 1, SENSOR.right + 1),
outerYs = listOf(SENSOR.top - 1, SENSOR.bottom + 1),
minor = 100f,
@@ -107,7 +105,7 @@
private val SENSOR = Rect(100 /* left */, 200 /* top */, 300 /* right */, 400 /* bottom */)
-private fun genTestCases(
+private fun genPositiveTestCases(
innerXs: List<Int>,
innerYs: List<Int>,
outerXs: List<Int>,
@@ -122,3 +120,15 @@
}
}
}
+
+private fun genNegativeTestCase(
+ outerXs: List<Int>,
+ outerYs: List<Int>,
+ minor: Float,
+ major: Float,
+ expected: Boolean
+): List<EllipseOverlapDetectorTest.TestCase> {
+ return outerXs.flatMap { x ->
+ outerYs.map { y -> EllipseOverlapDetectorTest.TestCase(x, y, minor, major, expected) }
+ }
+}
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 58eb7d4..e1c54976 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
@@ -18,7 +18,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
@@ -26,13 +25,13 @@
import static org.mockito.Mockito.when;
import android.app.DreamManager;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.shared.condition.Condition;
@@ -55,6 +54,9 @@
@Mock
DreamManager mDreamManager;
+ @Mock
+ KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -66,7 +68,7 @@
@Test
public void testInitialDreamingState() {
when(mDreamManager.isDreaming()).thenReturn(true);
- final DreamCondition condition = new DreamCondition(mContext, mDreamManager);
+ final DreamCondition condition = new DreamCondition(mDreamManager, mKeyguardUpdateMonitor);
condition.addCallback(mCallback);
verify(mCallback).onConditionChanged(eq(condition));
@@ -79,7 +81,7 @@
@Test
public void testInitialNonDreamingState() {
when(mDreamManager.isDreaming()).thenReturn(false);
- final DreamCondition condition = new DreamCondition(mContext, mDreamManager);
+ final DreamCondition condition = new DreamCondition(mDreamManager, mKeyguardUpdateMonitor);
condition.addCallback(mCallback);
verify(mCallback, never()).onConditionChanged(eq(condition));
@@ -91,15 +93,21 @@
*/
@Test
public void testChange() {
- final ArgumentCaptor<BroadcastReceiver> receiverCaptor =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
+ final ArgumentCaptor<KeyguardUpdateMonitorCallback> callbackCaptor =
+ ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
when(mDreamManager.isDreaming()).thenReturn(true);
- final DreamCondition condition = new DreamCondition(mContext, mDreamManager);
+ final DreamCondition condition = new DreamCondition(mDreamManager, mKeyguardUpdateMonitor);
condition.addCallback(mCallback);
- verify(mContext).registerReceiver(receiverCaptor.capture(), any());
+ verify(mKeyguardUpdateMonitor).registerCallback(callbackCaptor.capture());
+
clearInvocations(mCallback);
- receiverCaptor.getValue().onReceive(mContext, new Intent(Intent.ACTION_DREAMING_STOPPED));
+ callbackCaptor.getValue().onDreamingStateChanged(false);
verify(mCallback).onConditionChanged(eq(condition));
assertThat(condition.isConditionMet()).isFalse();
+
+ clearInvocations(mCallback);
+ callbackCaptor.getValue().onDreamingStateChanged(true);
+ verify(mCallback).onConditionChanged(eq(condition));
+ assertThat(condition.isConditionMet()).isTrue();
}
}
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 e20d3af..cfee3b8 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,6 +23,7 @@
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
@@ -42,6 +43,7 @@
@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 c326a86..d84a4f7 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,6 +26,7 @@
import androidx.test.filters.SmallTest
import com.android.settingslib.notification.EnableZenModeDialog
import com.android.systemui.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
@@ -60,6 +61,7 @@
@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 0fb181d..13d1e64 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,6 +17,7 @@
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
@@ -24,6 +25,7 @@
import kotlinx.coroutines.yield
/** Fake implementation of a quick affordance data source. */
+@RoboPilotTest
class FakeKeyguardQuickAffordanceConfig(
override val key: String,
override 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 292d067..b6dffff 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,6 +21,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.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
@@ -41,6 +42,7 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
+@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class FlashlightQuickAffordanceConfigTest : LeakCheckedTest() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
index f8cb408..b46d996 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
@@ -19,6 +19,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.R
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.controller.ControlsController
@@ -45,6 +46,7 @@
import org.mockito.MockitoAnnotations
@SmallTest
+@RoboPilotTest
@RunWith(Parameterized::class)
class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTestCase() {
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 26f0cdb..2fd4947 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,6 +20,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.R
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Expandable
import com.android.systemui.controls.controller.ControlsController
@@ -40,6 +41,7 @@
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 9a18ba8..9200d72 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,6 +23,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.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
@@ -48,6 +49,7 @@
@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 6989f44..bad4b36 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,6 +23,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.R
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.settings.UserFileManager
@@ -51,6 +52,7 @@
@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 a1c9f87..0797d07 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,6 +21,7 @@
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
@@ -43,6 +44,7 @@
@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 c38827a..d8c0341 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
@@ -19,7 +19,9 @@
import android.content.Context
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
@@ -37,7 +39,6 @@
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.times
import org.mockito.Mockito.verify
@@ -45,7 +46,8 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RoboPilotTest
+@RunWith(AndroidJUnit4::class)
class MuteQuickAffordanceConfigTest : SysuiTestCase() {
private lateinit var underTest: MuteQuickAffordanceConfig
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 faf18d3..26c0ea4 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,6 +20,7 @@
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
@@ -39,6 +40,7 @@
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 952882d..111b8e8 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
@@ -23,6 +23,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.R
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.animation.Expandable
@@ -48,6 +49,7 @@
@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 a9b9c90..1414bac 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,6 +21,7 @@
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
@@ -44,6 +45,7 @@
@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 726728a..1bab817 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
@@ -24,8 +24,8 @@
import android.content.pm.UserInfo
import android.hardware.biometrics.BiometricManager
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback
-import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
@@ -33,6 +33,7 @@
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.R
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.coroutines.collectLastValue
@@ -69,8 +70,9 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
+@RoboPilotTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@RunWith(AndroidTestingRunner::class)
+@RunWith(AndroidJUnit4::class)
class BiometricSettingsRepositoryTest : SysuiTestCase() {
private lateinit var underTest: BiometricSettingsRepository
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 fa40fc4..b50cf73 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
@@ -29,6 +29,7 @@
import android.hardware.face.FaceSensorProperties
import android.hardware.face.FaceSensorPropertiesInternal
import android.os.CancellationSignal
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId.fakeInstanceId
import com.android.internal.logging.UiEventLogger
@@ -36,6 +37,7 @@
import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER
import com.android.systemui.R
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.FlowValue
import com.android.systemui.coroutines.collectLastValue
@@ -81,7 +83,6 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.eq
@@ -98,7 +99,8 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@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 e57b044..264328b 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
@@ -18,9 +18,11 @@
import android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT
import android.hardware.biometrics.BiometricSourceType
+import androidx.test.ext.junit.runners.AndroidJUnit4
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
@@ -34,7 +36,6 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
@@ -44,7 +45,8 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RoboPilotTest
+@RunWith(AndroidJUnit4::class)
class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var dumpManager: DumpManager
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 bd6b7a8..7eb8a26 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
@@ -16,7 +16,9 @@
package com.android.systemui.keyguard.data.repository
+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
@@ -29,7 +31,6 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
@@ -38,7 +39,8 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RoboPilotTest
+@RunWith(AndroidJUnit4::class)
class DevicePostureRepositoryTest : SysuiTestCase() {
private lateinit var underTest: DevicePostureRepository
private lateinit var testScope: TestScope
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 12b8261..8dc04bd 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,6 +22,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.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
@@ -54,6 +55,7 @@
@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 b53a434..4b4c7e9 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,6 +22,7 @@
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
@@ -63,6 +64,7 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
+@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardRepositoryImplTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
index d0bfaa9..a17b596 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -23,8 +23,9 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.FlakyTest
import androidx.test.filters.SmallTest
+import com.android.app.animation.Interpolators
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.Interpolators
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
@@ -47,6 +48,7 @@
import org.junit.runner.RunWith
@SmallTest
+@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@FlakyTest(bugId = 270760395)
class KeyguardTransitionRepositoryTest : 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 9daf3f3..f974577 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
@@ -17,7 +17,9 @@
package com.android.systemui.keyguard.data.repository
import android.graphics.Point
+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.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
@@ -31,11 +33,11 @@
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)
+@RoboPilotTest
+@RunWith(AndroidJUnit4::class)
class LightRevealScrimRepositoryTest : SysuiTestCase() {
private lateinit var fakeKeyguardRepository: FakeKeyguardRepository
private lateinit var underTest: LightRevealScrimRepositoryImpl
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 a181137..bf3c73a 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,6 +21,7 @@
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.collectLastValue
import com.android.systemui.plugins.log.LogBuffer
@@ -43,6 +44,7 @@
@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/AlternateBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
index e7e5969..2180a8f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
@@ -19,6 +19,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.keyguard.ViewMediatorCallback
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
@@ -43,6 +44,7 @@
@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/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 68d694a..0d695aa 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,6 +20,7 @@
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.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
@@ -39,6 +40,7 @@
import org.mockito.MockitoAnnotations
@SmallTest
+@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardInteractorTest : SysuiTestCase() {
private lateinit var commandQueue: FakeCommandQueue
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 8a0cf4f..dfef947 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
@@ -21,6 +21,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger
+import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
@@ -48,6 +49,7 @@
@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 23f0523..6e21c00 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,6 +23,7 @@
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.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
@@ -71,6 +72,7 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
+@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardQuickAffordanceInteractorTest : 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 503687d..d66e420 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
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
+import com.android.systemui.RoboPilotTest
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -38,6 +39,7 @@
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 359854b..4440946 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,6 +18,7 @@
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
@@ -37,6 +38,7 @@
import org.mockito.MockitoAnnotations
@SmallTest
+@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class LightRevealScrimInteractorTest : SysuiTestCase() {
private val fakeKeyguardTransitionRepository = FakeKeyguardTransitionRepository()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt
index f86ac79..2b135cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt
@@ -19,6 +19,7 @@
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
@@ -28,6 +29,7 @@
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/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
index edac468..e35e971 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
@@ -21,6 +21,7 @@
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.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
@@ -39,6 +40,7 @@
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/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
index a5b78b74..3efe382 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/KeyguardTransitionAnimationFlowTest.kt
@@ -17,8 +17,8 @@
package com.android.systemui.keyguard.ui
import androidx.test.filters.SmallTest
+import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
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 706154e..cdd06ac 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,6 +18,7 @@
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.KeyguardTransitionInteractor
@@ -36,6 +37,7 @@
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 b15ce10..40511a0 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,6 +18,7 @@
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.KeyguardTransitionInteractor
@@ -35,6 +36,7 @@
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/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
index 9cd2220..0e9c99e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
@@ -21,6 +21,7 @@
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.classifier.FalsingCollector
import com.android.systemui.keyguard.DismissCallbackRegistry
@@ -44,6 +45,7 @@
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/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
index d94c108..c98058d 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,6 +18,7 @@
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.KeyguardTransitionInteractor
@@ -35,6 +36,7 @@
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 12ec24d..031b7fb 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,6 +18,7 @@
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.KeyguardTransitionInteractor
@@ -35,6 +36,7 @@
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 efa5f0c..c7ff882 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,6 +18,7 @@
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.KeyguardTransitionInteractor
@@ -35,6 +36,7 @@
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 98794fd..db251a0 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,6 +18,7 @@
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.KeyguardTransitionInteractor
@@ -41,6 +42,7 @@
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/media/controls/ui/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
index a72634b..1a00ac2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
@@ -110,6 +110,7 @@
lateinit var configListener: ArgumentCaptor<ConfigurationController.ConfigurationListener>
@Captor lateinit var visualStabilityCallback: ArgumentCaptor<OnReorderingAllowedListener>
@Captor lateinit var keyguardCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback>
+ @Captor lateinit var hostStateCallback: ArgumentCaptor<MediaHostStatesManager.Callback>
private val clock = FakeSystemClock()
private lateinit var mediaCarouselController: MediaCarouselController
@@ -143,6 +144,7 @@
verify(visualStabilityProvider)
.addPersistentReorderingAllowedListener(capture(visualStabilityCallback))
verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCallback))
+ verify(mediaHostStatesManager).addCallback(capture(hostStateCallback))
whenever(mediaControlPanelFactory.get()).thenReturn(panel)
whenever(panel.mediaViewController).thenReturn(mediaViewController)
whenever(mediaDataManager.smartspaceMediaData).thenReturn(smartspaceMediaData)
@@ -832,4 +834,16 @@
// Verify that seekbar listening attribute in media control panel is set to false.
verify(panel, times(MediaPlayerData.players().size)).listening = false
}
+
+ @Test
+ fun testOnHostStateChanged_updateVisibility() {
+ var stateUpdated = false
+ mediaCarouselController.updateUserVisibility = { stateUpdated = true }
+
+ // When the host state updates
+ hostStateCallback.value!!.onHostStateChanged(LOCATION_QS, mediaHostState)
+
+ // Then the carousel visibility is updated
+ assertTrue(stateUpdated)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
index eb78ded..2ce236d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
@@ -470,6 +470,21 @@
)
}
+ @Test
+ fun testQsExpandedChanged_noQqsMedia() {
+ // When we are looking at QQS with active media
+ whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
+ whenever(statusBarStateController.isExpanded).thenReturn(true)
+
+ // When there is no longer any active media
+ whenever(mediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(false)
+ mediaHierarchyManager.qsExpanded = false
+
+ // Then the carousel is set to not visible
+ verify(mediaCarouselScrollHandler).visibleToUser = false
+ assertThat(mediaCarouselScrollHandler.visibleToUser).isFalse()
+ }
+
private fun enableSplitShade() {
context
.getOrCreateTestableResources()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt
index db6fc13..38a666e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt
@@ -37,6 +37,7 @@
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
+import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -54,10 +55,12 @@
@Mock private lateinit var parent: ViewGroup
+ @Mock private lateinit var splitShadeStatusBar: ViewGroup
+
@Mock private lateinit var statusBarStateController: StatusBarStateController
private lateinit var underTest: NotificationPanelUnfoldAnimationController
- private lateinit var progressListener: TransitionProgressListener
+ private lateinit var progressListeners: List<TransitionProgressListener>
private var xTranslationMax = 0f
@Before
@@ -73,10 +76,13 @@
statusBarStateController,
progressProvider
)
+ whenever(parent.findViewById<ViewGroup>(R.id.split_shade_status_bar)).thenReturn(
+ splitShadeStatusBar
+ )
underTest.setup(parent)
- verify(progressProvider).addCallback(capture(progressListenerCaptor))
- progressListener = progressListenerCaptor.value
+ verify(progressProvider, atLeastOnce()).addCallback(capture(progressListenerCaptor))
+ progressListeners = progressListenerCaptor.allValues
}
@Test
@@ -86,16 +92,16 @@
val view = View(context)
whenever(parent.findViewById<View>(R.id.quick_settings_panel)).thenReturn(view)
- progressListener.onTransitionStarted()
+ onTransitionStarted()
assertThat(view.translationX).isZero()
- progressListener.onTransitionProgress(0f)
+ onTransitionProgress(0f)
assertThat(view.translationX).isZero()
- progressListener.onTransitionProgress(0.5f)
+ onTransitionProgress(0.5f)
assertThat(view.translationX).isZero()
- progressListener.onTransitionFinished()
+ onTransitionFinished()
assertThat(view.translationX).isZero()
}
@@ -106,16 +112,16 @@
val view = View(context)
whenever(parent.findViewById<View>(R.id.quick_settings_panel)).thenReturn(view)
- progressListener.onTransitionStarted()
+ onTransitionStarted()
assertThat(view.translationX).isZero()
- progressListener.onTransitionProgress(0f)
+ onTransitionProgress(0f)
assertThat(view.translationX).isEqualTo(xTranslationMax)
- progressListener.onTransitionProgress(0.5f)
+ onTransitionProgress(0.5f)
assertThat(view.translationX).isEqualTo(0.5f * xTranslationMax)
- progressListener.onTransitionFinished()
+ onTransitionFinished()
assertThat(view.translationX).isZero()
}
@@ -126,16 +132,88 @@
val view = View(context)
whenever(parent.findViewById<View>(R.id.quick_settings_panel)).thenReturn(view)
- progressListener.onTransitionStarted()
+ onTransitionStarted()
assertThat(view.translationX).isZero()
- progressListener.onTransitionProgress(0f)
+ onTransitionProgress(0f)
assertThat(view.translationX).isEqualTo(xTranslationMax)
- progressListener.onTransitionProgress(0.5f)
+ onTransitionProgress(0.5f)
assertThat(view.translationX).isEqualTo(0.5f * xTranslationMax)
- progressListener.onTransitionFinished()
+ onTransitionFinished()
assertThat(view.translationX).isZero()
}
+
+ @Test
+ fun whenInKeyguardState_statusBarViewDoesNotMove() {
+ whenever(statusBarStateController.getState()).thenReturn(KEYGUARD)
+
+ val view = View(context)
+ whenever(splitShadeStatusBar.findViewById<View>(R.id.date)).thenReturn(view)
+
+ onTransitionStarted()
+ assertThat(view.translationX).isZero()
+
+ onTransitionProgress(0f)
+ assertThat(view.translationX).isZero()
+
+ onTransitionProgress(0.5f)
+ assertThat(view.translationX).isZero()
+
+ onTransitionFinished()
+ assertThat(view.translationX).isZero()
+ }
+
+ @Test
+ fun whenInShadeState_statusBarViewDoesMove() {
+ whenever(statusBarStateController.getState()).thenReturn(SHADE)
+
+ val view = View(context)
+ whenever(splitShadeStatusBar.findViewById<View>(R.id.date)).thenReturn(view)
+
+ onTransitionStarted()
+ assertThat(view.translationX).isZero()
+
+ onTransitionProgress(0f)
+ assertThat(view.translationX).isEqualTo(xTranslationMax)
+
+ onTransitionProgress(0.5f)
+ assertThat(view.translationX).isEqualTo(0.5f * xTranslationMax)
+
+ onTransitionFinished()
+ assertThat(view.translationX).isZero()
+ }
+
+ @Test
+ fun whenInShadeLockedState_statusBarViewDoesMove() {
+ whenever(statusBarStateController.getState()).thenReturn(SHADE_LOCKED)
+
+ val view = View(context)
+ whenever(splitShadeStatusBar.findViewById<View>(R.id.date)).thenReturn(view)
+ onTransitionStarted()
+ assertThat(view.translationX).isZero()
+
+ onTransitionProgress(0f)
+ assertThat(view.translationX).isEqualTo(xTranslationMax)
+
+ onTransitionProgress(0.5f)
+ assertThat(view.translationX).isEqualTo(0.5f * xTranslationMax)
+
+ onTransitionFinished()
+ assertThat(view.translationX).isZero()
+ }
+
+ private fun onTransitionStarted() {
+ progressListeners.forEach { it.onTransitionStarted() }
+ }
+
+ private fun onTransitionProgress(progress: Float) {
+ progressListeners.forEach { it.onTransitionProgress(progress) }
+ }
+
+ private fun onTransitionFinished() {
+ progressListeners.forEach { it.onTransitionFinished() }
+ }
+
}
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 068d933..f870631 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -305,6 +305,7 @@
@Mock protected ActivityStarter mActivityStarter;
@Mock protected KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
+ protected final int mMaxUdfpsBurnInOffsetY = 5;
protected KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
protected KeyguardInteractor mKeyguardInteractor;
protected NotificationPanelViewController.TouchHandler mTouchHandler;
@@ -365,6 +366,8 @@
when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
mDisplayMetrics.density = 100;
when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
+ when(mResources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y))
+ .thenReturn(mMaxUdfpsBurnInOffsetY);
when(mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade))
.thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 600fb5c..48e0b53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -29,6 +29,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -44,6 +45,7 @@
import android.animation.Animator;
import android.animation.ValueAnimator;
+import android.graphics.Point;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.MotionEvent;
@@ -61,6 +63,7 @@
import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.phone.KeyguardClockPositionAlgorithm;
import org.junit.Before;
import org.junit.Ignore;
@@ -251,6 +254,43 @@
}
@Test
+ public void testOnDozeAmountChanged_positionClockAndNotificationsUsesUdfpsLocation() {
+ // GIVEN UDFPS is enrolled and we're on the keyguard
+ final Point udfpsLocationCenter = new Point(0, 100);
+ final float udfpsRadius = 10f;
+ when(mUpdateMonitor.isUdfpsEnrolled()).thenReturn(true);
+ when(mAuthController.getUdfpsLocation()).thenReturn(udfpsLocationCenter);
+ when(mAuthController.getUdfpsRadius()).thenReturn(udfpsRadius);
+ mNotificationPanelViewController.getStatusBarStateListener().onStateChanged(KEYGUARD);
+
+ // WHEN the doze amount changes
+ mNotificationPanelViewController.mClockPositionAlgorithm = mock(
+ KeyguardClockPositionAlgorithm.class);
+ mNotificationPanelViewController.getStatusBarStateListener().onDozeAmountChanged(1f, 1f);
+
+ // THEN the clock positions accounts for the UDFPS location & its worst case burn in
+ final float udfpsTop = udfpsLocationCenter.y - udfpsRadius - mMaxUdfpsBurnInOffsetY;
+ verify(mNotificationPanelViewController.mClockPositionAlgorithm).setup(
+ anyInt(),
+ anyFloat(),
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ /* darkAmount */ eq(1f),
+ anyFloat(),
+ anyBoolean(),
+ anyInt(),
+ anyFloat(),
+ anyInt(),
+ anyBoolean(),
+ /* udfpsTop */ eq(udfpsTop),
+ anyFloat(),
+ anyBoolean()
+ );
+ }
+
+
+ @Test
public void testSetExpandedHeight() {
mNotificationPanelViewController.setExpandedHeight(200);
assertThat((int) mNotificationPanelViewController.getExpandedHeight()).isEqualTo(200);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
index 9fe75ab..20da8a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
@@ -33,9 +33,9 @@
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
+import com.android.app.animation.Interpolators
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.Interpolators
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
index a1168f8..f0abf2f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/PropertyAnimatorTest.java
@@ -32,9 +32,9 @@
import android.view.View;
import android.view.animation.Interpolator;
+import com.android.app.animation.Interpolators;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.notification.stack.AnimationFilter;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ViewState;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 7153e59..f771606 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -801,6 +801,34 @@
}
@Test
+ public void onShadeClosesWithAnimationWillResetSwipeState() {
+ // GIVEN shade is expanded
+ mStackScroller.setIsExpanded(true);
+ clearInvocations(mNotificationSwipeHelper);
+
+ // WHEN closing the shade with the animations
+ mStackScroller.onExpansionStarted();
+ mStackScroller.setIsExpanded(false);
+ mStackScroller.onExpansionStopped();
+
+ // VERIFY swipe is reset
+ verify(mNotificationSwipeHelper).resetSwipeState();
+ }
+
+ @Test
+ public void onShadeClosesWithoutAnimationWillResetSwipeState() {
+ // GIVEN shade is expanded
+ mStackScroller.setIsExpanded(true);
+ clearInvocations(mNotificationSwipeHelper);
+
+ // WHEN closing the shade without the animation
+ mStackScroller.setIsExpanded(false);
+
+ // VERIFY swipe is reset
+ verify(mNotificationSwipeHelper).resetSwipeState();
+ }
+
+ @Test
public void testSplitShade_hasTopOverscroll() {
mTestableResources
.addOverride(R.bool.config_use_split_notification_shade, /* value= */ true);
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 780e0c5..6fda56c 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
@@ -116,7 +116,6 @@
.thenReturn(TEST_AUTO_DISMISS_TIME);
when(mVSProvider.isReorderingAllowed()).thenReturn(true);
mDependency.injectMockDependency(NotificationShadeWindowController.class);
- mDependency.injectMockDependency(ConfigurationController.class);
super.setUp();
mHeadsUpManager = new TestableHeadsUpManagerPhone(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
index 71ac7c4..683136d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
@@ -45,6 +45,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.util.Map;
import java.util.function.Consumer;
@@ -53,16 +55,18 @@
@SmallTest
public class ExtensionControllerImplTest extends SysuiTestCase {
+ @Mock
+ private ConfigurationController mConfigurationController;
+
private PluginManager mPluginManager;
private TunerService mTunerService;
private ExtensionController mExtensionController;
- private ConfigurationController mConfigurationController;
@Before
public void setup() {
+ MockitoAnnotations.initMocks(this);
mPluginManager = mDependency.injectMockDependency(PluginManager.class);
mTunerService = mDependency.injectMockDependency(TunerService.class);
- mConfigurationController = mDependency.injectMockDependency(ConfigurationController.class);
mExtensionController = new ExtensionControllerImpl(
mContext,
mock(LeakDetector.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
new file mode 100644
index 0000000..3fff136
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/RoboPilotTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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/animation/FakeLaunchAnimator.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeLaunchAnimator.kt
index 5b431e7..0983041 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeLaunchAnimator.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeLaunchAnimator.kt
@@ -14,6 +14,8 @@
package com.android.systemui.animation
+import com.android.app.animation.Interpolators
+
/** A [LaunchAnimator] to be used in tests. */
fun fakeLaunchAnimator(): LaunchAnimator {
return LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
diff --git a/services/core/java/com/android/server/SoundTriggerInternal.java b/services/core/java/com/android/server/SoundTriggerInternal.java
index e6c1750..6529465 100644
--- a/services/core/java/com/android/server/SoundTriggerInternal.java
+++ b/services/core/java/com/android/server/SoundTriggerInternal.java
@@ -142,6 +142,12 @@
@ModelParams int modelParam);
/**
+ * Invalidates the sound trigger session and clears any associated resources. Subsequent
+ * calls to this object will throw IllegalStateException.
+ */
+ void detach();
+
+ /**
* Unloads (and stops if running) the given keyphraseId
*/
int unloadKeyphraseModel(int keyphaseId);
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index a021174..ca482dc 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -2396,7 +2396,6 @@
mHbmData.timeWindowMillis = hbmTiming.getTimeWindowSecs_all().longValue() * 1000;
mHbmData.timeMaxMillis = hbmTiming.getTimeMaxSecs_all().longValue() * 1000;
mHbmData.timeMinMillis = hbmTiming.getTimeMinSecs_all().longValue() * 1000;
- mHbmData.thermalStatusLimit = convertThermalStatus(hbm.getThermalStatusLimit_all());
mHbmData.allowInLowPowerMode = hbm.getAllowInLowPowerMode_all();
final RefreshRateRange rr = hbm.getRefreshRate_all();
if (rr != null) {
@@ -2972,9 +2971,6 @@
/** Brightness level at which we transition from normal to high-brightness. */
public float transitionPoint;
- /** Enable HBM only if the thermal status is not higher than this. */
- public @PowerManager.ThermalStatus int thermalStatusLimit;
-
/** Whether HBM is allowed when {@code Settings.Global.LOW_POWER_MODE} is active. */
public boolean allowInLowPowerMode;
@@ -2993,15 +2989,13 @@
HighBrightnessModeData() {}
HighBrightnessModeData(float minimumLux, float transitionPoint, long timeWindowMillis,
- long timeMaxMillis, long timeMinMillis,
- @PowerManager.ThermalStatus int thermalStatusLimit, boolean allowInLowPowerMode,
+ long timeMaxMillis, long timeMinMillis, boolean allowInLowPowerMode,
float minimumHdrPercentOfScreen) {
this.minimumLux = minimumLux;
this.transitionPoint = transitionPoint;
this.timeWindowMillis = timeWindowMillis;
this.timeMaxMillis = timeMaxMillis;
this.timeMinMillis = timeMinMillis;
- this.thermalStatusLimit = thermalStatusLimit;
this.allowInLowPowerMode = allowInLowPowerMode;
this.minimumHdrPercentOfScreen = minimumHdrPercentOfScreen;
}
@@ -3016,7 +3010,6 @@
other.timeMaxMillis = timeMaxMillis;
other.timeMinMillis = timeMinMillis;
other.transitionPoint = transitionPoint;
- other.thermalStatusLimit = thermalStatusLimit;
other.allowInLowPowerMode = allowInLowPowerMode;
other.minimumHdrPercentOfScreen = minimumHdrPercentOfScreen;
}
@@ -3029,7 +3022,6 @@
+ ", timeWindow: " + timeWindowMillis + "ms"
+ ", timeMax: " + timeMaxMillis + "ms"
+ ", timeMin: " + timeMinMillis + "ms"
- + ", thermalStatusLimit: " + thermalStatusLimit
+ ", allowInLowPowerMode: " + allowInLowPowerMode
+ ", minimumHdrPercentOfScreen: " + minimumHdrPercentOfScreen
+ "} ";
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index f1efec0..78c5f0e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -2828,6 +2828,7 @@
pw.println(" mDisplayId=" + mDisplayId);
pw.println(" mLeadDisplayId=" + mLeadDisplayId);
pw.println(" mLightSensor=" + mLightSensor);
+ pw.println(" mDisplayBrightnessFollowers=" + mDisplayBrightnessFollowers);
pw.println();
pw.println("Display Power Controller Locked State:");
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 59e112e..a76f907 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -2222,6 +2222,7 @@
pw.println(" mDisplayId=" + mDisplayId);
pw.println(" mLeadDisplayId=" + mLeadDisplayId);
pw.println(" mLightSensor=" + mLightSensor);
+ pw.println(" mDisplayBrightnessFollowers=" + mDisplayBrightnessFollowers);
pw.println();
pw.println("Display Power Controller Locked State:");
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index ca208ac..11160a5 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -22,13 +22,8 @@
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
-import android.os.IThermalEventListener;
-import android.os.IThermalService;
import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.Temperature;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.MathUtils;
@@ -75,7 +70,6 @@
private final Runnable mHbmChangeCallback;
private final Runnable mRecalcRunnable;
private final Clock mClock;
- private final SkinThermalStatusObserver mSkinThermalStatusObserver;
private final Context mContext;
private final SettingsObserver mSettingsObserver;
private final Injector mInjector;
@@ -100,10 +94,8 @@
private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
private boolean mIsHdrLayerPresent = false;
-
// mMaxDesiredHdrSdrRatio should only be applied when there is a valid backlight->nits mapping
private float mMaxDesiredHdrSdrRatio = DEFAULT_MAX_DESIRED_HDR_SDR_RATIO;
- private boolean mIsThermalStatusWithinLimit = true;
private boolean mIsBlockedByLowPowerMode = false;
private int mWidth;
private int mHeight;
@@ -138,7 +130,6 @@
mBrightnessMax = brightnessMax;
mHbmChangeCallback = hbmChangeCallback;
mHighBrightnessModeMetadata = hbmMetadata;
- mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
mRecalcRunnable = this::recalculateTimeAllowance;
mHdrListener = new HdrListener();
@@ -261,7 +252,6 @@
void stop() {
registerHdrListener(null /*displayToken*/);
- mSkinThermalStatusObserver.stopObserving();
mSettingsObserver.stopObserving();
}
@@ -278,15 +268,10 @@
mDisplayStatsId = displayUniqueId.hashCode();
unregisterHdrListener();
- mSkinThermalStatusObserver.stopObserving();
mSettingsObserver.stopObserving();
if (deviceSupportsHbm()) {
registerHdrListener(displayToken);
recalculateTimeAllowance();
- if (mHbmData.thermalStatusLimit > PowerManager.THERMAL_STATUS_NONE) {
- mIsThermalStatusWithinLimit = true;
- mSkinThermalStatusObserver.startObserving();
- }
if (!mHbmData.allowInLowPowerMode) {
mIsBlockedByLowPowerMode = false;
mSettingsObserver.startObserving();
@@ -327,7 +312,6 @@
pw.println(" mIsTimeAvailable= " + mIsTimeAvailable);
pw.println(" mRunningStartTimeMillis="
+ TimeUtils.formatUptime(mHighBrightnessModeMetadata.getRunningStartTimeMillis()));
- pw.println(" mIsThermalStatusWithinLimit=" + mIsThermalStatusWithinLimit);
pw.println(" mIsBlockedByLowPowerMode=" + mIsBlockedByLowPowerMode);
pw.println(" width*height=" + mWidth + "*" + mHeight);
pw.println(" mEvents=");
@@ -344,8 +328,6 @@
}
lastStartTime = dumpHbmEvent(pw, event);
}
-
- mSkinThermalStatusObserver.dump(pw);
}
private long dumpHbmEvent(PrintWriter pw, HbmEvent event) {
@@ -367,7 +349,7 @@
// See {@link #getHdrBrightnessValue}.
return !mIsHdrLayerPresent
&& (mIsAutoBrightnessEnabled && mIsTimeAvailable && mIsInAllowedAmbientRange
- && mIsThermalStatusWithinLimit && !mIsBlockedByLowPowerMode);
+ && !mIsBlockedByLowPowerMode);
}
private boolean deviceSupportsHbm() {
@@ -469,7 +451,6 @@
+ ", isAutoBrightnessEnabled: " + mIsAutoBrightnessEnabled
+ ", mIsTimeAvailable: " + mIsTimeAvailable
+ ", mIsInAllowedAmbientRange: " + mIsInAllowedAmbientRange
- + ", mIsThermalStatusWithinLimit: " + mIsThermalStatusWithinLimit
+ ", mIsBlockedByLowPowerMode: " + mIsBlockedByLowPowerMode
+ ", mBrightness: " + mBrightness
+ ", mUnthrottledBrightness: " + mUnthrottledBrightness
@@ -499,13 +480,12 @@
}
private void updateHbmStats(int newMode) {
- final float transitionPoint = mHbmData.transitionPoint;
int state = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_OFF;
if (newMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
- && getHdrBrightnessValue() > transitionPoint) {
+ && getHdrBrightnessValue() > mHbmData.transitionPoint) {
state = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_HDR;
} else if (newMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT
- && mBrightness > transitionPoint) {
+ && mBrightness > mHbmData.transitionPoint) {
state = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT;
}
if (state == mHbmStatsState) {
@@ -519,16 +499,6 @@
final boolean newHbmSv =
(state == FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT);
if (oldHbmSv && !newHbmSv) {
- // HighBrightnessModeController (HBMC) currently supports throttling from two sources:
- // 1. Internal, received from HBMC.SkinThermalStatusObserver.notifyThrottling()
- // 2. External, received from HBMC.onBrightnessChanged()
- // TODO(b/216373254): Deprecate internal throttling source
- final boolean internalThermalThrottling = !mIsThermalStatusWithinLimit;
- final boolean externalThermalThrottling =
- mUnthrottledBrightness > transitionPoint && // We would've liked HBM brightness...
- mBrightness <= transitionPoint && // ...but we got NBM, because of...
- mThrottlingReason == BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL; // ...thermals.
-
// If more than one conditions are flipped and turn off HBM sunlight
// visibility, only one condition will be reported to make it simple.
if (!mIsAutoBrightnessEnabled && mIsAutoBrightnessOffByState) {
@@ -541,7 +511,7 @@
reason = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_LUX_DROP;
} else if (!mIsTimeAvailable) {
reason = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_TIME_LIMIT;
- } else if (internalThermalThrottling || externalThermalThrottling) {
+ } else if (isThermalThrottlingActive()) {
reason = FrameworkStatsLog
.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_THERMAL_LIMIT;
} else if (mIsHdrLayerPresent) {
@@ -561,6 +531,14 @@
mHbmStatsState = state;
}
+ @VisibleForTesting
+ boolean isThermalThrottlingActive() {
+ // We would've liked HBM, but we got NBM (normal brightness mode) because of thermals.
+ return mUnthrottledBrightness > mHbmData.transitionPoint
+ && mBrightness <= mHbmData.transitionPoint
+ && mThrottlingReason == BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL;
+ }
+
private String hbmStatsStateToString(int hbmStatsState) {
switch (hbmStatsState) {
case FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_OFF:
@@ -635,82 +613,6 @@
}
}
- private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
- private final Injector mInjector;
- private final Handler mHandler;
-
- private IThermalService mThermalService;
- private boolean mStarted;
-
- SkinThermalStatusObserver(Injector injector, Handler handler) {
- mInjector = injector;
- mHandler = handler;
- }
-
- @Override
- public void notifyThrottling(Temperature temp) {
- if (DEBUG) {
- Slog.d(TAG, "New thermal throttling status "
- + ", current thermal status = " + temp.getStatus()
- + ", threshold = " + mHbmData.thermalStatusLimit);
- }
- mHandler.post(() -> {
- mIsThermalStatusWithinLimit = temp.getStatus() <= mHbmData.thermalStatusLimit;
- // This recalculates HbmMode and runs mHbmChangeCallback if the mode has changed
- updateHbmMode();
- });
- }
-
- void startObserving() {
- if (mStarted) {
- if (DEBUG) {
- Slog.d(TAG, "Thermal status observer already started");
- }
- return;
- }
- mThermalService = mInjector.getThermalService();
- if (mThermalService == null) {
- Slog.w(TAG, "Could not observe thermal status. Service not available");
- return;
- }
- try {
- // We get a callback immediately upon registering so there's no need to query
- // for the current value.
- mThermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN);
- mStarted = true;
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to register thermal status listener", e);
- }
- }
-
- void stopObserving() {
- mIsThermalStatusWithinLimit = true;
- if (!mStarted) {
- if (DEBUG) {
- Slog.d(TAG, "Stop skipped because thermal status observer not started");
- }
- return;
- }
- try {
- mThermalService.unregisterThermalEventListener(this);
- mStarted = false;
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to unregister thermal status listener", e);
- }
- mThermalService = null;
- }
-
- void dump(PrintWriter writer) {
- writer.println(" SkinThermalStatusObserver:");
- writer.println(" mStarted: " + mStarted);
- if (mThermalService != null) {
- writer.println(" ThermalService available");
- } else {
- writer.println(" ThermalService not available");
- }
- }
- }
-
private final class SettingsObserver extends ContentObserver {
private final Uri mLowPowerModeSetting = Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE);
@@ -766,11 +668,6 @@
return SystemClock::uptimeMillis;
}
- public IThermalService getThermalService() {
- return IThermalService.Stub.asInterface(
- ServiceManager.getService(Context.THERMAL_SERVICE));
- }
-
public void reportHbmStateChange(int display, int state, int reason) {
FrameworkStatsLog.write(
FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED, display, state, reason);
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 0b6d1c8..dab00d8 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -181,19 +181,6 @@
*/
private String mThermalBrightnessThrottlingDataId;
- /**
- * Refresh rate range limitation based on the current device layout
- */
- @Nullable
- private SurfaceControl.RefreshRateRange mLayoutLimitedRefreshRate;
-
- /**
- * RefreshRateRange limitation for @Temperature.ThrottlingStatus
- */
- @NonNull
- private SparseArray<SurfaceControl.RefreshRateRange> mThermalRefreshRateThrottling =
- new SparseArray<>();
-
public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) {
mDisplayId = displayId;
mLayerStack = layerStack;
@@ -352,24 +339,24 @@
*/
public void updateLayoutLimitedRefreshRateLocked(
@Nullable SurfaceControl.RefreshRateRange layoutLimitedRefreshRate) {
- if (!Objects.equals(layoutLimitedRefreshRate, mLayoutLimitedRefreshRate)) {
- mLayoutLimitedRefreshRate = layoutLimitedRefreshRate;
- mDirty = true;
+ if (!Objects.equals(layoutLimitedRefreshRate, mBaseDisplayInfo.layoutLimitedRefreshRate)) {
+ mBaseDisplayInfo.layoutLimitedRefreshRate = layoutLimitedRefreshRate;
+ mInfo.set(null);
}
}
/**
- * Updates thermalRefreshRateThrottling
+ * Updates refreshRateThermalThrottling
*
- * @param refreshRanges new thermalRefreshRateThrottling ranges limited by layout or default
+ * @param refreshRanges new refreshRateThermalThrottling ranges limited by layout or default
*/
public void updateThermalRefreshRateThrottling(
@Nullable SparseArray<SurfaceControl.RefreshRateRange> refreshRanges) {
if (refreshRanges == null) {
refreshRanges = new SparseArray<>();
}
- if (!mThermalRefreshRateThrottling.contentEquals(refreshRanges)) {
- mThermalRefreshRateThrottling = refreshRanges;
- mDirty = true;
+ if (!mBaseDisplayInfo.refreshRateThermalThrottling.contentEquals(refreshRanges)) {
+ mBaseDisplayInfo.refreshRateThermalThrottling = refreshRanges;
+ mInfo.set(null);
}
}
@@ -512,9 +499,6 @@
mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT;
}
- mBaseDisplayInfo.layoutLimitedRefreshRate = mLayoutLimitedRefreshRate;
- mBaseDisplayInfo.thermalRefreshRateThrottling = mThermalRefreshRateThrottling;
-
mPrimaryDisplayDeviceInfo = deviceInfo;
mInfo.set(null);
mDirty = false;
@@ -968,8 +952,6 @@
pw.println("mDisplayGroupName=" + mDisplayGroupName);
pw.println("mThermalBrightnessThrottlingDataId=" + mThermalBrightnessThrottlingDataId);
pw.println("mLeadDisplayId=" + mLeadDisplayId);
- pw.println("mLayoutLimitedRefreshRate=" + mLayoutLimitedRefreshRate);
- pw.println("mThermalRefreshRateThrottling=" + mThermalRefreshRateThrottling);
}
@Override
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 06b7698..03b49f0 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -1705,13 +1705,14 @@
}
public void observe() {
- mInjector.registerDisplayListener(this, mHandler);
+ DisplayManager dm = mContext.getSystemService(DisplayManager.class);
+ dm.registerDisplayListener(this, mHandler);
// Populate existing displays
SparseArray<Display.Mode[]> modes = new SparseArray<>();
SparseArray<Display.Mode> defaultModes = new SparseArray<>();
DisplayInfo info = new DisplayInfo();
- Display[] displays = mInjector.getDisplays();
+ Display[] displays = dm.getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
for (Display d : displays) {
final int displayId = d.getDisplayId();
d.getDisplayInfo(info);
@@ -1750,9 +1751,17 @@
updateLayoutLimitedFrameRate(displayId, displayInfo);
}
+ @Nullable
private DisplayInfo getDisplayInfo(int displayId) {
+ Display d = mContext.getSystemService(DisplayManager.class).getDisplay(displayId);
+ if (d == null) {
+ // We can occasionally get a display added or changed event for a display that was
+ // subsequently removed, which means this returns null. Check this case and bail
+ // out early; if it gets re-attached we'll eventually get another call back for it.
+ return null;
+ }
DisplayInfo info = new DisplayInfo();
- mInjector.getDisplayInfo(displayId, info);
+ d.getDisplayInfo(info);
return info;
}
@@ -2423,7 +2432,8 @@
}
private void updateDefaultDisplayState() {
- Display display = mInjector.getDisplay(Display.DEFAULT_DISPLAY);
+ Display display = mContext.getSystemService(DisplayManager.class)
+ .getDisplay(Display.DEFAULT_DISPLAY);
if (display == null) {
return;
}
@@ -2740,7 +2750,8 @@
sensorManager.addProximityActiveListener(BackgroundThread.getExecutor(), this);
synchronized (mSensorObserverLock) {
- for (Display d : mInjector.getDisplays()) {
+ for (Display d : mDisplayManager.getDisplays(
+ DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED)) {
mDozeStateByDisplay.put(d.getDisplayId(), mInjector.isDozeState(d));
}
}
@@ -2751,7 +2762,8 @@
}
private void recalculateVotesLocked() {
- final Display[] displays = mInjector.getDisplays();
+ final Display[] displays = mDisplayManager.getDisplays(
+ DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
for (Display d : displays) {
int displayId = d.getDisplayId();
Vote vote = null;
@@ -2782,7 +2794,7 @@
@Override
public void onDisplayAdded(int displayId) {
- boolean isDozeState = mInjector.isDozeState(mInjector.getDisplay(displayId));
+ boolean isDozeState = mInjector.isDozeState(mDisplayManager.getDisplay(displayId));
synchronized (mSensorObserverLock) {
mDozeStateByDisplay.put(displayId, isDozeState);
recalculateVotesLocked();
@@ -2794,7 +2806,7 @@
boolean wasDozeState = mDozeStateByDisplay.get(displayId);
synchronized (mSensorObserverLock) {
mDozeStateByDisplay.put(displayId,
- mInjector.isDozeState(mInjector.getDisplay(displayId)));
+ mInjector.isDozeState(mDisplayManager.getDisplay(displayId)));
if (wasDozeState != mDozeStateByDisplay.get(displayId)) {
recalculateVotesLocked();
}
@@ -3164,13 +3176,8 @@
@NonNull ContentObserver observer);
void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener,
- Handler handler);
-
- void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener,
Handler handler, long flags);
- Display getDisplay(int displayId);
-
Display[] getDisplays();
boolean getDisplayInfo(int displayId, DisplayInfo displayInfo);
@@ -3215,22 +3222,11 @@
@Override
public void registerDisplayListener(DisplayManager.DisplayListener listener,
- Handler handler) {
- getDisplayManager().registerDisplayListener(listener, handler);
- }
-
- @Override
- public void registerDisplayListener(DisplayManager.DisplayListener listener,
Handler handler, long flags) {
getDisplayManager().registerDisplayListener(listener, handler, flags);
}
@Override
- public Display getDisplay(int displayId) {
- return getDisplayManager().getDisplay(displayId);
- }
-
- @Override
public Display[] getDisplays() {
return getDisplayManager().getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
}
@@ -3238,13 +3234,10 @@
@Override
public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
Display display = getDisplayManager().getDisplay(displayId);
- if (display == null) {
- // We can occasionally get a display added or changed event for a display that was
- // subsequently removed, which means this returns null. Check this case and bail
- // out early; if it gets re-attached we'll eventually get another call back for it.
- return false;
+ if (display != null) {
+ return display.getDisplayInfo(displayInfo);
}
- return display.getDisplayInfo(displayInfo);
+ return false;
}
@Override
diff --git a/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
index 8a3b329..c04735d 100644
--- a/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
+++ b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
@@ -138,7 +138,7 @@
for (Display d : displays) {
final int displayId = d.getDisplayId();
d.getDisplayInfo(info);
- localMap.put(displayId, info.thermalRefreshRateThrottling);
+ localMap.put(displayId, info.refreshRateThermalThrottling);
}
synchronized (mThermalObserverLock) {
for (int i = 0; i < size; i++) {
@@ -154,7 +154,7 @@
DisplayInfo displayInfo = new DisplayInfo();
mInjector.getDisplayInfo(displayId, displayInfo);
SparseArray<SurfaceControl.RefreshRateRange> throttlingMap =
- displayInfo.thermalRefreshRateThrottling;
+ displayInfo.refreshRateThermalThrottling;
synchronized (mThermalObserverLock) {
mThermalThrottlingByDisplay.put(displayId, throttlingMap);
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index de10b1b..6d70d21 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -345,6 +345,7 @@
if (!mCurrentDream.mIsPreviewMode && !mSentStartBroadcast) {
mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL,
null /* receiverPermission */, mDreamingStartedStoppedOptions);
+ mListener.onDreamStarted(mCurrentDream.mToken);
mSentStartBroadcast = true;
}
}
@@ -353,6 +354,7 @@
* Callback interface to be implemented by the {@link DreamManagerService}.
*/
public interface Listener {
+ void onDreamStarted(Binder token);
void onDreamStopped(Binder token);
}
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 0e26d46..d2dcc50 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -84,6 +84,7 @@
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Consumer;
/**
* Service api for managing dreams.
@@ -341,10 +342,24 @@
}
private void reportKeepDreamingWhenUnpluggingChanged(boolean keepDreaming) {
+ notifyDreamStateListeners(
+ listener -> listener.onKeepDreamingWhenUnpluggingChanged(keepDreaming));
+ }
+
+ private void reportDreamingStarted() {
+ notifyDreamStateListeners(listener -> listener.onDreamingStarted());
+ }
+
+ private void reportDreamingStopped() {
+ notifyDreamStateListeners(listener -> listener.onDreamingStopped());
+ }
+
+ private void notifyDreamStateListeners(
+ Consumer<DreamManagerInternal.DreamManagerStateListener> notifier) {
mHandler.post(() -> {
for (DreamManagerInternal.DreamManagerStateListener listener
: mDreamManagerStateListeners) {
- listener.onKeepDreamingWhenUnpluggingChanged(keepDreaming);
+ notifier.accept(listener);
}
});
}
@@ -767,12 +782,23 @@
private final DreamController.Listener mControllerListener = new DreamController.Listener() {
@Override
+ public void onDreamStarted(Binder token) {
+ // Note that this event is distinct from DreamManagerService#startDreamLocked as it
+ // tracks the DreamService attach point from DreamController, closest to the broadcast
+ // of ACTION_DREAMING_STARTED.
+
+ reportDreamingStarted();
+ }
+
+ @Override
public void onDreamStopped(Binder token) {
synchronized (mLock) {
if (mCurrentDream != null && mCurrentDream.token == token) {
cleanupDreamLocked();
}
}
+
+ reportDreamingStopped();
}
};
diff --git a/services/core/java/com/android/server/input/KeyboardBacklightController.java b/services/core/java/com/android/server/input/KeyboardBacklightController.java
index 048308e..48c346a 100644
--- a/services/core/java/com/android/server/input/KeyboardBacklightController.java
+++ b/services/core/java/com/android/server/input/KeyboardBacklightController.java
@@ -199,8 +199,11 @@
}
if (brightness.isPresent()) {
int brightnessValue = Math.max(0, Math.min(MAX_BRIGHTNESS, brightness.getAsInt()));
- int brightnessLevel = Arrays.binarySearch(BRIGHTNESS_VALUE_FOR_LEVEL, brightnessValue);
- updateBacklightState(inputDevice.getId(), keyboardBacklight, brightnessLevel,
+ int index = Arrays.binarySearch(BRIGHTNESS_VALUE_FOR_LEVEL, brightnessValue);
+ if (index < 0) {
+ index = Math.min(NUM_BRIGHTNESS_CHANGE_STEPS, -(index + 1));
+ }
+ updateBacklightState(inputDevice.getId(), keyboardBacklight, index,
false /* isTriggeredByKeyPress */);
if (DEBUG) {
Slog.d(TAG, "Restoring brightness level " + brightness.getAsInt());
diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
index 72c7dad..d8716b3 100644
--- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java
+++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
@@ -16,6 +16,8 @@
package com.android.server.input;
+import android.annotation.AnyThread;
+import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -99,6 +101,7 @@
private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2;
private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
+ private static final int MSG_CURRENT_IME_INFO_CHANGED = 5;
private final Context mContext;
private final NativeInputManagerService mNative;
@@ -108,16 +111,17 @@
private final Handler mHandler;
// Connected keyboards with associated keyboard layouts (either auto-detected or manually
- // selected layout). If the mapped value is null/empty, it means that no layout has been
- // configured for the keyboard and user might need to manually configure it from the Settings.
- private final SparseArray<Set<String>> mConfiguredKeyboards = new SparseArray<>();
+ // selected layout).
+ private final SparseArray<KeyboardConfiguration> mConfiguredKeyboards = new SparseArray<>();
private Toast mSwitchedKeyboardLayoutToast;
// This cache stores "best-matched" layouts so that we don't need to run the matching
// algorithm repeatedly.
@GuardedBy("mKeyboardLayoutCache")
private final Map<String, String> mKeyboardLayoutCache = new ArrayMap<>();
+ private final Object mImeInfoLock = new Object();
@Nullable
+ @GuardedBy("mImeInfoLock")
private ImeInfo mCurrentImeInfo;
KeyboardLayoutManager(Context context, NativeInputManagerService nativeService,
@@ -155,26 +159,32 @@
}
@Override
+ @MainThread
public void onInputDeviceAdded(int deviceId) {
onInputDeviceChanged(deviceId);
- if (useNewSettingsUi()) {
- // Force native callback to set up keyboard layout overlay for newly added keyboards
- reloadKeyboardLayouts();
- }
}
@Override
+ @MainThread
public void onInputDeviceRemoved(int deviceId) {
mConfiguredKeyboards.remove(deviceId);
maybeUpdateNotification();
}
@Override
+ @MainThread
public void onInputDeviceChanged(int deviceId) {
final InputDevice inputDevice = getInputDevice(deviceId);
if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
return;
}
+ KeyboardConfiguration config = mConfiguredKeyboards.get(deviceId);
+ if (config == null) {
+ config = new KeyboardConfiguration();
+ mConfiguredKeyboards.put(deviceId, config);
+ }
+
+ boolean needToShowNotification = false;
if (!useNewSettingsUi()) {
synchronized (mDataStore) {
String layout = getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
@@ -182,54 +192,66 @@
layout = getDefaultKeyboardLayout(inputDevice);
if (layout != null) {
setCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier(), layout);
- } else {
- mConfiguredKeyboards.put(inputDevice.getId(), new HashSet<>());
}
}
+ config.setCurrentLayout(layout);
+ if (layout == null) {
+ // In old settings show notification always until user manually selects a
+ // layout in the settings.
+ needToShowNotification = true;
+ }
}
} else {
final InputDeviceIdentifier identifier = inputDevice.getIdentifier();
final String key = getLayoutDescriptor(identifier);
Set<String> selectedLayouts = new HashSet<>();
- boolean needToShowMissingLayoutNotification = false;
for (ImeInfo imeInfo : getImeInfoListForLayoutMapping()) {
// Check if the layout has been previously configured
String layout = getKeyboardLayoutForInputDeviceInternal(identifier,
new ImeInfo(imeInfo.mUserId, imeInfo.mImeSubtypeHandle,
imeInfo.mImeSubtype));
if (layout == null) {
- needToShowMissingLayoutNotification = true;
- continue;
+ // If even one layout not configured properly, we need to ask user to configure
+ // the keyboard properly from the Settings.
+ selectedLayouts.clear();
+ break;
}
selectedLayouts.add(layout);
}
- if (needToShowMissingLayoutNotification) {
- // If even one layout not configured properly we will show configuration
- // notification allowing user to set the keyboard layout.
- selectedLayouts.clear();
- }
-
if (DEBUG) {
Slog.d(TAG,
"Layouts selected for input device: " + identifier + " -> selectedLayouts: "
+ selectedLayouts);
}
- mConfiguredKeyboards.set(inputDevice.getId(), selectedLayouts);
+
+ config.setConfiguredLayouts(selectedLayouts);
+
+ // Update current layout: If there is a change then need to reload.
+ synchronized (mImeInfoLock) {
+ String layout = getKeyboardLayoutForInputDeviceInternal(
+ inputDevice.getIdentifier(), mCurrentImeInfo);
+ if (!Objects.equals(layout, config.getCurrentLayout())) {
+ config.setCurrentLayout(layout);
+ mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
+ }
+ }
synchronized (mDataStore) {
try {
- if (!mDataStore.setSelectedKeyboardLayouts(key, selectedLayouts)) {
- // No need to show the notification only if layout selection didn't change
+ if (mDataStore.setSelectedKeyboardLayouts(key, selectedLayouts)) {
+ // Need to show the notification only if layout selection changed
// from the previous configuration
- return;
+ needToShowNotification = true;
}
} finally {
mDataStore.saveIfNeeded();
}
}
}
- maybeUpdateNotification();
+ if (needToShowNotification) {
+ maybeUpdateNotification();
+ }
}
private String getDefaultKeyboardLayout(final InputDevice inputDevice) {
@@ -323,12 +345,14 @@
reloadKeyboardLayouts();
}
+ @AnyThread
public KeyboardLayout[] getKeyboardLayouts() {
final ArrayList<KeyboardLayout> list = new ArrayList<>();
visitAllKeyboardLayouts((resources, keyboardLayoutResId, layout) -> list.add(layout));
return list.toArray(new KeyboardLayout[0]);
}
+ @AnyThread
public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
final InputDeviceIdentifier identifier) {
if (useNewSettingsUi()) {
@@ -375,6 +399,7 @@
KeyboardLayout[]::new);
}
+ @AnyThread
@Nullable
public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
Objects.requireNonNull(keyboardLayoutDescriptor,
@@ -543,6 +568,7 @@
return key.toString();
}
+ @AnyThread
@Nullable
public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
if (useNewSettingsUi()) {
@@ -566,6 +592,7 @@
}
}
+ @AnyThread
public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (useNewSettingsUi()) {
@@ -592,6 +619,7 @@
}
}
+ @AnyThread
public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
if (useNewSettingsUi()) {
Slog.e(TAG, "getEnabledKeyboardLayoutsForInputDevice API not supported");
@@ -608,6 +636,7 @@
}
}
+ @AnyThread
public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (useNewSettingsUi()) {
@@ -635,6 +664,7 @@
}
}
+ @AnyThread
public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (useNewSettingsUi()) {
@@ -667,6 +697,7 @@
}
}
+ @AnyThread
public void switchKeyboardLayout(int deviceId, int direction) {
if (useNewSettingsUi()) {
Slog.e(TAG, "switchKeyboardLayout API not supported");
@@ -675,7 +706,7 @@
mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
}
- // Must be called on handler.
+ @MainThread
private void handleSwitchKeyboardLayout(int deviceId, int direction) {
final InputDevice device = getInputDevice(deviceId);
if (device != null) {
@@ -713,23 +744,14 @@
}
@Nullable
+ @AnyThread
public String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
String keyboardLayoutDescriptor;
if (useNewSettingsUi()) {
- InputDevice inputDevice = getInputDevice(identifier);
- if (inputDevice == null) {
- // getKeyboardLayoutOverlay() called before input device added completely. Need
- // to wait till the device is added which will call reloadKeyboardLayouts()
- return null;
+ synchronized (mImeInfoLock) {
+ keyboardLayoutDescriptor = getKeyboardLayoutForInputDeviceInternal(identifier,
+ mCurrentImeInfo);
}
- if (mCurrentImeInfo == null) {
- // Haven't received onInputMethodSubtypeChanged() callback from IMMS. Will reload
- // keyboard layouts once we receive the callback.
- return null;
- }
-
- keyboardLayoutDescriptor = getKeyboardLayoutForInputDeviceInternal(identifier,
- mCurrentImeInfo);
} else {
keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
}
@@ -755,6 +777,7 @@
return result;
}
+ @AnyThread
@Nullable
public String getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
@UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
@@ -773,6 +796,7 @@
return layout;
}
+ @AnyThread
public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
@UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
@Nullable InputMethodSubtype imeSubtype,
@@ -783,8 +807,8 @@
}
Objects.requireNonNull(keyboardLayoutDescriptor,
"keyboardLayoutDescriptor must not be null");
- String key = createLayoutKey(identifier, userId,
- InputMethodSubtypeHandle.of(imeInfo, imeSubtype));
+ String key = createLayoutKey(identifier,
+ new ImeInfo(userId, InputMethodSubtypeHandle.of(imeInfo, imeSubtype), imeSubtype));
synchronized (mDataStore) {
try {
// Key for storing into data store = <device descriptor>,<userId>,<subtypeHandle>
@@ -803,6 +827,7 @@
}
}
+ @AnyThread
public KeyboardLayout[] getKeyboardLayoutListForInputDevice(InputDeviceIdentifier identifier,
@UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
@Nullable InputMethodSubtype imeSubtype) {
@@ -815,8 +840,8 @@
}
private KeyboardLayout[] getKeyboardLayoutListForInputDeviceInternal(
- InputDeviceIdentifier identifier, ImeInfo imeInfo) {
- String key = createLayoutKey(identifier, imeInfo.mUserId, imeInfo.mImeSubtypeHandle);
+ InputDeviceIdentifier identifier, @Nullable ImeInfo imeInfo) {
+ String key = createLayoutKey(identifier, imeInfo);
// Fetch user selected layout and always include it in layout list.
String userSelectedLayout;
@@ -826,7 +851,7 @@
final ArrayList<KeyboardLayout> potentialLayouts = new ArrayList<>();
String imeLanguageTag;
- if (imeInfo.mImeSubtype == null) {
+ if (imeInfo == null || imeInfo.mImeSubtype == null) {
imeLanguageTag = "";
} else {
ULocale imeLocale = imeInfo.mImeSubtype.getPhysicalKeyboardHintLanguageTag();
@@ -866,6 +891,7 @@
return potentialLayouts.toArray(new KeyboardLayout[0]);
}
+ @AnyThread
public void onInputMethodSubtypeChanged(@UserIdInt int userId,
@Nullable InputMethodSubtypeHandle subtypeHandle,
@Nullable InputMethodSubtype subtype) {
@@ -879,25 +905,45 @@
}
return;
}
- if (mCurrentImeInfo == null || !subtypeHandle.equals(mCurrentImeInfo.mImeSubtypeHandle)
- || mCurrentImeInfo.mUserId != userId) {
- mCurrentImeInfo = new ImeInfo(userId, subtypeHandle, subtype);
- mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
- if (DEBUG) {
- Slog.d(TAG, "InputMethodSubtype changed: userId=" + userId
- + " subtypeHandle=" + subtypeHandle);
+ synchronized (mImeInfoLock) {
+ if (mCurrentImeInfo == null || !subtypeHandle.equals(mCurrentImeInfo.mImeSubtypeHandle)
+ || mCurrentImeInfo.mUserId != userId) {
+ mCurrentImeInfo = new ImeInfo(userId, subtypeHandle, subtype);
+ mHandler.sendEmptyMessage(MSG_CURRENT_IME_INFO_CHANGED);
+ if (DEBUG) {
+ Slog.d(TAG, "InputMethodSubtype changed: userId=" + userId
+ + " subtypeHandle=" + subtypeHandle);
+ }
+ }
+ }
+ }
+
+ @MainThread
+ private void onCurrentImeInfoChanged() {
+ synchronized (mImeInfoLock) {
+ for (int i = 0; i < mConfiguredKeyboards.size(); i++) {
+ InputDevice inputDevice = Objects.requireNonNull(
+ getInputDevice(mConfiguredKeyboards.keyAt(i)));
+ String layout = getKeyboardLayoutForInputDeviceInternal(inputDevice.getIdentifier(),
+ mCurrentImeInfo);
+ KeyboardConfiguration config = mConfiguredKeyboards.valueAt(i);
+ if (!Objects.equals(layout, config.getCurrentLayout())) {
+ config.setCurrentLayout(layout);
+ mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
+ return;
+ }
}
}
}
@Nullable
private String getKeyboardLayoutForInputDeviceInternal(InputDeviceIdentifier identifier,
- ImeInfo imeInfo) {
+ @Nullable ImeInfo imeInfo) {
InputDevice inputDevice = getInputDevice(identifier);
if (inputDevice == null || inputDevice.isVirtual() || !inputDevice.isFullKeyboard()) {
return null;
}
- String key = createLayoutKey(identifier, imeInfo.mUserId, imeInfo.mImeSubtypeHandle);
+ String key = createLayoutKey(identifier, imeInfo);
String layout;
synchronized (mDataStore) {
layout = mDataStore.getKeyboardLayout(getLayoutDescriptor(identifier), key);
@@ -923,11 +969,7 @@
@Nullable
private static String getDefaultKeyboardLayoutBasedOnImeInfo(InputDevice inputDevice,
- ImeInfo imeInfo, KeyboardLayout[] layoutList) {
- if (imeInfo.mImeSubtypeHandle == null) {
- return null;
- }
-
+ @Nullable ImeInfo imeInfo, KeyboardLayout[] layoutList) {
Arrays.sort(layoutList);
// Check <VendorID, ProductID> matching for explicitly declared custom KCM files.
@@ -961,12 +1003,12 @@
}
}
- InputMethodSubtype subtype = imeInfo.mImeSubtype;
- // Can't auto select layout based on IME if subtype or language tag is null
- if (subtype == null) {
+ if (imeInfo == null || imeInfo.mImeSubtypeHandle == null || imeInfo.mImeSubtype == null) {
+ // Can't auto select layout based on IME info is null
return null;
}
+ InputMethodSubtype subtype = imeInfo.mImeSubtype;
// Check layout type, language tag information from IME for matching
ULocale pkLocale = subtype.getPhysicalKeyboardHintLanguageTag();
String pkLanguageTag =
@@ -1043,6 +1085,7 @@
mNative.reloadKeyboardLayouts();
}
+ @MainThread
private void maybeUpdateNotification() {
if (mConfiguredKeyboards.size() == 0) {
hideKeyboardLayoutNotification();
@@ -1051,7 +1094,7 @@
for (int i = 0; i < mConfiguredKeyboards.size(); i++) {
// If we have a keyboard with no selected layouts, we should always show missing
// layout notification even if there are other keyboards that are configured properly.
- if (mConfiguredKeyboards.valueAt(i).isEmpty()) {
+ if (!mConfiguredKeyboards.valueAt(i).hasConfiguredLayouts()) {
showMissingKeyboardLayoutNotification();
return;
}
@@ -1059,7 +1102,7 @@
showConfiguredKeyboardLayoutNotification();
}
- // Must be called on handler.
+ @MainThread
private void showMissingKeyboardLayoutNotification() {
final Resources r = mContext.getResources();
final String missingKeyboardLayoutNotificationContent = r.getString(
@@ -1084,6 +1127,7 @@
}
}
+ @MainThread
private void showKeyboardLayoutNotification(@NonNull String intentTitle,
@NonNull String intentContent, @Nullable InputDevice targetDevice) {
final NotificationManager notificationManager = mContext.getSystemService(
@@ -1119,7 +1163,7 @@
notification, UserHandle.ALL);
}
- // Must be called on handler.
+ @MainThread
private void hideKeyboardLayoutNotification() {
NotificationManager notificationManager = mContext.getSystemService(
NotificationManager.class);
@@ -1132,6 +1176,7 @@
UserHandle.ALL);
}
+ @MainThread
private void showConfiguredKeyboardLayoutNotification() {
final Resources r = mContext.getResources();
@@ -1144,8 +1189,8 @@
}
final InputDevice inputDevice = getInputDevice(mConfiguredKeyboards.keyAt(0));
- final Set<String> selectedLayouts = mConfiguredKeyboards.valueAt(0);
- if (inputDevice == null || selectedLayouts == null || selectedLayouts.isEmpty()) {
+ final KeyboardConfiguration config = mConfiguredKeyboards.valueAt(0);
+ if (inputDevice == null || !config.hasConfiguredLayouts()) {
return;
}
@@ -1153,10 +1198,11 @@
r.getString(
R.string.keyboard_layout_notification_selected_title,
inputDevice.getName()),
- createConfiguredNotificationText(mContext, selectedLayouts),
+ createConfiguredNotificationText(mContext, config.getConfiguredLayouts()),
inputDevice);
}
+ @MainThread
private String createConfiguredNotificationText(@NonNull Context context,
@NonNull Set<String> selectedLayouts) {
final Resources r = context.getResources();
@@ -1199,6 +1245,9 @@
case MSG_UPDATE_KEYBOARD_LAYOUTS:
updateKeyboardLayouts();
return true;
+ case MSG_CURRENT_IME_INFO_CHANGED:
+ onCurrentImeInfoChanged();
+ return true;
default:
return false;
}
@@ -1252,17 +1301,19 @@
return imeInfoList;
}
- private String createLayoutKey(InputDeviceIdentifier identifier, int userId,
- @NonNull InputMethodSubtypeHandle subtypeHandle) {
- Objects.requireNonNull(subtypeHandle, "subtypeHandle must not be null");
- return "layoutDescriptor:" + getLayoutDescriptor(identifier) + ",userId:" + userId
- + ",subtypeHandle:" + subtypeHandle.toStringHandle();
+ private String createLayoutKey(InputDeviceIdentifier identifier, @Nullable ImeInfo imeInfo) {
+ if (imeInfo == null) {
+ return getLayoutDescriptor(identifier);
+ }
+ Objects.requireNonNull(imeInfo.mImeSubtypeHandle, "subtypeHandle must not be null");
+ return "layoutDescriptor:" + getLayoutDescriptor(identifier) + ",userId:" + imeInfo.mUserId
+ + ",subtypeHandle:" + imeInfo.mImeSubtypeHandle.toStringHandle();
}
private static boolean isLayoutCompatibleWithLanguageTag(KeyboardLayout layout,
@NonNull String languageTag) {
LocaleList layoutLocales = layout.getLocales();
- if (layoutLocales.isEmpty()) {
+ if (layoutLocales.isEmpty() || TextUtils.isEmpty(languageTag)) {
// KCM file doesn't have an associated language tag. This can be from
// a 3rd party app so need to include it as a potential layout.
return true;
@@ -1350,6 +1401,39 @@
}
}
+ private static class KeyboardConfiguration {
+ // If null or empty, it means no layout is configured for the device. And user needs to
+ // manually set up the device.
+ @Nullable
+ private Set<String> mConfiguredLayouts;
+
+ // If null, it means no layout is selected for the device.
+ @Nullable
+ private String mCurrentLayout;
+
+ private boolean hasConfiguredLayouts() {
+ return mConfiguredLayouts != null && !mConfiguredLayouts.isEmpty();
+ }
+
+ @Nullable
+ private Set<String> getConfiguredLayouts() {
+ return mConfiguredLayouts;
+ }
+
+ private void setConfiguredLayouts(Set<String> configuredLayouts) {
+ mConfiguredLayouts = configuredLayouts;
+ }
+
+ @Nullable
+ private String getCurrentLayout() {
+ return mCurrentLayout;
+ }
+
+ private void setCurrentLayout(String currentLayout) {
+ mCurrentLayout = currentLayout;
+ }
+ }
+
private interface KeyboardLayoutVisitor {
void visitKeyboardLayout(Resources resources,
int keyboardLayoutResId, KeyboardLayout layout);
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 2d3b97b..8a9cfba 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -764,7 +764,7 @@
userRecord.mHandler, routerRecord));
Slog.i(TAG, TextUtils.formatSimple(
- "registerRouter2 | package: %s, uid: %d, pid: %d, router: %d",
+ "registerRouter2 | package: %s, uid: %d, pid: %d, router id: %d",
packageName, uid, pid, routerRecord.mRouterId));
}
@@ -776,10 +776,11 @@
return;
}
- Slog.i(TAG, TextUtils.formatSimple(
- "unregisterRouter2 | package: %s, router: %d",
- routerRecord.mPackageName,
- routerRecord.mRouterId));
+ Slog.i(
+ TAG,
+ TextUtils.formatSimple(
+ "unregisterRouter2 | package: %s, router id: %d",
+ routerRecord.mPackageName, routerRecord.mRouterId));
UserRecord userRecord = routerRecord.mUserRecord;
userRecord.mRouterRecords.remove(routerRecord);
@@ -806,9 +807,14 @@
return;
}
- Slog.i(TAG, TextUtils.formatSimple(
- "setDiscoveryRequestWithRouter2 | router: %d, discovery request: %s",
- routerRecord.mRouterId, discoveryRequest.toString()));
+ Slog.i(
+ TAG,
+ TextUtils.formatSimple(
+ "setDiscoveryRequestWithRouter2 | router: %s(id: %d), discovery request:"
+ + " %s",
+ routerRecord.mPackageName,
+ routerRecord.mRouterId,
+ discoveryRequest.toString()));
routerRecord.mDiscoveryPreference = discoveryRequest;
routerRecord.mUserRecord.mHandler.sendMessage(
@@ -832,10 +838,12 @@
.collect(Collectors.joining(","))
: null;
- Slog.i(TAG, TextUtils.formatSimple(
- "setRouteListingPreference | router: %d, route listing preference: [%s]",
- routerRecord.mRouterId,
- routeListingAsString));
+ Slog.i(
+ TAG,
+ TextUtils.formatSimple(
+ "setRouteListingPreference | router: %s(id: %d), route listing preference:"
+ + " [%s]",
+ routerRecord.mPackageName, routerRecord.mRouterId, routeListingAsString));
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(
@@ -851,9 +859,11 @@
RouterRecord routerRecord = mAllRouterRecords.get(binder);
if (routerRecord != null) {
- Slog.i(TAG, TextUtils.formatSimple(
- "setRouteVolumeWithRouter2 | router: %d, volume: %d",
- routerRecord.mRouterId, volume));
+ Slog.i(
+ TAG,
+ TextUtils.formatSimple(
+ "setRouteVolumeWithRouter2 | router: %s(id: %d), volume: %d",
+ routerRecord.mPackageName, routerRecord.mRouterId, volume));
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::setRouteVolumeOnHandler,
@@ -935,9 +945,11 @@
return;
}
- Slog.i(TAG, TextUtils.formatSimple(
- "selectRouteWithRouter2 | router: %d, route: %s",
- routerRecord.mRouterId, route.getId()));
+ Slog.i(
+ TAG,
+ TextUtils.formatSimple(
+ "selectRouteWithRouter2 | router: %s(id: %d), route: %s",
+ routerRecord.mPackageName, routerRecord.mRouterId, route.getId()));
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::selectRouteOnHandler,
@@ -954,9 +966,11 @@
return;
}
- Slog.i(TAG, TextUtils.formatSimple(
- "deselectRouteWithRouter2 | router: %d, route: %s",
- routerRecord.mRouterId, route.getId()));
+ Slog.i(
+ TAG,
+ TextUtils.formatSimple(
+ "deselectRouteWithRouter2 | router: %s(id: %d), route: %s",
+ routerRecord.mPackageName, routerRecord.mRouterId, route.getId()));
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::deselectRouteOnHandler,
@@ -973,9 +987,11 @@
return;
}
- Slog.i(TAG, TextUtils.formatSimple(
- "transferToRouteWithRouter2 | router: %d, route: %s",
- routerRecord.mRouterId, route.getId()));
+ Slog.i(
+ TAG,
+ TextUtils.formatSimple(
+ "transferToRouteWithRouter2 | router: %s(id: %d), route: %s",
+ routerRecord.mPackageName, routerRecord.mRouterId, route.getId()));
String defaultRouteId =
routerRecord.mUserRecord.mHandler.mSystemProvider.getDefaultRoute().getId();
@@ -1002,9 +1018,14 @@
return;
}
- Slog.i(TAG, TextUtils.formatSimple(
- "setSessionVolumeWithRouter2 | router: %d, session: %s, volume: %d",
- routerRecord.mRouterId, uniqueSessionId, volume));
+ Slog.i(
+ TAG,
+ TextUtils.formatSimple(
+ "setSessionVolumeWithRouter2 | router: %s(id: %d), session: %s, volume: %d",
+ routerRecord.mPackageName,
+ routerRecord.mRouterId,
+ uniqueSessionId,
+ volume));
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::setSessionVolumeOnHandler,
@@ -1021,9 +1042,11 @@
return;
}
- Slog.i(TAG, TextUtils.formatSimple(
- "releaseSessionWithRouter2 | router: %d, session: %s",
- routerRecord.mRouterId, uniqueSessionId));
+ Slog.i(
+ TAG,
+ TextUtils.formatSimple(
+ "releaseSessionWithRouter2 | router: %s(id: %d), session: %s",
+ routerRecord.mPackageName, routerRecord.mRouterId, uniqueSessionId));
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::releaseSessionOnHandler,
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 94d5aab..7a51126 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -19,9 +19,19 @@
import static android.Manifest.permission.MANAGE_MEDIA_PROJECTION;
import static android.app.ActivityManagerInternal.MEDIA_PROJECTION_TOKEN_EVENT_CREATED;
import static android.app.ActivityManagerInternal.MEDIA_PROJECTION_TOKEN_EVENT_DESTROYED;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.media.projection.IMediaProjectionManager.EXTRA_PACKAGE_REUSING_GRANTED_CONSENT;
+import static android.media.projection.IMediaProjectionManager.EXTRA_USER_REVIEW_GRANTED_CONSENT;
+import static android.media.projection.ReviewGrantedConsentResult.RECORD_CANCEL;
+import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_DISPLAY;
+import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_TASK;
+import static android.media.projection.ReviewGrantedConsentResult.UNKNOWN;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import android.Manifest;
+import android.annotation.EnforcePermission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
@@ -30,7 +40,9 @@
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -45,11 +57,13 @@
import android.media.projection.IMediaProjectionWatcherCallback;
import android.media.projection.MediaProjectionInfo;
import android.media.projection.MediaProjectionManager;
+import android.media.projection.ReviewGrantedConsentResult;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.os.PermissionEnforcer;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -57,6 +71,7 @@
import android.util.Slog;
import android.view.ContentRecordingSession;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
@@ -69,6 +84,7 @@
import java.io.PrintWriter;
import java.time.Duration;
import java.util.Map;
+import java.util.Objects;
/**
* Manages MediaProjection sessions.
@@ -161,10 +177,9 @@
}
}
-
@Override
public void onStart() {
- publishBinderService(Context.MEDIA_PROJECTION_SERVICE, new BinderService(),
+ publishBinderService(Context.MEDIA_PROJECTION_SERVICE, new BinderService(mContext),
false /*allowIsolated*/);
mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mMediaRouterCallback,
MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
@@ -305,6 +320,10 @@
}
return false;
}
+ if (mProjectionGrant != null) {
+ // Cache the session details.
+ mProjectionGrant.mSession = incomingSession;
+ }
return true;
}
}
@@ -323,9 +342,8 @@
}
}
-
/**
- * Reshows the permisison dialog for the user to review consent they've already granted in
+ * Re-shows the permission dialog for the user to review consent they've already granted in
* the given projection instance.
*
* <p>Preconditions:
@@ -337,18 +355,111 @@
* <p>Returns immediately but waits to start recording until user has reviewed their consent.
*/
@VisibleForTesting
- void requestConsentForInvalidProjection(IMediaProjection projection) {
+ void requestConsentForInvalidProjection() {
synchronized (mLock) {
Slog.v(TAG, "Reusing token: Reshow dialog for due to invalid projection.");
- // TODO(b/274790702): Trigger the permission dialog again in SysUI.
+ // Trigger the permission dialog again in SysUI
+ // Do not handle the result; SysUI will update us when the user has consented.
+ mContext.startActivityAsUser(buildReviewGrantedConsentIntent(),
+ UserHandle.getUserHandleForUid(mProjectionGrant.uid));
+ }
+ }
+
+ /**
+ * Returns an intent to re-show the consent dialog in SysUI. Should only be used for the
+ * scenario where the host app has re-used the consent token.
+ *
+ * <p>Consent dialog result handled in
+ * {@link BinderService#setUserReviewGrantedConsentResult(int)}.
+ */
+ private Intent buildReviewGrantedConsentIntent() {
+ final String permissionDialogString = mContext.getResources().getString(
+ R.string.config_mediaProjectionPermissionDialogComponent);
+ final ComponentName mediaProjectionPermissionDialogComponent =
+ ComponentName.unflattenFromString(permissionDialogString);
+ // We can use mProjectionGrant since we already checked that it matches the given token.
+ return new Intent().setComponent(mediaProjectionPermissionDialogComponent)
+ .putExtra(EXTRA_USER_REVIEW_GRANTED_CONSENT, true)
+ .putExtra(EXTRA_PACKAGE_REUSING_GRANTED_CONSENT, mProjectionGrant.packageName)
+ .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ }
+
+ /**
+ * Handles result of dialog shown from {@link BinderService#buildReviewGrantedConsentIntent()}.
+ *
+ * <p>Tears down session if user did not consent, or starts mirroring if user did consent.
+ */
+ @VisibleForTesting
+ void setUserReviewGrantedConsentResult(@ReviewGrantedConsentResult int consentResult,
+ @Nullable IMediaProjection projection) {
+ synchronized (mLock) {
+ final boolean consentGranted =
+ consentResult == RECORD_CONTENT_DISPLAY || consentResult == RECORD_CONTENT_TASK;
+ if (consentGranted && projection == null || !isCurrentProjection(
+ projection.asBinder())) {
+ Slog.v(TAG, "Reusing token: Ignore consent result of " + consentResult + " for a "
+ + "token that isn't current");
+ return;
+ }
+ if (mProjectionGrant == null) {
+ Slog.w(TAG, "Reusing token: Can't review consent with no ongoing projection.");
+ return;
+ }
+ if (mProjectionGrant.mSession == null
+ || !mProjectionGrant.mSession.isWaitingToRecord()) {
+ Slog.w(TAG, "Reusing token: Ignore consent result " + consentResult
+ + " if not waiting for the result.");
+ return;
+ }
+ Slog.v(TAG, "Reusing token: Handling user consent result " + consentResult);
+ switch (consentResult) {
+ case UNKNOWN:
+ case RECORD_CANCEL:
+ // Pass in null to stop mirroring.
+ setReviewedConsentSessionLocked(/* session= */ null);
+ // The grant may now be null if setting the session failed.
+ if (mProjectionGrant != null) {
+ // Always stop the projection.
+ mProjectionGrant.stop();
+ }
+ break;
+ case RECORD_CONTENT_DISPLAY:
+ // TODO(270118861) The app may have specified a particular id in the virtual
+ // display config. However - below will always return INVALID since it checks
+ // that window manager mirroring is not enabled (it is always enabled for MP).
+ setReviewedConsentSessionLocked(ContentRecordingSession.createDisplaySession(
+ DEFAULT_DISPLAY));
+ break;
+ case RECORD_CONTENT_TASK:
+ setReviewedConsentSessionLocked(ContentRecordingSession.createTaskSession(
+ mProjectionGrant.getLaunchCookie()));
+ break;
+ }
+ }
+ }
+
+ /**
+ * Updates the session after the user has reviewed consent. There must be a current session.
+ *
+ * @param session The new session details, or {@code null} to stop recording.
+ */
+ private void setReviewedConsentSessionLocked(@Nullable ContentRecordingSession session) {
+ if (session != null) {
+ session.setWaitingToRecord(false);
+ session.setVirtualDisplayId(mProjectionGrant.mVirtualDisplayId);
+ }
+
+ Slog.v(TAG, "Reusing token: Processed consent so set the session " + session);
+ if (!setContentRecordingSession(session)) {
+ Slog.e(TAG, "Reusing token: Failed to set session for reused consent, so stop");
+ // Do not need to invoke stop; updating the session does it for us.
}
}
// TODO(b/261563516): Remove internal method and test aidl directly, here and elsewhere.
@VisibleForTesting
MediaProjection createProjectionInternal(int uid, String packageName, int type,
- boolean isPermanentGrant, UserHandle callingUser,
- boolean packageAttemptedReusingGrantedConsent) {
+ boolean isPermanentGrant, UserHandle callingUser) {
MediaProjection projection;
ApplicationInfo ai;
try {
@@ -371,6 +482,34 @@
return projection;
}
+ // TODO(b/261563516): Remove internal method and test aidl directly, here and elsewhere.
+ @VisibleForTesting
+ MediaProjection getProjectionInternal(int uid, String packageName) {
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ // Supposedly the package has re-used the user's consent; confirm the provided details
+ // against the current projection token before re-using the current projection.
+ if (mProjectionGrant == null || mProjectionGrant.mSession == null
+ || !mProjectionGrant.mSession.isWaitingToRecord()) {
+ Slog.e(TAG, "Reusing token: Not possible to reuse the current projection "
+ + "instance");
+ return null;
+ }
+ // The package matches, go ahead and re-use the token for this request.
+ if (mProjectionGrant.uid == uid
+ && Objects.equals(mProjectionGrant.packageName, packageName)) {
+ Slog.v(TAG, "Reusing token: getProjection can reuse the current projection");
+ return mProjectionGrant;
+ } else {
+ Slog.e(TAG, "Reusing token: Not possible to reuse the current projection "
+ + "instance due to package details mismatching");
+ return null;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+ }
+
@VisibleForTesting
MediaProjectionInfo getActiveProjectionInfo() {
synchronized (mLock) {
@@ -395,6 +534,10 @@
private final class BinderService extends IMediaProjectionManager.Stub {
+ BinderService(Context context) {
+ super(PermissionEnforcer.fromContext(context));
+ }
+
@Override // Binder call
public boolean hasProjectionPermission(int uid, String packageName) {
final long token = Binder.clearCallingIdentity();
@@ -424,7 +567,25 @@
}
final UserHandle callingUser = Binder.getCallingUserHandle();
return createProjectionInternal(uid, packageName, type, isPermanentGrant,
- callingUser, false);
+ callingUser);
+ }
+
+ @Override // Binder call
+ @EnforcePermission(MANAGE_MEDIA_PROJECTION)
+ public IMediaProjection getProjection(int uid, String packageName) {
+ getProjection_enforcePermission();
+ if (packageName == null || packageName.isEmpty()) {
+ throw new IllegalArgumentException("package name must not be empty");
+ }
+
+ MediaProjection projection;
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ projection = getProjectionInternal(uid, packageName);
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+ return projection;
}
@Override // Binder call
@@ -562,7 +723,7 @@
}
@Override
- public void requestConsentForInvalidProjection(IMediaProjection projection) {
+ public void requestConsentForInvalidProjection(@NonNull IMediaProjection projection) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION to check if the given"
@@ -577,7 +738,22 @@
// Remove calling app identity before performing any privileged operations.
final long token = Binder.clearCallingIdentity();
try {
- MediaProjectionManagerService.this.requestConsentForInvalidProjection(projection);
+ MediaProjectionManagerService.this.requestConsentForInvalidProjection();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ @EnforcePermission(MANAGE_MEDIA_PROJECTION)
+ public void setUserReviewGrantedConsentResult(@ReviewGrantedConsentResult int consentResult,
+ @Nullable IMediaProjection projection) {
+ setUserReviewGrantedConsentResult_enforcePermission();
+ // Remove calling app identity before performing any privileged operations.
+ final long token = Binder.clearCallingIdentity();
+ try {
+ MediaProjectionManagerService.this.setUserReviewGrantedConsentResult(consentResult,
+ projection);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -594,7 +770,6 @@
}
}
-
private boolean checkPermission(String packageName, String permission) {
return mContext.getPackageManager().checkPermission(permission, packageName)
== PackageManager.PERMISSION_GRANTED;
@@ -630,6 +805,8 @@
// Set if MediaProjection#createVirtualDisplay has been invoked previously (it
// should only be called once).
private int mVirtualDisplayId = INVALID_DISPLAY;
+ // The associated session details already sent to WindowManager.
+ private ContentRecordingSession mSession;
MediaProjection(int type, int uid, String packageName, int targetSdkVersion,
boolean isPrivileged) {
@@ -883,6 +1060,18 @@
}
synchronized (mLock) {
mVirtualDisplayId = displayId;
+
+ // If prior session was does not have a valid display id, then update the display
+ // so recording can start.
+ if (mSession != null && mSession.getVirtualDisplayId() == INVALID_DISPLAY) {
+ Slog.v(TAG, "Virtual display now created, so update session with the virtual "
+ + "display id");
+ mSession.setVirtualDisplayId(mVirtualDisplayId);
+ if (!setContentRecordingSession(mSession)) {
+ Slog.e(TAG, "Failed to set session for virtual display id");
+ // Do not need to invoke stop; updating the session does it for us.
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index f733199..2460ce5 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -48,6 +48,7 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.metrics.LogMaker;
+import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.UserHandle;
@@ -60,6 +61,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IntArray;
+import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseBooleanArray;
@@ -387,7 +389,8 @@
NotificationChannel channel = new NotificationChannel(
id, channelName, channelImportance);
if (forRestore) {
- channel.populateFromXmlForRestore(parser, mContext);
+ final boolean pkgInstalled = r.uid != UNKNOWN_UID;
+ channel.populateFromXmlForRestore(parser, pkgInstalled, mContext);
} else {
channel.populateFromXml(parser);
}
@@ -2412,6 +2415,21 @@
mRestoredWithoutUids.remove(unrestoredPackageKey(pkg, changeUserId));
synchronized (mPackagePreferences) {
mPackagePreferences.put(packagePreferencesKey(r.pkg, r.uid), r);
+
+ // Try to restore any unrestored sound resources
+ for (NotificationChannel channel : r.channels.values()) {
+ if (!channel.isSoundRestored()) {
+ Uri uri = channel.getSound();
+ Uri restoredUri = channel.restoreSoundUri(mContext, uri, true);
+ if (Settings.System.DEFAULT_NOTIFICATION_URI.equals(
+ restoredUri)) {
+ Log.w(TAG,
+ "Could not restore sound: " + uri + " for channel: "
+ + channel);
+ }
+ channel.setSound(restoredUri, channel.getAudioAttributes());
+ }
+ }
}
if (r.migrateToPm) {
try {
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 064be7c..39cd888 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -745,6 +745,9 @@
applyPackageFilter(snapshot, remainingPredicate, result, remainingPkgSettings, sortTemp,
packageManagerService);
+ // Make sure the system server isn't in the result, because it can never be dexopted here.
+ result.removeIf(pkgSetting -> PLATFORM_PACKAGE_NAME.equals(pkgSetting.getPackageName()));
+
if (debug) {
Log.i(TAG, "Packages to be dexopted: " + packagesToString(result));
Log.i(TAG, "Packages skipped from dexopt: " + packagesToString(remainingPkgSettings));
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 006d7c8..29c5ada 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1148,8 +1148,13 @@
info.userId = userId;
info.installerPackageName = mInstallSource.mInstallerPackageName;
info.installerAttributionTag = mInstallSource.mInstallerAttributionTag;
- info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
- mResolvedBaseFile.getAbsolutePath() : null;
+ if (mContext.checkCallingOrSelfPermission(
+ Manifest.permission.READ_INSTALLED_SESSION_PATHS)
+ == PackageManager.PERMISSION_GRANTED && mResolvedBaseFile != null) {
+ info.resolvedBaseCodePath = mResolvedBaseFile.getAbsolutePath();
+ } else {
+ info.resolvedBaseCodePath = null;
+ }
info.progress = progress;
info.sealed = mSealed;
info.isCommitted = isCommitted();
@@ -2754,11 +2759,6 @@
: PackageInstaller.ACTION_CONFIRM_INSTALL);
intent.setPackage(mPm.getPackageInstallerPackageName());
intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
- synchronized (mLock) {
- intent.putExtra(PackageInstaller.EXTRA_RESOLVED_BASE_PATH,
- mResolvedBaseFile != null ? mResolvedBaseFile.getAbsolutePath() : null);
- }
-
sendOnUserActionRequired(mContext, target, sessionId, intent);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index eea6720..ef7d413 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -24,6 +24,7 @@
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static com.android.server.LocalManagerRegistry.ManagerNotFoundException;
+import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import android.accounts.IAccountManager;
import android.annotation.NonNull;
@@ -1954,6 +1955,8 @@
List<String> packageNames = null;
if (allPackages) {
packageNames = mInterface.getAllPackages();
+ // Compiling the system server is only supported from odrefresh, so skip it.
+ packageNames.removeIf(packageName -> PLATFORM_PACKAGE_NAME.equals(packageName));
} else {
String packageName = getNextArg();
if (packageName == null) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index e8f89d3..c54b111 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4922,6 +4922,8 @@
date.setTime(ps.getLoadingCompletedTime());
pw.print(prefix); pw.println(" loadingCompletedTime=" + sdf.format(date));
}
+ pw.print(prefix); pw.print(" appMetadataFilePath=");
+ pw.println(ps.getAppMetadataFilePath());
if (ps.getVolumeUuid() != null) {
pw.print(prefix); pw.print(" volumeUuid=");
pw.println(ps.getVolumeUuid());
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index aeadcd5..247a5c0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2186,12 +2186,6 @@
Intent.EXTRA_DOCK_STATE_UNDOCKED));
}
- // register for dream-related broadcasts
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_DREAMING_STARTED);
- filter.addAction(Intent.ACTION_DREAMING_STOPPED);
- mContext.registerReceiver(mDreamReceiver, filter);
-
// register for multiuser-relevant broadcasts
filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(mMultiuserReceiver, filter);
@@ -2993,6 +2987,7 @@
}
break;
case KeyEvent.KEYCODE_H:
+ case KeyEvent.KEYCODE_ENTER:
if (event.isMetaPressed()) {
return handleHomeShortcuts(displayId, focusedToken, event);
}
@@ -4785,21 +4780,6 @@
}
};
- BroadcastReceiver mDreamReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
- if (mKeyguardDelegate != null) {
- mKeyguardDelegate.onDreamingStarted();
- }
- } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
- if (mKeyguardDelegate != null) {
- mKeyguardDelegate.onDreamingStopped();
- }
- }
- }
- };
-
BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 646dc4e..495e239 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -18,6 +18,7 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.service.dreams.DreamManagerInternal;
import android.util.Log;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -27,6 +28,7 @@
import com.android.internal.policy.IKeyguardDrawnCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService;
+import com.android.server.LocalServices;
import com.android.server.UiThread;
import com.android.server.policy.WindowManagerPolicy.OnKeyguardExitResult;
import com.android.server.wm.EventLogTags;
@@ -60,6 +62,19 @@
private DrawnListener mDrawnListenerWhenConnect;
+ private final DreamManagerInternal.DreamManagerStateListener mDreamManagerStateListener =
+ new DreamManagerInternal.DreamManagerStateListener() {
+ @Override
+ public void onDreamingStarted() {
+ KeyguardServiceDelegate.this.onDreamingStarted();
+ }
+
+ @Override
+ public void onDreamingStopped() {
+ KeyguardServiceDelegate.this.onDreamingStopped();
+ }
+ };
+
private static final class KeyguardState {
KeyguardState() {
reset();
@@ -158,6 +173,11 @@
} else {
if (DEBUG) Log.v(TAG, "*** Keyguard started");
}
+
+ final DreamManagerInternal dreamManager =
+ LocalServices.getService(DreamManagerInternal.class);
+
+ dreamManager.registerDreamManagerStateListener(mDreamManagerStateListener);
}
private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
index fb400da..80cb085 100644
--- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
@@ -2340,6 +2340,10 @@
@Override
public void binderDied() {
+ synchronized (mLock) {
+ mSession = null;
+ clearSessionAndNotifyClientLocked(this);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 8bbcd27..c40d72c 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -807,11 +807,8 @@
if (under != null) {
under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null;
}
- // Create a transition if the activity is playing in case the current activity
- // didn't commit invisible. That's because if this activity has changed its
- // visibility while playing transition, there won't able to commit visibility until
- // the running transition finish.
- final Transition transition = r.mTransitionController.inPlayingTransition(r)
+ // Create a transition to make sure the activity change is collected.
+ final Transition transition = r.mTransitionController.isShellTransitionsEnabled()
&& !r.mTransitionController.isCollecting()
? r.mTransitionController.createTransition(TRANSIT_TO_FRONT) : null;
final boolean changed = r.setOccludesParent(false);
diff --git a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
index d844c6f..9647a62 100644
--- a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
+++ b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
@@ -84,6 +84,7 @@
PERMISSION_POLICY_ORDERED_ID,
VIRTUAL_DEVICE_SERVICE_ORDERED_ID,
DREAM_MANAGER_ORDERED_ID,
+ PRODUCT_ORDERED_ID,
SYSTEM_LAST_ORDERED_ID, // Update this when adding new ids
// Order Ids for mainline module services
MAINLINE_FIRST_ORDERED_ID,
@@ -119,11 +120,18 @@
int DREAM_MANAGER_ORDERED_ID = 4;
/**
+ * The identifier for an interceptor which is specific to the type of android product like
+ * automotive, wear, TV etc.
+ * @hide
+ */
+ int PRODUCT_ORDERED_ID = 5;
+
+ /**
* The final id, used by the framework to determine the valid range of ids. Update this when
* adding new ids.
* @hide
*/
- int SYSTEM_LAST_ORDERED_ID = DREAM_MANAGER_ORDERED_ID;
+ int SYSTEM_LAST_ORDERED_ID = PRODUCT_ORDERED_ID;
/**
* The first mainline module id, used by the framework to determine the valid range of ids
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index c6a2e0e..bc3a1a2 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -10551,8 +10551,8 @@
}
@Override
- boolean isSyncFinished() {
- if (!super.isSyncFinished()) return false;
+ boolean isSyncFinished(BLASTSyncEngine.SyncGroup group) {
+ if (!super.isSyncFinished(group)) return false;
if (mDisplayContent != null && mDisplayContent.mUnknownAppVisibilityController
.isVisibilityUnknown(this)) {
return false;
@@ -10572,11 +10572,14 @@
}
@Override
- void finishSync(Transaction outMergedTransaction, boolean cancel) {
+ void finishSync(Transaction outMergedTransaction, BLASTSyncEngine.SyncGroup group,
+ boolean cancel) {
// This override is just for getting metrics. allFinished needs to be checked before
// finish because finish resets all the states.
+ final BLASTSyncEngine.SyncGroup syncGroup = getSyncGroup();
+ if (syncGroup != null && group != getSyncGroup()) return;
mLastAllReadyAtSync = allSyncFinished();
- super.finishSync(outMergedTransaction, cancel);
+ super.finishSync(outMergedTransaction, group, cancel);
}
@Nullable
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index 7ecc083..778951a 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -27,7 +27,6 @@
import android.os.Trace;
import android.util.ArraySet;
import android.util.Slog;
-import android.util.SparseArray;
import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
@@ -61,6 +60,26 @@
* This works primarily by setting-up state and then watching/waiting for the registered subtrees
* to enter into a "finished" state (either by receiving drawn content or by disappearing). This
* checks the subtrees during surface-placement.
+ *
+ * By default, all Syncs will be serialized (and it is an error to start one while another is
+ * active). However, a sync can be explicitly started in "parallel". This does not guarantee that
+ * it will run in parallel; however, it will run in parallel as long as it's watched hierarchy
+ * doesn't overlap with any other syncs' watched hierarchies.
+ *
+ * Currently, a sync that is started as "parallel" implicitly ignores the subtree below it's
+ * direct members unless those members are activities (WindowStates are considered "part of" the
+ * activity). This allows "stratified" parallelism where, eg, a sync that is only at Task-level
+ * can run in parallel with another sync that includes only the task's activities.
+ *
+ * If, at any time, a container is added to a parallel sync that *is* watched by another sync, it
+ * will be forced to serialize with it. This is done by adding a dependency. A sync will only
+ * finish if it has no active dependencies. At this point it is effectively not parallel anymore.
+ *
+ * To avoid dependency cycles, if a sync B ultimately depends on a sync A and a container is added
+ * to A which is watched by B, that container will, instead, be moved from B to A instead of
+ * creating a cyclic dependency.
+ *
+ * When syncs overlap, this will attempt to finish everything in the order they were started.
*/
class BLASTSyncEngine {
private static final String TAG = "BLASTSyncEngine";
@@ -104,6 +123,18 @@
private SurfaceControl.Transaction mOrphanTransaction = null;
private String mTraceName;
+ private static final ArrayList<SyncGroup> NO_DEPENDENCIES = new ArrayList<>();
+
+ /**
+ * When `true`, this SyncGroup will only wait for mRootMembers to draw; otherwise,
+ * it waits for the whole subtree(s) rooted at the mRootMembers.
+ */
+ boolean mIgnoreIndirectMembers = false;
+
+ /** List of SyncGroups that must finish before this one can. */
+ @NonNull
+ ArrayList<SyncGroup> mDependencies = NO_DEPENDENCIES;
+
private SyncGroup(TransactionReadyListener listener, int id, String name) {
mSyncId = id;
mListener = listener;
@@ -133,19 +164,43 @@
return mOrphanTransaction;
}
- private void tryFinish() {
- if (!mReady) return;
+ /**
+ * Check if the sync-group ignores a particular container. This is used to allow syncs at
+ * different levels to run in parallel. The primary example is Recents while an activity
+ * sync is happening.
+ */
+ boolean isIgnoring(WindowContainer wc) {
+ // Some heuristics to avoid unnecessary work:
+ // 1. For now, require an explicit acknowledgement of potential "parallelism" across
+ // hierarchy levels (horizontal).
+ if (!mIgnoreIndirectMembers) return false;
+ // 2. Don't check WindowStates since they are below the relevant abstraction level (
+ // anything activity/token and above).
+ if (wc.asWindowState() != null) return false;
+ // Obviously, don't ignore anything that is directly part of this group.
+ return wc.mSyncGroup != this;
+ }
+
+ /** @return `true` if it finished. */
+ private boolean tryFinish() {
+ if (!mReady) return false;
ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: onSurfacePlacement checking %s",
mSyncId, mRootMembers);
+ if (!mDependencies.isEmpty()) {
+ ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Unfinished dependencies: %s",
+ mSyncId, mDependencies);
+ return false;
+ }
for (int i = mRootMembers.size() - 1; i >= 0; --i) {
final WindowContainer wc = mRootMembers.valueAt(i);
- if (!wc.isSyncFinished()) {
+ if (!wc.isSyncFinished(this)) {
ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Unfinished container: %s",
mSyncId, wc);
- return;
+ return false;
}
}
finishNow();
+ return true;
}
private void finishNow() {
@@ -158,7 +213,7 @@
merged.merge(mOrphanTransaction);
}
for (WindowContainer wc : mRootMembers) {
- wc.finishSync(merged, false /* cancel */);
+ wc.finishSync(merged, this, false /* cancel */);
}
final ArraySet<WindowContainer> wcAwaitingCommit = new ArraySet<>();
@@ -204,7 +259,7 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "onTransactionReady");
mListener.onTransactionReady(mSyncId, merged);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- mActiveSyncs.remove(mSyncId);
+ mActiveSyncs.remove(this);
mHandler.removeCallbacks(mOnTimeout);
// Immediately start the next pending sync-transaction if there is one.
@@ -230,54 +285,115 @@
}
}
- private void setReady(boolean ready) {
+ /** returns true if readiness changed. */
+ private boolean setReady(boolean ready) {
if (mReady == ready) {
- return;
+ return false;
}
ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Set ready %b", mSyncId, ready);
mReady = ready;
- if (!ready) return;
- mWm.mWindowPlacerLocked.requestTraversal();
+ if (ready) {
+ mWm.mWindowPlacerLocked.requestTraversal();
+ }
+ return true;
}
private void addToSync(WindowContainer wc) {
- if (!mRootMembers.add(wc)) {
+ if (mRootMembers.contains(wc)) {
return;
}
ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Adding to group: %s", mSyncId, wc);
- wc.setSyncGroup(this);
+ final SyncGroup dependency = wc.getSyncGroup();
+ if (dependency != null && dependency != this && !dependency.isIgnoring(wc)) {
+ // This syncgroup now conflicts with another one, so the whole group now must
+ // wait on the other group.
+ Slog.w(TAG, "SyncGroup " + mSyncId + " conflicts with " + dependency.mSyncId
+ + ": Making " + mSyncId + " depend on " + dependency.mSyncId);
+ if (mDependencies.contains(dependency)) {
+ // nothing, it's already a dependency.
+ } else if (dependency.dependsOn(this)) {
+ Slog.w(TAG, " Detected dependency cycle between " + mSyncId + " and "
+ + dependency.mSyncId + ": Moving " + wc + " to " + mSyncId);
+ // Since dependency already depends on this, make this now `wc`'s watcher
+ if (wc.mSyncGroup == null) {
+ wc.setSyncGroup(this);
+ } else {
+ // Explicit replacement.
+ wc.mSyncGroup.mRootMembers.remove(wc);
+ mRootMembers.add(wc);
+ wc.mSyncGroup = this;
+ }
+ } else {
+ if (mDependencies == NO_DEPENDENCIES) {
+ mDependencies = new ArrayList<>();
+ }
+ mDependencies.add(dependency);
+ }
+ } else {
+ mRootMembers.add(wc);
+ wc.setSyncGroup(this);
+ }
wc.prepareSync();
if (mReady) {
mWm.mWindowPlacerLocked.requestTraversal();
}
}
+ private boolean dependsOn(SyncGroup group) {
+ if (mDependencies.isEmpty()) return false;
+ // BFS search with membership check. We don't expect cycle here (since this is
+ // explicitly called to avoid cycles) but just to be safe.
+ final ArrayList<SyncGroup> fringe = mTmpFringe;
+ fringe.clear();
+ fringe.add(this);
+ for (int head = 0; head < fringe.size(); ++head) {
+ final SyncGroup next = fringe.get(head);
+ if (next == group) {
+ fringe.clear();
+ return true;
+ }
+ for (int i = 0; i < next.mDependencies.size(); ++i) {
+ if (fringe.contains(next.mDependencies.get(i))) continue;
+ fringe.add(next.mDependencies.get(i));
+ }
+ }
+ fringe.clear();
+ return false;
+ }
+
void onCancelSync(WindowContainer wc) {
mRootMembers.remove(wc);
}
private void onTimeout() {
- if (!mActiveSyncs.contains(mSyncId)) return;
+ if (!mActiveSyncs.contains(this)) return;
boolean allFinished = true;
for (int i = mRootMembers.size() - 1; i >= 0; --i) {
final WindowContainer<?> wc = mRootMembers.valueAt(i);
- if (!wc.isSyncFinished()) {
+ if (!wc.isSyncFinished(this)) {
allFinished = false;
Slog.i(TAG, "Unfinished container: " + wc);
}
}
+ for (int i = mDependencies.size() - 1; i >= 0; --i) {
+ allFinished = false;
+ Slog.i(TAG, "Unfinished dependency: " + mDependencies.get(i).mSyncId);
+ }
if (allFinished && !mReady) {
Slog.w(TAG, "Sync group " + mSyncId + " timed-out because not ready. If you see "
+ "this, please file a bug.");
}
finishNow();
+ removeFromDependencies(this);
}
}
private final WindowManagerService mWm;
private final Handler mHandler;
private int mNextSyncId = 0;
- private final SparseArray<SyncGroup> mActiveSyncs = new SparseArray<>();
+
+ /** Currently active syncs. Intentionally ordered by start time. */
+ private final ArrayList<SyncGroup> mActiveSyncs = new ArrayList<>();
/**
* A queue of pending sync-sets waiting for their turn to run.
@@ -288,6 +404,9 @@
private final ArrayList<Runnable> mOnIdleListeners = new ArrayList<>();
+ private final ArrayList<SyncGroup> mTmpFinishQueue = new ArrayList<>();
+ private final ArrayList<SyncGroup> mTmpFringe = new ArrayList<>();
+
BLASTSyncEngine(WindowManagerService wms) {
this(wms, wms.mH);
}
@@ -306,32 +425,39 @@
return new SyncGroup(listener, mNextSyncId++, name);
}
- int startSyncSet(TransactionReadyListener listener, long timeoutMs, String name) {
+ int startSyncSet(TransactionReadyListener listener, long timeoutMs, String name,
+ boolean parallel) {
final SyncGroup s = prepareSyncSet(listener, name);
- startSyncSet(s, timeoutMs);
+ startSyncSet(s, timeoutMs, parallel);
return s.mSyncId;
}
void startSyncSet(SyncGroup s) {
- startSyncSet(s, BLAST_TIMEOUT_DURATION);
+ startSyncSet(s, BLAST_TIMEOUT_DURATION, false /* parallel */);
}
- void startSyncSet(SyncGroup s, long timeoutMs) {
- if (mActiveSyncs.size() != 0) {
- // We currently only support one sync at a time, so start a new SyncGroup when there is
- // another may cause issue.
+ void startSyncSet(SyncGroup s, long timeoutMs, boolean parallel) {
+ final boolean alreadyRunning = mActiveSyncs.size() > 0;
+ if (!parallel && alreadyRunning) {
+ // We only support overlapping syncs when explicitly declared `parallel`.
Slog.e(TAG, "SyncGroup " + s.mSyncId
+ ": Started when there is other active SyncGroup");
}
- mActiveSyncs.put(s.mSyncId, s);
- ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Started for listener: %s",
- s.mSyncId, s.mListener);
+ mActiveSyncs.add(s);
+ // For now, parallel implies this.
+ s.mIgnoreIndirectMembers = parallel;
+ ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Started %sfor listener: %s",
+ s.mSyncId, (parallel && alreadyRunning ? "(in parallel) " : ""), s.mListener);
scheduleTimeout(s, timeoutMs);
}
@Nullable
SyncGroup getSyncSet(int id) {
- return mActiveSyncs.get(id);
+ for (int i = 0; i < mActiveSyncs.size(); ++i) {
+ if (mActiveSyncs.get(i).mSyncId != id) continue;
+ return mActiveSyncs.get(i);
+ }
+ return null;
}
boolean hasActiveSync() {
@@ -356,8 +482,8 @@
syncGroup.mSyncMethod = method;
}
- void setReady(int id, boolean ready) {
- getSyncGroup(id).setReady(ready);
+ boolean setReady(int id, boolean ready) {
+ return getSyncGroup(id).setReady(ready);
}
void setReady(int id) {
@@ -372,21 +498,68 @@
* Aborts the sync (ie. it doesn't wait for ready or anything to finish)
*/
void abort(int id) {
- getSyncGroup(id).finishNow();
+ final SyncGroup group = getSyncGroup(id);
+ group.finishNow();
+ removeFromDependencies(group);
}
private SyncGroup getSyncGroup(int id) {
- final SyncGroup syncGroup = mActiveSyncs.get(id);
+ final SyncGroup syncGroup = getSyncSet(id);
if (syncGroup == null) {
throw new IllegalStateException("SyncGroup is not started yet id=" + id);
}
return syncGroup;
}
+ /**
+ * Just removes `group` from any dependency lists. Does not try to evaluate anything. However,
+ * it will schedule traversals if any groups were changed in a way that could make them ready.
+ */
+ private void removeFromDependencies(SyncGroup group) {
+ boolean anyChange = false;
+ for (int i = 0; i < mActiveSyncs.size(); ++i) {
+ final SyncGroup active = mActiveSyncs.get(i);
+ if (!active.mDependencies.remove(group)) continue;
+ if (!active.mDependencies.isEmpty()) continue;
+ anyChange = true;
+ }
+ if (!anyChange) return;
+ mWm.mWindowPlacerLocked.requestTraversal();
+ }
+
void onSurfacePlacement() {
- // backwards since each state can remove itself if finished
- for (int i = mActiveSyncs.size() - 1; i >= 0; --i) {
- mActiveSyncs.valueAt(i).tryFinish();
+ if (mActiveSyncs.isEmpty()) return;
+ // queue in-order since we want interdependent syncs to become ready in the same order they
+ // started in.
+ mTmpFinishQueue.addAll(mActiveSyncs);
+ // There shouldn't be any dependency cycles or duplicates, but add an upper-bound just
+ // in case. Assuming absolute worst case, each visit will try and revisit everything
+ // before it, so n + (n-1) + (n-2) ... = (n+1)*n/2
+ int visitBounds = ((mActiveSyncs.size() + 1) * mActiveSyncs.size()) / 2;
+ while (!mTmpFinishQueue.isEmpty()) {
+ if (visitBounds <= 0) {
+ Slog.e(TAG, "Trying to finish more syncs than theoretically possible. This "
+ + "should never happen. Most likely a dependency cycle wasn't detected.");
+ }
+ --visitBounds;
+ final SyncGroup group = mTmpFinishQueue.remove(0);
+ final int grpIdx = mActiveSyncs.indexOf(group);
+ // Skip if it's already finished:
+ if (grpIdx < 0) continue;
+ if (!group.tryFinish()) continue;
+ // Finished, so update dependencies of any prior groups and retry if unblocked.
+ int insertAt = 0;
+ for (int i = 0; i < mActiveSyncs.size(); ++i) {
+ final SyncGroup active = mActiveSyncs.get(i);
+ if (!active.mDependencies.remove(group)) continue;
+ // Anything afterwards is already in queue.
+ if (i >= grpIdx) continue;
+ if (!active.mDependencies.isEmpty()) continue;
+ // `active` became unblocked so it can finish, since it started earlier, it should
+ // be checked next to maintain order.
+ mTmpFinishQueue.add(insertAt, mActiveSyncs.get(i));
+ insertAt += 1;
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/ContentRecordingController.java b/services/core/java/com/android/server/wm/ContentRecordingController.java
index a41dcc6..040da88 100644
--- a/services/core/java/com/android/server/wm/ContentRecordingController.java
+++ b/services/core/java/com/android/server/wm/ContentRecordingController.java
@@ -80,7 +80,7 @@
}
// Invalid scenario: ignore identical incoming session.
if (ContentRecordingSession.isProjectionOnSameDisplay(mSession, incomingSession)) {
- // TODO(242833866) if incoming session is no longer waiting to record, allow
+ // TODO(242833866): if incoming session is no longer waiting to record, allow
// the update through.
ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
@@ -99,7 +99,7 @@
incomingDisplayContent = wmService.mRoot.getDisplayContentOrCreate(
incomingSession.getVirtualDisplayId());
incomingDisplayContent.setContentRecordingSession(incomingSession);
- // TODO(b/270118861) When user grants consent to re-use, explicitly ask ContentRecorder
+ // TODO(b/270118861): When user grants consent to re-use, explicitly ask ContentRecorder
// to update, since no config/display change arrives. Mark recording as black.
}
// Takeover and stopping scenario: stop recording on the pre-existing session.
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 76d6951..8bfa426 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1755,7 +1755,7 @@
}
@Override
- boolean isSyncFinished() {
+ boolean isSyncFinished(BLASTSyncEngine.SyncGroup group) {
// Do not consider children because if they are requested to be synced, they should be
// added to sync group explicitly.
return !mRemoteDisplayChangeController.isWaitingForRemoteDisplayChange();
@@ -2267,6 +2267,12 @@
if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) {
return WmDisplayCutout.NO_CUTOUT;
}
+ if (displayWidth == displayHeight) {
+ Slog.w(TAG, "Ignore cutout because display size is square: " + displayWidth);
+ // Avoid UnsupportedOperationException because DisplayCutout#computeSafeInsets doesn't
+ // support square size.
+ return WmDisplayCutout.NO_CUTOUT;
+ }
if (rotation == ROTATION_0) {
return WmDisplayCutout.computeSafeInsets(
cutout, displayWidth, displayHeight);
@@ -3087,13 +3093,9 @@
mIsSizeForced = mInitialDisplayWidth != width || mInitialDisplayHeight != height;
if (mIsSizeForced) {
- // Set some sort of reasonable bounds on the size of the display that we will try
- // to emulate.
- final int minSize = 200;
- final int maxScale = 3;
- final int maxSize = Math.max(mInitialDisplayWidth, mInitialDisplayHeight) * maxScale;
- width = Math.min(Math.max(width, minSize), maxSize);
- height = Math.min(Math.max(height, minSize), maxSize);
+ final Point size = getValidForcedSize(width, height);
+ width = size.x;
+ height = size.y;
}
Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
@@ -3108,6 +3110,16 @@
mWmService.mDisplayWindowSettings.setForcedSize(this, width, height);
}
+ /** Returns a reasonable size for setting forced display size. */
+ Point getValidForcedSize(int w, int h) {
+ final int minSize = 200;
+ final int maxScale = 3;
+ final int maxSize = Math.max(mInitialDisplayWidth, mInitialDisplayHeight) * maxScale;
+ w = Math.min(Math.max(w, minSize), maxSize);
+ h = Math.min(Math.max(h, minSize), maxSize);
+ return new Point(w, h);
+ }
+
DisplayCutout loadDisplayCutout(int displayWidth, int displayHeight) {
if (mDisplayPolicy == null || mInitialDisplayCutout == null) {
return null;
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 3f7ab14..c6c3b14 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -2547,8 +2547,8 @@
}
@Override
- boolean isSyncFinished() {
- return super.isSyncFinished() && isReadyToTransit();
+ boolean isSyncFinished(BLASTSyncEngine.SyncGroup group) {
+ return super.isSyncFinished(group) && isReadyToTransit();
}
@Override
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 452bd6d..b314ed1 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -447,7 +447,7 @@
throw new IllegalStateException("Attempting to re-use a transition");
}
mState = STATE_COLLECTING;
- mSyncId = mSyncEngine.startSyncSet(this, timeoutMs, TAG);
+ mSyncId = mSyncEngine.startSyncSet(this, timeoutMs, TAG, false /* parallel */);
mSyncEngine.setSyncMethod(mSyncId, TransitionController.SYNC_METHOD);
mLogger.mSyncId = mSyncId;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index cf6efd2..f4a1765d 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3835,13 +3835,11 @@
void setSyncGroup(@NonNull BLASTSyncEngine.SyncGroup group) {
ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "setSyncGroup #%d on %s", group.mSyncId, this);
- if (group != null) {
- if (mSyncGroup != null && mSyncGroup != group) {
- // This can still happen if WMCore starts a new transition when there is ongoing
- // sync transaction from Shell. Please file a bug if it happens.
- throw new IllegalStateException("Can't sync on 2 engines simultaneously"
- + " currentSyncId=" + mSyncGroup.mSyncId + " newSyncId=" + group.mSyncId);
- }
+ if (mSyncGroup != null && mSyncGroup != group) {
+ // This can still happen if WMCore starts a new transition when there is ongoing
+ // sync transaction from Shell. Please file a bug if it happens.
+ throw new IllegalStateException("Can't sync on 2 groups simultaneously"
+ + " currentSyncId=" + mSyncGroup.mSyncId + " newSyncId=" + group.mSyncId);
}
mSyncGroup = group;
}
@@ -3883,12 +3881,16 @@
* @param cancel If true, this is being finished because it is leaving the sync group rather
* than due to the sync group completing.
*/
- void finishSync(Transaction outMergedTransaction, boolean cancel) {
+ void finishSync(Transaction outMergedTransaction, BLASTSyncEngine.SyncGroup group,
+ boolean cancel) {
if (mSyncState == SYNC_STATE_NONE) return;
+ final BLASTSyncEngine.SyncGroup syncGroup = getSyncGroup();
+ // If it's null, then we need to clean-up anyways.
+ if (syncGroup != null && group != syncGroup) return;
ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "finishSync cancel=%b for %s", cancel, this);
outMergedTransaction.merge(mSyncTransaction);
for (int i = mChildren.size() - 1; i >= 0; --i) {
- mChildren.get(i).finishSync(outMergedTransaction, cancel);
+ mChildren.get(i).finishSync(outMergedTransaction, group, cancel);
}
if (cancel && mSyncGroup != null) mSyncGroup.onCancelSync(this);
mSyncState = SYNC_STATE_NONE;
@@ -3903,7 +3905,7 @@
*
* @return {@code true} if this subtree is finished waiting for sync participants.
*/
- boolean isSyncFinished() {
+ boolean isSyncFinished(BLASTSyncEngine.SyncGroup group) {
if (!isVisibleRequested()) {
return true;
}
@@ -3917,7 +3919,7 @@
// Loop from top-down.
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer child = mChildren.get(i);
- final boolean childFinished = child.isSyncFinished();
+ final boolean childFinished = group.isIgnoring(child) || child.isSyncFinished(group);
if (childFinished && child.isVisibleRequested() && child.fillsParent()) {
// Any lower children will be covered-up, so we can consider this finished.
return true;
@@ -3968,11 +3970,11 @@
// This is getting removed.
if (oldParent.mSyncState != SYNC_STATE_NONE) {
// In order to keep the transaction in sync, merge it into the parent.
- finishSync(oldParent.mSyncTransaction, true /* cancel */);
+ finishSync(oldParent.mSyncTransaction, getSyncGroup(), true /* cancel */);
} else if (mSyncGroup != null) {
// This is watched directly by the sync-group, so merge this transaction into
// into the sync-group so it isn't lost
- finishSync(mSyncGroup.getOrphanTransaction(), true /* cancel */);
+ finishSync(mSyncGroup.getOrphanTransaction(), mSyncGroup, true /* cancel */);
} else {
throw new IllegalStateException("This container is in sync mode without a sync"
+ " group: " + this);
@@ -3981,7 +3983,7 @@
} else if (mSyncGroup == null) {
// This is being reparented out of the sync-group. To prevent ordering issues on
// this container, immediately apply/cancel sync on it.
- finishSync(getPendingTransaction(), true /* cancel */);
+ finishSync(getPendingTransaction(), getSyncGroup(), true /* cancel */);
return;
}
// Otherwise this is the "root" of a synced subtree, so continue on to preparation.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8822193..40b8274 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5780,10 +5780,12 @@
if (sizeStr != null && sizeStr.length() > 0) {
final int pos = sizeStr.indexOf(',');
if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
- int width, height;
try {
- width = Integer.parseInt(sizeStr.substring(0, pos));
- height = Integer.parseInt(sizeStr.substring(pos + 1));
+ final Point size = displayContent.getValidForcedSize(
+ Integer.parseInt(sizeStr.substring(0, pos)),
+ Integer.parseInt(sizeStr.substring(pos + 1)));
+ final int width = size.x;
+ final int height = size.y;
if (displayContent.mBaseDisplayWidth != width
|| displayContent.mBaseDisplayHeight != height) {
ProtoLog.i(WM_ERROR, "FORCED DISPLAY SIZE: %dx%d", width, height);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index a299592..2920652 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5634,7 +5634,7 @@
private void dropBufferFrom(Transaction t) {
SurfaceControl viewSurface = getClientViewRootSurface();
if (viewSurface == null) return;
- t.setBuffer(viewSurface, (android.hardware.HardwareBuffer) null);
+ t.unsetBuffer(viewSurface);
}
@Override
@@ -5678,7 +5678,7 @@
}
@Override
- boolean isSyncFinished() {
+ boolean isSyncFinished(BLASTSyncEngine.SyncGroup group) {
if (!isVisibleRequested() || isFullyTransparent()) {
// Don't wait for invisible windows. However, we don't alter the state in case the
// window becomes visible while the sync group is still active.
@@ -5689,11 +5689,14 @@
// Complete the sync state immediately for a drawn window that doesn't need to redraw.
onSyncFinishedDrawing();
}
- return super.isSyncFinished();
+ return super.isSyncFinished(group);
}
@Override
- void finishSync(Transaction outMergedTransaction, boolean cancel) {
+ void finishSync(Transaction outMergedTransaction, BLASTSyncEngine.SyncGroup group,
+ boolean cancel) {
+ final BLASTSyncEngine.SyncGroup syncGroup = getSyncGroup();
+ if (syncGroup != null && group != syncGroup) return;
mPrepareSyncSeqId = 0;
if (cancel) {
// This is leaving sync so any buffers left in the sync have a chance of
@@ -5701,7 +5704,7 @@
// window. To prevent this, drop the buffer.
dropBufferFrom(mSyncTransaction);
}
- super.finishSync(outMergedTransaction, cancel);
+ super.finishSync(outMergedTransaction, group, cancel);
}
boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {
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 981844c..f96ca58 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -153,12 +153,6 @@
<xs:annotation name="nullable"/>
<xs:annotation name="final"/>
</xs:element>
- <!-- The highest (most severe) thermal status at which high-brightness-mode is allowed
- to operate. -->
- <xs:element name="thermalStatusLimit" type="thermalStatus" minOccurs="0" maxOccurs="1">
- <xs:annotation name="nonnull"/>
- <xs:annotation name="final"/>
- </xs:element>
<xs:element name="allowInLowPowerMode" type="xs:boolean" minOccurs="0" maxOccurs="1">
<xs:annotation name="nonnull"/>
<xs:annotation name="final"/>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 8cb4837..ad6434e 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -156,7 +156,6 @@
method @NonNull public final java.math.BigDecimal getMinimumLux_all();
method @Nullable public final com.android.server.display.config.RefreshRateRange getRefreshRate_all();
method @Nullable public final com.android.server.display.config.SdrHdrRatioMap getSdrHdrRatioMap_all();
- method @NonNull public final com.android.server.display.config.ThermalStatus getThermalStatusLimit_all();
method public com.android.server.display.config.HbmTiming getTiming_all();
method @NonNull public final java.math.BigDecimal getTransitionPoint_all();
method public final void setAllowInLowPowerMode_all(@NonNull boolean);
@@ -165,7 +164,6 @@
method public final void setMinimumLux_all(@NonNull java.math.BigDecimal);
method public final void setRefreshRate_all(@Nullable com.android.server.display.config.RefreshRateRange);
method public final void setSdrHdrRatioMap_all(@Nullable com.android.server.display.config.SdrHdrRatioMap);
- method public final void setThermalStatusLimit_all(@NonNull com.android.server.display.config.ThermalStatus);
method public void setTiming_all(com.android.server.display.config.HbmTiming);
method public final void setTransitionPoint_all(@NonNull java.math.BigDecimal);
}
diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
index 3b10db4..e2a66f0 100644
--- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
@@ -16,8 +16,6 @@
package com.android.server.display;
-import static android.hardware.display.BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
-import static android.hardware.display.BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL;
import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR;
import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
@@ -29,6 +27,8 @@
import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.anyFloat;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
@@ -39,14 +39,10 @@
import android.content.Context;
import android.content.ContextWrapper;
+import android.hardware.display.BrightnessInfo;
import android.os.Binder;
import android.os.Handler;
-import android.os.IThermalEventListener;
-import android.os.IThermalService;
import android.os.Message;
-import android.os.PowerManager;
-import android.os.Temperature;
-import android.os.Temperature.ThrottlingStatus;
import android.os.test.TestLooper;
import android.test.mock.MockContentResolver;
import android.util.MathUtils;
@@ -66,8 +62,6 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -80,7 +74,6 @@
private static final long TIME_WINDOW_MILLIS = 55 * 1000;
private static final long TIME_ALLOWED_IN_WINDOW_MILLIS = 12 * 1000;
private static final long TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS = 5 * 1000;
- private static final int THERMAL_STATUS_LIMIT = PowerManager.THERMAL_STATUS_SEVERE;
private static final boolean ALLOW_IN_LOW_POWER_MODE = false;
private static final float DEFAULT_MIN = 0.01f;
@@ -102,17 +95,13 @@
@Rule
public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
- @Mock IThermalService mThermalServiceMock;
@Mock Injector mInjectorMock;
@Mock HighBrightnessModeController.HdrBrightnessDeviceConfig mHdrBrightnessDeviceConfigMock;
- @Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;
-
private static final HighBrightnessModeData DEFAULT_HBM_DATA =
new HighBrightnessModeData(MINIMUM_LUX, TRANSITION_POINT, TIME_WINDOW_MILLIS,
TIME_ALLOWED_IN_WINDOW_MILLIS, TIME_MINIMUM_AVAILABLE_TO_ENABLE_MILLIS,
- THERMAL_STATUS_LIMIT, ALLOW_IN_LOW_POWER_MODE,
- HDR_PERCENT_OF_SCREEN_REQUIRED_DEFAULT);
+ ALLOW_IN_LOW_POWER_MODE, HDR_PERCENT_OF_SCREEN_REQUIRED_DEFAULT);
@Before
public void setUp() {
@@ -125,8 +114,6 @@
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
when(mContextSpy.getContentResolver()).thenReturn(resolver);
-
- when(mInjectorMock.getThermalService()).thenReturn(mThermalServiceMock);
}
/////////////////
@@ -321,34 +308,14 @@
}
@Test
- public void testNoHbmInHighThermalState() throws Exception {
+ public void testHbmIsNotTurnedOffInHighThermalState() throws Exception {
final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
- verify(mThermalServiceMock).registerThermalEventListenerWithType(
- mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
- final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
+ // Disabled thermal throttling
+ hbmc.onBrightnessChanged(/*brightness=*/ 1f, /*unthrottledBrightness*/ 1f,
+ BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE);
- // Set the thermal status too high.
- listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
-
- // Try to go into HBM mode but fail
- hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
- hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
- advanceTime(10);
-
- assertEquals(HIGH_BRIGHTNESS_MODE_OFF, hbmc.getHighBrightnessMode());
- }
-
- @Test
- public void testHbmTurnsOffInHighThermalState() throws Exception {
- final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
-
- verify(mThermalServiceMock).registerThermalEventListenerWithType(
- mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
- final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
-
- // Set the thermal status tolerable
- listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_LIGHT));
+ assertFalse(hbmc.isThermalThrottlingActive());
// Try to go into HBM mode
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
@@ -357,15 +324,19 @@
assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode());
- // Set the thermal status too high and verify we're off.
- listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
+ // Enable thermal throttling
+ hbmc.onBrightnessChanged(/*brightness=*/ TRANSITION_POINT - 0.01f,
+ /*unthrottledBrightness*/ 1f, BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL);
advanceTime(10);
- assertEquals(HIGH_BRIGHTNESS_MODE_OFF, hbmc.getHighBrightnessMode());
+ assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode());
+ assertTrue(hbmc.isThermalThrottlingActive());
- // Set the thermal status low again and verify we're back on.
- listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_SEVERE));
+ // Disabled thermal throttling
+ hbmc.onBrightnessChanged(/*brightness=*/ 1f, /*unthrottledBrightness*/ 1f,
+ BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE);
advanceTime(1);
assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode());
+ assertFalse(hbmc.isThermalThrottlingActive());
}
@Test
@@ -578,33 +549,6 @@
anyInt());
}
- // Test reporting of thermal throttling when triggered by HighBrightnessModeController's
- // internal thermal throttling.
- @Test
- public void testHbmStats_InternalThermalOff() throws Exception {
- final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
- final int displayStatsId = mDisplayUniqueId.hashCode();
-
- verify(mThermalServiceMock).registerThermalEventListenerWithType(
- mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
- final IThermalEventListener thermListener = mThermalEventListenerCaptor.getValue();
-
- hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
- hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
- hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT + 0.01f);
- advanceTime(1);
- verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
- eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT),
- eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_TRANSITION_REASON_UNKNOWN));
-
- thermListener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
- advanceTime(10);
- assertEquals(HIGH_BRIGHTNESS_MODE_OFF, hbmc.getHighBrightnessMode());
- verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
- eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_OFF),
- eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_THERMAL_LIMIT));
- }
-
// Test reporting of thermal throttling when triggered externally through
// HighBrightnessModeController.onBrightnessChanged()
@Test
@@ -617,14 +561,16 @@
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
// Brightness is unthrottled, HBM brightness granted
- hbmc.onBrightnessChanged(hbmBrightness, hbmBrightness, BRIGHTNESS_MAX_REASON_NONE);
+ hbmc.onBrightnessChanged(hbmBrightness, hbmBrightness,
+ BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE);
advanceTime(1);
verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT),
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_TRANSITION_REASON_UNKNOWN));
// Brightness is thermally throttled, HBM brightness denied (NBM brightness granted)
- hbmc.onBrightnessChanged(nbmBrightness, hbmBrightness, BRIGHTNESS_MAX_REASON_THERMAL);
+ hbmc.onBrightnessChanged(nbmBrightness, hbmBrightness,
+ BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL);
advanceTime(1);
// We expect HBM mode to remain set to sunlight, indicating that HBMC *allows* this mode.
// However, we expect the HBM state reported by HBMC to be off, since external thermal
@@ -784,11 +730,7 @@
mTestLooper.dispatchAll();
}
- private Temperature getSkinTemp(@ThrottlingStatus int status) {
- return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
- }
-
private void hbmcOnBrightnessChanged(HighBrightnessModeController hbmc, float brightness) {
- hbmc.onBrightnessChanged(brightness, brightness, BRIGHTNESS_MAX_REASON_NONE);
+ hbmc.onBrightnessChanged(brightness, brightness, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
index 5ea3029..ff89be7 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
@@ -17,8 +17,6 @@
package com.android.server.display;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
@@ -28,7 +26,6 @@
import android.app.PropertyInvalidatedCache;
import android.graphics.Point;
-import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -50,7 +47,6 @@
private static final int LAYER_STACK = 0;
private static final int DISPLAY_WIDTH = 100;
private static final int DISPLAY_HEIGHT = 200;
- private static final int MODE_ID = 1;
private LogicalDisplay mLogicalDisplay;
private DisplayDevice mDisplayDevice;
@@ -69,9 +65,6 @@
mDisplayDeviceInfo.height = DISPLAY_HEIGHT;
mDisplayDeviceInfo.flags = DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
mDisplayDeviceInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
- mDisplayDeviceInfo.modeId = MODE_ID;
- mDisplayDeviceInfo.supportedModes = new Display.Mode[] {new Display.Mode(MODE_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT, /* refreshRate= */ 60)};
when(mDisplayDevice.getDisplayDeviceInfoLocked()).thenReturn(mDisplayDeviceInfo);
// Disable binder caches in this process.
@@ -175,34 +168,14 @@
}
@Test
- public void testUpdateLayoutLimitedRefreshRate() {
- SurfaceControl.RefreshRateRange layoutLimitedRefreshRate =
- new SurfaceControl.RefreshRateRange(0, 120);
- DisplayInfo info1 = mLogicalDisplay.getDisplayInfoLocked();
- mLogicalDisplay.updateLayoutLimitedRefreshRateLocked(layoutLimitedRefreshRate);
- DisplayInfo info2 = mLogicalDisplay.getDisplayInfoLocked();
- // Display info should only be updated when updateLocked is called
- assertEquals(info2, info1);
+ public void testLayoutLimitedRefreshRateNotClearedAfterUpdate() {
+ SurfaceControl.RefreshRateRange refreshRateRange = new SurfaceControl.RefreshRateRange(1,
+ 2);
+ mLogicalDisplay.updateLayoutLimitedRefreshRateLocked(refreshRateRange);
+ mLogicalDisplay.updateDisplayGroupIdLocked(1);
- mLogicalDisplay.updateLocked(mDeviceRepo);
- DisplayInfo info3 = mLogicalDisplay.getDisplayInfoLocked();
- assertNotEquals(info3, info2);
- assertEquals(layoutLimitedRefreshRate, info3.layoutLimitedRefreshRate);
- }
+ DisplayInfo result = mLogicalDisplay.getDisplayInfoLocked();
- @Test
- public void testUpdateRefreshRateThermalThrottling() {
- SparseArray<SurfaceControl.RefreshRateRange> refreshRanges = new SparseArray<>();
- refreshRanges.put(0, new SurfaceControl.RefreshRateRange(0, 120));
- DisplayInfo info1 = mLogicalDisplay.getDisplayInfoLocked();
- mLogicalDisplay.updateThermalRefreshRateThrottling(refreshRanges);
- DisplayInfo info2 = mLogicalDisplay.getDisplayInfoLocked();
- // Display info should only be updated when updateLocked is called
- assertEquals(info2, info1);
-
- mLogicalDisplay.updateLocked(mDeviceRepo);
- DisplayInfo info3 = mLogicalDisplay.getDisplayInfoLocked();
- assertNotEquals(info3, info2);
- assertTrue(refreshRanges.contentEquals(info3.thermalRefreshRateThrottling));
+ assertEquals(refreshRateRange, result.layoutLimitedRefreshRate);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index 4cfcee5..42c1fd9 100644
--- a/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -127,8 +127,7 @@
private static final String TAG = "DisplayModeDirectorTest";
private static final boolean DEBUG = false;
private static final float FLOAT_TOLERANCE = 0.01f;
- private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY;
- private static final int MODE_ID = 1;
+ private static final int DISPLAY_ID = 0;
private static final float TRANSITION_POINT = 0.763f;
private static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY;
@@ -2645,33 +2644,6 @@
assertNull(vote);
}
- @Test
- public void testUpdateLayoutLimitedRefreshRate() {
- DisplayModeDirector director =
- createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0);
- director.start(createMockSensorManager());
-
- ArgumentCaptor<DisplayListener> displayListenerCaptor =
- ArgumentCaptor.forClass(DisplayListener.class);
- verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
- any(Handler.class));
- DisplayListener displayListener = displayListenerCaptor.getValue();
-
- float refreshRate = 60;
- mInjector.mDisplayInfo.layoutLimitedRefreshRate =
- new RefreshRateRange(refreshRate, refreshRate);
- displayListener.onDisplayChanged(DISPLAY_ID);
-
- Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE);
- assertVoteForPhysicalRefreshRate(vote, /* refreshRate= */ refreshRate);
-
- mInjector.mDisplayInfo.layoutLimitedRefreshRate = null;
- displayListener.onDisplayChanged(DISPLAY_ID);
-
- vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE);
- assertNull(vote);
- }
-
private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) {
return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
}
@@ -2878,19 +2850,12 @@
public static class FakesInjector implements DisplayModeDirector.Injector {
private final FakeDeviceConfig mDeviceConfig;
- private final DisplayInfo mDisplayInfo;
- private final Display mDisplay;
private ContentObserver mBrightnessObserver;
private ContentObserver mSmoothDisplaySettingObserver;
private ContentObserver mForcePeakRefreshRateSettingObserver;
FakesInjector() {
mDeviceConfig = new FakeDeviceConfig();
- mDisplayInfo = new DisplayInfo();
- mDisplayInfo.defaultModeId = MODE_ID;
- mDisplayInfo.supportedModes = new Display.Mode[] {new Display.Mode(MODE_ID,
- 800, 600, /* refreshRate= */ 60)};
- mDisplay = createDisplay(DISPLAY_ID);
}
@NonNull
@@ -2911,25 +2876,16 @@
}
@Override
- public void registerDisplayListener(DisplayListener listener, Handler handler) {}
-
- @Override
public void registerDisplayListener(DisplayListener listener, Handler handler, long flag) {}
@Override
- public Display getDisplay(int displayId) {
- return mDisplay;
- }
-
- @Override
public Display[] getDisplays() {
- return new Display[] { mDisplay };
+ return new Display[] { createDisplay(DISPLAY_ID) };
}
@Override
public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
- displayInfo.copyFrom(mDisplayInfo);
- return true;
+ return false;
}
@Override
@@ -2953,7 +2909,7 @@
}
protected Display createDisplay(int id) {
- return new Display(DisplayManagerGlobal.getInstance(), id, mDisplayInfo,
+ return new Display(DisplayManagerGlobal.getInstance(), id, new DisplayInfo(),
ApplicationProvider.getApplicationContext().getResources());
}
diff --git a/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
index 13540d6..fd1889c 100644
--- a/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
@@ -253,7 +253,7 @@
public boolean getDisplayInfo(int displayId, DisplayInfo displayInfo) {
SparseArray<SurfaceControl.RefreshRateRange> config = mOverriddenConfig.get(displayId);
if (config != null) {
- displayInfo.thermalRefreshRateThrottling = config;
+ displayInfo.refreshRateThermalThrottling = config;
return true;
}
return false;
diff --git a/services/tests/servicestests/src/com/android/server/dreams/DreamControllerTest.java b/services/tests/servicestests/src/com/android/server/dreams/DreamControllerTest.java
index 1ef1197..d5ad815 100644
--- a/services/tests/servicestests/src/com/android/server/dreams/DreamControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/dreams/DreamControllerTest.java
@@ -25,6 +25,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.ServiceConnection;
@@ -54,6 +55,10 @@
private DreamController.Listener mListener;
@Mock
private Context mContext;
+
+ @Mock
+ private ActivityTaskManager mActivityTaskManager;
+
@Mock
private IBinder mIBinder;
@Mock
@@ -80,6 +85,10 @@
when(mIDreamService.asBinder()).thenReturn(mIBinder);
when(mIBinder.queryLocalInterface(anyString())).thenReturn(mIDreamService);
when(mContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true);
+ when(mContext.getSystemService(Context.ACTIVITY_TASK_SERVICE))
+ .thenReturn(mActivityTaskManager);
+ when(mContext.getSystemServiceName(ActivityTaskManager.class))
+ .thenReturn(Context.ACTIVITY_TASK_SERVICE);
mToken = new Binder();
mDreamName = ComponentName.unflattenFromString("dream");
@@ -104,6 +113,37 @@
}
@Test
+ public void startDream_dreamListenerNotified() {
+ // Call dream controller to start dreaming.
+ mDreamController.startDream(mToken, mDreamName, false /*isPreview*/, false /*doze*/,
+ 0 /*userId*/, null /*wakeLock*/, mOverlayName, "test" /*reason*/);
+
+ // Mock service connected.
+ final ServiceConnection serviceConnection = captureServiceConnection();
+ serviceConnection.onServiceConnected(mDreamName, mIBinder);
+ mLooper.dispatchAll();
+
+ // Verify that dream service is called to attach.
+ verify(mListener).onDreamStarted(any());
+ }
+
+ @Test
+ public void stopDream_dreamListenerNotified() {
+ // Start dream.
+ mDreamController.startDream(mToken, mDreamName, false /*isPreview*/, false /*doze*/,
+ 0 /*userId*/, null /*wakeLock*/, mOverlayName, "test" /*reason*/);
+ captureServiceConnection().onServiceConnected(mDreamName, mIBinder);
+ mLooper.dispatchAll();
+
+ // Stop dream.
+ mDreamController.stopDream(true /*immediate*/, "test stop dream" /*reason*/);
+ mLooper.dispatchAll();
+
+ // Verify that dream service is called to detach.
+ verify(mListener).onDreamStopped(any());
+ }
+
+ @Test
public void startDream_attachOnServiceConnectedInPreviewMode() throws RemoteException {
// Call dream controller to start dreaming.
mDreamController.startDream(mToken, mDreamName, true /*isPreview*/, false /*doze*/,
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
index 0f4d4e8..64c05dc 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
@@ -250,20 +250,24 @@
`when`(iInputManager.getInputDevice(DEVICE_ID)).thenReturn(keyboardWithBacklight)
`when`(iInputManager.getLights(DEVICE_ID)).thenReturn(listOf(keyboardBacklight))
- dataStore.setKeyboardBacklightBrightness(
- keyboardWithBacklight.descriptor,
- LIGHT_ID,
- MAX_BRIGHTNESS
- )
+ for (level in 1 until BRIGHTNESS_VALUE_FOR_LEVEL.size) {
+ dataStore.setKeyboardBacklightBrightness(
+ keyboardWithBacklight.descriptor,
+ LIGHT_ID,
+ BRIGHTNESS_VALUE_FOR_LEVEL[level] - 1
+ )
- keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
- keyboardBacklightController.notifyUserActivity()
- testLooper.dispatchNext()
- assertEquals(
- "Keyboard backlight level should be restored to the level saved in the data store",
- Color.argb(MAX_BRIGHTNESS, 0, 0, 0),
- lightColorMap[LIGHT_ID]
- )
+ keyboardBacklightController.onInputDeviceAdded(DEVICE_ID)
+ keyboardBacklightController.notifyUserActivity()
+ testLooper.dispatchNext()
+ assertEquals(
+ "Keyboard backlight level should be restored to the level saved in the data " +
+ "store",
+ Color.argb(BRIGHTNESS_VALUE_FOR_LEVEL[level], 0, 0, 0),
+ lightColorMap[LIGHT_ID]
+ )
+ keyboardBacklightController.onInputDeviceRemoved(DEVICE_ID)
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt b/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
index ea3f3bc..d0d28c3 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
@@ -633,6 +633,30 @@
0,
keyboardLayouts.size
)
+
+ // If IME doesn't have a corresponding language tag, then should show all available
+ // layouts no matter the script code.
+ keyboardLayouts =
+ keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
+ keyboardDevice.identifier, USER_ID, imeInfo, null
+ )
+ assertNotEquals(
+ "New UI: getKeyboardLayoutListForInputDevice API should return all layouts if" +
+ "language tag or subtype not provided",
+ 0,
+ keyboardLayouts.size
+ )
+ assertTrue("New UI: getKeyboardLayoutListForInputDevice API should contain Latin " +
+ "layouts if language tag or subtype not provided",
+ containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
+ )
+ assertTrue("New UI: getKeyboardLayoutListForInputDevice API should contain Cyrillic " +
+ "layouts if language tag or subtype not provided",
+ containsLayout(
+ keyboardLayouts,
+ createLayoutDescriptor("keyboard_layout_russian")
+ )
+ )
}
}
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
index 36c2001..5751db0 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
@@ -19,15 +19,25 @@
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
import static android.media.projection.MediaProjectionManager.TYPE_MIRRORING;
+import static android.media.projection.ReviewGrantedConsentResult.RECORD_CANCEL;
+import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_DISPLAY;
+import static android.media.projection.ReviewGrantedConsentResult.RECORD_CONTENT_TASK;
+import static android.media.projection.ReviewGrantedConsentResult.UNKNOWN;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.testng.Assert.assertThrows;
import android.app.ActivityManagerInternal;
@@ -37,7 +47,9 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.media.projection.IMediaProjection;
import android.media.projection.IMediaProjectionCallback;
+import android.media.projection.ReviewGrantedConsentResult;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -56,6 +68,8 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -108,6 +122,8 @@
private WindowManagerInternal mWindowManagerInternal;
@Mock
private PackageManager mPackageManager;
+ @Captor
+ private ArgumentCaptor<ContentRecordingSession> mSessionCaptor;
@Before
public void setup() throws Exception {
@@ -154,12 +170,15 @@
@Test
public void testCreateProjection() throws NameNotFoundException {
- MediaProjectionManagerService.MediaProjection projection =
- startProjectionPreconditions(/* packageAttemptedReusingGrantedConsent= */ false);
+ // Create a first projection.
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
projection.start(mIMediaProjectionCallback);
+ // We are allowed to create a new projection.
MediaProjectionManagerService.MediaProjection secondProjection =
- startProjectionPreconditions(/* packageAttemptedReusingGrantedConsent= */ false);
+ startProjectionPreconditions();
+
+ // This is a new projection.
assertThat(secondProjection).isNotNull();
assertThat(secondProjection).isNotEqualTo(projection);
}
@@ -167,44 +186,58 @@
@Test
public void testCreateProjection_attemptReuse_noPriorProjectionGrant()
throws NameNotFoundException {
- MediaProjectionManagerService.MediaProjection projection =
- startProjectionPreconditions(/* packageAttemptedReusingGrantedConsent= */ false);
+ // Create a first projection.
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
projection.start(mIMediaProjectionCallback);
- MediaProjectionManagerService.MediaProjection secondProjection =
- startProjectionPreconditions(/* packageAttemptedReusingGrantedConsent= */ true);
-
- assertThat(secondProjection).isNotNull();
- assertThat(secondProjection).isNotEqualTo(projection);
+ // We are not allowed to retrieve the prior projection, since we are not waiting for the
+ // user's consent.
+ assertThat(startReusedProjectionPreconditions()).isNull();
}
@Test
public void testCreateProjection_attemptReuse_priorProjectionGrant_notWaiting()
throws NameNotFoundException {
- MediaProjectionManagerService.MediaProjection projection =
- startProjectionPreconditions(/* packageAttemptedReusingGrantedConsent= */ false);
+ // Create a first projection.
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
projection.start(mIMediaProjectionCallback);
- // Mark this projection as not waiting.
+ // Mark this projection as not waiting for the user to review consent.
doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
any(ContentRecordingSession.class));
mService.setContentRecordingSession(DISPLAY_SESSION);
- // We are allowed to create another projection.
+ // We are not allowed to retrieve the prior projection, since we are not waiting for the
+ // user's consent.
+ assertThat(startReusedProjectionPreconditions()).isNull();
+ }
+
+ @Test
+ public void testCreateProjection_attemptReuse_priorProjectionGrant_waiting()
+ throws NameNotFoundException {
+ // Create a first projection.
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.start(mIMediaProjectionCallback);
+
+ // Mark this projection as waiting for the user to review consent.
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+ mService.setContentRecordingSession(mWaitingDisplaySession);
+
+ // We are allowed to create another projection, reusing a prior grant if necessary.
MediaProjectionManagerService.MediaProjection secondProjection =
- startProjectionPreconditions(/* packageAttemptedReusingGrantedConsent= */ true);
+ startReusedProjectionPreconditions();
+ // This is a new projection, since we are waiting for the user's consent; simply provide
+ // the projection grant from before.
assertThat(secondProjection).isNotNull();
-
- // But this is a new projection.
- assertThat(secondProjection).isNotEqualTo(projection);
+ assertThat(secondProjection).isEqualTo(projection);
}
@Test
public void testCreateProjection_attemptReuse_priorProjectionGrant_waiting_differentPackage()
throws NameNotFoundException {
- MediaProjectionManagerService.MediaProjection projection =
- startProjectionPreconditions(/* packageAttemptedReusingGrantedConsent= */ false);
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
projection.start(mIMediaProjectionCallback);
// Mark this projection as not waiting.
@@ -213,8 +246,7 @@
// We are allowed to create another projection.
MediaProjectionManagerService.MediaProjection secondProjection =
mService.createProjectionInternal(UID + 10, PACKAGE_NAME + "foo",
- TYPE_MIRRORING, /* isPermanentGrant= */ true,
- UserHandle.CURRENT, /* packageAttemptedReusingGrantedConsent= */ true);
+ TYPE_MIRRORING, /* isPermanentGrant= */ true, UserHandle.CURRENT);
assertThat(secondProjection).isNotNull();
@@ -366,6 +398,267 @@
assertThat(mService.isCurrentProjection(projection.asBinder())).isTrue();
}
+ @Test
+ public void testSetUserReviewGrantedConsentResult_noCurrentProjection() {
+ // Gracefully handle invocation without a current projection.
+ mService.setUserReviewGrantedConsentResult(RECORD_CONTENT_DISPLAY,
+ mock(IMediaProjection.class));
+ assertThat(mService.getActiveProjectionInfo()).isNull();
+ verify(mWindowManagerInternal, never()).setContentRecordingSession(any(
+ ContentRecordingSession.class));
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_projectionNotCurrent() throws Exception {
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.start(mIMediaProjectionCallback);
+ assertThat(mService.isCurrentProjection(projection)).isTrue();
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+ // Some other token.
+ final IMediaProjection otherProjection = mock(IMediaProjection.class);
+ doReturn(mock(IBinder.class)).when(otherProjection).asBinder();
+ // Waiting for user to review consent.
+ mService.setContentRecordingSession(mWaitingDisplaySession);
+ mService.setUserReviewGrantedConsentResult(RECORD_CONTENT_DISPLAY, otherProjection);
+
+ // Display result is ignored; only the first session is set.
+ verify(mWindowManagerInternal, times(1)).setContentRecordingSession(
+ eq(mWaitingDisplaySession));
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_projectionNull() throws Exception {
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.start(mIMediaProjectionCallback);
+ assertThat(mService.isCurrentProjection(projection)).isTrue();
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+ // Some other token.
+ final IMediaProjection otherProjection = null;
+ // Waiting for user to review consent.
+ mService.setContentRecordingSession(mWaitingDisplaySession);
+ mService.setUserReviewGrantedConsentResult(RECORD_CONTENT_DISPLAY, otherProjection);
+
+ // Display result is ignored; only the first session is set.
+ verify(mWindowManagerInternal, times(1)).setContentRecordingSession(
+ eq(mWaitingDisplaySession));
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_noVirtualDisplay() throws Exception {
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.start(mIMediaProjectionCallback);
+ // Do not indicate that the virtual display was created.
+ ContentRecordingSession session = mWaitingDisplaySession;
+ session.setVirtualDisplayId(INVALID_DISPLAY);
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+ // Waiting for user to review consent.
+ assertThat(mService.isCurrentProjection(projection)).isTrue();
+ mService.setContentRecordingSession(session);
+
+ mService.setUserReviewGrantedConsentResult(RECORD_CONTENT_DISPLAY, projection);
+ // A session is sent, indicating consent is granted to record but the virtual display isn't
+ // ready yet.
+ verify(mWindowManagerInternal, times(2)).setContentRecordingSession(
+ mSessionCaptor.capture());
+ // Examine latest value.
+ final ContentRecordingSession capturedSession = mSessionCaptor.getValue();
+ assertThat(capturedSession.isWaitingToRecord()).isFalse();
+ assertThat(capturedSession.getVirtualDisplayId()).isEqualTo(INVALID_DISPLAY);
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_thenVirtualDisplayCreated() throws Exception {
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.start(mIMediaProjectionCallback);
+ assertThat(mService.isCurrentProjection(projection)).isTrue();
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+ // Waiting for user to review consent.
+ mService.setContentRecordingSession(mWaitingDisplaySession);
+ mService.setUserReviewGrantedConsentResult(RECORD_CONTENT_DISPLAY, projection);
+
+ // Virtual Display is finally created.
+ projection.notifyVirtualDisplayCreated(10);
+ verifySetSessionWithContent(ContentRecordingSession.RECORD_CONTENT_DISPLAY);
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_unknown_updatedSession() throws Exception {
+ testSetUserReviewGrantedConsentResult_userCancelsSession(
+ /* isSetSessionSuccessful= */ true, UNKNOWN);
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_unknown_failedToUpdateSession()
+ throws Exception {
+ testSetUserReviewGrantedConsentResult_userCancelsSession(
+ /* isSetSessionSuccessful= */ false, UNKNOWN);
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_cancel_updatedSession() throws Exception {
+ testSetUserReviewGrantedConsentResult_userCancelsSession(
+ /* isSetSessionSuccessful= */ true, RECORD_CANCEL);
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_cancel_failedToUpdateSession()
+ throws Exception {
+ testSetUserReviewGrantedConsentResult_userCancelsSession(
+ /* isSetSessionSuccessful= */ false, RECORD_CANCEL);
+ }
+
+ /**
+ * Executes and validates scenario where the consent result indicates the projection ends.
+ */
+ private void testSetUserReviewGrantedConsentResult_userCancelsSession(
+ boolean isSetSessionSuccessful, @ReviewGrantedConsentResult int consentResult)
+ throws Exception {
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.start(mIMediaProjectionCallback);
+ projection.notifyVirtualDisplayCreated(10);
+ // Waiting for user to review consent.
+ assertThat(mService.isCurrentProjection(projection)).isTrue();
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+ mService.setContentRecordingSession(mWaitingDisplaySession);
+
+ doReturn(isSetSessionSuccessful).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+
+ mService.setUserReviewGrantedConsentResult(consentResult, projection);
+ verify(mWindowManagerInternal, atLeastOnce()).setContentRecordingSession(
+ mSessionCaptor.capture());
+ // Null value to stop session.
+ assertThat(mSessionCaptor.getValue()).isNull();
+ assertThat(mService.isCurrentProjection(projection.asBinder())).isFalse();
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_displayMirroring_startedSession()
+ throws NameNotFoundException {
+ testSetUserReviewGrantedConsentResult_startedSession(RECORD_CONTENT_DISPLAY,
+ ContentRecordingSession.RECORD_CONTENT_DISPLAY);
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_displayMirroring_failedToStartSession()
+ throws NameNotFoundException {
+ testSetUserReviewGrantedConsentResult_failedToStartSession(RECORD_CONTENT_DISPLAY,
+ ContentRecordingSession.RECORD_CONTENT_DISPLAY);
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_taskMirroring_startedSession()
+ throws NameNotFoundException {
+ testSetUserReviewGrantedConsentResult_startedSession(RECORD_CONTENT_TASK,
+ ContentRecordingSession.RECORD_CONTENT_TASK);
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_taskMirroring_failedToStartSession()
+ throws NameNotFoundException {
+ testSetUserReviewGrantedConsentResult_failedToStartSession(RECORD_CONTENT_TASK,
+ ContentRecordingSession.RECORD_CONTENT_TASK);
+ }
+
+ /**
+ * Executes and validates scenario where the consent result indicates the projection continues,
+ * and successfully started projection.
+ */
+ private void testSetUserReviewGrantedConsentResult_startedSession(
+ @ReviewGrantedConsentResult int consentResult,
+ @ContentRecordingSession.RecordContent int recordedContent)
+ throws NameNotFoundException {
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.setLaunchCookie(mock(IBinder.class));
+ projection.start(mIMediaProjectionCallback);
+ projection.notifyVirtualDisplayCreated(10);
+ // Waiting for user to review consent.
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+ mService.setContentRecordingSession(mWaitingDisplaySession);
+
+ mService.setUserReviewGrantedConsentResult(consentResult, projection);
+ verifySetSessionWithContent(recordedContent);
+ assertThat(mService.isCurrentProjection(projection)).isTrue();
+ }
+
+ /**
+ * Executes and validates scenario where the consent result indicates the projection continues,
+ * but unable to continue projection.
+ */
+ private void testSetUserReviewGrantedConsentResult_failedToStartSession(
+ @ReviewGrantedConsentResult int consentResult,
+ @ContentRecordingSession.RecordContent int recordedContent)
+ throws NameNotFoundException {
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.start(mIMediaProjectionCallback);
+ projection.notifyVirtualDisplayCreated(10);
+ // Waiting for user to review consent.
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ eq(mWaitingDisplaySession));
+ mService.setContentRecordingSession(mWaitingDisplaySession);
+
+ doReturn(false).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+
+ mService.setUserReviewGrantedConsentResult(consentResult, projection);
+ verifySetSessionWithContent(recordedContent);
+ assertThat(mService.isCurrentProjection(projection.asBinder())).isFalse();
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_displayMirroring_noPriorSession()
+ throws NameNotFoundException {
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.setLaunchCookie(mock(IBinder.class));
+ projection.start(mIMediaProjectionCallback);
+ // Skip setting the prior session details.
+
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+
+ mService.setUserReviewGrantedConsentResult(RECORD_CONTENT_DISPLAY, projection);
+ // Result is ignored & session not updated.
+ verify(mWindowManagerInternal, never()).setContentRecordingSession(any(
+ ContentRecordingSession.class));
+ // Current session continues.
+ assertThat(mService.isCurrentProjection(projection)).isTrue();
+ }
+
+ @Test
+ public void testSetUserReviewGrantedConsentResult_displayMirroring_sessionNotWaiting()
+ throws NameNotFoundException {
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.setLaunchCookie(mock(IBinder.class));
+ projection.start(mIMediaProjectionCallback);
+ // Session is not waiting for user's consent.
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+ mService.setContentRecordingSession(DISPLAY_SESSION);
+
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+
+ mService.setUserReviewGrantedConsentResult(RECORD_CONTENT_DISPLAY, projection);
+ // Result is ignored; only the original session was ever sent.
+ verify(mWindowManagerInternal).setContentRecordingSession(eq(
+ DISPLAY_SESSION));
+ // Current session continues.
+ assertThat(mService.isCurrentProjection(projection)).isTrue();
+ }
+
+ private void verifySetSessionWithContent(@ContentRecordingSession.RecordContent int content) {
+ verify(mWindowManagerInternal, atLeastOnce()).setContentRecordingSession(
+ mSessionCaptor.capture());
+ assertThat(mSessionCaptor.getValue()).isNotNull();
+ assertThat(mSessionCaptor.getValue().getContentToRecord()).isEqualTo(content);
+ }
+
// Set up preconditions for creating a projection.
private MediaProjectionManagerService.MediaProjection createProjectionPreconditions(
MediaProjectionManagerService service)
@@ -373,14 +666,7 @@
doReturn(mAppInfo).when(mPackageManager).getApplicationInfoAsUser(anyString(),
any(ApplicationInfoFlags.class), any(UserHandle.class));
return service.createProjectionInternal(UID, PACKAGE_NAME,
- TYPE_MIRRORING, /* isPermanentGrant= */ true, UserHandle.CURRENT,
- /* packageAttemptedReusingGrantedConsent= */ false);
- }
-
- // Set up preconditions for creating a projection.
- private MediaProjectionManagerService.MediaProjection createProjectionPreconditions()
- throws NameNotFoundException {
- return createProjectionPreconditions(mService);
+ TYPE_MIRRORING, /* isPermanentGrant= */ true, UserHandle.CURRENT);
}
// Set up preconditions for starting a projection, with no foreground service requirements.
@@ -391,19 +677,6 @@
return createProjectionPreconditions(service);
}
- // Set up preconditions for starting a projection, specifying if it is possible to reuse the
- // the current projection.
- private MediaProjectionManagerService.MediaProjection startProjectionPreconditions(
- boolean packageAttemptedReusingGrantedConsent)
- throws NameNotFoundException {
- mAppInfo.privateFlags |= PRIVATE_FLAG_PRIVILEGED;
- doReturn(mAppInfo).when(mPackageManager).getApplicationInfoAsUser(anyString(),
- any(ApplicationInfoFlags.class), any(UserHandle.class));
- return mService.createProjectionInternal(UID, PACKAGE_NAME,
- TYPE_MIRRORING, /* isPermanentGrant= */ true, UserHandle.CURRENT,
- packageAttemptedReusingGrantedConsent);
- }
-
// Set up preconditions for starting a projection, with no foreground service requirements.
private MediaProjectionManagerService.MediaProjection startProjectionPreconditions()
throws NameNotFoundException {
@@ -411,6 +684,15 @@
return createProjectionPreconditions(mService);
}
+ // Set up preconditions for starting a projection, retrieving a pre-existing projection.
+ private MediaProjectionManagerService.MediaProjection startReusedProjectionPreconditions()
+ throws NameNotFoundException {
+ mAppInfo.privateFlags |= PRIVATE_FLAG_PRIVILEGED;
+ doReturn(mAppInfo).when(mPackageManager).getApplicationInfoAsUser(anyString(),
+ any(ApplicationInfoFlags.class), any(UserHandle.class));
+ return mService.getProjectionInternal(UID, PACKAGE_NAME);
+ }
+
private static class FakeIMediaProjectionCallback extends IMediaProjectionCallback.Stub {
@Override
public void onStop() throws RemoteException {
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 94f52bb..5dbc6ab 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -40,7 +40,6 @@
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MAX;
import static android.app.NotificationManager.IMPORTANCE_NONE;
-import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
@@ -5312,7 +5311,7 @@
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(baos.toByteArray())), null);
NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
- restored.populateFromXmlForRestore(parser, getContext());
+ restored.populateFromXmlForRestore(parser, true, getContext());
assertNull(restored.getSound());
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index f6d10b9..c78b03e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -140,6 +140,7 @@
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -170,6 +171,12 @@
Uri.parse("content://" + TEST_AUTHORITY
+ "/internal/audio/media/10?title=Test&canonical=1");
+ private static final Uri ANDROID_RES_SOUND_URI =
+ Uri.parse("android.resource://" + TEST_AUTHORITY + "/raw/test");
+
+ private static final Uri FILE_SOUND_URI =
+ Uri.parse("file://" + TEST_AUTHORITY + "/product/media/test.ogg");
+
@Mock PermissionHelper mPermissionHelper;
@Mock RankingHandler mHandler;
@Mock PackageManager mPm;
@@ -1338,6 +1345,57 @@
assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound());
}
+ /**
+ * Test sound Uri restore retry behavior when channel is restored before package
+ * and then package is installed.
+ */
+ @Test
+ public void testRestoreXml_withNonExistentCanonicalizedSoundUriAndMissingPackage()
+ throws Exception {
+ // canonicalization returns CANONICAL_SOUND_URI for getSoundForBackup (backup part)
+ doReturn(CANONICAL_SOUND_URI)
+ .when(mTestIContentProvider).canonicalize(any(), eq(SOUND_URI));
+
+ NotificationChannel channel =
+ new NotificationChannel("id", "name", IMPORTANCE_LOW);
+ channel.setSound(SOUND_URI, mAudioAttributes);
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+ ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true,
+ USER_SYSTEM, channel.getId());
+
+ // canonicalization / uncanonicalization returns null for the restore part
+ doReturn(null)
+ .when(mTestIContentProvider).canonicalize(any(), eq(CANONICAL_SOUND_URI));
+ doReturn(null)
+ .when(mTestIContentProvider).uncanonicalize(any(), any());
+
+ // simulate package not installed
+ when(mPm.getPackageUidAsUser(PKG_N_MR1, USER_SYSTEM)).thenReturn(UNKNOWN_UID);
+ when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenThrow(
+ new PackageManager.NameNotFoundException());
+
+ loadStreamXml(baos, true, USER_SYSTEM);
+
+ // 1st restore pass fails
+ NotificationChannel actualChannel = mHelper.getNotificationChannel(
+ PKG_N_MR1, UNKNOWN_UID, channel.getId(), false);
+ // sound is CANONICAL_SOUND_URI, unchanged from backup
+ assertEquals(CANONICAL_SOUND_URI, actualChannel.getSound());
+ // sound is flagged as not restored
+ assertFalse(actualChannel.isSoundRestored());
+
+ // package is "installed"
+ when(mPm.getPackageUidAsUser(PKG_N_MR1, USER_SYSTEM)).thenReturn(UID_N_MR1);
+
+ // Trigger 2nd restore pass
+ mHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_N_MR1},
+ new int[]{UID_N_MR1});
+
+ // sound is flagged as restored and set to default URI
+ assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound());
+ assertTrue(actualChannel.isSoundRestored());
+ }
+
/**
* Although we don't make backups with uncanonicalized uris anymore, we used to, so we have to
@@ -1363,7 +1421,9 @@
backupWithUncanonicalizedSoundUri.getBytes(), true, USER_SYSTEM);
NotificationChannel actualChannel = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, id, false);
+
assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound());
+ assertTrue(actualChannel.isSoundRestored());
}
@Test
@@ -1389,6 +1449,73 @@
}
@Test
+ public void testBackupRestoreXml_withAndroidResourceSoundUri() throws Exception {
+ // Mock ContentResolver.getResourceId:
+ // throw exception on restore 1st pass => simulate app not installed yet
+ // then return a valid resource on package update => sim. app installed
+ ContentResolver contentResolver = mock(ContentResolver.class);
+ when(mContext.getContentResolver()).thenReturn(contentResolver);
+ ContentResolver.OpenResourceIdResult resId = mock(
+ ContentResolver.OpenResourceIdResult.class);
+ when(contentResolver.getResourceId(ANDROID_RES_SOUND_URI)).thenReturn(resId).thenThrow(
+ new FileNotFoundException("")).thenReturn(resId);
+
+ mHelper = new PreferencesHelper(mContext, mPm, mHandler, mMockZenModeHelper,
+ mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+
+ NotificationChannel channel =
+ new NotificationChannel("id", "name", IMPORTANCE_LOW);
+ channel.setSound(ANDROID_RES_SOUND_URI, mAudioAttributes);
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+ ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true,
+ USER_SYSTEM, channel.getId());
+
+ // simulate package not installed
+ when(mPm.getPackageUidAsUser(PKG_N_MR1, USER_SYSTEM)).thenReturn(UNKNOWN_UID);
+ when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenThrow(
+ new PackageManager.NameNotFoundException());
+
+ loadStreamXml(baos, true, USER_SYSTEM);
+
+ NotificationChannel actualChannel = mHelper.getNotificationChannel(
+ PKG_N_MR1, UNKNOWN_UID, channel.getId(), false);
+ // sound is ANDROID_RES_SOUND_URI, unchanged from backup
+ assertEquals(ANDROID_RES_SOUND_URI, actualChannel.getSound());
+ // sound is flagged as not restored
+ assertFalse(actualChannel.isSoundRestored());
+
+ // package is "installed"
+ when(mPm.getPackageUidAsUser(PKG_N_MR1, USER_SYSTEM)).thenReturn(UID_N_MR1);
+
+ // Trigger 2nd restore pass
+ mHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_N_MR1},
+ new int[]{UID_N_MR1});
+
+ // sound is flagged as restored
+ assertEquals(ANDROID_RES_SOUND_URI, actualChannel.getSound());
+ assertTrue(actualChannel.isSoundRestored());
+ }
+
+ @Test
+ public void testBackupRestoreXml_withFileResourceSoundUri() throws Exception {
+ NotificationChannel channel =
+ new NotificationChannel("id", "name", IMPORTANCE_LOW);
+ channel.setSound(FILE_SOUND_URI, mAudioAttributes);
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+ ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true,
+ USER_SYSTEM, channel.getId());
+
+ loadStreamXml(baos, true, USER_SYSTEM);
+
+ NotificationChannel actualChannel = mHelper.getNotificationChannel(
+ PKG_N_MR1, UID_N_MR1, channel.getId(), false);
+ // sound is FILE_SOUND_URI, unchanged from backup
+ assertEquals(FILE_SOUND_URI, actualChannel.getSound());
+ // sound is flagged as restored
+ assertTrue(actualChannel.isSoundRestored());
+ }
+
+ @Test
public void testChannelXml_backup() throws Exception {
NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
diff --git a/services/tests/voiceinteractiontests/TEST_MAPPING b/services/tests/voiceinteractiontests/TEST_MAPPING
new file mode 100644
index 0000000..6cbc49a
--- /dev/null
+++ b/services/tests/voiceinteractiontests/TEST_MAPPING
@@ -0,0 +1,17 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksVoiceInteractionTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksVoiceInteractionTests"
+ }
+ ]
+}
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
index 8f0a5e6..bf6901e 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
@@ -21,6 +21,8 @@
import static android.view.KeyEvent.KEYCODE_C;
import static android.view.KeyEvent.KEYCODE_CTRL_LEFT;
import static android.view.KeyEvent.KEYCODE_E;
+import static android.view.KeyEvent.KEYCODE_ENTER;
+import static android.view.KeyEvent.KEYCODE_H;
import static android.view.KeyEvent.KEYCODE_K;
import static android.view.KeyEvent.KEYCODE_M;
import static android.view.KeyEvent.KEYCODE_META_LEFT;
@@ -164,4 +166,24 @@
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_ALT_LEFT}, 0);
mPhoneWindowManager.assertToggleCapsLock();
}
+
+ /**
+ * META + H to go to homescreen
+ */
+ @Test
+ public void testMetaH() {
+ mPhoneWindowManager.overrideLaunchHome();
+ sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_H}, 0);
+ mPhoneWindowManager.assertGoToHomescreen();
+ }
+
+ /**
+ * META + ENTER to go to homescreen
+ */
+ @Test
+ public void testMetaEnter() {
+ mPhoneWindowManager.overrideLaunchHome();
+ sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_ENTER}, 0);
+ mPhoneWindowManager.assertGoToHomescreen();
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
index 6368f47..676bfb0 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
@@ -117,9 +117,9 @@
throw new RuntimeException(e);
}
- for (KeyEvent event: events) {
+ for (int i = count - 1; i >= 0; i--) {
final long eventTime = SystemClock.uptimeMillis();
- final int keyCode = event.getKeyCode();
+ final int keyCode = keyCodes[i];
final KeyEvent upEvent = new KeyEvent(downTime, eventTime, KeyEvent.ACTION_UP, keyCode,
0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
InputDevice.SOURCE_KEYBOARD);
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index a2ee8a4..2665e19 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -353,6 +353,10 @@
() -> LocalServices.getService(eq(StatusBarManagerInternal.class)));
}
+ void overrideLaunchHome() {
+ doNothing().when(mPhoneWindowManager).launchHomeFromHotKey(anyInt());
+ }
+
/**
* Below functions will check the policy behavior could be invoked.
*/
@@ -480,4 +484,9 @@
transitionCaptor.getValue().onAppTransitionFinishedLocked(any());
verify(mPhoneWindowManager).lockNow(null);
}
+
+ void assertGoToHomescreen() {
+ waitForIdle();
+ verify(mPhoneWindowManager).launchHomeFromHotKey(anyInt());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index fb4f2ee..1cec0ef 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -41,8 +41,9 @@
import android.annotation.NonNull;
import android.app.WindowConfiguration;
-import android.content.res.Configuration;
+import android.content.ContentResolver;
import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -439,6 +440,7 @@
public void testDisplayWindowSettingsAppliedOnDisplayReady() {
// Set forced densities for two displays in DisplayWindowSettings
final DisplayContent dc = createMockSimulatedDisplay();
+ final ContentResolver contentResolver = useFakeSettingsProvider();
mDisplayWindowSettings.setForcedDensity(mPrimaryDisplay.getDisplayInfo(), 123,
0 /* userId */);
mDisplayWindowSettings.setForcedDensity(dc.getDisplayInfo(), 456, 0 /* userId */);
@@ -450,15 +452,21 @@
assertFalse(mPrimaryDisplay.mWaitingForConfig);
assertFalse(dc.mWaitingForConfig);
+ final int invalidW = Integer.MAX_VALUE;
+ final int invalidH = Integer.MAX_VALUE;
+ // Verify that applyForcedPropertiesForDefaultDisplay() handles invalid size request.
+ Settings.Global.putString(contentResolver, Settings.Global.DISPLAY_SIZE_FORCED,
+ invalidW + "," + invalidH);
// Notify WM that the displays are ready and check that they are reconfigured.
mWm.displayReady();
waitUntilHandlersIdle();
- final Configuration config = new Configuration();
- mPrimaryDisplay.computeScreenConfiguration(config);
- assertEquals(123, config.densityDpi);
- dc.computeScreenConfiguration(config);
- assertEquals(456, config.densityDpi);
+ // Density is set successfully.
+ assertEquals(123, mPrimaryDisplay.getConfiguration().densityDpi);
+ assertEquals(456, dc.getConfiguration().densityDpi);
+ // Invalid size won't be applied.
+ assertNotEquals(invalidW, mPrimaryDisplay.mBaseDisplayWidth);
+ assertNotEquals(invalidH, mPrimaryDisplay.mBaseDisplayHeight);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
index 77efc4b..ddd630e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
@@ -48,6 +48,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
/**
* Test class for {@link BLASTSyncEngine}.
@@ -225,7 +227,7 @@
parentWC.onSyncFinishedDrawing();
topChildWC.onSyncFinishedDrawing();
// Even though bottom isn't finished, we should see callback because it is occluded by top.
- assertFalse(botChildWC.isSyncFinished());
+ assertFalse(botChildWC.isSyncFinished(botChildWC.getSyncGroup()));
bse.onSurfacePlacement();
verify(listener, times(1)).onTransactionReady(eq(id), notNull());
@@ -416,9 +418,217 @@
assertTrue(bse.isReady(nextId[0]));
}
+ @Test
+ public void testStratifiedParallel() {
+ TestWindowContainer parentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer childWC = new TestWindowContainer(mWm, true /* waiter */);
+ parentWC.addChild(childWC, POSITION_TOP);
+ childWC.mVisibleRequested = true;
+ childWC.mFillsParent = true;
+
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
+
+ BLASTSyncEngine.TransactionReadyListener listenerChild = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+ BLASTSyncEngine.TransactionReadyListener listenerParent = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ // Start a sync-set for the "inner" stuff
+ int childSync = startSyncSet(bse, listenerChild);
+ bse.addToSyncSet(childSync, childWC);
+ bse.setReady(childSync);
+
+ // Start sync-set for the "outer" stuff but explicitly parallel (it should ignore child)
+ int parentSync = startSyncSet(bse, listenerParent, true /* parallel */);
+ bse.addToSyncSet(parentSync, parentWC);
+ bse.setReady(parentSync);
+
+ bse.onSurfacePlacement();
+ // Nothing should have happened yet
+ verify(listenerChild, times(0)).onTransactionReady(anyInt(), any());
+ verify(listenerParent, times(0)).onTransactionReady(anyInt(), any());
+
+ // Now, make PARENT ready, since they are in parallel, this should work
+ parentWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+
+ // Parent should become ready while child is still waiting.
+ verify(listenerParent, times(1)).onTransactionReady(eq(parentSync), notNull());
+ verify(listenerChild, times(0)).onTransactionReady(anyInt(), any());
+
+ // Child should still work
+ childWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+ verify(listenerChild, times(1)).onTransactionReady(eq(childSync), notNull());
+ }
+
+ @Test
+ public void testDependencies() {
+ TestWindowContainer parentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer childWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer childWC2 = new TestWindowContainer(mWm, true /* waiter */);
+ parentWC.addChild(childWC, POSITION_TOP);
+ childWC.mVisibleRequested = true;
+ childWC.mFillsParent = true;
+ childWC2.mVisibleRequested = true;
+ childWC2.mFillsParent = true;
+
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ // This is non-parallel, so it is waiting on the child as-well
+ int sync1 = startSyncSet(bse, listener);
+ bse.addToSyncSet(sync1, parentWC);
+ bse.setReady(sync1);
+
+ // Create one which will end-up depending on the *next* sync
+ int sync2 = startSyncSet(bse, listener, true /* parallel */);
+
+ // If another sync tries to sync on the same subtree, it must now serialize with the other.
+ int sync3 = startSyncSet(bse, listener, true /* parallel */);
+ bse.addToSyncSet(sync3, childWC);
+ bse.addToSyncSet(sync3, childWC2);
+ bse.setReady(sync3);
+
+ // This will depend on sync3.
+ int sync4 = startSyncSet(bse, listener, true /* parallel */);
+ bse.addToSyncSet(sync4, childWC2);
+ bse.setReady(sync4);
+
+ // This makes sync2 depend on sync3. Since both sync2 and sync4 depend on sync3, when sync3
+ // finishes, sync2 should run first since it was created first.
+ bse.addToSyncSet(sync2, childWC2);
+ bse.setReady(sync2);
+
+ childWC.onSyncFinishedDrawing();
+ childWC2.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+
+ // Nothing should be ready yet since everything ultimately depends on sync1.
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ parentWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+
+ // They should all be ready, now, so just verify that the order is expected
+ InOrder readyOrder = Mockito.inOrder(listener);
+ // sync1 is the first one, so it should call ready first.
+ readyOrder.verify(listener).onTransactionReady(eq(sync1), any());
+ // everything else depends on sync3, so it should call ready next.
+ readyOrder.verify(listener).onTransactionReady(eq(sync3), any());
+ // both sync2 and sync4 depend on sync3, but sync2 started first, so it should go next.
+ readyOrder.verify(listener).onTransactionReady(eq(sync2), any());
+ readyOrder.verify(listener).onTransactionReady(eq(sync4), any());
+ }
+
+ @Test
+ public void testStratifiedParallelParentFirst() {
+ TestWindowContainer parentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer childWC = new TestWindowContainer(mWm, true /* waiter */);
+ parentWC.addChild(childWC, POSITION_TOP);
+ childWC.mVisibleRequested = true;
+ childWC.mFillsParent = true;
+
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ // This is parallel, so it should ignore children
+ int sync1 = startSyncSet(bse, listener, true /* parallel */);
+ bse.addToSyncSet(sync1, parentWC);
+ bse.setReady(sync1);
+
+ int sync2 = startSyncSet(bse, listener, true /* parallel */);
+ bse.addToSyncSet(sync2, childWC);
+ bse.setReady(sync2);
+
+ childWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+
+ // Sync2 should have run in parallel
+ verify(listener, times(1)).onTransactionReady(eq(sync2), any());
+ verify(listener, times(0)).onTransactionReady(eq(sync1), any());
+
+ parentWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+
+ verify(listener, times(1)).onTransactionReady(eq(sync1), any());
+ }
+
+ @Test
+ public void testDependencyCycle() {
+ TestWindowContainer parentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer childWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer childWC2 = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer childWC3 = new TestWindowContainer(mWm, true /* waiter */);
+ parentWC.addChild(childWC, POSITION_TOP);
+ childWC.mVisibleRequested = true;
+ childWC.mFillsParent = true;
+ childWC2.mVisibleRequested = true;
+ childWC2.mFillsParent = true;
+ childWC3.mVisibleRequested = true;
+ childWC3.mFillsParent = true;
+
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ // This is non-parallel, so it is waiting on the child as-well
+ int sync1 = startSyncSet(bse, listener);
+ bse.addToSyncSet(sync1, parentWC);
+ bse.setReady(sync1);
+
+ // Sync 2 depends on sync1 AND childWC2
+ int sync2 = startSyncSet(bse, listener, true /* parallel */);
+ bse.addToSyncSet(sync2, childWC);
+ bse.addToSyncSet(sync2, childWC2);
+ bse.setReady(sync2);
+
+ // Sync 3 depends on sync2 AND childWC3
+ int sync3 = startSyncSet(bse, listener, true /* parallel */);
+ bse.addToSyncSet(sync3, childWC2);
+ bse.addToSyncSet(sync3, childWC3);
+ bse.setReady(sync3);
+
+ // Now make sync1 depend on WC3 (which would make it depend on sync3). This would form
+ // a cycle, so it should instead move childWC3 into sync1.
+ bse.addToSyncSet(sync1, childWC3);
+
+ // Sync3 should no-longer have childWC3 as a root-member since a window can currently only
+ // be directly watched by 1 syncgroup maximum (due to implementation of isSyncFinished).
+ assertFalse(bse.getSyncSet(sync3).mRootMembers.contains(childWC3));
+
+ childWC3.onSyncFinishedDrawing();
+ childWC2.onSyncFinishedDrawing();
+ parentWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+
+ // make sure sync3 hasn't run even though all its (original) members are ready
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ // Now finish the last container and make sure everything finishes (didn't "deadlock" due
+ // to a dependency cycle.
+ childWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+
+ InOrder readyOrder = Mockito.inOrder(listener);
+ readyOrder.verify(listener).onTransactionReady(eq(sync1), any());
+ readyOrder.verify(listener).onTransactionReady(eq(sync2), any());
+ readyOrder.verify(listener).onTransactionReady(eq(sync3), any());
+ }
+
static int startSyncSet(BLASTSyncEngine engine,
BLASTSyncEngine.TransactionReadyListener listener) {
- return engine.startSyncSet(listener, BLAST_TIMEOUT_DURATION, "Test");
+ return engine.startSyncSet(listener, BLAST_TIMEOUT_DURATION, "Test", false /* parallel */);
+ }
+
+ static int startSyncSet(BLASTSyncEngine engine,
+ BLASTSyncEngine.TransactionReadyListener listener, boolean parallel) {
+ return engine.startSyncSet(listener, BLAST_TIMEOUT_DURATION, "Test", parallel);
}
static class TestWindowContainer extends WindowContainer {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 653b52b..0dac346 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1196,7 +1196,8 @@
player.start();
player.finish();
- app.getTask().finishSync(mWm.mTransactionFactory.get(), false /* cancel */);
+ app.getTask().finishSync(mWm.mTransactionFactory.get(), app.getTask().getSyncGroup(),
+ false /* cancel */);
// The open transition is finished. Continue to play seamless display change transition,
// so the previous async rotation controller should still exist.
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index 984b868..4530963 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -394,7 +394,7 @@
assertTrue(token.isVisible());
final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
- token.finishSync(t, false /* cancel */);
+ token.finishSync(t, token.getSyncGroup(), false /* cancel */);
transit.onTransactionReady(transit.getSyncId(), t);
dc.mTransitionController.finishTransition(transit);
assertFalse(wallpaperWindow.isVisible());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index d19c996..600681f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -1006,7 +1006,8 @@
BLASTSyncEngine.TransactionReadyListener transactionListener =
mock(BLASTSyncEngine.TransactionReadyListener.class);
- final int id = bse.startSyncSet(transactionListener, BLAST_TIMEOUT_DURATION, "Test");
+ final int id = bse.startSyncSet(transactionListener, BLAST_TIMEOUT_DURATION, "Test",
+ false /* parallel */);
bse.addToSyncSet(id, task);
bse.setReady(id);
bse.onSurfacePlacement();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index f85cdf0..07244a4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -66,6 +66,7 @@
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -81,6 +82,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.Settings;
import android.service.voice.IVoiceInteractionSession;
import android.util.SparseArray;
import android.view.Display;
@@ -109,6 +111,7 @@
import com.android.internal.policy.AttributeCache;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.wm.DisplayWindowSettings.SettingsProvider.SettingsEntry;
import org.junit.After;
@@ -146,6 +149,7 @@
WindowManagerService mWm;
private final IWindow mIWindow = new TestIWindow();
private Session mMockSession;
+ private boolean mUseFakeSettingsProvider;
DisplayInfo mDisplayInfo = new DisplayInfo();
DisplayContent mDefaultDisplay;
@@ -272,16 +276,9 @@
@After
public void tearDown() throws Exception {
- // Revert back to device overrides.
- mAtm.mWindowManager.mLetterboxConfiguration.resetFixedOrientationLetterboxAspectRatio();
- mAtm.mWindowManager.mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
- mAtm.mWindowManager.mLetterboxConfiguration.resetLetterboxVerticalPositionMultiplier();
- mAtm.mWindowManager.mLetterboxConfiguration.resetIsHorizontalReachabilityEnabled();
- mAtm.mWindowManager.mLetterboxConfiguration.resetIsVerticalReachabilityEnabled();
- mAtm.mWindowManager.mLetterboxConfiguration
- .resetIsSplitScreenAspectRatioForUnresizableAppsEnabled();
- mAtm.mWindowManager.mLetterboxConfiguration
- .resetIsDisplayAspectRatioEnabledForFixedOrientationLetterbox();
+ if (mUseFakeSettingsProvider) {
+ FakeSettingsProvider.clearSettingsProvider();
+ }
}
/**
@@ -428,6 +425,17 @@
// Called before display is created.
}
+ /** Avoid writing values to real Settings. */
+ ContentResolver useFakeSettingsProvider() {
+ mUseFakeSettingsProvider = true;
+ FakeSettingsProvider.clearSettingsProvider();
+ final FakeSettingsProvider provider = new FakeSettingsProvider();
+ // SystemServicesTestRule#setUpSystemCore has called spyOn for the ContentResolver.
+ final ContentResolver resolver = mContext.getContentResolver();
+ doReturn(provider.getIContentProvider()).when(resolver).acquireProvider(Settings.AUTHORITY);
+ return resolver;
+ }
+
private WindowState createCommonWindow(WindowState parent, int type, String name) {
final WindowState win = createWindow(parent, type, name);
// Prevent common windows from been IME targets.
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 07dc1c6..18d0c5a 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -49,6 +49,7 @@
import android.telephony.TelephonyManager;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import java.io.FileDescriptor;
@@ -129,6 +130,9 @@
private final Function<SoundTrigger.StatusListener, SoundTriggerModule> mModuleProvider;
private final Supplier<List<ModuleProperties>> mModulePropertiesProvider;
+ @GuardedBy("mLock")
+ private boolean mIsDetached = false;
+
SoundTriggerHelper(Context context,
@NonNull Function<SoundTrigger.StatusListener, SoundTriggerModule> moduleProvider,
int moduleId,
@@ -184,7 +188,7 @@
* recognition.
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
*/
- int startGenericRecognition(UUID modelId, GenericSoundModel soundModel,
+ public int startGenericRecognition(UUID modelId, GenericSoundModel soundModel,
IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig,
boolean runInBatterySaverMode) {
MetricsLogger.count(mContext, "sth_start_recognition", 1);
@@ -195,6 +199,9 @@
}
synchronized (mLock) {
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
ModelData modelData = getOrCreateGenericModelDataLocked(modelId);
if (modelData == null) {
Slog.w(TAG, "Irrecoverable error occurred, check UUID / sound model data.");
@@ -214,7 +221,7 @@
* @param callback The callback for the recognition events related to the given keyphrase.
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
*/
- int startKeyphraseRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
+ public int startKeyphraseRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig,
boolean runInBatterySaverMode) {
synchronized (mLock) {
@@ -223,6 +230,10 @@
return STATUS_ERROR;
}
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
+
if (DBG) {
Slog.d(TAG, "startKeyphraseRecognition for keyphraseId=" + keyphraseId
+ " soundModel=" + soundModel + ", callback=" + callback.asBinder()
@@ -311,7 +322,7 @@
* for the recognition.
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
*/
- int startRecognition(SoundModel soundModel, ModelData modelData,
+ private int startRecognition(SoundModel soundModel, ModelData modelData,
IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig,
int keyphraseId, boolean runInBatterySaverMode) {
synchronized (mLock) {
@@ -385,7 +396,7 @@
*
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
*/
- int stopGenericRecognition(UUID modelId, IRecognitionStatusCallback callback) {
+ public int stopGenericRecognition(UUID modelId, IRecognitionStatusCallback callback) {
synchronized (mLock) {
MetricsLogger.count(mContext, "sth_stop_recognition", 1);
if (callback == null || modelId == null) {
@@ -393,7 +404,9 @@
modelId);
return STATUS_ERROR;
}
-
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
ModelData modelData = mModelDataMap.get(modelId);
if (modelData == null || !modelData.isGenericModel()) {
Slog.w(TAG, "Attempting stopRecognition on invalid model with id:" + modelId);
@@ -418,7 +431,7 @@
*
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
*/
- int stopKeyphraseRecognition(int keyphraseId, IRecognitionStatusCallback callback) {
+ public int stopKeyphraseRecognition(int keyphraseId, IRecognitionStatusCallback callback) {
synchronized (mLock) {
MetricsLogger.count(mContext, "sth_stop_recognition", 1);
if (callback == null) {
@@ -426,7 +439,9 @@
keyphraseId);
return STATUS_ERROR;
}
-
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);
if (modelData == null || !modelData.isKeyphraseModel()) {
Slog.w(TAG, "No model exists for given keyphrase Id " + keyphraseId);
@@ -538,6 +553,11 @@
}
public ModuleProperties getModuleProperties() {
+ synchronized (mLock) {
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
+ }
for (ModuleProperties moduleProperties : mModulePropertiesProvider.get()) {
if (moduleProperties.getId() == mModuleId) {
return moduleProperties;
@@ -547,7 +567,7 @@
return null;
}
- int unloadKeyphraseSoundModel(int keyphraseId) {
+ public int unloadKeyphraseSoundModel(int keyphraseId) {
synchronized (mLock) {
MetricsLogger.count(mContext, "sth_unload_keyphrase_sound_model", 1);
ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);
@@ -555,7 +575,9 @@
|| !modelData.isKeyphraseModel()) {
return STATUS_ERROR;
}
-
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
// Stop recognition if it's the current one.
modelData.setRequested(false);
int status = updateRecognitionLocked(modelData, false);
@@ -574,12 +596,15 @@
}
}
- int unloadGenericSoundModel(UUID modelId) {
+ public int unloadGenericSoundModel(UUID modelId) {
synchronized (mLock) {
MetricsLogger.count(mContext, "sth_unload_generic_sound_model", 1);
if (modelId == null || mModule == null) {
return STATUS_ERROR;
}
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
ModelData modelData = mModelDataMap.get(modelId);
if (modelData == null || !modelData.isGenericModel()) {
Slog.w(TAG, "Unload error: Attempting unload invalid generic model with id:" +
@@ -615,19 +640,25 @@
}
}
- boolean isRecognitionRequested(UUID modelId) {
+ public boolean isRecognitionRequested(UUID modelId) {
synchronized (mLock) {
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
ModelData modelData = mModelDataMap.get(modelId);
return modelData != null && modelData.isRequested();
}
}
- int getGenericModelState(UUID modelId) {
+ public int getGenericModelState(UUID modelId) {
synchronized (mLock) {
MetricsLogger.count(mContext, "sth_get_generic_model_state", 1);
if (modelId == null || mModule == null) {
return STATUS_ERROR;
}
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
ModelData modelData = mModelDataMap.get(modelId);
if (modelData == null || !modelData.isGenericModel()) {
Slog.w(TAG, "GetGenericModelState error: Invalid generic model id:" +
@@ -647,19 +678,20 @@
}
}
- int getKeyphraseModelState(UUID modelId) {
- Slog.w(TAG, "GetKeyphraseModelState error: Not implemented");
- return STATUS_ERROR;
- }
-
- int setParameter(UUID modelId, @ModelParams int modelParam, int value) {
+ public int setParameter(UUID modelId, @ModelParams int modelParam, int value) {
synchronized (mLock) {
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
return setParameterLocked(mModelDataMap.get(modelId), modelParam, value);
}
}
- int setKeyphraseParameter(int keyphraseId, @ModelParams int modelParam, int value) {
+ public int setKeyphraseParameter(int keyphraseId, @ModelParams int modelParam, int value) {
synchronized (mLock) {
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
return setParameterLocked(getKeyphraseModelDataLocked(keyphraseId), modelParam, value);
}
}
@@ -678,14 +710,20 @@
return mModule.setParameter(modelData.getHandle(), modelParam, value);
}
- int getParameter(@NonNull UUID modelId, @ModelParams int modelParam) {
+ public int getParameter(@NonNull UUID modelId, @ModelParams int modelParam) {
synchronized (mLock) {
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
return getParameterLocked(mModelDataMap.get(modelId), modelParam);
}
}
- int getKeyphraseParameter(int keyphraseId, @ModelParams int modelParam) {
+ public int getKeyphraseParameter(int keyphraseId, @ModelParams int modelParam) {
synchronized (mLock) {
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
return getParameterLocked(getKeyphraseModelDataLocked(keyphraseId), modelParam);
}
}
@@ -707,15 +745,21 @@
}
@Nullable
- ModelParamRange queryParameter(@NonNull UUID modelId, @ModelParams int modelParam) {
+ public ModelParamRange queryParameter(@NonNull UUID modelId, @ModelParams int modelParam) {
synchronized (mLock) {
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
return queryParameterLocked(mModelDataMap.get(modelId), modelParam);
}
}
@Nullable
- ModelParamRange queryKeyphraseParameter(int keyphraseId, @ModelParams int modelParam) {
+ public ModelParamRange queryKeyphraseParameter(int keyphraseId, @ModelParams int modelParam) {
synchronized (mLock) {
+ if (mIsDetached) {
+ throw new IllegalStateException("SoundTriggerHelper has been detached");
+ }
return queryParameterLocked(getKeyphraseModelDataLocked(keyphraseId), modelParam);
}
}
@@ -1115,12 +1159,14 @@
*/
public void detach() {
synchronized (mLock) {
+ if (mIsDetached) return;
for (ModelData model : mModelDataMap.values()) {
forceStopAndUnloadModelLocked(model, null);
}
mModelDataMap.clear();
internalClearGlobalStateLocked();
if (mModule != null) {
+ mIsDetached = true;
mModule.detach();
mModule = null;
}
@@ -1289,7 +1335,7 @@
* @param modelData Model data to be used for recognition
* @return True if device state allows recognition to run, false if not.
*/
- boolean isRecognitionAllowedByPowerState(ModelData modelData) {
+ private boolean isRecognitionAllowedByPowerState(ModelData modelData) {
return mSoundTriggerPowerSaveMode == PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED
|| (mSoundTriggerPowerSaveMode == PowerManager.SOUND_TRIGGER_MODE_CRITICAL_ONLY
&& modelData.shouldRunInBatterySaverMode());
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 790be8d..46e634f 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -1663,6 +1663,11 @@
}
@Override
+ public void detach() {
+ mSoundTriggerHelper.detach();
+ }
+
+ @Override
public int unloadKeyphraseModel(int keyphraseId) {
return mSoundTriggerHelper.unloadKeyphraseSoundModel(keyphraseId);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionBinderProxy.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionBinderProxy.java
index dd9fee3..0ef2f06 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionBinderProxy.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionBinderProxy.java
@@ -69,4 +69,9 @@
public SoundTrigger.ModelParamRange queryParameter(int i, int i1) throws RemoteException {
return mDelegate.queryParameter(i, i1);
}
+
+ @Override
+ public void detach() throws RemoteException {
+ mDelegate.detach();
+ }
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionPermissionsDecorator.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionPermissionsDecorator.java
index c0c3e6f..0f8a945 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionPermissionsDecorator.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerSessionPermissionsDecorator.java
@@ -113,6 +113,15 @@
"This object isn't intended to be used as a Binder.");
}
+ @Override
+ public void detach() {
+ try {
+ mDelegate.detach();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
// TODO: Share this code with SoundTriggerMiddlewarePermission.
private boolean isHoldingPermissions() {
try {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 1d7b966..bb50c79 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1856,6 +1856,11 @@
"This object isn't intended to be used as a Binder.");
}
+ @Override
+ public void detach() {
+ mSession.detach();
+ }
+
private int unloadKeyphraseModel(int keyphraseId) {
final long caller = Binder.clearCallingIdentity();
try {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 282b64d..18e4c37 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -3008,4 +3008,14 @@
* @return {@code true} if the timeout duration is set successfully, {@code false} otherwise.
*/
boolean setSatelliteListeningTimeoutDuration(in long timeoutMillis);
+
+ /**
+ * This API can be used by only CTS to update satellite pointing UI app package and class names.
+ *
+ * @param packageName The package name of the satellite pointing UI app.
+ * @param className The class name of the satellite pointing UI app.
+ * @return {@code true} if the satellite pointing UI app package and class is set successfully,
+ * {@code false} otherwise.
+ */
+ boolean setSatellitePointingUiClassName(in String packageName, in String className);
}