Merge changes from topic "splashscreen-surface" into sc-dev am: fc1efcb428

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14186656

Change-Id: Ie0e17006e404de22c20cce84cf7a43fdf0eb85e7
This commit is contained in:
Vadim Caen
2021-05-25 15:24:45 +00:00
committed by Automerger Merge Worker
5 changed files with 173 additions and 29 deletions

View File

@@ -73,8 +73,8 @@ import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo; import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionInfo; import android.content.pm.PermissionInfo;
import android.content.pm.ProviderInfo; import android.content.pm.ProviderInfo;
@@ -4108,7 +4108,7 @@ public final class ActivityThread extends ClientTransactionHandler
} }
synchronized (this) { synchronized (this) {
if (mSplashScreenGlobal != null) { if (mSplashScreenGlobal != null) {
mSplashScreenGlobal.dispatchOnExitAnimation(r.token, v); mSplashScreenGlobal.handOverSplashScreenView(r.token, v);
} }
} }
} }

View File

@@ -571,7 +571,10 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
// recreate this Surface, so only release it when we are fully // recreate this Surface, so only release it when we are fully
// detached. // detached.
if (mSurfacePackage != null) { if (mSurfacePackage != null) {
mTmpTransaction.reparent(mSurfacePackage.getSurfaceControl(), null).apply(); final SurfaceControl sc = mSurfacePackage.getSurfaceControl();
if (sc != null && sc.isValid()) {
mTmpTransaction.reparent(sc, null).apply();
}
mSurfacePackage.release(); mSurfacePackage.release();
mSurfacePackage = null; mSurfacePackage = null;
} }
@@ -1826,7 +1829,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
*/ */
public void setChildSurfacePackage(@NonNull SurfaceControlViewHost.SurfacePackage p) { public void setChildSurfacePackage(@NonNull SurfaceControlViewHost.SurfacePackage p) {
final SurfaceControl lastSc = mSurfacePackage != null ? final SurfaceControl lastSc = mSurfacePackage != null ?
mSurfacePackage.getSurfaceControl() : null; mSurfacePackage.getSurfaceControl() : null;
if (mSurfaceControl != null && lastSc != null) { if (mSurfaceControl != null && lastSc != null) {
mTmpTransaction.reparent(lastSc, null).apply(); mTmpTransaction.reparent(lastSc, null).apply();
mSurfacePackage.release(); mSurfacePackage.release();
@@ -1839,8 +1842,11 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
private void reparentSurfacePackage(SurfaceControl.Transaction t, private void reparentSurfacePackage(SurfaceControl.Transaction t,
SurfaceControlViewHost.SurfacePackage p) { SurfaceControlViewHost.SurfacePackage p) {
initEmbeddedHierarchyForAccessibility(p);
final SurfaceControl sc = p.getSurfaceControl(); final SurfaceControl sc = p.getSurfaceControl();
if (sc == null || !sc.isValid()) {
return;
}
initEmbeddedHierarchyForAccessibility(p);
final SurfaceControl parent; final SurfaceControl parent;
if (mUseBlastAdapter) { if (mUseBlastAdapter) {
parent = mBlastSurfaceControl; parent = mBlastSurfaceControl;

View File

@@ -220,7 +220,13 @@ public interface SplashScreen {
} }
} }
public void dispatchOnExitAnimation(IBinder token, SplashScreenView view) { public void handOverSplashScreenView(@NonNull IBinder token,
@NonNull SplashScreenView splashScreenView) {
transferSurface(splashScreenView);
dispatchOnExitAnimation(token, splashScreenView);
}
private void dispatchOnExitAnimation(IBinder token, SplashScreenView view) {
synchronized (mGlobalLock) { synchronized (mGlobalLock) {
final SplashScreenImpl impl = findImpl(token); final SplashScreenImpl impl = findImpl(token);
if (impl == null) { if (impl == null) {
@@ -240,5 +246,9 @@ public interface SplashScreen {
return impl != null && impl.mExitAnimationListener != null; return impl != null && impl.mExitAnimationListener != null;
} }
} }
private void transferSurface(@NonNull SplashScreenView splashScreenView) {
splashScreenView.transferSurface();
}
} }
} }

View File

@@ -30,6 +30,7 @@ import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@@ -38,13 +39,17 @@ import android.os.Parcelable;
import android.os.Trace; import android.os.Trace;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceView;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.view.WindowInsetsController; import android.view.WindowInsetsController;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.policy.DecorView; import com.android.internal.policy.DecorView;
@@ -92,6 +97,14 @@ public final class SplashScreenView extends FrameLayout {
// The host activity when transfer view to it. // The host activity when transfer view to it.
private Activity mHostActivity; private Activity mHostActivity;
@Nullable
private SurfaceControlViewHost.SurfacePackage mSurfacePackageCopy;
@Nullable
private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
@Nullable
private SurfaceView mSurfaceView;
// cache original window and status // cache original window and status
private Window mWindow; private Window mWindow;
private int mAppWindowFlags; private int mAppWindowFlags;
@@ -114,6 +127,7 @@ public final class SplashScreenView extends FrameLayout {
private @ColorInt int mIconBackground; private @ColorInt int mIconBackground;
private Bitmap mParceledIconBitmap; private Bitmap mParceledIconBitmap;
private Drawable mIconDrawable; private Drawable mIconDrawable;
private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
private int mBrandingImageWidth; private int mBrandingImageWidth;
private int mBrandingImageHeight; private int mBrandingImageHeight;
private Drawable mBrandingDrawable; private Drawable mBrandingDrawable;
@@ -133,7 +147,10 @@ public final class SplashScreenView extends FrameLayout {
mIconSize = parcelable.getIconSize(); mIconSize = parcelable.getIconSize();
mBackgroundColor = parcelable.getBackgroundColor(); mBackgroundColor = parcelable.getBackgroundColor();
mIconBackground = parcelable.getIconBackground(); mIconBackground = parcelable.getIconBackground();
if (parcelable.mIconBitmap != null) { mSurfacePackage = parcelable.mSurfacePackage;
if (mSurfacePackage == null && parcelable.mIconBitmap != null) {
// We only create a Bitmap copies of immobile icons since animated icon are using
// a surface view
mIconDrawable = new BitmapDrawable(mContext.getResources(), parcelable.mIconBitmap); mIconDrawable = new BitmapDrawable(mContext.getResources(), parcelable.mIconBitmap);
mParceledIconBitmap = parcelable.mIconBitmap; mParceledIconBitmap = parcelable.mIconBitmap;
} }
@@ -145,6 +162,9 @@ public final class SplashScreenView extends FrameLayout {
} }
mIconAnimationStart = Instant.ofEpochMilli(parcelable.mIconAnimationStartMillis); mIconAnimationStart = Instant.ofEpochMilli(parcelable.mIconAnimationStartMillis);
mIconAnimationDuration = Duration.ofMillis(parcelable.mIconAnimationDurationMillis); mIconAnimationDuration = Duration.ofMillis(parcelable.mIconAnimationDurationMillis);
if (DEBUG) {
Log.d(TAG, String.format("Building from parcel drawable: %s", mIconDrawable));
}
return this; return this;
} }
@@ -167,7 +187,7 @@ public final class SplashScreenView extends FrameLayout {
/** /**
* Set the Drawable object to fill the center view. * Set the Drawable object to fill the center view.
*/ */
public Builder setCenterViewDrawable(Drawable drawable) { public Builder setCenterViewDrawable(@Nullable Drawable drawable) {
mIconDrawable = drawable; mIconDrawable = drawable;
return this; return this;
} }
@@ -191,7 +211,7 @@ public final class SplashScreenView extends FrameLayout {
/** /**
* Set the Drawable object and size for the branding view. * Set the Drawable object and size for the branding view.
*/ */
public Builder setBrandingDrawable(Drawable branding, int width, int height) { public Builder setBrandingDrawable(@Nullable Drawable branding, int width, int height) {
mBrandingDrawable = branding; mBrandingDrawable = branding;
mBrandingImageWidth = width; mBrandingImageWidth = width;
mBrandingImageHeight = height; mBrandingImageHeight = height;
@@ -209,22 +229,30 @@ public final class SplashScreenView extends FrameLayout {
view.mInitBackgroundColor = mBackgroundColor; view.mInitBackgroundColor = mBackgroundColor;
view.mInitIconBackgroundColor = mIconBackground; view.mInitIconBackgroundColor = mIconBackground;
view.setBackgroundColor(mBackgroundColor); view.setBackgroundColor(mBackgroundColor);
view.mIconView = view.findViewById(R.id.splashscreen_icon_view);
view.mBrandingImageView = view.findViewById(R.id.splashscreen_branding_view); view.mBrandingImageView = view.findViewById(R.id.splashscreen_branding_view);
// center icon // center icon
if (mIconSize != 0) { if (mIconDrawable instanceof SplashScreenView.IconAnimateListener
final ViewGroup.LayoutParams params = view.mIconView.getLayoutParams(); || mSurfacePackage != null) {
params.width = mIconSize; view.mIconView = createSurfaceView(view);
params.height = mIconSize;
view.mIconView.setLayoutParams(params);
}
if (mIconDrawable != null) {
view.mIconView.setBackground(mIconDrawable);
view.initIconAnimation(mIconDrawable, view.initIconAnimation(mIconDrawable,
mIconAnimationDuration != null ? mIconAnimationDuration.toMillis() : 0); mIconAnimationDuration != null ? mIconAnimationDuration.toMillis() : 0);
view.mIconAnimationStart = mIconAnimationStart;
view.mIconAnimationDuration = mIconAnimationDuration;
} else {
view.mIconView = view.findViewById(R.id.splashscreen_icon_view);
if (mIconSize != 0) {
final ViewGroup.LayoutParams params = view.mIconView.getLayoutParams();
params.width = mIconSize;
params.height = mIconSize;
view.mIconView.setLayoutParams(params);
if (mIconDrawable != null) {
view.mIconView.setBackground(mIconDrawable);
}
}
} }
view.mIconAnimationStart = mIconAnimationStart;
view.mIconAnimationDuration = mIconAnimationDuration;
if (mParceledIconBitmap != null) { if (mParceledIconBitmap != null) {
view.mParceledIconBitmap = mParceledIconBitmap; view.mParceledIconBitmap = mParceledIconBitmap;
} }
@@ -242,14 +270,60 @@ public final class SplashScreenView extends FrameLayout {
view.mParceledBrandingBitmap = mParceledBrandingBitmap; view.mParceledBrandingBitmap = mParceledBrandingBitmap;
} }
if (DEBUG) { if (DEBUG) {
Log.d(TAG, " build " + view + " Icon: view: " + view.mIconView + " drawable: " Log.d(TAG, "Build " + view
+ mIconDrawable + " size: " + mIconSize + "\n Branding: view: " + "\nIcon: view: " + view.mIconView + " drawable: "
+ view.mBrandingImageView + " drawable: " + mBrandingDrawable + mIconDrawable + " size: " + mIconSize
+ " size w: " + mBrandingImageWidth + " h: " + mBrandingImageHeight); + "\nBranding: view: " + view.mBrandingImageView + " drawable: "
+ mBrandingDrawable + " size w: " + mBrandingImageWidth + " h: "
+ mBrandingImageHeight);
} }
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return view; return view;
} }
private SurfaceView createSurfaceView(@NonNull SplashScreenView view) {
final SurfaceView surfaceView = new SurfaceView(view.getContext());
if (mSurfacePackage == null) {
if (DEBUG) {
Log.d(TAG,
"Creating Original SurfacePackage. SurfaceView: " + surfaceView);
}
SurfaceControlViewHost viewHost = new SurfaceControlViewHost(mContext,
mContext.getDisplay(),
surfaceView.getHostToken());
ImageView imageView = new ImageView(mContext);
imageView.setBackground(mIconDrawable);
viewHost.setView(imageView, mIconSize, mIconSize);
SurfaceControlViewHost.SurfacePackage surfacePackage = viewHost.getSurfacePackage();
surfaceView.setChildSurfacePackage(surfacePackage);
view.mSurfacePackage = surfacePackage;
view.mSurfacePackageCopy = new SurfaceControlViewHost.SurfacePackage(
surfacePackage);
} else {
if (DEBUG) {
Log.d(TAG, "Using copy of SurfacePackage in the client");
}
view.mSurfacePackage = mSurfacePackage;
}
if (mIconSize != 0) {
LayoutParams lp = new FrameLayout.LayoutParams(mIconSize, mIconSize);
lp.gravity = Gravity.CENTER;
surfaceView.setLayoutParams(lp);
if (DEBUG) {
Log.d(TAG, "Icon size " + mIconSize);
}
}
// We ensure that we can blend the alpha of the surface view with the SplashScreenView
surfaceView.setUseAlpha();
surfaceView.setZOrderOnTop(true);
surfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
view.addView(surfaceView);
view.mSurfaceView = surfaceView;
return surfaceView;
}
} }
/** @hide */ /** @hide */
@@ -297,6 +371,35 @@ public final class SplashScreenView extends FrameLayout {
return mRevealAnimationSupported; return mRevealAnimationSupported;
} }
/**
* Called when this {@link SplashScreenView} has been copied to be transferred to the client.
*
* @hide
*/
public void onCopied() {
if (mSurfaceView == null) {
return;
}
if (DEBUG) {
Log.d(TAG, "Setting SurfaceView's SurfacePackage to null.");
}
// If we don't release the surface package, the surface will be reparented to this
// surface view. So once it's copied into the client process, we release it.
mSurfacePackage.release();
mSurfacePackage = null;
}
@Override
public void setAlpha(float alpha) {
super.setAlpha(alpha);
// The surface view's alpha is not multiplied with the containing view's alpha, so we
// manually do it here
if (mSurfaceView != null) {
mSurfaceView.setAlpha(mSurfaceView.getAlpha() * alpha);
}
}
/** /**
* Returns the duration of the icon animation if icon is animatable. * Returns the duration of the icon animation if icon is animatable.
* *
@@ -316,6 +419,22 @@ public final class SplashScreenView extends FrameLayout {
return mIconAnimationStart; return mIconAnimationStart;
} }
void transferSurface() {
if (mSurfacePackage == null) {
return;
}
if (DEBUG) {
mSurfacePackage.getSurfaceControl().addOnReparentListener(
(transaction, parent) -> Log.e(TAG,
String.format("SurfacePackage'surface reparented.\n Parent: %s",
parent), new Throwable()));
Log.d(TAG, "Transferring surface " + mSurfaceView.toString());
}
mSurfaceView.setChildSurfacePackage(mSurfacePackage);
}
void initIconAnimation(Drawable iconDrawable, long duration) { void initIconAnimation(Drawable iconDrawable, long duration) {
if (!(iconDrawable instanceof IconAnimateListener)) { if (!(iconDrawable instanceof IconAnimateListener)) {
return; return;
@@ -477,7 +596,7 @@ public final class SplashScreenView extends FrameLayout {
private int mBackgroundColor; private int mBackgroundColor;
private int mIconBackground; private int mIconBackground;
private Bitmap mIconBitmap; private Bitmap mIconBitmap = null;
private int mBrandingWidth; private int mBrandingWidth;
private int mBrandingHeight; private int mBrandingHeight;
private Bitmap mBrandingBitmap; private Bitmap mBrandingBitmap;
@@ -485,14 +604,20 @@ public final class SplashScreenView extends FrameLayout {
private long mIconAnimationStartMillis; private long mIconAnimationStartMillis;
private long mIconAnimationDurationMillis; private long mIconAnimationDurationMillis;
private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
public SplashScreenViewParcelable(SplashScreenView view) { public SplashScreenViewParcelable(SplashScreenView view) {
ViewGroup.LayoutParams params = view.getIconView().getLayoutParams(); mIconSize = view.mIconView.getWidth();
mIconSize = params.height;
mBackgroundColor = view.getInitBackgroundColor(); mBackgroundColor = view.getInitBackgroundColor();
mIconBackground = view.getIconBackgroundColor(); mIconBackground = view.getIconBackgroundColor();
mIconBitmap = copyDrawable(view.getIconView().getBackground()); mSurfacePackage = view.mSurfacePackageCopy;
if (mSurfacePackage == null) {
// We only need to copy the drawable if we are not using a SurfaceView
mIconBitmap = copyDrawable(view.getIconView().getBackground());
}
mBrandingBitmap = copyDrawable(view.getBrandingView().getBackground()); mBrandingBitmap = copyDrawable(view.getBrandingView().getBackground());
params = view.getBrandingView().getLayoutParams();
ViewGroup.LayoutParams params = view.getBrandingView().getLayoutParams();
mBrandingWidth = params.width; mBrandingWidth = params.width;
mBrandingHeight = params.height; mBrandingHeight = params.height;
@@ -535,6 +660,7 @@ public final class SplashScreenView extends FrameLayout {
mIconAnimationStartMillis = source.readLong(); mIconAnimationStartMillis = source.readLong();
mIconAnimationDurationMillis = source.readLong(); mIconAnimationDurationMillis = source.readLong();
mIconBackground = source.readInt(); mIconBackground = source.readInt();
mSurfacePackage = source.readTypedObject(SurfaceControlViewHost.SurfacePackage.CREATOR);
} }
@Override @Override
@@ -553,6 +679,7 @@ public final class SplashScreenView extends FrameLayout {
dest.writeLong(mIconAnimationStartMillis); dest.writeLong(mIconAnimationStartMillis);
dest.writeLong(mIconAnimationDurationMillis); dest.writeLong(mIconAnimationDurationMillis);
dest.writeInt(mIconBackground); dest.writeInt(mIconBackground);
dest.writeTypedObject(mSurfacePackage, flags);
} }
public static final @NonNull Parcelable.Creator<SplashScreenViewParcelable> CREATOR = public static final @NonNull Parcelable.Creator<SplashScreenViewParcelable> CREATOR =

View File

@@ -375,6 +375,7 @@ public class StartingSurfaceDrawer {
if (preView != null && preView.mContentView != null if (preView != null && preView.mContentView != null
&& preView.mContentView.isCopyable()) { && preView.mContentView.isCopyable()) {
parcelable = new SplashScreenViewParcelable(preView.mContentView); parcelable = new SplashScreenViewParcelable(preView.mContentView);
preView.mContentView.onCopied();
} else { } else {
parcelable = null; parcelable = null;
} }