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.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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user