Merge "Load higher resolution resource for icon on splash screen when needed" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
11b1cb280b
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user