diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index 47052a77e2..128d95603f 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -180,7 +180,7 @@ public class Hotseat extends FrameLayout public void updateColor(ExtractedColors extractedColors, boolean animate) { if (!mHasVerticalHotseat) { - int color = extractedColors.getColor(ExtractedColors.HOTSEAT_INDEX, Color.TRANSPARENT); + int color = extractedColors.getColor(ExtractedColors.HOTSEAT_INDEX); if (mBackgroundColorAnimator != null) { mBackgroundColorAnimator.cancel(); } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index a8d3d15d54..da52b4f3e2 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -466,6 +466,14 @@ public class Launcher extends BaseActivity @Override public void onExtractedColorsChanged() { loadExtractedColorsAndColorItems(); + + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onExtractedColorsChanged(); + } + } + + public ExtractedColors getExtractedColors() { + return mExtractedColors; } @Override @@ -481,9 +489,9 @@ public class Launcher extends BaseActivity mExtractedColors.load(this); mHotseat.updateColor(mExtractedColors, !mPaused); mWorkspace.getPageIndicator().updateColor(mExtractedColors); - boolean lightStatusBar = (FeatureFlags.LIGHT_STATUS_BAR - && mExtractedColors.getColor(ExtractedColors.STATUS_BAR_INDEX, - ExtractedColors.DEFAULT_DARK) == ExtractedColors.DEFAULT_LIGHT); + boolean lightStatusBar = (FeatureFlags.LIGHT_STATUS_BAR && + mExtractedColors.getColor(ExtractedColors.STATUS_BAR_INDEX) == + ExtractedColors.DEFAULT_LIGHT); // It's possible that All Apps is visible when this is run, // so always use light status bar in that case. Only change nav bar color to status bar // color when All Apps is visible. diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java index ff037b8f90..32f179f467 100644 --- a/src/com/android/launcher3/LauncherCallbacks.java +++ b/src/com/android/launcher3/LauncherCallbacks.java @@ -107,4 +107,6 @@ public interface LauncherCallbacks { void setLauncherSearchCallback(Object callbacks); boolean shouldShowDiscoveryBounce(); + + void onExtractedColorsChanged(); } diff --git a/src/com/android/launcher3/dynamicui/ColorExtractionService.java b/src/com/android/launcher3/dynamicui/ColorExtractionService.java index f94d442e07..9379a7285f 100644 --- a/src/com/android/launcher3/dynamicui/ColorExtractionService.java +++ b/src/com/android/launcher3/dynamicui/ColorExtractionService.java @@ -21,6 +21,7 @@ import android.app.IntentService; import android.app.WallpaperManager; import android.content.Intent; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; @@ -61,6 +62,10 @@ public class ColorExtractionService extends IntentService { if (wallpaperManager.getWallpaperInfo() != null) { // We can't extract colors from live wallpapers, so just use the default color always. extractedColors.updateHotseatPalette(null); + + if (FeatureFlags.QSB_IN_HOTSEAT) { + extractedColors.updateWallpaperThemePalette(null); + } } else { // We extract colors for the hotseat and status bar separately, // since they only consider part of the wallpaper. @@ -69,6 +74,10 @@ public class ColorExtractionService extends IntentService { if (FeatureFlags.LIGHT_STATUS_BAR) { extractedColors.updateStatusBarPalette(getStatusBarPalette()); } + + if (FeatureFlags.QSB_IN_HOTSEAT) { + extractedColors.updateWallpaperThemePalette(getWallpaperPalette()); + } } // Save the extracted colors and wallpaper id to LauncherProvider. @@ -140,4 +149,23 @@ public class ColorExtractionService extends IntentService { .clearFilters() .generate(); } + + @TargetApi(Build.VERSION_CODES.N) + private Palette getWallpaperPalette() { + WallpaperManager wallpaperManager = WallpaperManager.getInstance(this); + if (Utilities.ATLEAST_NOUGAT) { + try (ParcelFileDescriptor fd = wallpaperManager + .getWallpaperFile(WallpaperManager.FLAG_SYSTEM)) { + Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor()); + if (bitmap != null) { + return Palette.from(bitmap).clearFilters().generate(); + } + } catch (IOException | NullPointerException e) { + Log.e(TAG, "Fetching partial bitmap failed, trying old method", e); + } + } + + Bitmap wallpaper = ((BitmapDrawable) wallpaperManager.getDrawable()).getBitmap(); + return Palette.from(wallpaper).clearFilters().generate(); + } } diff --git a/src/com/android/launcher3/dynamicui/ExtractedColors.java b/src/com/android/launcher3/dynamicui/ExtractedColors.java index 711508ea5a..2e52a0b8ca 100644 --- a/src/com/android/launcher3/dynamicui/ExtractedColors.java +++ b/src/com/android/launcher3/dynamicui/ExtractedColors.java @@ -23,6 +23,9 @@ import android.support.v7.graphics.Palette; import android.util.Log; import com.android.launcher3.Utilities; +import com.android.launcher3.config.FeatureFlags; + +import java.util.Arrays; /** * Saves and loads colors extracted from the wallpaper, as well as the associated wallpaper id. @@ -32,31 +35,43 @@ public class ExtractedColors { public static final int DEFAULT_LIGHT = Color.WHITE; public static final int DEFAULT_DARK = Color.BLACK; - public static final int DEFAULT_COLOR = DEFAULT_LIGHT; // These color profile indices should NOT be changed, since they are used when saving and // loading extracted colors. New colors should always be added at the end. public static final int VERSION_INDEX = 0; public static final int HOTSEAT_INDEX = 1; public static final int STATUS_BAR_INDEX = 2; - // public static final int VIBRANT_INDEX = 2; - // public static final int VIBRANT_DARK_INDEX = 3; - // public static final int VIBRANT_LIGHT_INDEX = 4; - // public static final int MUTED_INDEX = 5; - // public static final int MUTED_DARK_INDEX = 6; - // public static final int MUTED_LIGHT_INDEX = 7; + public static final int WALLPAPER_VIBRANT_INDEX = 3; - public static final int NUM_COLOR_PROFILES = 2; - private static final int VERSION = 1; + private static final int VERSION; + private static final int[] DEFAULT_VALUES; + + static { + if (FeatureFlags.QSB_IN_HOTSEAT) { + VERSION = 2; + DEFAULT_VALUES = new int[] { + VERSION, // VERSION_INDEX + 0x40FFFFFF, // HOTSEAT_INDEX: White with 25% alpha + DEFAULT_DARK, // STATUS_BAR_INDEX + 0xFFCCCCCC, // WALLPAPER_VIBRANT_INDEX + }; + } else { + VERSION = 1; + DEFAULT_VALUES = new int[] { + VERSION, // VERSION_INDEX + 0x40FFFFFF, // HOTSEAT_INDEX: White with 25% alpha + DEFAULT_DARK, // STATUS_BAR_INDEX + }; + } + } private static final String COLOR_SEPARATOR = ","; - private int[] mColors; + private final int[] mColors; public ExtractedColors() { // The first entry is reserved for the version number. - mColors = new int[NUM_COLOR_PROFILES + 1]; - mColors[VERSION_INDEX] = VERSION; + mColors = Arrays.copyOf(DEFAULT_VALUES, DEFAULT_VALUES.length); } public void setColorAtIndex(int index, int color) { @@ -78,17 +93,6 @@ public class ExtractedColors { return colorsStringBuilder.toString(); } - /** - * Decodes a comma-separated String into {@link #mColors}. - */ - void decodeFromString(String colorsString) { - String[] splitColorsString = colorsString.split(COLOR_SEPARATOR); - mColors = new int[splitColorsString.length]; - for (int i = 0; i < mColors.length; i++) { - mColors[i] = Integer.parseInt(splitColorsString[i]); - } - } - /** * Loads colors and wallpaper id from {@link Utilities#getPrefs(Context)}. * These were saved there in {@link ColorExtractionService}. @@ -97,19 +101,22 @@ public class ExtractedColors { String encodedString = Utilities.getPrefs(context).getString( ExtractionUtils.EXTRACTED_COLORS_PREFERENCE_KEY, VERSION + ""); - decodeFromString(encodedString); - - if (mColors[VERSION_INDEX] != VERSION) { + String[] splitColorsString = encodedString.split(COLOR_SEPARATOR); + if (splitColorsString.length == DEFAULT_VALUES.length && + Integer.parseInt(splitColorsString[VERSION_INDEX]) == VERSION) { + // Parse and apply the saved values. + for (int i = 0; i < mColors.length; i++) { + mColors[i] = Integer.parseInt(splitColorsString[i]); + } + } else { + // Leave the values as default values as the saved values may not be compatible. ExtractionUtils.startColorExtractionService(context); } } /** @param index must be one of the index values defined at the top of this class. */ - public int getColor(int index, int defaultColor) { - if (index > VERSION_INDEX && index < mColors.length) { - return mColors[index]; - } - return defaultColor; + public int getColor(int index) { + return mColors[index]; } /** @@ -125,7 +132,7 @@ public class ExtractedColors { } else if (hotseatPalette != null && ExtractionUtils.isSuperDark(hotseatPalette)) { hotseatColor = ColorUtils.setAlphaComponent(Color.WHITE, (int) (0.18f * 255)); } else { - hotseatColor = ColorUtils.setAlphaComponent(Color.WHITE, (int) (0.25f * 255)); + hotseatColor = DEFAULT_VALUES[HOTSEAT_INDEX]; } setColorAtIndex(HOTSEAT_INDEX, hotseatColor); } @@ -134,4 +141,10 @@ public class ExtractedColors { setColorAtIndex(STATUS_BAR_INDEX, ExtractionUtils.isSuperLight(statusBarPalette) ? DEFAULT_LIGHT : DEFAULT_DARK); } + + public void updateWallpaperThemePalette(Palette wallpaperPalette) { + int defaultColor = DEFAULT_VALUES[WALLPAPER_VIBRANT_INDEX]; + setColorAtIndex(WALLPAPER_VIBRANT_INDEX, wallpaperPalette == null + ? defaultColor : wallpaperPalette.getVibrantColor(defaultColor)); + } } diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java index 3ceba84191..91fc1f04ac 100644 --- a/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java +++ b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java @@ -221,7 +221,7 @@ public class PageIndicatorLineCaret extends PageIndicator { */ public void updateColor(ExtractedColors extractedColors) { int originalLineAlpha = mLinePaint.getAlpha(); - int color = extractedColors.getColor(ExtractedColors.HOTSEAT_INDEX, Color.TRANSPARENT); + int color = extractedColors.getColor(ExtractedColors.HOTSEAT_INDEX); if (color != Color.TRANSPARENT) { color = ColorUtils.setAlphaComponent(color, 255); if (color == Color.BLACK) { diff --git a/src/com/android/launcher3/testing/LauncherExtension.java b/src/com/android/launcher3/testing/LauncherExtension.java index 12f3b846af..031da2061c 100644 --- a/src/com/android/launcher3/testing/LauncherExtension.java +++ b/src/com/android/launcher3/testing/LauncherExtension.java @@ -230,5 +230,8 @@ public class LauncherExtension extends Launcher { public boolean shouldShowDiscoveryBounce() { return false; } + + @Override + public void onExtractedColorsChanged() { } } } diff --git a/src_flags/com/android/launcher3/config/FeatureFlags.java b/src_flags/com/android/launcher3/config/FeatureFlags.java index a97823dafe..159f125a98 100644 --- a/src_flags/com/android/launcher3/config/FeatureFlags.java +++ b/src_flags/com/android/launcher3/config/FeatureFlags.java @@ -55,4 +55,6 @@ public final class FeatureFlags { public static final boolean ADAPTIVE_ICON_SHADOW = true; // When enabled, app discovery will be enabled if service is implemented public static final boolean DISCOVERY_ENABLED = false; + // When enabled, the qsb will be moved to the hotseat. + public static final boolean QSB_IN_HOTSEAT = true; }