summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author wilsonshih <wilsonshih@google.com> 2021-08-30 21:21:12 +0800
committer wilsonshih <wilsonshih@google.com> 2021-09-07 10:46:38 +0800
commitbcb99535f904b1b75f94934b7361d8cf42915796 (patch)
tree96ef55a9965df7a65ef07e98c285306a70a565f6
parentb24386ba3eba270532f741b815667b8262dd155f (diff)
Adding the SurfaceView on splash screen thread.
The SurfaceView of the AVD icon should be create on splash screen thread instead of worker thread, this can guarantee that the first frame of the FrameLayout and AVD will be draw at the same frame. And it also become faster by combining two view in same traversal together. Also stop the AVD animation after splash screen window removed. Bug: 195736516 Test: verify no more Choreographer#doFrame on splash screen thread after splash screen window removed. Change-Id: I5942db8974f1272d9c26ac19b164312e4424be66
-rw-r--r--core/java/android/window/SplashScreenView.java53
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java15
4 files changed, 79 insertions, 19 deletions
diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java
index 6a875d1be65d..f14294ee512e 100644
--- a/core/java/android/window/SplashScreenView.java
+++ b/core/java/android/window/SplashScreenView.java
@@ -59,6 +59,7 @@ import com.android.internal.util.ContrastColorUtil;
import java.time.Duration;
import java.time.Instant;
+import java.util.function.Consumer;
/**
* <p>The view which allows an activity to customize its splash screen exit animation.</p>
@@ -144,6 +145,7 @@ public final class SplashScreenView extends FrameLayout {
private Bitmap mParceledBrandingBitmap;
private Instant mIconAnimationStart;
private Duration mIconAnimationDuration;
+ private Consumer<Runnable> mUiThreadInitTask;
public Builder(@NonNull Context context) {
mContext = context;
@@ -232,6 +234,15 @@ public final class SplashScreenView extends FrameLayout {
}
/**
+ * Set the Runnable that can receive the task which should be executed on UI thread.
+ * @param uiThreadInitTask
+ */
+ public Builder setUiThreadInitConsumer(Consumer<Runnable> uiThreadInitTask) {
+ mUiThreadInitTask = uiThreadInitTask;
+ return this;
+ }
+
+ /**
* Set the Drawable object and size for the branding view.
*/
public Builder setBrandingDrawable(@Nullable Drawable branding, int width, int height) {
@@ -262,7 +273,11 @@ public final class SplashScreenView extends FrameLayout {
// center icon
if (mIconDrawable instanceof SplashScreenView.IconAnimateListener
|| mSurfacePackage != null) {
- view.mIconView = createSurfaceView(view);
+ if (mUiThreadInitTask != null) {
+ mUiThreadInitTask.accept(() -> view.mIconView = createSurfaceView(view));
+ } else {
+ view.mIconView = createSurfaceView(view);
+ }
view.initIconAnimation(mIconDrawable,
mIconAnimationDuration != null ? mIconAnimationDuration.toMillis() : 0);
view.mIconAnimationStart = mIconAnimationStart;
@@ -316,6 +331,7 @@ public final class SplashScreenView extends FrameLayout {
}
private SurfaceView createSurfaceView(@NonNull SplashScreenView view) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "SplashScreenView#createSurfaceView");
final Context viewContext = view.getContext();
final SurfaceView surfaceView = new SurfaceView(viewContext);
surfaceView.setPadding(0, 0, 0, 0);
@@ -361,6 +377,7 @@ public final class SplashScreenView extends FrameLayout {
view.addView(surfaceView);
view.mSurfaceView = surfaceView;
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return surfaceView;
}
}
@@ -532,17 +549,14 @@ public final class SplashScreenView extends FrameLayout {
private void releaseAnimationSurfaceHost() {
if (mSurfaceHost != null && !mIsCopied) {
- final SurfaceControlViewHost finalSurfaceHost = mSurfaceHost;
+ if (DEBUG) {
+ Log.d(TAG,
+ "Shell removed splash screen."
+ + " Releasing SurfaceControlViewHost on thread #"
+ + Thread.currentThread().getId());
+ }
+ releaseIconHost(mSurfaceHost);
mSurfaceHost = null;
- finalSurfaceHost.getView().post(() -> {
- if (DEBUG) {
- Log.d(TAG,
- "Shell removed splash screen."
- + " Releasing SurfaceControlViewHost on thread #"
- + Thread.currentThread().getId());
- }
- finalSurfaceHost.release();
- });
} else if (mSurfacePackage != null && mSurfaceHost == null) {
mSurfacePackage = null;
mClientCallback.sendResult(null);
@@ -550,6 +564,18 @@ public final class SplashScreenView extends FrameLayout {
}
/**
+ * Release the host which hold the SurfaceView of the icon.
+ * @hide
+ */
+ public static void releaseIconHost(SurfaceControlViewHost host) {
+ final Drawable background = host.getView().getBackground();
+ if (background instanceof SplashScreenView.IconAnimateListener) {
+ ((SplashScreenView.IconAnimateListener) background).stopAnimation();
+ }
+ host.release();
+ }
+
+ /**
* Called when this view is attached to an activity. This also makes SystemUI colors
* transparent so the content of splash screen view can draw fully.
*
@@ -640,6 +666,11 @@ public final class SplashScreenView extends FrameLayout {
* @return true if this drawable object can also be animated and it can be played now.
*/
boolean prepareAnimate(long duration, Runnable startListener);
+
+ /**
+ * Stop animation.
+ */
+ void stopAnimation();
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 3db33f3f1216..8df7cbb27807 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -138,12 +138,14 @@ public class SplashscreenContentDrawer {
* null if failed.
*/
void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
- int taskId, Consumer<SplashScreenView> splashScreenViewConsumer) {
+ int taskId, Consumer<SplashScreenView> splashScreenViewConsumer,
+ Consumer<Runnable> uiThreadInitConsumer) {
mSplashscreenWorkerHandler.post(() -> {
SplashScreenView contentView;
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "makeSplashScreenContentView");
- contentView = makeSplashScreenContentView(context, info, suggestType);
+ contentView = makeSplashScreenContentView(context, info, suggestType,
+ uiThreadInitConsumer);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} catch (RuntimeException e) {
Slog.w(TAG, "failed creating starting window content at taskId: "
@@ -239,7 +241,7 @@ public class SplashscreenContentDrawer {
}
private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai,
- @StartingWindowType int suggestType) {
+ @StartingWindowType int suggestType, Consumer<Runnable> uiThreadInitConsumer) {
updateDensity();
getWindowAttrs(context, mTmpAttrs);
@@ -254,6 +256,7 @@ public class SplashscreenContentDrawer {
.setWindowBGColor(themeBGColor)
.overlayDrawable(legacyDrawable)
.chooseStyle(suggestType)
+ .setUiThreadInitConsumer(uiThreadInitConsumer)
.build();
}
@@ -324,6 +327,7 @@ public class SplashscreenContentDrawer {
private int mThemeColor;
private Drawable[] mFinalIconDrawables;
private int mFinalIconSize = mIconSize;
+ private Consumer<Runnable> mUiThreadInitTask;
StartingWindowViewBuilder(@NonNull Context context, @NonNull ActivityInfo aInfo) {
mContext = context;
@@ -345,6 +349,11 @@ public class SplashscreenContentDrawer {
return this;
}
+ StartingWindowViewBuilder setUiThreadInitConsumer(Consumer<Runnable> uiThreadInitTask) {
+ mUiThreadInitTask = uiThreadInitTask;
+ return this;
+ }
+
SplashScreenView build() {
Drawable iconDrawable;
final int animationDuration;
@@ -391,7 +400,8 @@ public class SplashscreenContentDrawer {
animationDuration = 0;
}
- return fillViewWithIcon(mFinalIconSize, mFinalIconDrawables, animationDuration);
+ return fillViewWithIcon(mFinalIconSize, mFinalIconDrawables, animationDuration,
+ mUiThreadInitTask);
}
private class ShapeIconFactory extends BaseIconFactory {
@@ -469,7 +479,7 @@ public class SplashscreenContentDrawer {
}
private SplashScreenView fillViewWithIcon(int iconSize, @Nullable Drawable[] iconDrawable,
- int animationDuration) {
+ int animationDuration, Consumer<Runnable> uiThreadInitTask) {
Drawable foreground = null;
Drawable background = null;
if (iconDrawable != null) {
@@ -485,7 +495,8 @@ public class SplashscreenContentDrawer {
.setIconSize(iconSize)
.setIconBackground(background)
.setCenterViewDrawable(foreground)
- .setAnimationDurationMillis(animationDuration);
+ .setAnimationDurationMillis(animationDuration)
+ .setUiThreadInitConsumer(uiThreadInitTask);
if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
&& mTmpAttrs.mBrandingImage != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
index 951b97e791c9..f0685a81d25f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
@@ -304,6 +304,13 @@ public class SplashscreenIconDrawableFactory {
return true;
}
+ @Override
+ public void stopAnimation() {
+ if (mIconAnimator != null) {
+ mIconAnimator.end();
+ }
+ }
+
private final Callback mCallback = new Callback() {
@Override
public void invalidateDrawable(@NonNull Drawable who) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 645b881558fb..debe6d56dd92 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -332,7 +332,7 @@ public class StartingSurfaceDrawer {
mSysuiProxy.requestTopUi(true, TAG);
}
mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId,
- viewSupplier::setView);
+ viewSupplier::setView, viewSupplier::setUiThreadInitTask);
try {
if (addWindow(taskId, appToken, rootLayout, display, params, suggestType)) {
// We use the splash screen worker thread to create SplashScreenView while adding
@@ -367,6 +367,7 @@ public class StartingSurfaceDrawer {
private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
private SplashScreenView mView;
private boolean mIsViewSet;
+ private Runnable mUiThreadInitTask;
void setView(SplashScreenView view) {
synchronized (this) {
mView = view;
@@ -375,6 +376,12 @@ public class StartingSurfaceDrawer {
}
}
+ void setUiThreadInitTask(Runnable initTask) {
+ synchronized (this) {
+ mUiThreadInitTask = initTask;
+ }
+ }
+
@Override
public @Nullable SplashScreenView get() {
synchronized (this) {
@@ -384,6 +391,10 @@ public class StartingSurfaceDrawer {
} catch (InterruptedException ignored) {
}
}
+ if (mUiThreadInitTask != null) {
+ mUiThreadInitTask.run();
+ mUiThreadInitTask = null;
+ }
return mView;
}
}
@@ -506,7 +517,7 @@ public class StartingSurfaceDrawer {
Slog.v(TAG, reason + "the splash screen. Releasing SurfaceControlViewHost for task:"
+ taskId);
}
- viewHost.getView().post(viewHost::release);
+ SplashScreenView.releaseIconHost(viewHost);
}
protected boolean addWindow(int taskId, IBinder appToken, View view, Display display,