Loading libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +91 −18 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 Loading @@ -131,7 +131,6 @@ public class SplashscreenContentDrawer { shellSplashscreenWorkerThread.start(); mSplashscreenWorkerHandler = shellSplashscreenWorkerThread.getThreadHandler(); mColorCache = new ColorCache(mContext, mSplashscreenWorkerHandler); mSplashScreenExecutor = splashScreenExecutor; } /** Loading Loading @@ -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"); Loading @@ -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); } } Loading @@ -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); } } Loading Loading @@ -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; Loading Loading @@ -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); } } } libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java +14 −9 Original line number Diff line number Diff line Loading @@ -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 = Loading @@ -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) { Loading @@ -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)}; } /** Loading @@ -106,12 +106,17 @@ 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) { // 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) { synchronized (mPaint) { Loading libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +1 −2 Original line number Diff line number Diff line Loading @@ -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); Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +91 −18 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 Loading @@ -131,7 +131,6 @@ public class SplashscreenContentDrawer { shellSplashscreenWorkerThread.start(); mSplashscreenWorkerHandler = shellSplashscreenWorkerThread.getThreadHandler(); mColorCache = new ColorCache(mContext, mSplashscreenWorkerHandler); mSplashScreenExecutor = splashScreenExecutor; } /** Loading Loading @@ -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"); Loading @@ -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); } } Loading @@ -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); } } Loading Loading @@ -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; Loading Loading @@ -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); } } }
libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java +14 −9 Original line number Diff line number Diff line Loading @@ -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 = Loading @@ -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) { Loading @@ -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)}; } /** Loading @@ -106,12 +106,17 @@ 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) { // 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) { synchronized (mPaint) { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +1 −2 Original line number Diff line number Diff line Loading @@ -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); Loading