diff --git a/libs/WindowManager/Shell/res/values-night/colors.xml b/libs/WindowManager/Shell/res/values-night/colors.xml
index 24b364043938f..83c4d93982f4e 100644
--- a/libs/WindowManager/Shell/res/values-night/colors.xml
+++ b/libs/WindowManager/Shell/res/values-night/colors.xml
@@ -17,4 +17,6 @@
@color/GM2_grey_200
+
+ @color/splash_screen_bg_dark
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index 1674d0bf78beb..350beafae961f 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -35,4 +35,9 @@
#E8EAED
#5F6368
#3C4043
+
+
+ #FFFFFF
+ #000000
+ @color/splash_screen_bg_light
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 25d034c51f461..e25a05c4cfafe 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -167,4 +167,7 @@
72dp
+
+
+ 108dp
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
new file mode 100644
index 0000000000000..f3f2fc3686b63
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.startingsurface;
+
+import android.annotation.NonNull;
+import android.app.ActivityThread;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.os.Build;
+import android.util.Slog;
+import android.view.Gravity;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import com.android.internal.R;
+import com.android.internal.graphics.palette.Palette;
+import com.android.internal.graphics.palette.Quantizer;
+import com.android.internal.graphics.palette.VariationalKMeansQuantizer;
+import com.android.internal.policy.PhoneWindow;
+
+import java.util.List;
+
+/**
+ * Util class to create the view for a splash screen content.
+ */
+class SplashscreenContentDrawer {
+ private static final String TAG = StartingSurfaceDrawer.TAG;
+ private static final boolean DEBUG = StartingSurfaceDrawer.DEBUG_SPLASH_SCREEN;
+
+ // The acceptable area ratio of foreground_icon_area/background_icon_area, if there is an
+ // icon which it's non-transparent foreground area is similar to it's background area, then
+ // do not enlarge the foreground drawable.
+ // 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 final Context mContext;
+ private int mIconSize;
+
+ SplashscreenContentDrawer(Context context) {
+ mContext = context;
+ }
+
+ private void updateDensity() {
+ mIconSize = mContext.getResources().getDimensionPixelSize(
+ com.android.wm.shell.R.dimen.starting_surface_icon_size);
+ }
+
+ private int getSystemBGColor() {
+ final Context systemContext = ActivityThread.currentApplication();
+ if (systemContext == null) {
+ Slog.e(TAG, "System context does not exist!");
+ return Color.BLACK;
+ }
+ final Resources res = systemContext.getResources();
+ return res.getColor(com.android.wm.shell.R.color.splash_window_background_default);
+ }
+
+ private Drawable createDefaultBackgroundDrawable() {
+ return new ColorDrawable(getSystemBGColor());
+ }
+
+ View makeSplashScreenContentView(PhoneWindow win, Context context, int iconRes,
+ int splashscreenContentResId) {
+ updateDensity();
+ win.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ // splash screen content will be deprecated after S.
+ final View ssc = makeSplashscreenContentDrawable(win, context, splashscreenContentResId);
+ if (ssc != null) {
+ return ssc;
+ }
+
+ final TypedArray typedArray = context.obtainStyledAttributes(
+ com.android.internal.R.styleable.Window);
+ final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
+ typedArray.recycle();
+ final Drawable themeBGDrawable;
+ if (resId == 0) {
+ Slog.w(TAG, "Window background not exist!");
+ themeBGDrawable = createDefaultBackgroundDrawable();
+ } else {
+ themeBGDrawable = context.getDrawable(resId);
+ }
+ final Drawable iconDrawable = iconRes != 0 ? context.getDrawable(iconRes)
+ : context.getPackageManager().getDefaultActivityIcon();
+ // TODO (b/173975965) Tracking the performance on improved splash screen.
+ final StartingWindowViewBuilder builder = new StartingWindowViewBuilder();
+ return builder
+ .setPhoneWindow(win)
+ .setContext(context)
+ .setThemeDrawable(themeBGDrawable)
+ .setIconDrawable(iconDrawable).build();
+ }
+
+ private class StartingWindowViewBuilder {
+ // materials
+ private Drawable mThemeBGDrawable;
+ private Drawable mIconDrawable;
+ private PhoneWindow mPhoneWindow;
+ private Context mContext;
+
+ // result
+ private boolean mBuildComplete = false;
+ private View mCachedResult;
+ private int mThemeColor;
+ private Drawable mFinalIconDrawable;
+ private float mScale = 1f;
+
+ StartingWindowViewBuilder setThemeDrawable(Drawable background) {
+ mThemeBGDrawable = background;
+ mBuildComplete = false;
+ return this;
+ }
+
+ StartingWindowViewBuilder setIconDrawable(Drawable iconDrawable) {
+ mIconDrawable = iconDrawable;
+ mBuildComplete = false;
+ return this;
+ }
+
+ StartingWindowViewBuilder setPhoneWindow(PhoneWindow window) {
+ mPhoneWindow = window;
+ mBuildComplete = false;
+ return this;
+ }
+
+ StartingWindowViewBuilder setContext(Context context) {
+ mContext = context;
+ mBuildComplete = false;
+ return this;
+ }
+
+ View build() {
+ if (mBuildComplete) {
+ return mCachedResult;
+ }
+ if (mPhoneWindow == null || mContext == null) {
+ Slog.e(TAG, "Unable to create StartingWindowView, lack of materials!");
+ return null;
+ }
+ if (mThemeBGDrawable == null) {
+ Slog.w(TAG, "Theme Background Drawable is null, forget to set Theme Drawable?");
+ mThemeBGDrawable = createDefaultBackgroundDrawable();
+ }
+ processThemeColor();
+ if (!processAdaptiveIcon() && mIconDrawable != null) {
+ if (DEBUG) {
+ Slog.d(TAG, "The icon is not an AdaptiveIconDrawable");
+ }
+ mFinalIconDrawable = mIconDrawable;
+ }
+ final int iconSize = mFinalIconDrawable != null ? (int) (mIconSize * mScale) : 0;
+ mCachedResult = fillViewWithIcon(mPhoneWindow, mContext, iconSize, mFinalIconDrawable);
+ mBuildComplete = true;
+ return mCachedResult;
+ }
+
+ private void processThemeColor() {
+ final DrawableColorTester themeBGTester =
+ new DrawableColorTester(mThemeBGDrawable, true /* filterTransparent */);
+ if (themeBGTester.nonTransparentRatio() == 0) {
+ // the window background is transparent, unable to draw
+ Slog.w(TAG, "Window background is transparent, fill background with black color");
+ mThemeColor = getSystemBGColor();
+ } else {
+ mThemeColor = themeBGTester.getDominateColor();
+ }
+ }
+
+ private boolean processAdaptiveIcon() {
+ if (!(mIconDrawable instanceof AdaptiveIconDrawable)) {
+ return false;
+ }
+
+ final AdaptiveIconDrawable adaptiveIconDrawable = (AdaptiveIconDrawable) mIconDrawable;
+ final DrawableColorTester backIconTester =
+ new DrawableColorTester(adaptiveIconDrawable.getBackground());
+
+ final Drawable iconForeground = adaptiveIconDrawable.getForeground();
+ final DrawableColorTester foreIconTester =
+ new DrawableColorTester(iconForeground, true /* filterTransparent */);
+
+ final boolean foreComplex = foreIconTester.isComplexColor();
+ final int foreMainColor = foreIconTester.getDominateColor();
+
+ if (DEBUG) {
+ Slog.d(TAG, "foreground complex color? " + foreComplex + " main color: "
+ + Integer.toHexString(foreMainColor));
+ }
+ final boolean backComplex = backIconTester.isComplexColor();
+ final int backMainColor = backIconTester.getDominateColor();
+ if (DEBUG) {
+ Slog.d(TAG, "background complex color? " + backComplex + " main color: "
+ + Integer.toHexString(backMainColor));
+ Slog.d(TAG, "theme color? " + Integer.toHexString(mThemeColor));
+ }
+
+ // Only draw the foreground of AdaptiveIcon to the splash screen if below condition
+ // meet:
+ // A. The background of the adaptive icon is not complicated. If it is complicated,
+ // it may contain some information, and
+ // 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)
+ || (backIconTester.isGrayscale()
+ && !isRgbSimilarInHsv(mThemeColor, foreMainColor)))) {
+ if (DEBUG) {
+ Slog.d(TAG, "makeSplashScreenContentView: choose fg icon");
+ }
+ // Using AdaptiveIconDrawable here can help keep the shape consistent with the
+ // current settings.
+ mFinalIconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(mThemeColor), iconForeground);
+ // 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;
+ }
+ } else {
+ if (DEBUG) {
+ Slog.d(TAG, "makeSplashScreenContentView: draw whole icon");
+ }
+ mFinalIconDrawable = adaptiveIconDrawable;
+ }
+ return true;
+ }
+
+ private View fillViewWithIcon(PhoneWindow win, Context context,
+ int iconSize, Drawable iconDrawable) {
+ final StartingSurfaceWindowView surfaceWindowView =
+ new StartingSurfaceWindowView(context, iconSize);
+ surfaceWindowView.setBackground(new ColorDrawable(mThemeColor));
+ if (iconDrawable != null) {
+ surfaceWindowView.setIconDrawable(iconDrawable);
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "fillViewWithIcon surfaceWindowView " + surfaceWindowView);
+ }
+ win.setContentView(surfaceWindowView);
+ makeSystemUIColorsTransparent(win);
+ return surfaceWindowView;
+ }
+
+ private void makeSystemUIColorsTransparent(PhoneWindow win) {
+ win.setStatusBarColor(Color.TRANSPARENT);
+ win.setNavigationBarColor(Color.TRANSPARENT);
+ }
+ }
+
+ private static boolean isRgbSimilarInHsv(int a, int b) {
+ if (a == b) {
+ return true;
+ }
+ final float[] aHsv = new float[3];
+ final float[] bHsv = new float[3];
+ Color.colorToHSV(a, aHsv);
+ Color.colorToHSV(b, bHsv);
+ // Minimum degree of the hue between two colors, the result range is 0-180.
+ int minAngle = (int) Math.abs(aHsv[0] - bHsv[0]);
+ minAngle = (minAngle + 180) % 360 - 180;
+
+ // Calculate the difference between two colors based on the HSV dimensions.
+ final float normalizeH = minAngle / 180f;
+ final double square = Math.pow(normalizeH, 2)
+ + Math.pow(aHsv[1] - bHsv[1], 2)
+ + Math.pow(aHsv[2] - bHsv[2], 2);
+ final double mean = square / 3;
+ final double root = Math.sqrt(mean);
+ if (DEBUG) {
+ Slog.d(TAG, "hsvDiff " + minAngle + " a: " + Integer.toHexString(a)
+ + " b " + Integer.toHexString(b) + " ah " + aHsv[0] + " bh " + bHsv[0]
+ + " root " + root);
+ }
+ return root < 0.1;
+ }
+
+ private static View makeSplashscreenContentDrawable(PhoneWindow win, Context ctx,
+ int splashscreenContentResId) {
+ // doesn't support windowSplashscreenContent after S
+ // TODO add an allowlist to skip some packages if needed
+ final int targetSdkVersion = ctx.getApplicationInfo().targetSdkVersion;
+ if (DEBUG) {
+ Slog.d(TAG, "target sdk for package: " + targetSdkVersion);
+ }
+ if (targetSdkVersion >= Build.VERSION_CODES.S) {
+ return null;
+ }
+ if (splashscreenContentResId == 0) {
+ return null;
+ }
+ final Drawable drawable = ctx.getDrawable(splashscreenContentResId);
+ if (drawable == null) {
+ return null;
+ }
+ View view = new View(ctx);
+ view.setBackground(drawable);
+ win.setContentView(view);
+ return view;
+ }
+
+ private static class DrawableColorTester {
+ private final ColorTester mColorChecker;
+
+ DrawableColorTester(Drawable drawable) {
+ this(drawable, false /* filterTransparent */);
+ }
+
+ DrawableColorTester(Drawable drawable, boolean filterTransparent) {
+ // Some applications use LayerDrawable for their windowBackground. To ensure that we
+ // only get the real background, so that the color is not affected by the alpha of the
+ // upper layer, try to get the lower layer here. This can also speed up the calculation.
+ if (drawable instanceof LayerDrawable) {
+ LayerDrawable layerDrawable = (LayerDrawable) drawable;
+ if (layerDrawable.getNumberOfLayers() > 0) {
+ if (DEBUG) {
+ Slog.d(TAG, "replace drawable with bottom layer drawable");
+ }
+ drawable = layerDrawable.getDrawable(0);
+ }
+ }
+ mColorChecker = drawable instanceof ColorDrawable
+ ? new SingleColorTester((ColorDrawable) drawable)
+ : new ComplexDrawableTester(drawable, filterTransparent);
+ }
+
+ public float nonTransparentRatio() {
+ return mColorChecker.nonTransparentRatio();
+ }
+
+ public boolean isComplexColor() {
+ return mColorChecker.isComplexColor();
+ }
+
+ public int getDominateColor() {
+ return mColorChecker.getDominantColor();
+ }
+
+ public boolean isGrayscale() {
+ return mColorChecker.isGrayscale();
+ }
+
+ /**
+ * A help class to check the color information from a Drawable.
+ */
+ private interface ColorTester {
+ float nonTransparentRatio();
+ boolean isComplexColor();
+ int getDominantColor();
+ boolean isGrayscale();
+ }
+
+ private static boolean isGrayscaleColor(int color) {
+ final int red = Color.red(color);
+ final int green = Color.green(color);
+ final int blue = Color.blue(color);
+ return red == green && green == blue;
+ }
+
+ /**
+ * For ColorDrawable only.
+ * There will be only one color so don't spend too much resource for it.
+ */
+ private static class SingleColorTester implements ColorTester {
+ private final ColorDrawable mColorDrawable;
+
+ SingleColorTester(@NonNull ColorDrawable drawable) {
+ mColorDrawable = drawable;
+ }
+
+ @Override
+ public float nonTransparentRatio() {
+ final int alpha = mColorDrawable.getAlpha();
+ return (float) (alpha / 255);
+ }
+
+ @Override
+ public boolean isComplexColor() {
+ return false;
+ }
+
+ @Override
+ public int getDominantColor() {
+ return mColorDrawable.getColor();
+ }
+
+ @Override
+ public boolean isGrayscale() {
+ return isGrayscaleColor(mColorDrawable.getColor());
+ }
+ }
+
+ /**
+ * For any other Drawable except ColorDrawable.
+ * This will use the Palette API to check the color information and use a quantizer to
+ * filter out transparent colors when needed.
+ */
+ private static class ComplexDrawableTester implements ColorTester {
+ private static final int MAX_BITMAP_SIZE = 40;
+ private final Palette mPalette;
+ private final boolean mFilterTransparent;
+ private static final TransparentFilterQuantizer TRANSPARENT_FILTER_QUANTIZER =
+ new TransparentFilterQuantizer();
+
+ ComplexDrawableTester(Drawable drawable, boolean filterTransparent) {
+ final Rect initialBounds = drawable.copyBounds();
+ int width = drawable.getIntrinsicWidth();
+ int height = drawable.getIntrinsicHeight();
+
+ // Some drawables do not have intrinsic dimensions
+ if (width <= 0 || height <= 0) {
+ width = MAX_BITMAP_SIZE;
+ height = MAX_BITMAP_SIZE;
+ } else {
+ width = Math.min(width, MAX_BITMAP_SIZE);
+ height = Math.min(height, MAX_BITMAP_SIZE);
+ }
+
+ final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ final Canvas bmpCanvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
+ drawable.draw(bmpCanvas);
+ // restore to original bounds
+ drawable.setBounds(initialBounds);
+
+ final Palette.Builder builder = new Palette.Builder(bitmap)
+ .maximumColorCount(5).clearFilters();
+ // The Palette API will ignore Alpha, so it cannot handle transparent pixels, but
+ // sometimes we will need this information to know if this Drawable object is
+ // transparent.
+ mFilterTransparent = filterTransparent;
+ if (mFilterTransparent) {
+ builder.setQuantizer(TRANSPARENT_FILTER_QUANTIZER);
+ }
+ mPalette = builder.generate();
+ bitmap.recycle();
+ }
+
+ @Override
+ public float nonTransparentRatio() {
+ return mFilterTransparent ? TRANSPARENT_FILTER_QUANTIZER.mNonTransparentRatio : 1;
+ }
+
+ @Override
+ public boolean isComplexColor() {
+ return mPalette.getSwatches().size() > 1;
+ }
+
+ @Override
+ public int getDominantColor() {
+ final Palette.Swatch mainSwatch = mPalette.getDominantSwatch();
+ if (mainSwatch != null) {
+ return mainSwatch.getRgb();
+ }
+ return Color.BLACK;
+ }
+
+ @Override
+ public boolean isGrayscale() {
+ final List swatches = mPalette.getSwatches();
+ if (swatches != null) {
+ for (int i = swatches.size() - 1; i >= 0; i--) {
+ Palette.Swatch swatch = swatches.get(i);
+ if (!isGrayscaleColor(swatch.getRgb())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static class TransparentFilterQuantizer implements Quantizer {
+ private static final int NON_TRANSPARENT = 0xFF000000;
+ private final Quantizer mInnerQuantizer = new VariationalKMeansQuantizer();
+ private float mNonTransparentRatio;
+ @Override
+ public void quantize(final int[] pixels, final int maxColors,
+ final Palette.Filter[] filters) {
+ mNonTransparentRatio = 0;
+ int realSize = 0;
+ for (int i = pixels.length - 1; i > 0; i--) {
+ if ((pixels[i] & NON_TRANSPARENT) != 0) {
+ realSize++;
+ }
+ }
+ if (realSize == 0) {
+ if (DEBUG) {
+ Slog.d(TAG, "quantize: this is pure transparent image");
+ }
+ mInnerQuantizer.quantize(pixels, maxColors, filters);
+ return;
+ }
+ mNonTransparentRatio = (float) realSize / pixels.length;
+ final int[] samplePixels = new int[realSize];
+ int rowIndex = 0;
+ for (int i = pixels.length - 1; i > 0; i--) {
+ if ((pixels[i] & NON_TRANSPARENT) == NON_TRANSPARENT) {
+ samplePixels[rowIndex] = pixels[i];
+ rowIndex++;
+ }
+ }
+ mInnerQuantizer.quantize(samplePixels, maxColors, filters);
+ }
+
+ @Override
+ public List getQuantizedColors() {
+ return mInnerQuantizer.getQuantizedColors();
+ }
+ }
+ }
+ }
+
+ private static class StartingSurfaceWindowView extends FrameLayout {
+ // TODO animate the icon view
+ private final View mIconView;
+
+ StartingSurfaceWindowView(Context context, int iconSize) {
+ super(context);
+
+ final boolean emptyIcon = iconSize == 0;
+ if (emptyIcon) {
+ mIconView = null;
+ } else {
+ mIconView = new View(context);
+ FrameLayout.LayoutParams params =
+ new FrameLayout.LayoutParams(iconSize, iconSize);
+ params.gravity = Gravity.CENTER;
+ addView(mIconView, params);
+ }
+ setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+ }
+
+ // TODO support animatable icon
+ void setIconDrawable(Drawable icon) {
+ if (mIconView != null) {
+ mIconView.setBackground(icon);
+ }
+ }
+ }
+}
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 e144ca3226861..786a1fd896ebd 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
@@ -35,7 +35,6 @@ import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
import android.os.RemoteException;
@@ -64,6 +63,7 @@ import java.util.function.Consumer;
* class to remove the starting window of the Task.
* @hide
*/
+
public class StartingSurfaceDrawer {
static final String TAG = StartingSurfaceDrawer.class.getSimpleName();
static final boolean DEBUG_SPLASH_SCREEN = false;
@@ -72,6 +72,7 @@ public class StartingSurfaceDrawer {
private final Context mContext;
private final DisplayManager mDisplayManager;
final ShellExecutor mMainExecutor;
+ private final SplashscreenContentDrawer mSplashscreenContentDrawer;
// TODO(b/131727939) remove this when clearing ActivityRecord
private static final int REMOVE_WHEN_TIMEOUT = 2000;
@@ -80,6 +81,7 @@ public class StartingSurfaceDrawer {
mContext = context;
mDisplayManager = mContext.getSystemService(DisplayManager.class);
mMainExecutor = mainExecutor;
+ mSplashscreenContentDrawer = new SplashscreenContentDrawer(context);
}
private final SparseArray mStartingWindowRecords = new SparseArray<>();
@@ -234,7 +236,6 @@ public class StartingSurfaceDrawer {
return;
}
context = displayContext;
-
if (theme != context.getThemeResId() || labelRes != 0) {
try {
context = context.createPackageContext(
@@ -347,7 +348,12 @@ public class StartingSurfaceDrawer {
}
params.setTitle("Splash Screen " + activityInfo.packageName);
- addSplashscreenContent(win, context, splashscreenContentResId[0]);
+ final View contentView = mSplashscreenContentDrawer.makeSplashScreenContentView(win,
+ context, iconRes, splashscreenContentResId[0]);
+ if (contentView == null) {
+ Slog.w(TAG, "Adding splash screen window for " + activityInfo.packageName + " failed!");
+ return;
+ }
final View view = win.getDecorView();
@@ -459,20 +465,4 @@ public class StartingSurfaceDrawer {
mTaskSnapshotWindow = taskSnapshotWindow;
}
}
-
- private void addSplashscreenContent(PhoneWindow win, Context ctx,
- int splashscreenContentResId) {
- if (splashscreenContentResId == 0) {
- return;
- }
- final Drawable drawable = ctx.getDrawable(splashscreenContentResId);
- if (drawable == null) {
- return;
- }
-
- // We wrap this into a view so the system insets get applied to the drawable.
- final View v = new View(ctx);
- v.setBackground(drawable);
- win.setContentView(v);
- }
}