Merge "Add timeouts to animations in UserSwitchingDialog." into udc-dev am: d3446e4eb8 am: d847e507fe am: 40a01945bd

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22967258

Change-Id: Ic704e40c8936169fd388b48890fe66f6c725b4f1
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot
2023-05-02 22:30:32 +00:00
committed by Automerger Merge Worker

View File

@@ -33,6 +33,8 @@ import android.graphics.Shader;
import android.graphics.drawable.Animatable2; import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.os.Trace; import android.os.Trace;
import android.os.UserHandle; import android.os.UserHandle;
@@ -53,6 +55,8 @@ import com.android.internal.util.ObjectUtils;
import com.android.internal.util.UserIcons; import com.android.internal.util.UserIcons;
import com.android.server.wm.WindowManagerService; import com.android.server.wm.WindowManagerService;
import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* Dialog to show during the user switch. This dialog shows target user's name and their profile * Dialog to show during the user switch. This dialog shows target user's name and their profile
* picture with a circular spinner animation around it if the animations for this dialog are not * picture with a circular spinner animation around it if the animations for this dialog are not
@@ -64,9 +68,14 @@ class UserSwitchingDialog extends Dialog {
// User switching doesn't happen that frequently, so it doesn't hurt to have it always on // User switching doesn't happen that frequently, so it doesn't hurt to have it always on
protected static final boolean DEBUG = true; protected static final boolean DEBUG = true;
private static final long DIALOG_SHOW_HIDE_ANIMATION_DURATION_MS = 300; private static final long DIALOG_SHOW_HIDE_ANIMATION_DURATION_MS = 300;
private final boolean mDisableAnimations; private final boolean mDisableAnimations;
// Time to wait for the onAnimationEnd() callbacks before moving on
private static final int ANIMATION_TIMEOUT_MS = 1000;
private final Handler mHandler = new Handler(Looper.myLooper());
protected final UserInfo mOldUser; protected final UserInfo mOldUser;
protected final UserInfo mNewUser; protected final UserInfo mNewUser;
private final String mSwitchingFromSystemUserMessage; private final String mSwitchingFromSystemUserMessage;
@@ -180,7 +189,7 @@ class UserSwitchingDialog extends Dialog {
@Override @Override
public void show() { public void show() {
asyncTraceBegin("", 0); asyncTraceBegin("dialog", 0);
super.show(); super.show();
} }
@@ -188,7 +197,7 @@ class UserSwitchingDialog extends Dialog {
public void dismiss() { public void dismiss() {
super.dismiss(); super.dismiss();
stopFreezingScreen(); stopFreezingScreen();
asyncTraceEnd("", 0); asyncTraceEnd("dialog", 0);
} }
public void show(@NonNull Runnable onShown) { public void show(@NonNull Runnable onShown) {
@@ -217,20 +226,18 @@ class UserSwitchingDialog extends Dialog {
if (!mNeedToFreezeScreen) { if (!mNeedToFreezeScreen) {
return; return;
} }
if (DEBUG) Slog.d(TAG, "startFreezingScreen"); traceBegin("startFreezingScreen");
Trace.traceBegin(TRACE_TAG, "startFreezingScreen");
mWindowManager.startFreezingScreen(0, 0); mWindowManager.startFreezingScreen(0, 0);
Trace.traceEnd(TRACE_TAG); traceEnd("startFreezingScreen");
} }
private void stopFreezingScreen() { private void stopFreezingScreen() {
if (!mNeedToFreezeScreen) { if (!mNeedToFreezeScreen) {
return; return;
} }
if (DEBUG) Slog.d(TAG, "stopFreezingScreen"); traceBegin("stopFreezingScreen");
Trace.traceBegin(TRACE_TAG, "stopFreezingScreen");
mWindowManager.stopFreezingScreen(); mWindowManager.stopFreezingScreen();
Trace.traceEnd(TRACE_TAG); traceEnd("stopFreezingScreen");
} }
private void startShowAnimation(Runnable onAnimationEnd) { private void startShowAnimation(Runnable onAnimationEnd) {
@@ -238,13 +245,13 @@ class UserSwitchingDialog extends Dialog {
onAnimationEnd.run(); onAnimationEnd.run();
return; return;
} }
asyncTraceBegin("-showAnimation", 1); asyncTraceBegin("showAnimation", 1);
startDialogAnimation(new AlphaAnimation(0, 1), () -> { startDialogAnimation("show", new AlphaAnimation(0, 1), () -> {
asyncTraceEnd("-showAnimation", 1); asyncTraceEnd("showAnimation", 1);
asyncTraceBegin("-spinnerAnimation", 2); asyncTraceBegin("spinnerAnimation", 2);
startProgressAnimation(() -> { startProgressAnimation(() -> {
asyncTraceEnd("-spinnerAnimation", 2); asyncTraceEnd("spinnerAnimation", 2);
onAnimationEnd.run(); onAnimationEnd.run();
}); });
@@ -257,9 +264,9 @@ class UserSwitchingDialog extends Dialog {
onAnimationEnd.run(); onAnimationEnd.run();
return; return;
} }
asyncTraceBegin("-dismissAnimation", 3); asyncTraceBegin("dismissAnimation", 3);
startDialogAnimation(new AlphaAnimation(1, 0), () -> { startDialogAnimation("dismiss", new AlphaAnimation(1, 0), () -> {
asyncTraceEnd("-dismissAnimation", 3); asyncTraceEnd("dismissAnimation", 3);
onAnimationEnd.run(); onAnimationEnd.run();
}); });
@@ -271,10 +278,11 @@ class UserSwitchingDialog extends Dialog {
onAnimationEnd.run(); onAnimationEnd.run();
return; return;
} }
final Runnable onAnimationEndWithTimeout = animationWithTimeout("spinner", onAnimationEnd);
avd.registerAnimationCallback(new Animatable2.AnimationCallback() { avd.registerAnimationCallback(new Animatable2.AnimationCallback() {
@Override @Override
public void onAnimationEnd(Drawable drawable) { public void onAnimationEnd(Drawable drawable) {
onAnimationEnd.run(); onAnimationEndWithTimeout.run();
} }
}); });
avd.start(); avd.start();
@@ -291,12 +299,13 @@ class UserSwitchingDialog extends Dialog {
return null; return null;
} }
private void startDialogAnimation(Animation animation, Runnable onAnimationEnd) { private void startDialogAnimation(String name, Animation animation, Runnable onAnimationEnd) {
final View view = findViewById(R.id.content); final View view = findViewById(R.id.content);
if (mDisableAnimations || view == null) { if (mDisableAnimations || view == null) {
onAnimationEnd.run(); onAnimationEnd.run();
return; return;
} }
final Runnable onAnimationEndWithTimeout = animationWithTimeout(name, onAnimationEnd);
animation.setDuration(DIALOG_SHOW_HIDE_ANIMATION_DURATION_MS); animation.setDuration(DIALOG_SHOW_HIDE_ANIMATION_DURATION_MS);
animation.setAnimationListener(new Animation.AnimationListener() { animation.setAnimationListener(new Animation.AnimationListener() {
@Override @Override
@@ -306,7 +315,7 @@ class UserSwitchingDialog extends Dialog {
@Override @Override
public void onAnimationEnd(Animation animation) { public void onAnimationEnd(Animation animation) {
onAnimationEnd.run(); onAnimationEndWithTimeout.run();
} }
@Override @Override
@@ -317,11 +326,39 @@ class UserSwitchingDialog extends Dialog {
view.startAnimation(animation); view.startAnimation(animation);
} }
private Runnable animationWithTimeout(String name, Runnable onAnimationEnd) {
final AtomicBoolean isFirst = new AtomicBoolean(true);
final Runnable onAnimationEndOrTimeout = () -> {
if (isFirst.getAndSet(false)) {
mHandler.removeCallbacksAndMessages(null);
onAnimationEnd.run();
}
};
mHandler.postDelayed(() -> {
Slog.w(TAG, name + " animation not completed in " + ANIMATION_TIMEOUT_MS + " ms");
onAnimationEndOrTimeout.run();
}, ANIMATION_TIMEOUT_MS);
return onAnimationEndOrTimeout;
}
private void asyncTraceBegin(String subTag, int subCookie) { private void asyncTraceBegin(String subTag, int subCookie) {
if (DEBUG) Slog.d(TAG, "asyncTraceBegin-" + subTag);
Trace.asyncTraceBegin(TRACE_TAG, TAG + subTag, mTraceCookie + subCookie); Trace.asyncTraceBegin(TRACE_TAG, TAG + subTag, mTraceCookie + subCookie);
} }
private void asyncTraceEnd(String subTag, int subCookie) { private void asyncTraceEnd(String subTag, int subCookie) {
Trace.asyncTraceEnd(TRACE_TAG, TAG + subTag, mTraceCookie + subCookie); Trace.asyncTraceEnd(TRACE_TAG, TAG + subTag, mTraceCookie + subCookie);
if (DEBUG) Slog.d(TAG, "asyncTraceEnd-" + subTag);
}
private void traceBegin(String msg) {
if (DEBUG) Slog.d(TAG, "traceBegin-" + msg);
Trace.traceBegin(TRACE_TAG, msg);
}
private void traceEnd(String msg) {
Trace.traceEnd(TRACE_TAG);
if (DEBUG) Slog.d(TAG, "traceEnd-" + msg);
} }
} }