Merge "Update density dpi before load drawable." into tm-dev am: c122c97cff
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17951297 Change-Id: I56c6db76b789dc7ac6a6a14b45881f2d996b85ce Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -35,6 +35,8 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
@@ -53,6 +55,7 @@ import android.os.SystemClock;
|
|||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
@@ -68,7 +71,6 @@ import com.android.internal.graphics.palette.VariationalKMeansQuantizer;
|
|||||||
import com.android.internal.protolog.common.ProtoLog;
|
import com.android.internal.protolog.common.ProtoLog;
|
||||||
import com.android.launcher3.icons.BaseIconFactory;
|
import com.android.launcher3.icons.BaseIconFactory;
|
||||||
import com.android.launcher3.icons.IconProvider;
|
import com.android.launcher3.icons.IconProvider;
|
||||||
import com.android.wm.shell.common.ShellExecutor;
|
|
||||||
import com.android.wm.shell.common.TransactionPool;
|
import com.android.wm.shell.common.TransactionPool;
|
||||||
import com.android.wm.shell.protolog.ShellProtoLogGroup;
|
import com.android.wm.shell.protolog.ShellProtoLogGroup;
|
||||||
|
|
||||||
@@ -102,7 +104,7 @@ public class SplashscreenContentDrawer {
|
|||||||
*/
|
*/
|
||||||
private static final float NO_BACKGROUND_SCALE = 192f / 160;
|
private static final float NO_BACKGROUND_SCALE = 192f / 160;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final IconProvider mIconProvider;
|
private final HighResIconProvider mHighResIconProvider;
|
||||||
|
|
||||||
private int mIconSize;
|
private int mIconSize;
|
||||||
private int mDefaultIconSize;
|
private int mDefaultIconSize;
|
||||||
@@ -115,12 +117,10 @@ public class SplashscreenContentDrawer {
|
|||||||
private final Handler mSplashscreenWorkerHandler;
|
private final Handler mSplashscreenWorkerHandler;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final ColorCache mColorCache;
|
final ColorCache mColorCache;
|
||||||
private final ShellExecutor mSplashScreenExecutor;
|
|
||||||
|
|
||||||
SplashscreenContentDrawer(Context context, IconProvider iconProvider, TransactionPool pool,
|
SplashscreenContentDrawer(Context context, IconProvider iconProvider, TransactionPool pool) {
|
||||||
ShellExecutor splashScreenExecutor) {
|
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mIconProvider = iconProvider;
|
mHighResIconProvider = new HighResIconProvider(mContext, iconProvider);
|
||||||
mTransactionPool = pool;
|
mTransactionPool = pool;
|
||||||
|
|
||||||
// Initialize Splashscreen worker thread
|
// Initialize Splashscreen worker thread
|
||||||
@@ -131,7 +131,6 @@ public class SplashscreenContentDrawer {
|
|||||||
shellSplashscreenWorkerThread.start();
|
shellSplashscreenWorkerThread.start();
|
||||||
mSplashscreenWorkerHandler = shellSplashscreenWorkerThread.getThreadHandler();
|
mSplashscreenWorkerHandler = shellSplashscreenWorkerThread.getThreadHandler();
|
||||||
mColorCache = new ColorCache(mContext, mSplashscreenWorkerHandler);
|
mColorCache = new ColorCache(mContext, mSplashscreenWorkerHandler);
|
||||||
mSplashScreenExecutor = splashScreenExecutor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -416,18 +415,16 @@ public class SplashscreenContentDrawer {
|
|||||||
|| mTmpAttrs.mIconBgColor == mThemeColor) {
|
|| mTmpAttrs.mIconBgColor == mThemeColor) {
|
||||||
mFinalIconSize *= NO_BACKGROUND_SCALE;
|
mFinalIconSize *= NO_BACKGROUND_SCALE;
|
||||||
}
|
}
|
||||||
createIconDrawable(iconDrawable, false);
|
createIconDrawable(iconDrawable, false /* legacy */, false /* loadInDetail */);
|
||||||
} else {
|
} else {
|
||||||
final float iconScale = (float) mIconSize / (float) mDefaultIconSize;
|
final float iconScale = (float) mIconSize / (float) mDefaultIconSize;
|
||||||
final int densityDpi = mContext.getResources().getConfiguration().densityDpi;
|
final int densityDpi = mContext.getResources().getConfiguration().densityDpi;
|
||||||
final int scaledIconDpi =
|
final int scaledIconDpi =
|
||||||
(int) (0.5f + iconScale * densityDpi * NO_BACKGROUND_SCALE);
|
(int) (0.5f + iconScale * densityDpi * NO_BACKGROUND_SCALE);
|
||||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "getIcon");
|
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "getIcon");
|
||||||
iconDrawable = mIconProvider.getIcon(mActivityInfo, scaledIconDpi);
|
iconDrawable = mHighResIconProvider.getIcon(
|
||||||
|
mActivityInfo, densityDpi, scaledIconDpi);
|
||||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||||
if (iconDrawable == null) {
|
|
||||||
iconDrawable = mContext.getPackageManager().getDefaultActivityIcon();
|
|
||||||
}
|
|
||||||
if (!processAdaptiveIcon(iconDrawable)) {
|
if (!processAdaptiveIcon(iconDrawable)) {
|
||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
|
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
|
||||||
"The icon is not an AdaptiveIconDrawable");
|
"The icon is not an AdaptiveIconDrawable");
|
||||||
@@ -437,7 +434,8 @@ public class SplashscreenContentDrawer {
|
|||||||
scaledIconDpi, mFinalIconSize);
|
scaledIconDpi, mFinalIconSize);
|
||||||
final Bitmap bitmap = factory.createScaledBitmapWithoutShadow(iconDrawable);
|
final Bitmap bitmap = factory.createScaledBitmapWithoutShadow(iconDrawable);
|
||||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||||
createIconDrawable(new BitmapDrawable(bitmap), true);
|
createIconDrawable(new BitmapDrawable(bitmap), true,
|
||||||
|
mHighResIconProvider.mLoadInDetail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,14 +448,16 @@ public class SplashscreenContentDrawer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createIconDrawable(Drawable iconDrawable, boolean legacy) {
|
private void createIconDrawable(Drawable iconDrawable, boolean legacy,
|
||||||
|
boolean loadInDetail) {
|
||||||
if (legacy) {
|
if (legacy) {
|
||||||
mFinalIconDrawables = SplashscreenIconDrawableFactory.makeLegacyIconDrawable(
|
mFinalIconDrawables = SplashscreenIconDrawableFactory.makeLegacyIconDrawable(
|
||||||
iconDrawable, mDefaultIconSize, mFinalIconSize, mSplashscreenWorkerHandler);
|
iconDrawable, mDefaultIconSize, mFinalIconSize, loadInDetail,
|
||||||
|
mSplashscreenWorkerHandler);
|
||||||
} else {
|
} else {
|
||||||
mFinalIconDrawables = SplashscreenIconDrawableFactory.makeIconDrawable(
|
mFinalIconDrawables = SplashscreenIconDrawableFactory.makeIconDrawable(
|
||||||
mTmpAttrs.mIconBgColor, mThemeColor, iconDrawable, mDefaultIconSize,
|
mTmpAttrs.mIconBgColor, mThemeColor, iconDrawable, mDefaultIconSize,
|
||||||
mFinalIconSize, mSplashscreenWorkerHandler);
|
mFinalIconSize, loadInDetail, mSplashscreenWorkerHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,11 +506,11 @@ public class SplashscreenContentDrawer {
|
|||||||
// Using AdaptiveIconDrawable here can help keep the shape consistent with the
|
// Using AdaptiveIconDrawable here can help keep the shape consistent with the
|
||||||
// current settings.
|
// current settings.
|
||||||
mFinalIconSize = (int) (0.5f + mIconSize * noBgScale);
|
mFinalIconSize = (int) (0.5f + mIconSize * noBgScale);
|
||||||
createIconDrawable(iconForeground, false);
|
createIconDrawable(iconForeground, false, mHighResIconProvider.mLoadInDetail);
|
||||||
} else {
|
} else {
|
||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
|
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
|
||||||
"processAdaptiveIcon: draw whole icon");
|
"processAdaptiveIcon: draw whole icon");
|
||||||
createIconDrawable(iconDrawable, false);
|
createIconDrawable(iconDrawable, false, mHighResIconProvider.mLoadInDetail);
|
||||||
}
|
}
|
||||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||||
return true;
|
return true;
|
||||||
@@ -1015,4 +1015,77 @@ public class SplashscreenContentDrawer {
|
|||||||
playAnimation.run();
|
playAnimation.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When loading a BitmapDrawable object with specific density, there will decode the image based
|
||||||
|
* on the density from display metrics, so even when load with higher override density, the
|
||||||
|
* final intrinsic size of a BitmapDrawable can still not big enough to draw on expect size.
|
||||||
|
*
|
||||||
|
* So here we use a standalone IconProvider object to load the Drawable object for higher
|
||||||
|
* density, and the resources object won't affect the entire system.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static class HighResIconProvider {
|
||||||
|
private final Context mSharedContext;
|
||||||
|
private final IconProvider mSharedIconProvider;
|
||||||
|
private boolean mLoadInDetail;
|
||||||
|
|
||||||
|
// only create standalone icon provider when the density dpi is low.
|
||||||
|
private Context mStandaloneContext;
|
||||||
|
private IconProvider mStandaloneIconProvider;
|
||||||
|
|
||||||
|
HighResIconProvider(Context context, IconProvider sharedIconProvider) {
|
||||||
|
mSharedContext = context;
|
||||||
|
mSharedIconProvider = sharedIconProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
Drawable getIcon(ActivityInfo activityInfo, int currentDpi, int iconDpi) {
|
||||||
|
mLoadInDetail = false;
|
||||||
|
Drawable drawable;
|
||||||
|
if (currentDpi < iconDpi && currentDpi < DisplayMetrics.DENSITY_XHIGH) {
|
||||||
|
drawable = loadFromStandalone(activityInfo, currentDpi, iconDpi);
|
||||||
|
} else {
|
||||||
|
drawable = mSharedIconProvider.getIcon(activityInfo, iconDpi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawable == null) {
|
||||||
|
drawable = mSharedContext.getPackageManager().getDefaultActivityIcon();
|
||||||
|
}
|
||||||
|
return drawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drawable loadFromStandalone(ActivityInfo activityInfo, int currentDpi,
|
||||||
|
int iconDpi) {
|
||||||
|
if (mStandaloneContext == null) {
|
||||||
|
final Configuration defConfig = mSharedContext.getResources().getConfiguration();
|
||||||
|
mStandaloneContext = mSharedContext.createConfigurationContext(defConfig);
|
||||||
|
mStandaloneIconProvider = new IconProvider(mStandaloneContext);
|
||||||
|
}
|
||||||
|
Resources resources;
|
||||||
|
try {
|
||||||
|
resources = mStandaloneContext.getPackageManager()
|
||||||
|
.getResourcesForApplication(activityInfo.applicationInfo);
|
||||||
|
} catch (PackageManager.NameNotFoundException | Resources.NotFoundException exc) {
|
||||||
|
resources = null;
|
||||||
|
}
|
||||||
|
if (resources != null) {
|
||||||
|
updateResourcesDpi(resources, iconDpi);
|
||||||
|
}
|
||||||
|
final Drawable drawable = mStandaloneIconProvider.getIcon(activityInfo, iconDpi);
|
||||||
|
mLoadInDetail = true;
|
||||||
|
// reset density dpi
|
||||||
|
if (resources != null) {
|
||||||
|
updateResourcesDpi(resources, currentDpi);
|
||||||
|
}
|
||||||
|
return drawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateResourcesDpi(Resources resources, int densityDpi) {
|
||||||
|
final Configuration config = resources.getConfiguration();
|
||||||
|
final DisplayMetrics displayMetrics = resources.getDisplayMetrics();
|
||||||
|
config.densityDpi = densityDpi;
|
||||||
|
displayMetrics.densityDpi = densityDpi;
|
||||||
|
resources.updateConfiguration(config, displayMetrics);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public class SplashscreenIconDrawableFactory {
|
|||||||
*/
|
*/
|
||||||
static Drawable[] makeIconDrawable(@ColorInt int backgroundColor, @ColorInt int themeColor,
|
static Drawable[] makeIconDrawable(@ColorInt int backgroundColor, @ColorInt int themeColor,
|
||||||
@NonNull Drawable foregroundDrawable, int srcIconSize, int iconSize,
|
@NonNull Drawable foregroundDrawable, int srcIconSize, int iconSize,
|
||||||
Handler splashscreenWorkerHandler) {
|
boolean loadInDetail, Handler splashscreenWorkerHandler) {
|
||||||
Drawable foreground;
|
Drawable foreground;
|
||||||
Drawable background = null;
|
Drawable background = null;
|
||||||
boolean drawBackground =
|
boolean drawBackground =
|
||||||
@@ -74,13 +74,13 @@ public class SplashscreenIconDrawableFactory {
|
|||||||
// If the icon is Adaptive, we already use the icon background.
|
// If the icon is Adaptive, we already use the icon background.
|
||||||
drawBackground = false;
|
drawBackground = false;
|
||||||
foreground = new ImmobileIconDrawable(foregroundDrawable,
|
foreground = new ImmobileIconDrawable(foregroundDrawable,
|
||||||
srcIconSize, iconSize, splashscreenWorkerHandler);
|
srcIconSize, iconSize, loadInDetail, splashscreenWorkerHandler);
|
||||||
} else {
|
} else {
|
||||||
// Adaptive icon don't handle transparency so we draw the background of the adaptive
|
// Adaptive icon don't handle transparency so we draw the background of the adaptive
|
||||||
// icon with the same color as the window background color instead of using two layers
|
// icon with the same color as the window background color instead of using two layers
|
||||||
foreground = new ImmobileIconDrawable(
|
foreground = new ImmobileIconDrawable(
|
||||||
new AdaptiveForegroundDrawable(foregroundDrawable),
|
new AdaptiveForegroundDrawable(foregroundDrawable),
|
||||||
srcIconSize, iconSize, splashscreenWorkerHandler);
|
srcIconSize, iconSize, loadInDetail, splashscreenWorkerHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawBackground) {
|
if (drawBackground) {
|
||||||
@@ -91,9 +91,9 @@ public class SplashscreenIconDrawableFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Drawable[] makeLegacyIconDrawable(@NonNull Drawable iconDrawable, int srcIconSize,
|
static Drawable[] makeLegacyIconDrawable(@NonNull Drawable iconDrawable, int srcIconSize,
|
||||||
int iconSize, Handler splashscreenWorkerHandler) {
|
int iconSize, boolean loadInDetail, Handler splashscreenWorkerHandler) {
|
||||||
return new Drawable[]{new ImmobileIconDrawable(iconDrawable, srcIconSize, iconSize,
|
return new Drawable[]{new ImmobileIconDrawable(iconDrawable, srcIconSize, iconSize,
|
||||||
splashscreenWorkerHandler)};
|
loadInDetail, splashscreenWorkerHandler)};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,11 +106,16 @@ public class SplashscreenIconDrawableFactory {
|
|||||||
private final Matrix mMatrix = new Matrix();
|
private final Matrix mMatrix = new Matrix();
|
||||||
private Bitmap mIconBitmap;
|
private Bitmap mIconBitmap;
|
||||||
|
|
||||||
ImmobileIconDrawable(Drawable drawable, int srcIconSize, int iconSize,
|
ImmobileIconDrawable(Drawable drawable, int srcIconSize, int iconSize, boolean loadInDetail,
|
||||||
Handler splashscreenWorkerHandler) {
|
Handler splashscreenWorkerHandler) {
|
||||||
final float scale = (float) iconSize / srcIconSize;
|
// This icon has lower density, don't scale it.
|
||||||
mMatrix.setScale(scale, scale);
|
if (loadInDetail) {
|
||||||
splashscreenWorkerHandler.post(() -> preDrawIcon(drawable, srcIconSize));
|
splashscreenWorkerHandler.post(() -> preDrawIcon(drawable, iconSize));
|
||||||
|
} else {
|
||||||
|
final float scale = (float) iconSize / srcIconSize;
|
||||||
|
mMatrix.setScale(scale, scale);
|
||||||
|
splashscreenWorkerHandler.post(() -> preDrawIcon(drawable, srcIconSize));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preDrawIcon(Drawable drawable, int size) {
|
private void preDrawIcon(Drawable drawable, int size) {
|
||||||
|
|||||||
@@ -153,8 +153,7 @@ public class StartingSurfaceDrawer {
|
|||||||
mContext = context;
|
mContext = context;
|
||||||
mDisplayManager = mContext.getSystemService(DisplayManager.class);
|
mDisplayManager = mContext.getSystemService(DisplayManager.class);
|
||||||
mSplashScreenExecutor = splashScreenExecutor;
|
mSplashScreenExecutor = splashScreenExecutor;
|
||||||
mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, iconProvider, pool,
|
mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, iconProvider, pool);
|
||||||
mSplashScreenExecutor);
|
|
||||||
mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance());
|
mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance());
|
||||||
mWindowManagerGlobal = WindowManagerGlobal.getInstance();
|
mWindowManagerGlobal = WindowManagerGlobal.getInstance();
|
||||||
mDisplayManager.getDisplay(DEFAULT_DISPLAY);
|
mDisplayManager.getDisplay(DEFAULT_DISPLAY);
|
||||||
|
|||||||
Reference in New Issue
Block a user