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.os.Handler;
23 import android.os.RemoteException;
24 import android.os.Trace;
25 import android.os.UserHandle;
26 import android.util.Log;
27 import android.view.Display;
28 import android.view.IWallpaperVisibilityListener;
29 import android.view.IWindowManager;
30 import android.view.WindowManagerGlobal;
31 
32 import com.android.internal.annotations.VisibleForTesting;
33 import com.android.internal.colorextraction.ColorExtractor;
34 import com.android.internal.colorextraction.types.ExtractionType;
35 import com.android.internal.colorextraction.types.Tonal;
36 import com.android.keyguard.KeyguardUpdateMonitor;
37 import com.android.systemui.Dumpable;
38 
39 import java.io.FileDescriptor;
40 import java.io.PrintWriter;
41 import java.util.Arrays;
42 
43 /**
44  * ColorExtractor aware of wallpaper visibility
45  */
46 public class SysuiColorExtractor extends ColorExtractor implements Dumpable {
47     private static final String TAG = "SysuiColorExtractor";
48     private boolean mWallpaperVisible;
49     private boolean mMediaBackdropVisible;
50     // Colors to return when the wallpaper isn't visible
51     private final GradientColors mWpHiddenColors;
52 
SysuiColorExtractor(Context context)53     public SysuiColorExtractor(Context context) {
54         this(context, new Tonal(context), true);
55     }
56 
57     @VisibleForTesting
SysuiColorExtractor(Context context, ExtractionType type, boolean registerVisibility)58     public SysuiColorExtractor(Context context, ExtractionType type, boolean registerVisibility) {
59         super(context, type);
60         mWpHiddenColors = new GradientColors();
61 
62         WallpaperColors systemColors = getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
63         updateDefaultGradients(systemColors);
64 
65         if (registerVisibility) {
66             try {
67                 IWindowManager windowManagerService = WindowManagerGlobal.getWindowManagerService();
68                 Handler handler = Handler.getMain();
69                 boolean visible = windowManagerService.registerWallpaperVisibilityListener(
70                         new IWallpaperVisibilityListener.Stub() {
71                             @Override
72                             public void onWallpaperVisibilityChanged(boolean newVisibility,
73                                     int displayId) throws RemoteException {
74                                 handler.post(() -> setWallpaperVisible(newVisibility));
75                             }
76                         }, Display.DEFAULT_DISPLAY);
77                 setWallpaperVisible(visible);
78             } catch (RemoteException e) {
79                 Log.w(TAG, "Can't listen to wallpaper visibility changes", e);
80             }
81         }
82 
83         WallpaperManager wallpaperManager = context.getSystemService(WallpaperManager.class);
84         if (wallpaperManager != null) {
85             // Listen to all users instead of only the current one.
86             wallpaperManager.removeOnColorsChangedListener(this);
87             wallpaperManager.addOnColorsChangedListener(this, null /* handler */,
88                     UserHandle.USER_ALL);
89         }
90     }
91 
updateDefaultGradients(WallpaperColors colors)92     private void updateDefaultGradients(WallpaperColors colors) {
93         Tonal.applyFallback(colors, mWpHiddenColors);
94     }
95 
96     @Override
onColorsChanged(WallpaperColors colors, int which, int userId)97     public void onColorsChanged(WallpaperColors colors, int which, int userId) {
98         if (userId != KeyguardUpdateMonitor.getCurrentUser()) {
99             // Colors do not belong to current user, ignoring.
100             return;
101         }
102 
103         super.onColorsChanged(colors, which);
104 
105         if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
106             updateDefaultGradients(colors);
107         }
108     }
109 
110     @VisibleForTesting
getFallbackColors()111     GradientColors getFallbackColors() {
112         return mWpHiddenColors;
113     }
114 
115     /**
116      * Get TYPE_NORMAL colors when wallpaper is visible, or fallback otherwise.
117      *
118      * @param which FLAG_LOCK or FLAG_SYSTEM
119      * @return colors
120      */
121     @Override
getColors(int which)122     public GradientColors getColors(int which) {
123         return getColors(which, TYPE_DARK);
124     }
125 
126     /**
127      * Wallpaper colors when the wallpaper is visible, fallback otherwise.
128      *
129      * @param which FLAG_LOCK or FLAG_SYSTEM
130      * @param type TYPE_NORMAL, TYPE_DARK or TYPE_EXTRA_DARK
131      * @return colors
132      */
133     @Override
getColors(int which, int type)134     public GradientColors getColors(int which, int type) {
135         return getColors(which, type, false /* ignoreVisibility */);
136     }
137 
138     /**
139      * Get TYPE_NORMAL colors, possibly ignoring wallpaper visibility.
140      *
141      * @param which FLAG_LOCK or FLAG_SYSTEM
142      * @param ignoreWallpaperVisibility whether you want fallback colors or not if the wallpaper
143      *                                  isn't visible
144      * @return
145      */
getColors(int which, boolean ignoreWallpaperVisibility)146     public GradientColors getColors(int which, boolean ignoreWallpaperVisibility) {
147         return getColors(which, TYPE_NORMAL, ignoreWallpaperVisibility);
148     }
149 
150     /**
151      *
152      * @param which FLAG_LOCK or FLAG_SYSTEM
153      * @param type TYPE_NORMAL, TYPE_DARK or TYPE_EXTRA_DARK
154      * @param ignoreWallpaperVisibility true if true wallpaper colors should be returning
155      *                                  if it's visible or not
156      * @return colors
157      */
getColors(int which, int type, boolean ignoreWallpaperVisibility)158     public GradientColors getColors(int which, int type, boolean ignoreWallpaperVisibility) {
159         // mWallpaperVisible only handles the "system wallpaper" and will be always set to false
160         // if we have different lock and system wallpapers.
161         if (which == WallpaperManager.FLAG_SYSTEM) {
162             if (mWallpaperVisible || ignoreWallpaperVisibility) {
163                 return super.getColors(which, type);
164             } else {
165                 return mWpHiddenColors;
166             }
167         } else {
168             if (mMediaBackdropVisible) {
169                 return mWpHiddenColors;
170             } else {
171                 return super.getColors(which, type);
172             }
173         }
174     }
175 
176     @VisibleForTesting
setWallpaperVisible(boolean visible)177     void setWallpaperVisible(boolean visible) {
178         if (mWallpaperVisible != visible) {
179             mWallpaperVisible = visible;
180             triggerColorsChanged(WallpaperManager.FLAG_SYSTEM);
181         }
182     }
183 
setMediaBackdropVisible(boolean visible)184     public void setMediaBackdropVisible(boolean visible) {
185         if (mMediaBackdropVisible != visible) {
186             mMediaBackdropVisible = visible;
187             triggerColorsChanged(WallpaperManager.FLAG_LOCK);
188         }
189     }
190 
191     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)192     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
193         pw.println("SysuiColorExtractor:");
194 
195         pw.println("  Current wallpaper colors:");
196         pw.println("    system: " + mSystemColors);
197         pw.println("    lock: " + mLockColors);
198 
199         GradientColors[] system = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
200         GradientColors[] lock = mGradientColors.get(WallpaperManager.FLAG_LOCK);
201         pw.println("  Gradients:");
202         pw.println("    system: " + Arrays.toString(system));
203         pw.println("    lock: " + Arrays.toString(lock));
204         pw.println("  Default scrim: " + mWpHiddenColors);
205 
206     }
207 }
208