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