1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.statusbar.phone; 16 17 import android.content.Context; 18 import android.hardware.display.ColorDisplayManager; 19 import android.hardware.display.NightDisplayListener; 20 import android.os.Handler; 21 import android.provider.Settings.Secure; 22 23 import com.android.internal.annotations.VisibleForTesting; 24 import com.android.systemui.Dependency; 25 import com.android.systemui.qs.AutoAddTracker; 26 import com.android.systemui.qs.QSTileHost; 27 import com.android.systemui.qs.SecureSetting; 28 import com.android.systemui.statusbar.policy.CastController; 29 import com.android.systemui.statusbar.policy.CastController.CastDevice; 30 import com.android.systemui.statusbar.policy.DataSaverController; 31 import com.android.systemui.statusbar.policy.DataSaverController.Listener; 32 import com.android.systemui.statusbar.policy.HotspotController; 33 import com.android.systemui.statusbar.policy.HotspotController.Callback; 34 35 import javax.inject.Inject; 36 import javax.inject.Named; 37 38 /** 39 * Manages which tiles should be automatically added to QS. 40 */ 41 public class AutoTileManager { 42 public static final String HOTSPOT = "hotspot"; 43 public static final String SAVER = "saver"; 44 public static final String INVERSION = "inversion"; 45 public static final String WORK = "work"; 46 public static final String NIGHT = "night"; 47 public static final String CAST = "cast"; 48 49 private final Context mContext; 50 private final QSTileHost mHost; 51 private final Handler mHandler; 52 private final AutoAddTracker mAutoTracker; 53 private final HotspotController mHotspotController; 54 private final DataSaverController mDataSaverController; 55 private final ManagedProfileController mManagedProfileController; 56 private final NightDisplayListener mNightDisplayListener; 57 private final CastController mCastController; 58 59 @Inject AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host, @Named(Dependency.BG_HANDLER_NAME) Handler handler, HotspotController hotspotController, DataSaverController dataSaverController, ManagedProfileController managedProfileController, NightDisplayListener nightDisplayListener, CastController castController)60 public AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host, 61 @Named(Dependency.BG_HANDLER_NAME) Handler handler, 62 HotspotController hotspotController, 63 DataSaverController dataSaverController, 64 ManagedProfileController managedProfileController, 65 NightDisplayListener nightDisplayListener, 66 CastController castController) { 67 mAutoTracker = autoAddTracker; 68 mContext = context; 69 mHost = host; 70 mHandler = handler; 71 mHotspotController = hotspotController; 72 mDataSaverController = dataSaverController; 73 mManagedProfileController = managedProfileController; 74 mNightDisplayListener = nightDisplayListener; 75 mCastController = castController; 76 if (!mAutoTracker.isAdded(HOTSPOT)) { 77 hotspotController.addCallback(mHotspotCallback); 78 } 79 if (!mAutoTracker.isAdded(SAVER)) { 80 dataSaverController.addCallback(mDataSaverListener); 81 } 82 if (!mAutoTracker.isAdded(INVERSION)) { 83 mColorsSetting = new SecureSetting(mContext, mHandler, 84 Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) { 85 @Override 86 protected void handleValueChanged(int value, boolean observedChange) { 87 if (mAutoTracker.isAdded(INVERSION)) return; 88 if (value != 0) { 89 mHost.addTile(INVERSION); 90 mAutoTracker.setTileAdded(INVERSION); 91 mHandler.post(() -> mColorsSetting.setListening(false)); 92 } 93 } 94 }; 95 mColorsSetting.setListening(true); 96 } 97 if (!mAutoTracker.isAdded(WORK)) { 98 managedProfileController.addCallback(mProfileCallback); 99 } 100 if (!mAutoTracker.isAdded(NIGHT) 101 && ColorDisplayManager.isNightDisplayAvailable(mContext)) { 102 nightDisplayListener.setCallback(mNightDisplayCallback); 103 } 104 if (!mAutoTracker.isAdded(CAST)) { 105 castController.addCallback(mCastCallback); 106 } 107 } 108 destroy()109 public void destroy() { 110 if (mColorsSetting != null) { 111 mColorsSetting.setListening(false); 112 } 113 mAutoTracker.destroy(); 114 mHotspotController.removeCallback(mHotspotCallback); 115 mDataSaverController.removeCallback(mDataSaverListener); 116 mManagedProfileController.removeCallback(mProfileCallback); 117 if (ColorDisplayManager.isNightDisplayAvailable(mContext)) { 118 mNightDisplayListener.setCallback(null); 119 } 120 mCastController.removeCallback(mCastCallback); 121 } 122 unmarkTileAsAutoAdded(String tabSpec)123 public void unmarkTileAsAutoAdded(String tabSpec) { 124 mAutoTracker.setTileRemoved(tabSpec); 125 } 126 127 private final ManagedProfileController.Callback mProfileCallback = 128 new ManagedProfileController.Callback() { 129 @Override 130 public void onManagedProfileChanged() { 131 if (mAutoTracker.isAdded(WORK)) return; 132 if (mManagedProfileController.hasActiveProfile()) { 133 mHost.addTile(WORK); 134 mAutoTracker.setTileAdded(WORK); 135 } 136 } 137 138 @Override 139 public void onManagedProfileRemoved() { 140 } 141 }; 142 143 private SecureSetting mColorsSetting; 144 145 private final DataSaverController.Listener mDataSaverListener = new Listener() { 146 @Override 147 public void onDataSaverChanged(boolean isDataSaving) { 148 if (mAutoTracker.isAdded(SAVER)) return; 149 if (isDataSaving) { 150 mHost.addTile(SAVER); 151 mAutoTracker.setTileAdded(SAVER); 152 mHandler.post(() -> mDataSaverController.removeCallback(mDataSaverListener)); 153 } 154 } 155 }; 156 157 private final HotspotController.Callback mHotspotCallback = new Callback() { 158 @Override 159 public void onHotspotChanged(boolean enabled, int numDevices) { 160 if (mAutoTracker.isAdded(HOTSPOT)) return; 161 if (enabled) { 162 mHost.addTile(HOTSPOT); 163 mAutoTracker.setTileAdded(HOTSPOT); 164 mHandler.post(() -> mHotspotController.removeCallback(mHotspotCallback)); 165 } 166 } 167 }; 168 169 @VisibleForTesting 170 final NightDisplayListener.Callback mNightDisplayCallback = 171 new NightDisplayListener.Callback() { 172 @Override 173 public void onActivated(boolean activated) { 174 if (activated) { 175 addNightTile(); 176 } 177 } 178 179 @Override 180 public void onAutoModeChanged(int autoMode) { 181 if (autoMode == ColorDisplayManager.AUTO_MODE_CUSTOM_TIME 182 || autoMode == ColorDisplayManager.AUTO_MODE_TWILIGHT) { 183 addNightTile(); 184 } 185 } 186 187 private void addNightTile() { 188 if (mAutoTracker.isAdded(NIGHT)) return; 189 mHost.addTile(NIGHT); 190 mAutoTracker.setTileAdded(NIGHT); 191 mHandler.post(() -> mNightDisplayListener.setCallback(null)); 192 } 193 }; 194 195 @VisibleForTesting 196 final CastController.Callback mCastCallback = new CastController.Callback() { 197 @Override 198 public void onCastDevicesChanged() { 199 if (mAutoTracker.isAdded(CAST)) return; 200 201 boolean isCasting = false; 202 for (CastDevice device : mCastController.getCastDevices()) { 203 if (device.state == CastDevice.STATE_CONNECTED 204 || device.state == CastDevice.STATE_CONNECTING) { 205 isCasting = true; 206 break; 207 } 208 } 209 210 if (isCasting) { 211 mHost.addTile(CAST); 212 mAutoTracker.setTileAdded(CAST); 213 mHandler.post(() -> mCastController.removeCallback(mCastCallback)); 214 } 215 } 216 }; 217 } 218