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