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:
Wei Sheng Shih
2022-05-11 02:20:34 +00:00
committed by Automerger Merge Worker
3 changed files with 106 additions and 29 deletions

View File

@@ -35,6 +35,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
@@ -53,6 +55,7 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Slog;
import android.view.ContextThemeWrapper;
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.launcher3.icons.BaseIconFactory;
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.protolog.ShellProtoLogGroup;
@@ -102,7 +104,7 @@ public class SplashscreenContentDrawer {
*/
private static final float NO_BACKGROUND_SCALE = 192f / 160;
private final Context mContext;
private final IconProvider mIconProvider;
private final HighResIconProvider mHighResIconProvider;
private int mIconSize;
private int mDefaultIconSize;
@@ -115,12 +117,10 @@ public class SplashscreenContentDrawer {
private final Handler mSplashscreenWorkerHandler;
@VisibleForTesting
final ColorCache mColorCache;
private final ShellExecutor mSplashScreenExecutor;
SplashscreenContentDrawer(Context context, IconProvider iconProvider, TransactionPool pool,
ShellExecutor splashScreenExecutor) {
SplashscreenContentDrawer(Context context, IconProvider iconProvider, TransactionPool pool) {
mContext = context;
mIconProvider = iconProvider;
mHighResIconProvider = new HighResIconProvider(mContext, iconProvider);
mTransactionPool = pool;
// Initialize Splashscreen worker thread
@@ -131,7 +131,6 @@ public class SplashscreenContentDrawer {
shellSplashscreenWorkerThread.start();
mSplashscreenWorkerHandler = shellSplashscreenWorkerThread.getThreadHandler();
mColorCache = new ColorCache(mContext, mSplashscreenWorkerHandler);
mSplashScreenExecutor = splashScreenExecutor;
}
/**
@@ -416,18 +415,16 @@ public class SplashscreenContentDrawer {
|| mTmpAttrs.mIconBgColor == mThemeColor) {
mFinalIconSize *= NO_BACKGROUND_SCALE;
}
createIconDrawable(iconDrawable, false);
createIconDrawable(iconDrawable, false /* legacy */, false /* loadInDetail */);
} else {
final float iconScale = (float) mIconSize / (float) mDefaultIconSize;
final int densityDpi = mContext.getResources().getConfiguration().densityDpi;
final int scaledIconDpi =
(int) (0.5f + iconScale * densityDpi * NO_BACKGROUND_SCALE);
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "getIcon");
iconDrawable = mIconProvider.getIcon(mActivityInfo, scaledIconDpi);
iconDrawable = mHighResIconProvider.getIcon(
mActivityInfo, densityDpi, scaledIconDpi);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (iconDrawable == null) {
iconDrawable = mContext.getPackageManager().getDefaultActivityIcon();
}
if (!processAdaptiveIcon(iconDrawable)) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
"The icon is not an AdaptiveIconDrawable");
@@ -437,7 +434,8 @@ public class SplashscreenContentDrawer {
scaledIconDpi, mFinalIconSize);
final Bitmap bitmap = factory.createScaledBitmapWithoutShadow(iconDrawable);
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) {
mFinalIconDrawables = SplashscreenIconDrawableFactory.makeLegacyIconDrawable(
iconDrawable, mDefaultIconSize, mFinalIconSize, mSplashscreenWorkerHandler);
iconDrawable, mDefaultIconSize, mFinalIconSize, loadInDetail,
mSplashscreenWorkerHandler);
} else {
mFinalIconDrawables = SplashscreenIconDrawableFactory.makeIconDrawable(
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
// current settings.
mFinalIconSize = (int) (0.5f + mIconSize * noBgScale);
createIconDrawable(iconForeground, false);
createIconDrawable(iconForeground, false, mHighResIconProvider.mLoadInDetail);
} else {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
"processAdaptiveIcon: draw whole icon");
createIconDrawable(iconDrawable, false);
createIconDrawable(iconDrawable, false, mHighResIconProvider.mLoadInDetail);
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return true;
@@ -1015,4 +1015,77 @@ public class SplashscreenContentDrawer {
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);
}
}
}

View File

@@ -62,7 +62,7 @@ public class SplashscreenIconDrawableFactory {
*/
static Drawable[] makeIconDrawable(@ColorInt int backgroundColor, @ColorInt int themeColor,
@NonNull Drawable foregroundDrawable, int srcIconSize, int iconSize,
Handler splashscreenWorkerHandler) {
boolean loadInDetail, Handler splashscreenWorkerHandler) {
Drawable foreground;
Drawable background = null;
boolean drawBackground =
@@ -74,13 +74,13 @@ public class SplashscreenIconDrawableFactory {
// If the icon is Adaptive, we already use the icon background.
drawBackground = false;
foreground = new ImmobileIconDrawable(foregroundDrawable,
srcIconSize, iconSize, splashscreenWorkerHandler);
srcIconSize, iconSize, loadInDetail, splashscreenWorkerHandler);
} else {
// 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
foreground = new ImmobileIconDrawable(
new AdaptiveForegroundDrawable(foregroundDrawable),
srcIconSize, iconSize, splashscreenWorkerHandler);
srcIconSize, iconSize, loadInDetail, splashscreenWorkerHandler);
}
if (drawBackground) {
@@ -91,9 +91,9 @@ public class SplashscreenIconDrawableFactory {
}
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,
splashscreenWorkerHandler)};
loadInDetail, splashscreenWorkerHandler)};
}
/**
@@ -106,11 +106,16 @@ public class SplashscreenIconDrawableFactory {
private final Matrix mMatrix = new Matrix();
private Bitmap mIconBitmap;
ImmobileIconDrawable(Drawable drawable, int srcIconSize, int iconSize,
ImmobileIconDrawable(Drawable drawable, int srcIconSize, int iconSize, boolean loadInDetail,
Handler splashscreenWorkerHandler) {
final float scale = (float) iconSize / srcIconSize;
mMatrix.setScale(scale, scale);
splashscreenWorkerHandler.post(() -> preDrawIcon(drawable, srcIconSize));
// This icon has lower density, don't scale it.
if (loadInDetail) {
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) {

View File

@@ -153,8 +153,7 @@ public class StartingSurfaceDrawer {
mContext = context;
mDisplayManager = mContext.getSystemService(DisplayManager.class);
mSplashScreenExecutor = splashScreenExecutor;
mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, iconProvider, pool,
mSplashScreenExecutor);
mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, iconProvider, pool);
mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance());
mWindowManagerGlobal = WindowManagerGlobal.getInstance();
mDisplayManager.getDisplay(DEFAULT_DISPLAY);