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