Merge "Avoid cutting off AVD on splash screen."
This commit is contained in:
committed by
Android (Google) Code Review
commit
77832901df
@@ -22,6 +22,9 @@ import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLAS
|
||||
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
|
||||
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
||||
|
||||
import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MAX_ANIMATION_DURATION;
|
||||
import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MINIMAL_ANIMATION_DURATION;
|
||||
|
||||
import android.annotation.ColorInt;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
@@ -46,6 +49,7 @@ import android.graphics.drawable.LayerDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.SystemClock;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
@@ -322,6 +326,33 @@ public class SplashscreenContentDrawer {
|
||||
private int mAnimationDuration = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optimal animation duration to keep the splash screen from showing.
|
||||
*
|
||||
* @param animationDuration The animation duration defined from app.
|
||||
* @param appReadyDuration The real duration from the starting the app to the first app window
|
||||
* drawn.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static long getShowingDuration(long animationDuration, long appReadyDuration) {
|
||||
if (animationDuration <= appReadyDuration) {
|
||||
// app window ready took longer time than animation, it can be removed ASAP.
|
||||
return appReadyDuration;
|
||||
}
|
||||
if (appReadyDuration < MAX_ANIMATION_DURATION) {
|
||||
if (animationDuration > MAX_ANIMATION_DURATION
|
||||
|| appReadyDuration < MINIMAL_ANIMATION_DURATION) {
|
||||
// animation is too long or too short, cut off with minimal duration
|
||||
return MINIMAL_ANIMATION_DURATION;
|
||||
}
|
||||
// animation is longer than dOpt but shorter than max, allow it to play till finish
|
||||
return MAX_ANIMATION_DURATION;
|
||||
}
|
||||
// the shortest duration is longer than dMax, cut off no matter how long the animation
|
||||
// will be.
|
||||
return appReadyDuration;
|
||||
}
|
||||
|
||||
private class StartingWindowViewBuilder {
|
||||
private final Context mContext;
|
||||
private final ActivityInfo mActivityInfo;
|
||||
@@ -977,9 +1008,27 @@ public class SplashscreenContentDrawer {
|
||||
* Create and play the default exit animation for splash screen view.
|
||||
*/
|
||||
void applyExitAnimation(SplashScreenView view, SurfaceControl leash,
|
||||
Rect frame, Runnable finishCallback) {
|
||||
final SplashScreenExitAnimation animation = new SplashScreenExitAnimation(mContext, view,
|
||||
leash, frame, mMainWindowShiftLength, mTransactionPool, finishCallback);
|
||||
animation.startAnimations();
|
||||
Rect frame, Runnable finishCallback, long createTime) {
|
||||
final Runnable playAnimation = () -> {
|
||||
final SplashScreenExitAnimation animation = new SplashScreenExitAnimation(mContext,
|
||||
view, leash, frame, mMainWindowShiftLength, mTransactionPool, finishCallback);
|
||||
animation.startAnimations();
|
||||
};
|
||||
if (view.getIconView() == null) {
|
||||
playAnimation.run();
|
||||
return;
|
||||
}
|
||||
final long appReadyDuration = SystemClock.uptimeMillis() - createTime;
|
||||
final long animDuration = view.getIconAnimationDuration() != null
|
||||
? view.getIconAnimationDuration().toMillis() : 0;
|
||||
final long minimumShowingDuration = getShowingDuration(animDuration, appReadyDuration);
|
||||
final long delayed = minimumShowingDuration - appReadyDuration;
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
|
||||
"applyExitAnimation delayed: %s", delayed);
|
||||
if (delayed > 0) {
|
||||
view.postDelayed(playAnimation, delayed);
|
||||
} else {
|
||||
playAnimation.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.hardware.display.DisplayManager;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
@@ -120,6 +121,25 @@ public class StartingSurfaceDrawer {
|
||||
private StartingSurface.SysuiProxy mSysuiProxy;
|
||||
private final StartingWindowRemovalInfo mTmpRemovalInfo = new StartingWindowRemovalInfo();
|
||||
|
||||
/**
|
||||
* The minimum duration during which the splash screen is shown when the splash screen icon is
|
||||
* animated.
|
||||
*/
|
||||
static final long MINIMAL_ANIMATION_DURATION = 400L;
|
||||
|
||||
/**
|
||||
* Allow the icon style splash screen to be displayed for longer to give time for the animation
|
||||
* to finish, i.e. the extra buffer time to keep the splash screen if the animation is slightly
|
||||
* longer than the {@link #MINIMAL_ANIMATION_DURATION} duration.
|
||||
*/
|
||||
static final long TIME_WINDOW_DURATION = 100L;
|
||||
|
||||
/**
|
||||
* The maximum duration during which the splash screen will be shown if the application is ready
|
||||
* to show before the icon animation finishes.
|
||||
*/
|
||||
static final long MAX_ANIMATION_DURATION = MINIMAL_ANIMATION_DURATION + TIME_WINDOW_DURATION;
|
||||
|
||||
/**
|
||||
* @param splashScreenExecutor The thread used to control add and remove starting window.
|
||||
*/
|
||||
@@ -593,7 +613,8 @@ public class StartingSurfaceDrawer {
|
||||
if (removalInfo.playRevealAnimation) {
|
||||
mSplashscreenContentDrawer.applyExitAnimation(record.mContentView,
|
||||
removalInfo.windowAnimationLeash, removalInfo.mainFrame,
|
||||
() -> removeWindowInner(record.mDecorView, true));
|
||||
() -> removeWindowInner(record.mDecorView, true),
|
||||
record.mCreateTime);
|
||||
} else {
|
||||
// the SplashScreenView has been copied to client, hide the view to skip
|
||||
// default exit animation
|
||||
@@ -641,6 +662,7 @@ public class StartingSurfaceDrawer {
|
||||
private boolean mSetSplashScreen;
|
||||
private @StartingWindowType int mSuggestType;
|
||||
private int mBGColor;
|
||||
private final long mCreateTime;
|
||||
|
||||
StartingWindowRecord(IBinder appToken, View decorView,
|
||||
TaskSnapshotWindow taskSnapshotWindow, @StartingWindowType int suggestType) {
|
||||
@@ -651,6 +673,7 @@ public class StartingSurfaceDrawer {
|
||||
mBGColor = mTaskSnapshotWindow.getBackgroundColor();
|
||||
}
|
||||
mSuggestType = suggestType;
|
||||
mCreateTime = SystemClock.uptimeMillis();
|
||||
}
|
||||
|
||||
private void setSplashScreenView(SplashScreenView splashScreenView) {
|
||||
|
||||
@@ -24,6 +24,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||
import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MAX_ANIMATION_DURATION;
|
||||
import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MINIMAL_ANIMATION_DURATION;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
@@ -297,6 +299,56 @@ public class StartingSurfaceDrawerTests {
|
||||
assertEquals(mStartingSurfaceDrawer.mStartingWindowRecords.size(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimumAnimationDuration() {
|
||||
final long maxDuration = MAX_ANIMATION_DURATION;
|
||||
final long minDuration = MINIMAL_ANIMATION_DURATION;
|
||||
|
||||
final long shortDuration = minDuration - 1;
|
||||
final long medianShortDuration = minDuration + 1;
|
||||
final long medianLongDuration = maxDuration - 1;
|
||||
final long longAppDuration = maxDuration + 1;
|
||||
|
||||
// static icon
|
||||
assertEquals(shortDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
0, shortDuration));
|
||||
// median launch + static icon
|
||||
assertEquals(medianShortDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
0, medianShortDuration));
|
||||
// long launch + static icon
|
||||
assertEquals(longAppDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
0, longAppDuration));
|
||||
|
||||
// fast launch + animatable icon
|
||||
assertEquals(shortDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
shortDuration, shortDuration));
|
||||
assertEquals(minDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
medianShortDuration, shortDuration));
|
||||
assertEquals(minDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
longAppDuration, shortDuration));
|
||||
|
||||
// median launch + animatable icon
|
||||
assertEquals(medianShortDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
shortDuration, medianShortDuration));
|
||||
assertEquals(medianShortDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
medianShortDuration, medianShortDuration));
|
||||
assertEquals(minDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
longAppDuration, medianShortDuration));
|
||||
// between min < max launch + animatable icon
|
||||
assertEquals(medianLongDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
medianShortDuration, medianLongDuration));
|
||||
assertEquals(maxDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
medianLongDuration, medianShortDuration));
|
||||
|
||||
// long launch + animatable icon
|
||||
assertEquals(longAppDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
shortDuration, longAppDuration));
|
||||
assertEquals(longAppDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
medianShortDuration, longAppDuration));
|
||||
assertEquals(longAppDuration, SplashscreenContentDrawer.getShowingDuration(
|
||||
longAppDuration, longAppDuration));
|
||||
}
|
||||
|
||||
private StartingWindowInfo createWindowInfo(int taskId, int themeResId) {
|
||||
StartingWindowInfo windowInfo = new StartingWindowInfo();
|
||||
final ActivityInfo info = new ActivityInfo();
|
||||
|
||||
Reference in New Issue
Block a user