Merge "Adding the SurfaceView on splash screen thread." into sc-v2-dev

This commit is contained in:
Wei Sheng Shih
2021-09-07 10:45:02 +00:00
committed by Android (Google) Code Review
4 changed files with 79 additions and 19 deletions

View File

@@ -59,6 +59,7 @@ import com.android.internal.util.ContrastColorUtil;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.function.Consumer;
/** /**
* <p>The view which allows an activity to customize its splash screen exit animation.</p> * <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 Bitmap mParceledBrandingBitmap;
private Instant mIconAnimationStart; private Instant mIconAnimationStart;
private Duration mIconAnimationDuration; private Duration mIconAnimationDuration;
private Consumer<Runnable> mUiThreadInitTask;
public Builder(@NonNull Context context) { public Builder(@NonNull Context context) {
mContext = context; mContext = context;
@@ -231,6 +233,15 @@ public final class SplashScreenView extends FrameLayout {
return this; return this;
} }
/**
* 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. * Set the Drawable object and size for the branding view.
*/ */
@@ -262,7 +273,11 @@ public final class SplashScreenView extends FrameLayout {
// center icon // center icon
if (mIconDrawable instanceof SplashScreenView.IconAnimateListener if (mIconDrawable instanceof SplashScreenView.IconAnimateListener
|| mSurfacePackage != null) { || mSurfacePackage != null) {
view.mIconView = createSurfaceView(view); if (mUiThreadInitTask != null) {
mUiThreadInitTask.accept(() -> view.mIconView = createSurfaceView(view));
} else {
view.mIconView = createSurfaceView(view);
}
view.initIconAnimation(mIconDrawable, view.initIconAnimation(mIconDrawable,
mIconAnimationDuration != null ? mIconAnimationDuration.toMillis() : 0); mIconAnimationDuration != null ? mIconAnimationDuration.toMillis() : 0);
view.mIconAnimationStart = mIconAnimationStart; view.mIconAnimationStart = mIconAnimationStart;
@@ -316,6 +331,7 @@ public final class SplashScreenView extends FrameLayout {
} }
private SurfaceView createSurfaceView(@NonNull SplashScreenView view) { private SurfaceView createSurfaceView(@NonNull SplashScreenView view) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "SplashScreenView#createSurfaceView");
final Context viewContext = view.getContext(); final Context viewContext = view.getContext();
final SurfaceView surfaceView = new SurfaceView(viewContext); final SurfaceView surfaceView = new SurfaceView(viewContext);
surfaceView.setPadding(0, 0, 0, 0); surfaceView.setPadding(0, 0, 0, 0);
@@ -361,6 +377,7 @@ public final class SplashScreenView extends FrameLayout {
view.addView(surfaceView); view.addView(surfaceView);
view.mSurfaceView = surfaceView; view.mSurfaceView = surfaceView;
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return surfaceView; return surfaceView;
} }
} }
@@ -532,23 +549,32 @@ public final class SplashScreenView extends FrameLayout {
private void releaseAnimationSurfaceHost() { private void releaseAnimationSurfaceHost() {
if (mSurfaceHost != null && !mIsCopied) { 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; 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) { } else if (mSurfacePackage != null && mSurfaceHost == null) {
mSurfacePackage = null; mSurfacePackage = null;
mClientCallback.sendResult(null); mClientCallback.sendResult(null);
} }
} }
/**
* 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 * 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. * 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. * @return true if this drawable object can also be animated and it can be played now.
*/ */
boolean prepareAnimate(long duration, Runnable startListener); boolean prepareAnimate(long duration, Runnable startListener);
/**
* Stop animation.
*/
void stopAnimation();
} }
/** /**

View File

@@ -138,12 +138,14 @@ public class SplashscreenContentDrawer {
* null if failed. * null if failed.
*/ */
void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info, void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
int taskId, Consumer<SplashScreenView> splashScreenViewConsumer) { int taskId, Consumer<SplashScreenView> splashScreenViewConsumer,
Consumer<Runnable> uiThreadInitConsumer) {
mSplashscreenWorkerHandler.post(() -> { mSplashscreenWorkerHandler.post(() -> {
SplashScreenView contentView; SplashScreenView contentView;
try { try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "makeSplashScreenContentView"); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "makeSplashScreenContentView");
contentView = makeSplashScreenContentView(context, info, suggestType); contentView = makeSplashScreenContentView(context, info, suggestType,
uiThreadInitConsumer);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} catch (RuntimeException e) { } catch (RuntimeException e) {
Slog.w(TAG, "failed creating starting window content at taskId: " Slog.w(TAG, "failed creating starting window content at taskId: "
@@ -239,7 +241,7 @@ public class SplashscreenContentDrawer {
} }
private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai, private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai,
@StartingWindowType int suggestType) { @StartingWindowType int suggestType, Consumer<Runnable> uiThreadInitConsumer) {
updateDensity(); updateDensity();
getWindowAttrs(context, mTmpAttrs); getWindowAttrs(context, mTmpAttrs);
@@ -254,6 +256,7 @@ public class SplashscreenContentDrawer {
.setWindowBGColor(themeBGColor) .setWindowBGColor(themeBGColor)
.overlayDrawable(legacyDrawable) .overlayDrawable(legacyDrawable)
.chooseStyle(suggestType) .chooseStyle(suggestType)
.setUiThreadInitConsumer(uiThreadInitConsumer)
.build(); .build();
} }
@@ -324,6 +327,7 @@ public class SplashscreenContentDrawer {
private int mThemeColor; private int mThemeColor;
private Drawable[] mFinalIconDrawables; private Drawable[] mFinalIconDrawables;
private int mFinalIconSize = mIconSize; private int mFinalIconSize = mIconSize;
private Consumer<Runnable> mUiThreadInitTask;
StartingWindowViewBuilder(@NonNull Context context, @NonNull ActivityInfo aInfo) { StartingWindowViewBuilder(@NonNull Context context, @NonNull ActivityInfo aInfo) {
mContext = context; mContext = context;
@@ -345,6 +349,11 @@ public class SplashscreenContentDrawer {
return this; return this;
} }
StartingWindowViewBuilder setUiThreadInitConsumer(Consumer<Runnable> uiThreadInitTask) {
mUiThreadInitTask = uiThreadInitTask;
return this;
}
SplashScreenView build() { SplashScreenView build() {
Drawable iconDrawable; Drawable iconDrawable;
final int animationDuration; final int animationDuration;
@@ -391,7 +400,8 @@ public class SplashscreenContentDrawer {
animationDuration = 0; animationDuration = 0;
} }
return fillViewWithIcon(mFinalIconSize, mFinalIconDrawables, animationDuration); return fillViewWithIcon(mFinalIconSize, mFinalIconDrawables, animationDuration,
mUiThreadInitTask);
} }
private class ShapeIconFactory extends BaseIconFactory { private class ShapeIconFactory extends BaseIconFactory {
@@ -469,7 +479,7 @@ public class SplashscreenContentDrawer {
} }
private SplashScreenView fillViewWithIcon(int iconSize, @Nullable Drawable[] iconDrawable, private SplashScreenView fillViewWithIcon(int iconSize, @Nullable Drawable[] iconDrawable,
int animationDuration) { int animationDuration, Consumer<Runnable> uiThreadInitTask) {
Drawable foreground = null; Drawable foreground = null;
Drawable background = null; Drawable background = null;
if (iconDrawable != null) { if (iconDrawable != null) {
@@ -485,7 +495,8 @@ public class SplashscreenContentDrawer {
.setIconSize(iconSize) .setIconSize(iconSize)
.setIconBackground(background) .setIconBackground(background)
.setCenterViewDrawable(foreground) .setCenterViewDrawable(foreground)
.setAnimationDurationMillis(animationDuration); .setAnimationDurationMillis(animationDuration)
.setUiThreadInitConsumer(uiThreadInitTask);
if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
&& mTmpAttrs.mBrandingImage != null) { && mTmpAttrs.mBrandingImage != null) {

View File

@@ -304,6 +304,13 @@ public class SplashscreenIconDrawableFactory {
return true; return true;
} }
@Override
public void stopAnimation() {
if (mIconAnimator != null) {
mIconAnimator.end();
}
}
private final Callback mCallback = new Callback() { private final Callback mCallback = new Callback() {
@Override @Override
public void invalidateDrawable(@NonNull Drawable who) { public void invalidateDrawable(@NonNull Drawable who) {

View File

@@ -332,7 +332,7 @@ public class StartingSurfaceDrawer {
mSysuiProxy.requestTopUi(true, TAG); mSysuiProxy.requestTopUi(true, TAG);
} }
mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId, mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId,
viewSupplier::setView); viewSupplier::setView, viewSupplier::setUiThreadInitTask);
try { try {
if (addWindow(taskId, appToken, rootLayout, display, params, suggestType)) { if (addWindow(taskId, appToken, rootLayout, display, params, suggestType)) {
// We use the splash screen worker thread to create SplashScreenView while adding // 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 static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
private SplashScreenView mView; private SplashScreenView mView;
private boolean mIsViewSet; private boolean mIsViewSet;
private Runnable mUiThreadInitTask;
void setView(SplashScreenView view) { void setView(SplashScreenView view) {
synchronized (this) { synchronized (this) {
mView = view; mView = view;
@@ -375,6 +376,12 @@ public class StartingSurfaceDrawer {
} }
} }
void setUiThreadInitTask(Runnable initTask) {
synchronized (this) {
mUiThreadInitTask = initTask;
}
}
@Override @Override
public @Nullable SplashScreenView get() { public @Nullable SplashScreenView get() {
synchronized (this) { synchronized (this) {
@@ -384,6 +391,10 @@ public class StartingSurfaceDrawer {
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
} }
} }
if (mUiThreadInitTask != null) {
mUiThreadInitTask.run();
mUiThreadInitTask = null;
}
return mView; return mView;
} }
} }
@@ -506,7 +517,7 @@ public class StartingSurfaceDrawer {
Slog.v(TAG, reason + "the splash screen. Releasing SurfaceControlViewHost for task:" Slog.v(TAG, reason + "the splash screen. Releasing SurfaceControlViewHost for task:"
+ taskId); + taskId);
} }
viewHost.getView().post(viewHost::release); SplashScreenView.releaseIconHost(viewHost);
} }
protected boolean addWindow(int taskId, IBinder appToken, View view, Display display, protected boolean addWindow(int taskId, IBinder appToken, View view, Display display,