diff options
| author | 2021-09-07 10:45:02 +0000 | |
|---|---|---|
| committer | 2021-09-07 10:45:02 +0000 | |
| commit | 50c8b2d994ca64e3883015efc5e16837cfc7f887 (patch) | |
| tree | dc1edaeca2c236fabe950a3120e12ec30b79f835 | |
| parent | 6fbb385f246a4cd501a0ab81516f49f3bb1eb604 (diff) | |
| parent | bcb99535f904b1b75f94934b7361d8cf42915796 (diff) | |
Merge "Adding the SurfaceView on splash screen thread." into sc-v2-dev
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, |