Merge "Load higher resolution resource for icon on splash screen when needed" into sc-dev

This commit is contained in:
Wei Sheng Shih
2021-04-27 06:01:29 +00:00
committed by Android (Google) Code Review
5 changed files with 98 additions and 96 deletions

View File

@@ -52,9 +52,6 @@
when the PIP menu is shown in center. -->
<string translatable="false" name="pip_menu_bounds">"596 280 1324 690"</string>
<!-- maximum animation duration for the icon when entering the starting window -->
<integer name="max_starting_window_intro_icon_anim_duration">1000</integer>
<!-- Animation duration when exit starting window: icon going away -->
<integer name="starting_window_icon_exit_anim_duration">166</integer>

View File

@@ -178,7 +178,9 @@
<dimen name="bubble_stack_user_education_side_inset">72dp</dimen>
<!-- The width/height of the icon view on staring surface. -->
<dimen name="starting_surface_icon_size">108dp</dimen>
<dimen name="starting_surface_icon_size">160dp</dimen>
<!-- The default width/height of the icon on the spec of adaptive icon drawable. -->
<dimen name="default_icon_size">108dp</dimen>
<!-- The width/height of the size compat restart button. -->
<dimen name="size_compat_button_size">48dp</dimen>

View File

@@ -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;

View File

@@ -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);

View File

@@ -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());
}