Add API for show branding image on splash screen.(4/N)

Add API windowSplashScreenBrandingImage to attach branding image
on splash screen.

Bug: 73289295
Test: build and flash
Test: StartingSurfaceDrawerTests SplashscreenTests

Change-Id: I15ab799d4e7bb74ce6814fa9375334db18022f3a
This commit is contained in:
wilsonshih
2021-01-14 17:38:10 +08:00
committed by Vadim Caen
parent ae7ee3f3ef
commit 8ac1b58101
10 changed files with 151 additions and 35 deletions

View File

@@ -1658,6 +1658,7 @@ package android {
field public static final int windowSplashScreenAnimatedIcon = 16844333; // 0x101062d
field public static final int windowSplashScreenAnimationDuration = 16844334; // 0x101062e
field public static final int windowSplashScreenBackground = 16844332; // 0x101062c
field public static final int windowSplashScreenBrandingImage = 16844335; // 0x101062f
field public static final int windowSplashscreenContent = 16844132; // 0x1010564
field @Deprecated public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c

View File

@@ -2730,6 +2730,7 @@ package android.window {
}
public final class SplashScreenView extends android.widget.FrameLayout {
method @Nullable public android.view.View getBrandingView();
method public boolean isIconAnimating();
}

View File

@@ -68,7 +68,9 @@ public final class SplashScreenView extends FrameLayout {
private boolean mNotCopyable;
private int mInitBackgroundColor;
private View mIconView;
private Bitmap mParceledBitmap;
private Bitmap mParceledIconBitmap;
private View mBrandingImageView;
private Bitmap mParceledBrandingBitmap;
private Animatable mAnimatableIcon;
private ValueAnimator mAnimator;
@@ -88,9 +90,13 @@ public final class SplashScreenView extends FrameLayout {
private final Context mContext;
private int mIconSize;
private @ColorInt int mBackgroundColor;
private Bitmap mParceledBitmap;
private Bitmap mParceledIconBitmap;
private Drawable mIconDrawable;
private int mIconAnimationDuration;
private int mBrandingImageWidth;
private int mBrandingImageHeight;
private Drawable mBrandingDrawable;
private Bitmap mParceledBrandingBitmap;
public Builder(@NonNull Context context) {
mContext = context;
@@ -103,9 +109,15 @@ public final class SplashScreenView extends FrameLayout {
public Builder createFromParcel(SplashScreenViewParcelable parcelable) {
mIconSize = parcelable.getIconSize();
mBackgroundColor = parcelable.getBackgroundColor();
if (parcelable.getBitmap() != null) {
mIconDrawable = new BitmapDrawable(mContext.getResources(), parcelable.getBitmap());
mParceledBitmap = parcelable.getBitmap();
if (parcelable.mIconBitmap != null) {
mIconDrawable = new BitmapDrawable(mContext.getResources(), parcelable.mIconBitmap);
mParceledIconBitmap = parcelable.mIconBitmap;
}
if (parcelable.mBrandingBitmap != null) {
setBrandingDrawable(new BitmapDrawable(mContext.getResources(),
parcelable.mBrandingBitmap), parcelable.mBrandingWidth,
parcelable.mBrandingHeight);
mParceledBrandingBitmap = parcelable.mBrandingBitmap;
}
return this;
}
@@ -142,6 +154,16 @@ public final class SplashScreenView extends FrameLayout {
return this;
}
/**
* Set the Drawable object and size for the branding view.
*/
public Builder setBrandingDrawable(Drawable branding, int width, int height) {
mBrandingDrawable = branding;
mBrandingImageWidth = width;
mBrandingImageHeight = height;
return this;
}
/**
* Create SplashScreenWindowView object from materials.
*/
@@ -152,6 +174,8 @@ public final class SplashScreenView extends FrameLayout {
view.mInitBackgroundColor = mBackgroundColor;
view.setBackgroundColor(mBackgroundColor);
view.mIconView = view.findViewById(R.id.splashscreen_icon_view);
view.mBrandingImageView = view.findViewById(R.id.splashscreen_branding_view);
// center icon
if (mIconSize != 0) {
final ViewGroup.LayoutParams params = view.mIconView.getLayoutParams();
params.width = mIconSize;
@@ -162,12 +186,27 @@ public final class SplashScreenView extends FrameLayout {
view.mIconView.setBackground(mIconDrawable);
view.initIconAnimation(mIconDrawable, mIconAnimationDuration);
}
if (mParceledBitmap != null) {
view.mParceledBitmap = mParceledBitmap;
if (mParceledIconBitmap != null) {
view.mParceledIconBitmap = mParceledIconBitmap;
}
// branding image
if (mBrandingImageHeight > 0 && mBrandingImageWidth > 0) {
final ViewGroup.LayoutParams params = view.mBrandingImageView.getLayoutParams();
params.width = mBrandingImageWidth;
params.height = mBrandingImageHeight;
view.mBrandingImageView.setLayoutParams(params);
}
if (mBrandingDrawable != null) {
view.mBrandingImageView.setBackground(mBrandingDrawable);
}
if (mParceledBrandingBitmap != null) {
view.mParceledBrandingBitmap = mParceledBrandingBitmap;
}
if (DEBUG) {
Log.d(TAG, " build " + view + " center view? " + view.mIconView
+ " iconSize " + mIconSize);
Log.d(TAG, " build " + view + " Icon: view: " + view.mIconView + " drawable: "
+ mIconDrawable + " size: " + mIconSize + "\n Branding: view: "
+ view.mBrandingImageView + " drawable: " + mBrandingDrawable
+ " size w: " + mBrandingImageWidth + " h: " + mBrandingImageHeight);
}
return view;
}
@@ -266,10 +305,15 @@ public final class SplashScreenView extends FrameLayout {
*/
public void remove() {
setVisibility(GONE);
if (mParceledBitmap != null) {
if (mParceledIconBitmap != null) {
mIconView.setBackground(null);
mParceledBitmap.recycle();
mParceledBitmap = null;
mParceledIconBitmap.recycle();
mParceledIconBitmap = null;
}
if (mParceledBrandingBitmap != null) {
mBrandingImageView.setBackground(null);
mParceledBrandingBitmap.recycle();
mParceledBrandingBitmap = null;
}
if (mWindow != null) {
final DecorView decorView = (DecorView) mWindow.peekDecorView();
@@ -329,6 +373,15 @@ public final class SplashScreenView extends FrameLayout {
return mIconView;
}
/**
* Get the branding image view.
* @hide
*/
@TestApi
public @Nullable View getBrandingView() {
return mBrandingImageView;
}
/**
* Get the initial background color of this view.
* @hide
@@ -344,27 +397,40 @@ public final class SplashScreenView extends FrameLayout {
public static class SplashScreenViewParcelable implements Parcelable {
private int mIconSize;
private int mBackgroundColor;
private Bitmap mBitmap;
private Bitmap mIconBitmap;
private int mBrandingWidth;
private int mBrandingHeight;
private Bitmap mBrandingBitmap;
public SplashScreenViewParcelable(SplashScreenView view) {
final ViewGroup.LayoutParams params = view.getIconView().getLayoutParams();
ViewGroup.LayoutParams params = view.getIconView().getLayoutParams();
mIconSize = params.height;
mBackgroundColor = view.getInitBackgroundColor();
final Drawable background = view.getIconView().getBackground();
if (background != null) {
final Rect initialBounds = background.copyBounds();
mIconBitmap = copyDrawable(view.getIconView().getBackground());
mBrandingBitmap = copyDrawable(view.getBrandingView().getBackground());
params = view.getBrandingView().getLayoutParams();
mBrandingWidth = params.width;
mBrandingHeight = params.height;
}
private Bitmap copyDrawable(Drawable drawable) {
if (drawable != null) {
final Rect initialBounds = drawable.copyBounds();
final int width = initialBounds.width();
final int height = initialBounds.height();
final Bitmap iconSnapshot = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
final Canvas bmpCanvas = new Canvas(iconSnapshot);
background.setBounds(0, 0, width, height);
background.draw(bmpCanvas);
mBitmap = iconSnapshot.createAshmemBitmap();
iconSnapshot.recycle();
final Bitmap snapshot = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas bmpCanvas = new Canvas(snapshot);
drawable.setBounds(0, 0, width, height);
drawable.draw(bmpCanvas);
final Bitmap copyBitmap = snapshot.createAshmemBitmap();
snapshot.recycle();
return copyBitmap;
}
return null;
}
private SplashScreenViewParcelable(@NonNull Parcel source) {
@@ -374,7 +440,10 @@ public final class SplashScreenView extends FrameLayout {
private void readParcel(@NonNull Parcel source) {
mIconSize = source.readInt();
mBackgroundColor = source.readInt();
mBitmap = source.readTypedObject(Bitmap.CREATOR);
mIconBitmap = source.readTypedObject(Bitmap.CREATOR);
mBrandingWidth = source.readInt();
mBrandingHeight = source.readInt();
mBrandingBitmap = source.readTypedObject(Bitmap.CREATOR);
}
@Override
@@ -386,7 +455,10 @@ public final class SplashScreenView extends FrameLayout {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mIconSize);
dest.writeInt(mBackgroundColor);
dest.writeTypedObject(mBitmap, flags);
dest.writeTypedObject(mIconBitmap, flags);
dest.writeInt(mBrandingWidth);
dest.writeInt(mBrandingHeight);
dest.writeTypedObject(mBrandingBitmap, flags);
}
public static final @NonNull Parcelable.Creator<SplashScreenViewParcelable> CREATOR =
@@ -403,9 +475,13 @@ public final class SplashScreenView extends FrameLayout {
* Release the bitmap if another process cannot handle it.
*/
public void clearIfNeeded() {
if (mBitmap != null) {
mBitmap.recycle();
mBitmap = null;
if (mIconBitmap != null) {
mIconBitmap.recycle();
mIconBitmap = null;
}
if (mBrandingBitmap != null) {
mBrandingBitmap.recycle();
mBrandingBitmap = null;
}
}
@@ -416,9 +492,5 @@ public final class SplashScreenView extends FrameLayout {
int getBackgroundColor() {
return mBackgroundColor;
}
Bitmap getBitmap() {
return mBitmap;
}
}
}

View File

@@ -25,4 +25,10 @@
android:layout_width="wrap_content"
android:layout_gravity="center"/>
<View android:id="@+id/splashscreen_branding_view"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="60dp"/>
</android.window.SplashScreenView>

View File

@@ -2262,6 +2262,7 @@
-->
<enum name="always" value="3" />
</attr>
<!-- The background color for the splash screen, if not specify then system will
calculate from windowBackground. -->
<attr name="windowSplashScreenBackground" format="color"/>
@@ -2274,6 +2275,10 @@
when playing the splash screen starting window. The maximum animation duration should
be limited below 1000ms. -->
<attr name="windowSplashScreenAnimationDuration" format="integer"/>
<!-- Place an drawable image in the bottom of the starting window, it can be used to
represent the branding of the application. -->
<attr name="windowSplashScreenBrandingImage" format="reference"/>
</declare-styleable>
<!-- The set of attributes that describe a AlertDialog's theme. -->

View File

@@ -3069,6 +3069,7 @@
<public name="windowSplashScreenBackground"/>
<public name="windowSplashScreenAnimatedIcon"/>
<public name="windowSplashScreenAnimationDuration"/>
<public name="windowSplashScreenBrandingImage"/>
</public-group>
<public-group type="drawable" first-id="0x010800b5">

View File

@@ -1820,6 +1820,7 @@
<java-symbol type="dimen" name="cross_profile_apps_thumbnail_size" />
<java-symbol type="layout" name="splash_screen_view" />
<java-symbol type="id" name="splashscreen_icon_view" />
<java-symbol type="id" name="splashscreen_branding_view" />
<!-- From services -->
<java-symbol type="anim" name="screen_rotate_0_enter" />

View File

@@ -169,6 +169,7 @@ please see themes_device_defaults.xml.
<item name="windowBackgroundFallback">?attr/colorBackground</item>
<item name="windowSplashScreenBackground">@color/transparent</item>
<item name="windowSplashScreenAnimatedIcon">@null</item>
<item name="windowSplashScreenBrandingImage">@null</item>
<item name="windowClipToOutline">false</item>
<item name="windowFrame">@null</item>
<item name="windowNoTitle">false</item>

View File

@@ -173,4 +173,10 @@
<!-- The width/height of the icon view on staring surface. -->
<dimen name="starting_surface_icon_size">108dp</dimen>
<!-- The width of the brand image on staring surface. -->
<dimen name="starting_surface_brand_image_width">200dp</dimen>
<!-- The height of the brand image on staring surface. -->
<dimen name="starting_surface_brand_image_height">80dp</dimen>
</resources>

View File

@@ -59,6 +59,8 @@ public class SplashscreenContentDrawer {
private final int mMaxIconAnimationDuration;
private int mIconSize;
private int mBrandingImageWidth;
private int mBrandingImageHeight;
SplashscreenContentDrawer(Context context, int maxIconAnimationDuration) {
mContext = context;
@@ -68,6 +70,10 @@ public class SplashscreenContentDrawer {
private void updateDensity() {
mIconSize = mContext.getResources().getDimensionPixelSize(
com.android.wm.shell.R.dimen.starting_surface_icon_size);
mBrandingImageWidth = mContext.getResources().getDimensionPixelSize(
com.android.wm.shell.R.dimen.starting_surface_brand_image_width);
mBrandingImageHeight = mContext.getResources().getDimensionPixelSize(
com.android.wm.shell.R.dimen.starting_surface_brand_image_height);
}
private int getSystemBGColor() {
@@ -124,13 +130,15 @@ public class SplashscreenContentDrawer {
.setContext(context)
.setThemeDrawable(themeBGDrawable)
.setIconDrawable(iconDrawable)
.setIconAnimationDuration(animationDuration).build();
.setIconAnimationDuration(animationDuration)
.setBrandingDrawable(attrs.mBrandingImage).build();
}
private static class SplashScreenWindowAttrs {
private int mWindowBgResId = 0;
private int mWindowBgColor = Color.TRANSPARENT;
private Drawable mReplaceIcon = null;
private Drawable mBrandingImage = null;
private int mAnimationDuration = 0;
static SplashScreenWindowAttrs createWindowAttrs(Context context) {
@@ -144,11 +152,14 @@ public class SplashscreenContentDrawer {
R.styleable.Window_windowSplashScreenAnimatedIcon);
attrs.mAnimationDuration = typedArray.getInt(
R.styleable.Window_windowSplashScreenAnimationDuration, 0);
attrs.mBrandingImage = typedArray.getDrawable(
R.styleable.Window_windowSplashScreenBrandingImage);
typedArray.recycle();
if (DEBUG) {
Slog.d(TAG, "window attributes color: "
+ Integer.toHexString(attrs.mWindowBgColor)
+ " icon " + attrs.mReplaceIcon + " duration " + attrs.mAnimationDuration);
+ " icon " + attrs.mReplaceIcon + " duration " + attrs.mAnimationDuration
+ " brandImage " + attrs.mBrandingImage);
}
return attrs;
}
@@ -160,6 +171,7 @@ public class SplashscreenContentDrawer {
private Window mWindow;
private int mIconAnimationDuration;
private Context mContext;
private Drawable mBrandingDrawable;
// result
private boolean mBuildComplete = false;
@@ -192,6 +204,12 @@ public class SplashscreenContentDrawer {
return this;
}
StartingWindowViewBuilder setBrandingDrawable(Drawable branding) {
mBrandingDrawable = branding;
mBuildComplete = false;
return this;
}
StartingWindowViewBuilder setContext(Context context) {
mContext = context;
mBuildComplete = false;
@@ -302,6 +320,10 @@ public class SplashscreenContentDrawer {
builder.setCenterViewDrawable(iconDrawable);
}
builder.setAnimationDuration(mIconAnimationDuration);
if (mBrandingDrawable != null) {
builder.setBrandingDrawable(mBrandingDrawable, mBrandingImageWidth,
mBrandingImageHeight);
}
final SplashScreenView splashScreenView = builder.build();
if (DEBUG) {
Slog.d(TAG, "fillViewWithIcon surfaceWindowView " + splashScreenView);