1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.systemui.colorextraction; 18 19 import android.app.WallpaperColors; 20 import android.app.WallpaperManager; 21 import android.content.Context; 22 import android.graphics.Color; 23 import android.os.UserHandle; 24 25 import com.android.internal.annotations.VisibleForTesting; 26 import com.android.internal.colorextraction.ColorExtractor; 27 import com.android.internal.colorextraction.types.ExtractionType; 28 import com.android.internal.colorextraction.types.Tonal; 29 import com.android.keyguard.KeyguardUpdateMonitor; 30 import com.android.systemui.Dumpable; 31 import com.android.systemui.dagger.SysUISingleton; 32 import com.android.systemui.dump.DumpManager; 33 import com.android.systemui.statusbar.policy.ConfigurationController; 34 35 import java.io.PrintWriter; 36 import java.util.Arrays; 37 38 import javax.inject.Inject; 39 40 /** 41 * ColorExtractor aware of wallpaper visibility 42 */ 43 @SysUISingleton 44 public class SysuiColorExtractor extends ColorExtractor implements Dumpable, 45 ConfigurationController.ConfigurationListener { 46 private static final String TAG = "SysuiColorExtractor"; 47 private final Tonal mTonal; 48 private boolean mHasMediaArtwork; 49 private final GradientColors mNeutralColorsLock; 50 private final GradientColors mBackdropColors; 51 52 @Inject SysuiColorExtractor( Context context, ConfigurationController configurationController, DumpManager dumpManager)53 public SysuiColorExtractor( 54 Context context, 55 ConfigurationController configurationController, 56 DumpManager dumpManager) { 57 this( 58 context, 59 new Tonal(context), 60 configurationController, 61 context.getSystemService(WallpaperManager.class), 62 dumpManager, 63 false /* immediately */); 64 } 65 66 @VisibleForTesting SysuiColorExtractor( Context context, ExtractionType type, ConfigurationController configurationController, WallpaperManager wallpaperManager, DumpManager dumpManager, boolean immediately)67 public SysuiColorExtractor( 68 Context context, 69 ExtractionType type, 70 ConfigurationController configurationController, 71 WallpaperManager wallpaperManager, 72 DumpManager dumpManager, 73 boolean immediately) { 74 super(context, type, immediately, wallpaperManager); 75 mTonal = type instanceof Tonal ? (Tonal) type : new Tonal(context); 76 mNeutralColorsLock = new GradientColors(); 77 configurationController.addCallback(this); 78 dumpManager.registerDumpable(getClass().getSimpleName(), this); 79 80 mBackdropColors = new GradientColors(); 81 mBackdropColors.setMainColor(Color.BLACK); 82 83 // Listen to all users instead of only the current one. 84 if (wallpaperManager.isWallpaperSupported()) { 85 wallpaperManager.removeOnColorsChangedListener(this); 86 wallpaperManager.addOnColorsChangedListener(this, null /* handler */, 87 UserHandle.USER_ALL); 88 } 89 } 90 91 @Override extractWallpaperColors()92 protected void extractWallpaperColors() { 93 super.extractWallpaperColors(); 94 // mTonal is final but this method will be invoked by the base class during its ctor. 95 if (mTonal == null || mNeutralColorsLock == null) { 96 return; 97 } 98 mTonal.applyFallback(mLockColors == null ? mSystemColors : mLockColors, mNeutralColorsLock); 99 } 100 101 @Override onColorsChanged(WallpaperColors colors, int which, int userId)102 public void onColorsChanged(WallpaperColors colors, int which, int userId) { 103 if (userId != KeyguardUpdateMonitor.getCurrentUser()) { 104 // Colors do not belong to current user, ignoring. 105 return; 106 } 107 if ((which & WallpaperManager.FLAG_LOCK) != 0) { 108 mTonal.applyFallback(colors, mNeutralColorsLock); 109 } 110 super.onColorsChanged(colors, which); 111 } 112 113 @Override onUiModeChanged()114 public void onUiModeChanged() { 115 extractWallpaperColors(); 116 triggerColorsChanged(WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK); 117 } 118 119 @Override getColors(int which, int type)120 public GradientColors getColors(int which, int type) { 121 if (mHasMediaArtwork && (which & WallpaperManager.FLAG_LOCK) != 0) { 122 return mBackdropColors; 123 } 124 return super.getColors(which, type); 125 } 126 127 /** 128 * Colors that should be using for scrims. 129 * 130 * They will be: 131 * - A light gray if the wallpaper is light 132 * - A dark gray if the wallpaper is very dark or we're in night mode. 133 * - Black otherwise 134 */ getNeutralColors()135 public GradientColors getNeutralColors() { 136 return mHasMediaArtwork ? mBackdropColors : mNeutralColorsLock; 137 } 138 setHasMediaArtwork(boolean hasBackdrop)139 public void setHasMediaArtwork(boolean hasBackdrop) { 140 if (mHasMediaArtwork != hasBackdrop) { 141 mHasMediaArtwork = hasBackdrop; 142 triggerColorsChanged(WallpaperManager.FLAG_LOCK); 143 } 144 } 145 146 @Override dump(PrintWriter pw, String[] args)147 public void dump(PrintWriter pw, String[] args) { 148 pw.println("SysuiColorExtractor:"); 149 150 pw.println(" Current wallpaper colors:"); 151 pw.println(" system: " + mSystemColors); 152 pw.println(" lock: " + mLockColors); 153 154 GradientColors[] system = mGradientColors.get(WallpaperManager.FLAG_SYSTEM); 155 GradientColors[] lock = mGradientColors.get(WallpaperManager.FLAG_LOCK); 156 pw.println(" Gradients:"); 157 pw.println(" system: " + Arrays.toString(system)); 158 pw.println(" lock: " + Arrays.toString(lock)); 159 pw.println(" Neutral colors: " + mNeutralColorsLock); 160 pw.println(" Has media backdrop: " + mHasMediaArtwork); 161 162 } 163 } 164