Merge "Adding the SurfaceView on splash screen thread." into sc-v2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
50c8b2d994
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user