From 8ac1b58101556b4ae63172de96e480dad8123f38 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Thu, 14 Jan 2021 17:38:10 +0800 Subject: [PATCH] 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 --- core/api/current.txt | 1 + core/api/test-current.txt | 1 + .../java/android/window/SplashScreenView.java | 138 +++++++++++++----- core/res/res/layout/splash_screen_view.xml | 6 + core/res/res/values/attrs.xml | 5 + core/res/res/values/public.xml | 1 + core/res/res/values/symbols.xml | 1 + core/res/res/values/themes.xml | 1 + libs/WindowManager/Shell/res/values/dimen.xml | 6 + .../SplashscreenContentDrawer.java | 26 +++- 10 files changed, 151 insertions(+), 35 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index efbc60fb5280c..50d46be869d4f 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -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 diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 7b373201a3fc9..3e2accccc45f6 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -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(); } diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java index 3d3d3468c6da4..5292875f46f2a 100644 --- a/core/java/android/window/SplashScreenView.java +++ b/core/java/android/window/SplashScreenView.java @@ -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 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; - } } } diff --git a/core/res/res/layout/splash_screen_view.xml b/core/res/res/layout/splash_screen_view.xml index 61f27013d558c..513da5e431e55 100644 --- a/core/res/res/layout/splash_screen_view.xml +++ b/core/res/res/layout/splash_screen_view.xml @@ -25,4 +25,10 @@ android:layout_width="wrap_content" android:layout_gravity="center"/> + + \ No newline at end of file diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 6949c4bb9f41c..14f118056ceb5 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2262,6 +2262,7 @@ --> + @@ -2274,6 +2275,10 @@ when playing the splash screen starting window. The maximum animation duration should be limited below 1000ms. --> + + + diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 8f4d8baa845d6..45e6392beb244 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3069,6 +3069,7 @@ + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 93c9a8e6b1c99..f66d33b02b698 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1820,6 +1820,7 @@ + diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 325e0578425d8..87ae1623ca920 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -169,6 +169,7 @@ please see themes_device_defaults.xml. ?attr/colorBackground @color/transparent @null + @null false @null false diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml index 034e65c608a3f..cb2aada2a9cff 100644 --- a/libs/WindowManager/Shell/res/values/dimen.xml +++ b/libs/WindowManager/Shell/res/values/dimen.xml @@ -173,4 +173,10 @@ 108dp + + + 200dp + + + 80dp diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java index db0a4a6ad731b..45d5515289408 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java @@ -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);