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.FileDescriptor;
36 import java.io.PrintWriter;
37 import java.util.Arrays;
38 
39 import javax.inject.Inject;
40 
41 /**
42  * ColorExtractor aware of wallpaper visibility
43  */
44 @SysUISingleton
45 public class SysuiColorExtractor extends ColorExtractor implements Dumpable,
46         ConfigurationController.ConfigurationListener {
47     private static final String TAG = "SysuiColorExtractor";
48     private final Tonal mTonal;
49     private boolean mHasMediaArtwork;
50     private final GradientColors mNeutralColorsLock;
51     private final GradientColors mBackdropColors;
52 
53     @Inject
SysuiColorExtractor( Context context, ConfigurationController configurationController, DumpManager dumpManager)54     public SysuiColorExtractor(
55             Context context,
56             ConfigurationController configurationController,
57             DumpManager dumpManager) {
58         this(
59                 context,
60                 new Tonal(context),
61                 configurationController,
62                 context.getSystemService(WallpaperManager.class),
63                 dumpManager,
64                 false /* immediately */);
65     }
66 
67     @VisibleForTesting
SysuiColorExtractor( Context context, ExtractionType type, ConfigurationController configurationController, WallpaperManager wallpaperManager, DumpManager dumpManager, boolean immediately)68     public SysuiColorExtractor(
69             Context context,
70             ExtractionType type,
71             ConfigurationController configurationController,
72             WallpaperManager wallpaperManager,
73             DumpManager dumpManager,
74             boolean immediately) {
75         super(context, type, immediately, wallpaperManager);
76         mTonal = type instanceof Tonal ? (Tonal) type : new Tonal(context);
77         mNeutralColorsLock = new GradientColors();
78         configurationController.addCallback(this);
79         dumpManager.registerDumpable(getClass().getSimpleName(), this);
80 
81         mBackdropColors = new GradientColors();
82         mBackdropColors.setMainColor(Color.BLACK);
83 
84         // Listen to all users instead of only the current one.
85         if (wallpaperManager.isWallpaperSupported()) {
86             wallpaperManager.removeOnColorsChangedListener(this);
87             wallpaperManager.addOnColorsChangedListener(this, null /* handler */,
88                     UserHandle.USER_ALL);
89         }
90     }
91 
92     @Override
extractWallpaperColors()93     protected void extractWallpaperColors() {
94         super.extractWallpaperColors();
95         // mTonal is final but this method will be invoked by the base class during its ctor.
96         if (mTonal == null || mNeutralColorsLock == null) {
97             return;
98         }
99         mTonal.applyFallback(mLockColors == null ? mSystemColors : mLockColors, mNeutralColorsLock);
100     }
101 
102     @Override
onColorsChanged(WallpaperColors colors, int which, int userId)103     public void onColorsChanged(WallpaperColors colors, int which, int userId) {
104         if (userId != KeyguardUpdateMonitor.getCurrentUser()) {
105             // Colors do not belong to current user, ignoring.
106             return;
107         }
108         if ((which & WallpaperManager.FLAG_LOCK) != 0) {
109             mTonal.applyFallback(colors, mNeutralColorsLock);
110         }
111         super.onColorsChanged(colors, which);
112     }
113 
114     @Override
onUiModeChanged()115     public void onUiModeChanged() {
116         extractWallpaperColors();
117         triggerColorsChanged(WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
118     }
119 
120     @Override
getColors(int which, int type)121     public GradientColors getColors(int which, int type) {
122         if (mHasMediaArtwork && (which & WallpaperManager.FLAG_LOCK) != 0) {
123             return mBackdropColors;
124         }
125         return super.getColors(which, type);
126     }
127 
128     /**
129      * Colors that should be using for scrims.
130      *
131      * They will be:
132      * - A light gray if the wallpaper is light
133      * - A dark gray if the wallpaper is very dark or we're in night mode.
134      * - Black otherwise
135      */
getNeutralColors()136     public GradientColors getNeutralColors() {
137         return mHasMediaArtwork ? mBackdropColors : mNeutralColorsLock;
138     }
139 
setHasMediaArtwork(boolean hasBackdrop)140     public void setHasMediaArtwork(boolean hasBackdrop) {
141         if (mHasMediaArtwork != hasBackdrop) {
142             mHasMediaArtwork = hasBackdrop;
143             triggerColorsChanged(WallpaperManager.FLAG_LOCK);
144         }
145     }
146 
147     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)148     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
149         pw.println("SysuiColorExtractor:");
150 
151         pw.println("  Current wallpaper colors:");
152         pw.println("    system: " + mSystemColors);
153         pw.println("    lock: " + mLockColors);
154 
155         GradientColors[] system = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
156         GradientColors[] lock = mGradientColors.get(WallpaperManager.FLAG_LOCK);
157         pw.println("  Gradients:");
158         pw.println("    system: " + Arrays.toString(system));
159         pw.println("    lock: " + Arrays.toString(lock));
160         pw.println("  Neutral colors: " + mNeutralColorsLock);
161         pw.println("  Has media backdrop: " + mHasMediaArtwork);
162 
163     }
164 }
165