From 1d699ec6b1ac4283aab012a16119465bc5da40a0 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Tue, 13 Apr 2021 18:56:02 +0800 Subject: [PATCH] Load higher resolution resource for icon on splash screen when needed Enlarge the basic icon visible size to 160dp, and loading higher icon drawable if available. For replaced icon we also enlarge the visible area. And if the icon does not need to draw the background, apply another 1.3 times scale than normal case. TODO: need to handle legacy icon. Bug: 182883560 Test: atest SplashscreenTests Change-Id: Ia72a72a743a7ef5f80f247393c1a5bd0b6653a48 --- .../WindowManager/Shell/res/values/config.xml | 3 - libs/WindowManager/Shell/res/values/dimen.xml | 4 +- .../SplashscreenContentDrawer.java | 180 +++++++++--------- .../SplashscreenIconDrawableFactory.java | 1 + .../StartingSurfaceDrawer.java | 6 +- 5 files changed, 98 insertions(+), 96 deletions(-) diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml index a138fee325506..e8757b5d96f45 100644 --- a/libs/WindowManager/Shell/res/values/config.xml +++ b/libs/WindowManager/Shell/res/values/config.xml @@ -52,9 +52,6 @@ when the PIP menu is shown in center. --> "596 280 1324 690" - - 1000 - 166 diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml index 3ced8d3ec6e73..ef731235a3c42 100644 --- a/libs/WindowManager/Shell/res/values/dimen.xml +++ b/libs/WindowManager/Shell/res/values/dimen.xml @@ -178,7 +178,9 @@ 72dp - 108dp + 160dp + + 108dp 48dp 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 ccf062ea3e9d5..1d3a60b8193de 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 @@ -18,7 +18,6 @@ package com.android.wm.shell.startingsurface; import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; -import static android.os.UserHandle.getUserHandleForUid; import android.annotation.ColorInt; import android.annotation.NonNull; @@ -68,11 +67,12 @@ public class SplashscreenContentDrawer { // For example, an icon with the foreground 108*108 opaque pixels and it's background // also 108*108 pixels, then do not enlarge this icon if only need to show foreground icon. private static final float ENLARGE_FOREGROUND_ICON_THRESHOLD = (72f * 72f) / (108f * 108f); + private static final float NO_BACKGROUND_SCALE = 1.3f; private final Context mContext; private final IconProvider mIconProvider; - private final int mMaxAnimatableIconDuration; private int mIconSize; + private int mDefaultIconSize; private int mBrandingImageWidth; private int mBrandingImageHeight; private final int mAppRevealDuration; @@ -84,11 +84,10 @@ public class SplashscreenContentDrawer { private final SplashScreenWindowAttrs mTmpAttrs = new SplashScreenWindowAttrs(); private final Handler mSplashscreenWorkerHandler; - SplashscreenContentDrawer(Context context, int maxAnimatableIconDuration, - int iconExitAnimDuration, int appRevealAnimDuration, TransactionPool pool) { + SplashscreenContentDrawer(Context context, int iconExitAnimDuration, int appRevealAnimDuration, + TransactionPool pool) { mContext = context; mIconProvider = new IconProvider(context); - mMaxAnimatableIconDuration = maxAnimatableIconDuration; mAppRevealDuration = appRevealAnimDuration; mIconExitDuration = iconExitAnimDuration; mTransactionPool = pool; @@ -122,11 +121,7 @@ public class SplashscreenContentDrawer { context, splashScreenResId); if (contentView == null) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "makeSplashScreenContentView"); - if (emptyView) { - contentView = makeEmptySplashScreenContentView(context); - } else { - contentView = makeSplashScreenContentView(context, info); - } + contentView = makeSplashScreenContentView(context, info, emptyView); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } } catch (RuntimeException e) { @@ -141,6 +136,8 @@ public class SplashscreenContentDrawer { private void updateDensity() { mIconSize = mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.starting_surface_icon_size); + mDefaultIconSize = mContext.getResources().getDimensionPixelSize( + com.android.wm.shell.R.dimen.default_icon_size); mBrandingImageWidth = mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.starting_surface_brand_image_width); mBrandingImageHeight = mContext.getResources().getDimensionPixelSize( @@ -195,46 +192,20 @@ public class SplashscreenContentDrawer { } } - private SplashScreenView makeEmptySplashScreenContentView(Context context) { - getWindowAttrs(context, mTmpAttrs); - final StartingWindowViewBuilder builder = new StartingWindowViewBuilder(); - final int themeBGColor = peekWindowBGColor(context); - final SplashScreenView view = builder - .setContext(context) - .setWindowBGColor(themeBGColor) - .build(); - view.setNotCopyable(); - return view; - } - - private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai) { + private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai, + boolean emptyView) { updateDensity(); getWindowAttrs(context, mTmpAttrs); final StartingWindowViewBuilder builder = new StartingWindowViewBuilder(); - final int animationDuration; - Drawable iconDrawable; - if (mTmpAttrs.mReplaceIcon != null) { - iconDrawable = mTmpAttrs.mReplaceIcon; - animationDuration = Math.max(0, - Math.min(mTmpAttrs.mAnimationDuration, mMaxAnimatableIconDuration)); - } else { - iconDrawable = mIconProvider.getIconForUI( - ai, getUserHandleForUid(ai.applicationInfo.uid)); - if (iconDrawable == null) { - iconDrawable = context.getPackageManager().getDefaultActivityIcon(); - } - animationDuration = 0; - } final int themeBGColor = peekWindowBGColor(context); // TODO (b/173975965) Tracking the performance on improved splash screen. return builder .setContext(context) .setWindowBGColor(themeBGColor) - .setIconDrawable(iconDrawable) - .setIconAnimationDuration(animationDuration) - .setBrandingDrawable(mTmpAttrs.mBrandingImage) - .setIconBackground(mTmpAttrs.mIconBgColor).build(); + .makeEmptyView(emptyView) + .setActivityInfo(ai) + .build(); } private static void getWindowAttrs(Context context, SplashScreenWindowAttrs attrs) { @@ -270,11 +241,9 @@ public class SplashscreenContentDrawer { } private class StartingWindowViewBuilder { - private Drawable mIconDrawable; - private int mIconAnimationDuration; + private ActivityInfo mActivityInfo; private Context mContext; - private Drawable mBrandingDrawable; - private @ColorInt int mIconBackground; + private boolean mEmptyView; // result private boolean mBuildComplete = false; @@ -289,26 +258,14 @@ public class SplashscreenContentDrawer { return this; } - StartingWindowViewBuilder setIconDrawable(Drawable iconDrawable) { - mIconDrawable = iconDrawable; + StartingWindowViewBuilder makeEmptyView(boolean empty) { + mEmptyView = empty; mBuildComplete = false; return this; } - StartingWindowViewBuilder setIconAnimationDuration(int iconAnimationDuration) { - mIconAnimationDuration = iconAnimationDuration; - mBuildComplete = false; - return this; - } - - StartingWindowViewBuilder setBrandingDrawable(Drawable branding) { - mBrandingDrawable = branding; - mBuildComplete = false; - return this; - } - - StartingWindowViewBuilder setIconBackground(int color) { - mIconBackground = color; + StartingWindowViewBuilder setActivityInfo(ActivityInfo ai) { + mActivityInfo = ai; mBuildComplete = false; return this; } @@ -323,40 +280,66 @@ public class SplashscreenContentDrawer { if (mBuildComplete) { return mCachedResult; } - if (mContext == null) { + if (mContext == null || mActivityInfo == null) { Slog.e(TAG, "Unable to create StartingWindowView, lack of materials!"); return null; } - if (!processAdaptiveIcon() && mIconDrawable != null) { - if (DEBUG) { - Slog.d(TAG, "The icon is not an AdaptiveIconDrawable"); + Drawable iconDrawable; + final int animationDuration; + final int iconSize; + if (mEmptyView) { + // empty splash screen case + animationDuration = 0; + iconSize = 0; + } else if (mTmpAttrs.mReplaceIcon != null) { + // replaced icon, don't process + iconDrawable = mTmpAttrs.mReplaceIcon; + animationDuration = mTmpAttrs.mAnimationDuration; + createIconDrawable(iconDrawable, mIconSize); + iconSize = mIconSize; + } else { + final float iconScale = (float) mIconSize / (float) mDefaultIconSize; + iconDrawable = mIconProvider.getIcon(mActivityInfo); + if (iconDrawable == null) { + iconDrawable = mContext.getPackageManager().getDefaultActivityIcon(); } - createIconDrawable(mIconDrawable, mIconSize); + if (!processAdaptiveIcon(iconDrawable, iconScale)) { + if (DEBUG) { + Slog.d(TAG, "The icon is not an AdaptiveIconDrawable"); + } + // TODO process legacy icon(bitmap) + final Drawable tempIcon = loadIconByDensity(iconDrawable, iconScale); + createIconDrawable(tempIcon, mIconSize); + } + animationDuration = 0; + iconSize = (int) (0.5 + mIconSize * mScale); } - final int iconSize = mFinalIconDrawable != null ? (int) (mIconSize * mScale) : 0; - mCachedResult = fillViewWithIcon(mContext, iconSize, mFinalIconDrawable); + + mCachedResult = fillViewWithIcon(iconSize, mFinalIconDrawable, animationDuration); mBuildComplete = true; return mCachedResult; } private void createIconDrawable(Drawable iconDrawable, int iconSize) { mFinalIconDrawable = SplashscreenIconDrawableFactory.makeIconDrawable( - mIconBackground != Color.TRANSPARENT ? mIconBackground : mThemeColor, + mTmpAttrs.mIconBgColor != Color.TRANSPARENT + ? mTmpAttrs.mIconBgColor : mThemeColor, iconDrawable, iconSize, mSplashscreenWorkerHandler); } - private boolean processAdaptiveIcon() { - if (!(mIconDrawable instanceof AdaptiveIconDrawable)) { + private boolean processAdaptiveIcon(Drawable iconDrawable, float iconScale) { + if (!(iconDrawable instanceof AdaptiveIconDrawable)) { return false; } Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "processAdaptiveIcon"); - final AdaptiveIconDrawable adaptiveIconDrawable = (AdaptiveIconDrawable) mIconDrawable; + final AdaptiveIconDrawable adaptiveIconDrawable = + (AdaptiveIconDrawable) iconDrawable; final DrawableColorTester backIconTester = new DrawableColorTester(adaptiveIconDrawable.getBackground()); - final Drawable iconForeground = adaptiveIconDrawable.getForeground(); + Drawable iconForeground = adaptiveIconDrawable.getForeground(); final DrawableColorTester foreIconTester = new DrawableColorTester(iconForeground, true /* filterTransparent */); @@ -382,7 +365,9 @@ public class SplashscreenContentDrawer { // B. The background of the adaptive icon is similar to the theme color, or // C. The background of the adaptive icon is grayscale, and the foreground of the // adaptive icon forms a certain contrast with the theme color. - if (!backComplex && (isRgbSimilarInHsv(mThemeColor, backMainColor) + // D. Didn't specify icon background color. + if (!backComplex && mTmpAttrs.mIconBgColor == Color.TRANSPARENT + && (isRgbSimilarInHsv(mThemeColor, backMainColor) || (backIconTester.isGrayscale() && !isRgbSimilarInHsv(mThemeColor, foreMainColor)))) { if (DEBUG) { @@ -390,8 +375,13 @@ public class SplashscreenContentDrawer { } // Reference AdaptiveIcon description, outer is 108 and inner is 72, so we // should enlarge the size 108/72 if we only draw adaptiveIcon's foreground. - if (foreIconTester.nonTransparentRatio() < ENLARGE_FOREGROUND_ICON_THRESHOLD) { - mScale = 1.5f; + final float noBgScale = + foreIconTester.nonTransparentRatio() < ENLARGE_FOREGROUND_ICON_THRESHOLD + ? NO_BACKGROUND_SCALE : 1f; + final Drawable tempIcon = loadIconByDensity(iconDrawable, iconScale * noBgScale); + if (tempIcon instanceof AdaptiveIconDrawable) { + mScale = noBgScale; + iconForeground = ((AdaptiveIconDrawable) tempIcon).getForeground(); } // Using AdaptiveIconDrawable here can help keep the shape consistent with the // current settings. @@ -401,30 +391,44 @@ public class SplashscreenContentDrawer { if (DEBUG) { Slog.d(TAG, "makeSplashScreenContentView: draw whole icon"); } - createIconDrawable(adaptiveIconDrawable, mIconSize); + final Drawable tempIcon = loadIconByDensity(iconDrawable, iconScale); + createIconDrawable(tempIcon, mIconSize); } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); return true; } - private SplashScreenView fillViewWithIcon(Context context, - int iconSize, Drawable iconDrawable) { - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "fillViewWithIcon"); - final SplashScreenView.Builder builder = new SplashScreenView.Builder(context); - builder.setIconSize(iconSize).setBackgroundColor(mThemeColor) - .setIconBackground(mIconBackground); - if (iconDrawable != null) { - builder.setCenterViewDrawable(iconDrawable); + private Drawable loadIconByDensity(Drawable baseDrawable, float scale) { + if (scale == 1 && baseDrawable != null) { + return baseDrawable; } - builder.setAnimationDurationMillis(mIconAnimationDuration); - if (mBrandingDrawable != null) { - builder.setBrandingDrawable(mBrandingDrawable, mBrandingImageWidth, + final int densityDpi = mContext.getResources().getDisplayMetrics().densityDpi; + final int updateDpi = (int) (0.5f + scale * densityDpi); + return mIconProvider.getIcon(mActivityInfo, updateDpi); + } + + private SplashScreenView fillViewWithIcon(int iconSize, Drawable iconDrawable, + int animationDuration) { + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "fillViewWithIcon"); + final SplashScreenView.Builder builder = new SplashScreenView.Builder(mContext); + builder.setBackgroundColor(mThemeColor); + if (iconDrawable != null) { + builder.setIconSize(iconSize) + .setIconBackground(mTmpAttrs.mIconBgColor) + .setCenterViewDrawable(iconDrawable) + .setAnimationDurationMillis(animationDuration); + } + if (mTmpAttrs.mBrandingImage != null) { + builder.setBrandingDrawable(mTmpAttrs.mBrandingImage, mBrandingImageWidth, mBrandingImageHeight); } final SplashScreenView splashScreenView = builder.build(); if (DEBUG) { Slog.d(TAG, "fillViewWithIcon surfaceWindowView " + splashScreenView); } + if (mEmptyView) { + splashScreenView.setNotCopyable(); + } splashScreenView.makeSystemUIColorsTransparent(); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); return splashScreenView; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java index 85845d0d9c891..6cbba9f135865 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java @@ -59,6 +59,7 @@ public class SplashscreenIconDrawableFactory { return new ImmobileIconDrawable((AdaptiveIconDrawable) foregroundDrawable, iconSize, splashscreenWorkerHandler); } else { + // TODO for legacy icon don't use adaptive icon drawable to wrapper it return new ImmobileIconDrawable(new AdaptiveIconDrawable( new ColorDrawable(backgroundColor), foregroundDrawable), iconSize, splashscreenWorkerHandler); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index e4b28696bc4f0..6d3eeae43a968 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -114,14 +114,12 @@ public class StartingSurfaceDrawer { mContext = context; mDisplayManager = mContext.getSystemService(DisplayManager.class); mSplashScreenExecutor = splashScreenExecutor; - final int maxAnimatableIconDuration = context.getResources().getInteger( - com.android.wm.shell.R.integer.max_starting_window_intro_icon_anim_duration); final int iconExitAnimDuration = context.getResources().getInteger( com.android.wm.shell.R.integer.starting_window_icon_exit_anim_duration); final int appRevealAnimDuration = context.getResources().getInteger( com.android.wm.shell.R.integer.starting_window_app_reveal_anim_duration); - mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, - maxAnimatableIconDuration, iconExitAnimDuration, appRevealAnimDuration, pool); + mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, iconExitAnimDuration, + appRevealAnimDuration, pool); mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance()); }