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