summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java109
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java3
3 files changed, 106 insertions, 29 deletions
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 d89ddd2074f0..8cee4f1dc8fb 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
@@ -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);
+ }
+ }
}
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 5f52071bf950..7f6bfd23f72b 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
@@ -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) {
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 464ab1ae2a8c..54d62edf2570 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
@@ -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);