diff options
5 files changed, 88 insertions, 44 deletions
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java index 2d794fb01ad6..62fcef3d6559 100644 --- a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java +++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java @@ -16,12 +16,14 @@ package com.google.android.colorextraction; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.WallpaperColors; import android.app.WallpaperManager; import android.content.Context; -import android.support.annotation.NonNull; +import android.os.AsyncTask; +import android.os.Trace; import android.support.annotation.VisibleForTesting; -import android.support.v4.graphics.ColorUtils; import android.util.Log; import android.util.SparseArray; @@ -29,6 +31,7 @@ import com.google.android.colorextraction.types.ExtractionType; import com.google.android.colorextraction.types.Tonal; import java.util.ArrayList; +import java.util.List; /** * Class to process wallpaper colors and generate a tonal palette based on them. @@ -50,6 +53,8 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener private final ArrayList<OnColorsChangedListener> mOnColorsChangedListeners; private final Context mContext; private final ExtractionType mExtractionType; + private WallpaperColors mSystemColors; + private WallpaperColors mLockColors; public ColorExtractor(Context context) { this(context, new Tonal()); @@ -70,7 +75,6 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener } mOnColorsChangedListeners = new ArrayList<>(); - WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class); if (wallpaperManager == null) { Log.w(TAG, "Can't listen to color changes!"); @@ -78,17 +82,25 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener wallpaperManager.addOnColorsChangedListener(this); // Initialize all gradients with the current colors - GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM); - extractInto(wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM), + Trace.beginSection("ColorExtractor#getWallpaperColors"); + mSystemColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM); + mLockColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK); + + GradientColors[] systemColors = mGradientColors.get( + WallpaperManager.FLAG_SYSTEM); + extractInto(mSystemColors, systemColors[TYPE_NORMAL], systemColors[TYPE_DARK], systemColors[TYPE_EXTRA_DARK]); GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK); - extractInto(wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK), + extractInto(mLockColors, lockColors[TYPE_NORMAL], lockColors[TYPE_DARK], lockColors[TYPE_EXTRA_DARK]); + triggerColorsChanged(WallpaperManager.FLAG_SYSTEM + | WallpaperManager.FLAG_LOCK); + Trace.endSection(); } } @@ -110,6 +122,7 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener * @param type TYPE_NORMAL, TYPE_DARK or TYPE_EXTRA_DARK * @return colors */ + @NonNull public GradientColors getColors(int which, int type) { if (type != TYPE_NORMAL && type != TYPE_DARK && type != TYPE_EXTRA_DARK) { throw new IllegalArgumentException( @@ -121,16 +134,35 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener return mGradientColors.get(which)[type]; } + /** + * Get the last available WallpaperColors without forcing new extraction. + * + * @param which FLAG_LOCK or FLAG_SYSTEM + * @return Last cached colors + */ + @Nullable + public WallpaperColors getWallpaperColors(int which) { + if (which == WallpaperManager.FLAG_LOCK) { + return mLockColors; + } else if (which == WallpaperManager.FLAG_SYSTEM) { + return mSystemColors; + } else { + throw new IllegalArgumentException("Invalid value for which: " + which); + } + } + @Override public void onColorsChanged(WallpaperColors colors, int which) { boolean changed = false; if ((which & WallpaperManager.FLAG_LOCK) != 0) { + mLockColors = colors; GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK); extractInto(colors, lockColors[TYPE_NORMAL], lockColors[TYPE_DARK], lockColors[TYPE_EXTRA_DARK]); changed = true; } if ((which & WallpaperManager.FLAG_SYSTEM) != 0) { + mSystemColors = colors; GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM); extractInto(colors, systemColors[TYPE_NORMAL], systemColors[TYPE_DARK], systemColors[TYPE_EXTRA_DARK]); diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index bb4412375ff8..776d07616d9a 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -268,6 +268,9 @@ public class Dependency extends SystemUI { mProviders.put(AccessibilityManagerWrapper.class, () -> new AccessibilityManagerWrapper(mContext)); + // Creating a new instance will trigger color extraction. + // Thankfully this only happens once - during boot - and WallpaperManagerService + // loads colors from cache. mProviders.put(SysuiColorExtractor.class, () -> new SysuiColorExtractor(mContext)); mProviders.put(TunablePaddingService.class, () -> new TunablePaddingService()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 754c34486954..0bd58df13002 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -304,8 +304,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, mNeedsDrawableColorUpdate = false; if (mKeyguardShowing) { // Always animate color changes if we're seeing the keyguard - mScrimInFront.setColors(mLockColors); - mScrimBehind.setColors(mLockColors); + mScrimInFront.setColors(mLockColors, true /* animated */); + mScrimBehind.setColors(mLockColors, true /* animated */); } else { // Only animate scrim color if the scrim view is actually visible boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index b734929ea56b..f019fb946e59 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -4573,16 +4573,13 @@ public class StatusBar extends SystemUI implements DemoMode, .supportsDarkText(); // And wallpaper defines if QS should be light or dark. boolean useDarkTheme = false; - final WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class); - if (wallpaperManager != null) { - WallpaperColors wallpaperColors = wallpaperManager - .getWallpaperColors(WallpaperManager.FLAG_SYSTEM); - if (wallpaperColors != null) { - final int mainColor = wallpaperColors.getPrimaryColor().toArgb(); - final float[] hsl = new float[3]; - ColorUtils.colorToHSL(mainColor, hsl); - useDarkTheme = hsl[2] < 0.2f; - } + final WallpaperColors systemColors = + mColorExtractor.getWallpaperColors(WallpaperManager.FLAG_SYSTEM); + if (systemColors != null) { + int mainColor = systemColors.getPrimaryColor().toArgb(); + float[] hsl = new float[3]; + ColorUtils.colorToHSL(mainColor, hsl); + useDarkTheme = hsl[2] < 0.2f; } // Enable/disable dark UI. diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index dfcc1665bfc4..2aa524c4c5c8 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -32,6 +32,7 @@ import android.app.IWallpaperManager; import android.app.IWallpaperManagerCallback; import android.app.PendingIntent; import android.app.UserSwitchObserver; +import android.app.WallpaperColors; import android.app.WallpaperInfo; import android.app.WallpaperManager; import android.app.admin.DevicePolicyManager; @@ -55,7 +56,6 @@ import android.graphics.BitmapRegionDecoder; import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.os.Binder; import android.os.Bundle; import android.os.Environment; @@ -64,8 +64,8 @@ import android.os.FileUtils; import android.os.Handler; import android.os.IBinder; import android.os.IRemoteCallback; -import android.os.Process; import android.os.ParcelFileDescriptor; +import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SELinux; @@ -76,12 +76,10 @@ import android.os.UserManager; import android.service.wallpaper.IWallpaperConnection; import android.service.wallpaper.IWallpaperEngine; import android.service.wallpaper.IWallpaperService; -import android.app.WallpaperColors; import android.service.wallpaper.WallpaperService; import android.system.ErrnoException; import android.system.Os; import android.util.EventLog; -import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.Xml; @@ -99,7 +97,6 @@ import com.android.server.EventLogTags; import com.android.server.FgThread; import com.android.server.SystemService; -import java.util.ArrayList; import libcore.io.IoUtils; import org.xmlpull.v1.XmlPullParser; @@ -347,32 +344,44 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { needsExtraction = wallpaper.primaryColors == null; } - // This should not be synchronized because color extraction - // might take a while. + // Let's notify the current values, it's fine if it's null, it just means + // that we don't know yet. + notifyColorListeners(wallpaper.primaryColors, which); + if (needsExtraction) { extractColors(wallpaper); + notifyColorListeners(wallpaper.primaryColors, which); } + } + private void notifyColorListeners(WallpaperColors wallpaperColors, int which) { + final IWallpaperManagerCallback[] listeners; + final IWallpaperManagerCallback keyguardListener; synchronized (mLock) { - final int n = mColorsChangedListeners.beginBroadcast(); - for (int i = 0; i < n; i++) { - IWallpaperManagerCallback callback = mColorsChangedListeners.getBroadcastItem(i); - try { - callback.onWallpaperColorsChanged(wallpaper.primaryColors, which); - } catch (RemoteException e) { - // Callback is gone, it's not necessary to unregister it since - // RemoteCallbackList#getBroadcastItem will take care of it. - } + // Make a synchronized copy of the listeners to avoid concurrent list modification. + int callbackCount = mColorsChangedListeners.beginBroadcast(); + listeners = new IWallpaperManagerCallback[callbackCount]; + for (int i = 0; i < callbackCount; i++) { + listeners[i] = mColorsChangedListeners.getBroadcastItem(i); } mColorsChangedListeners.finishBroadcast(); + keyguardListener = mKeyguardListener; + } - final IWallpaperManagerCallback cb = mKeyguardListener; - if (cb != null) { - try { - cb.onWallpaperColorsChanged(wallpaper.primaryColors, which); - } catch (RemoteException e) { - // Oh well it went away; no big deal - } + for (int i = 0; i < listeners.length; i++) { + try { + listeners[i].onWallpaperColorsChanged(wallpaperColors, which); + } catch (RemoteException e) { + // Callback is gone, it's not necessary to unregister it since + // RemoteCallbackList#getBroadcastItem will take care of it. + } + } + + if (keyguardListener != null) { + try { + keyguardListener.onWallpaperColorsChanged(wallpaperColors, which); + } catch (RemoteException e) { + // Oh well it went away; no big deal } } } @@ -414,6 +423,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { synchronized (mLock) { if (wallpaper.wallpaperId == wallpaperId) { wallpaper.primaryColors = colors; + // Now that we have the colors, let's save them into the xml + // to avoid having to run this again. + saveSettingsLocked(wallpaper.userId); } else { Slog.w(TAG, "Not setting primary colors since wallpaper changed"); } @@ -1366,6 +1378,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { RuntimeException e = null; try { + wallpaper.primaryColors = null; wallpaper.imageWallpaperPending = false; if (userId != mCurrentUserId) return; if (bindWallpaperComponentLocked(defaultFailed @@ -1843,6 +1856,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { try { wallpaper.imageWallpaperPending = false; if (bindWallpaperComponentLocked(name, false, true, wallpaper, null)) { + wallpaper.primaryColors = null; wallpaper.wallpaperId = makeWallpaperIdLocked(); notifyCallbacksLocked(wallpaper); shouldNotifyColors = true; @@ -1979,7 +1993,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } wallpaper.wallpaperComponent = componentName; wallpaper.connection = newConn; - wallpaper.primaryColors = null; newConn.mReply = reply; try { if (wallpaper.userId == mCurrentUserId) { @@ -2185,7 +2198,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { out.attribute(null, "colorValue"+i, Integer.toString(wc.toArgb())); } } - out.attribute(null, "supportsDarkText", + out.attribute(null, "colorHints", Integer.toString(wallpaper.primaryColors.getColorHints())); } @@ -2422,7 +2435,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { int colorsCount = getAttributeInt(parser, "colorsCount", 0); if (colorsCount > 0) { Color primary = null, secondary = null, tertiary = null; - final List<Color> colors = new ArrayList<>(); for (int i = 0; i < colorsCount; i++) { Color color = Color.valueOf(getAttributeInt(parser, "colorValue" + i, 0)); if (i == 0) { |