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.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;
@@ -231,6 +233,15 @@ public final class SplashScreenView extends FrameLayout {
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.
*/
@@ -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,23 +549,32 @@ 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);
}
}
/**
* 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();
}
/**

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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,