• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.statusbar.phone;
18 
19 import android.app.PendingIntent;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.res.Resources;
23 import android.os.HandlerThread;
24 import android.os.Looper;
25 import android.os.Process;
26 import android.util.Log;
27 
28 import com.android.systemui.R;
29 import com.android.systemui.qs.QSTile;
30 import com.android.systemui.qs.tiles.AirplaneModeTile;
31 import com.android.systemui.qs.tiles.BluetoothTile;
32 import com.android.systemui.qs.tiles.CastTile;
33 import com.android.systemui.qs.tiles.CellularTile;
34 import com.android.systemui.qs.tiles.ColorInversionTile;
35 import com.android.systemui.qs.tiles.DndTile;
36 import com.android.systemui.qs.tiles.FlashlightTile;
37 import com.android.systemui.qs.tiles.HotspotTile;
38 import com.android.systemui.qs.tiles.IntentTile;
39 import com.android.systemui.qs.tiles.LocationTile;
40 import com.android.systemui.qs.tiles.RotationLockTile;
41 import com.android.systemui.qs.tiles.WifiTile;
42 import com.android.systemui.statusbar.policy.BluetoothController;
43 import com.android.systemui.statusbar.policy.CastController;
44 import com.android.systemui.statusbar.policy.FlashlightController;
45 import com.android.systemui.statusbar.policy.HotspotController;
46 import com.android.systemui.statusbar.policy.KeyguardMonitor;
47 import com.android.systemui.statusbar.policy.LocationController;
48 import com.android.systemui.statusbar.policy.NetworkController;
49 import com.android.systemui.statusbar.policy.RotationLockController;
50 import com.android.systemui.statusbar.policy.SecurityController;
51 import com.android.systemui.statusbar.policy.UserSwitcherController;
52 import com.android.systemui.statusbar.policy.ZenModeController;
53 import com.android.systemui.tuner.TunerService;
54 import com.android.systemui.tuner.TunerService.Tunable;
55 
56 import java.util.ArrayList;
57 import java.util.Arrays;
58 import java.util.Collection;
59 import java.util.LinkedHashMap;
60 import java.util.List;
61 import java.util.Map;
62 
63 /** Platform implementation of the quick settings tile host **/
64 public class QSTileHost implements QSTile.Host, Tunable {
65     private static final String TAG = "QSTileHost";
66     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
67 
68     protected static final String TILES_SETTING = "sysui_qs_tiles";
69 
70     private final Context mContext;
71     private final PhoneStatusBar mStatusBar;
72     private final LinkedHashMap<String, QSTile<?>> mTiles = new LinkedHashMap<>();
73     protected final ArrayList<String> mTileSpecs = new ArrayList<>();
74     private final BluetoothController mBluetooth;
75     private final LocationController mLocation;
76     private final RotationLockController mRotation;
77     private final NetworkController mNetwork;
78     private final ZenModeController mZen;
79     private final HotspotController mHotspot;
80     private final CastController mCast;
81     private final Looper mLooper;
82     private final FlashlightController mFlashlight;
83     private final UserSwitcherController mUserSwitcherController;
84     private final KeyguardMonitor mKeyguard;
85     private final SecurityController mSecurity;
86 
87     private Callback mCallback;
88 
QSTileHost(Context context, PhoneStatusBar statusBar, BluetoothController bluetooth, LocationController location, RotationLockController rotation, NetworkController network, ZenModeController zen, HotspotController hotspot, CastController cast, FlashlightController flashlight, UserSwitcherController userSwitcher, KeyguardMonitor keyguard, SecurityController security)89     public QSTileHost(Context context, PhoneStatusBar statusBar,
90             BluetoothController bluetooth, LocationController location,
91             RotationLockController rotation, NetworkController network,
92             ZenModeController zen, HotspotController hotspot,
93             CastController cast, FlashlightController flashlight,
94             UserSwitcherController userSwitcher, KeyguardMonitor keyguard,
95             SecurityController security) {
96         mContext = context;
97         mStatusBar = statusBar;
98         mBluetooth = bluetooth;
99         mLocation = location;
100         mRotation = rotation;
101         mNetwork = network;
102         mZen = zen;
103         mHotspot = hotspot;
104         mCast = cast;
105         mFlashlight = flashlight;
106         mUserSwitcherController = userSwitcher;
107         mKeyguard = keyguard;
108         mSecurity = security;
109 
110         final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(),
111                 Process.THREAD_PRIORITY_BACKGROUND);
112         ht.start();
113         mLooper = ht.getLooper();
114 
115         TunerService.get(mContext).addTunable(this, TILES_SETTING);
116     }
117 
destroy()118     public void destroy() {
119         TunerService.get(mContext).removeTunable(this);
120     }
121 
122     @Override
setCallback(Callback callback)123     public void setCallback(Callback callback) {
124         mCallback = callback;
125     }
126 
127     @Override
getTiles()128     public Collection<QSTile<?>> getTiles() {
129         return mTiles.values();
130     }
131 
132     @Override
startActivityDismissingKeyguard(final Intent intent)133     public void startActivityDismissingKeyguard(final Intent intent) {
134         mStatusBar.postStartActivityDismissingKeyguard(intent, 0);
135     }
136 
137     @Override
startActivityDismissingKeyguard(PendingIntent intent)138     public void startActivityDismissingKeyguard(PendingIntent intent) {
139         mStatusBar.postStartActivityDismissingKeyguard(intent);
140     }
141 
142     @Override
warn(String message, Throwable t)143     public void warn(String message, Throwable t) {
144         // already logged
145     }
146 
147     @Override
collapsePanels()148     public void collapsePanels() {
149         mStatusBar.postAnimateCollapsePanels();
150     }
151 
152     @Override
getLooper()153     public Looper getLooper() {
154         return mLooper;
155     }
156 
157     @Override
getContext()158     public Context getContext() {
159         return mContext;
160     }
161 
162     @Override
getBluetoothController()163     public BluetoothController getBluetoothController() {
164         return mBluetooth;
165     }
166 
167     @Override
getLocationController()168     public LocationController getLocationController() {
169         return mLocation;
170     }
171 
172     @Override
getRotationLockController()173     public RotationLockController getRotationLockController() {
174         return mRotation;
175     }
176 
177     @Override
getNetworkController()178     public NetworkController getNetworkController() {
179         return mNetwork;
180     }
181 
182     @Override
getZenModeController()183     public ZenModeController getZenModeController() {
184         return mZen;
185     }
186 
187     @Override
getHotspotController()188     public HotspotController getHotspotController() {
189         return mHotspot;
190     }
191 
192     @Override
getCastController()193     public CastController getCastController() {
194         return mCast;
195     }
196 
197     @Override
getFlashlightController()198     public FlashlightController getFlashlightController() {
199         return mFlashlight;
200     }
201 
202     @Override
getKeyguardMonitor()203     public KeyguardMonitor getKeyguardMonitor() {
204         return mKeyguard;
205     }
206 
getUserSwitcherController()207     public UserSwitcherController getUserSwitcherController() {
208         return mUserSwitcherController;
209     }
210 
getSecurityController()211     public SecurityController getSecurityController() {
212         return mSecurity;
213     }
214 
215     @Override
onTuningChanged(String key, String newValue)216     public void onTuningChanged(String key, String newValue) {
217         if (!TILES_SETTING.equals(key)) {
218             return;
219         }
220         if (DEBUG) Log.d(TAG, "Recreating tiles");
221         final List<String> tileSpecs = loadTileSpecs(newValue);
222         if (tileSpecs.equals(mTileSpecs)) return;
223         for (Map.Entry<String, QSTile<?>> tile : mTiles.entrySet()) {
224             if (!tileSpecs.contains(tile.getKey())) {
225                 if (DEBUG) Log.d(TAG, "Destroying tile: " + tile.getKey());
226                 tile.getValue().destroy();
227             }
228         }
229         final LinkedHashMap<String, QSTile<?>> newTiles = new LinkedHashMap<>();
230         for (String tileSpec : tileSpecs) {
231             if (mTiles.containsKey(tileSpec)) {
232                 newTiles.put(tileSpec, mTiles.get(tileSpec));
233             } else {
234                 if (DEBUG) Log.d(TAG, "Creating tile: " + tileSpec);
235                 try {
236                     newTiles.put(tileSpec, createTile(tileSpec));
237                 } catch (Throwable t) {
238                     Log.w(TAG, "Error creating tile for spec: " + tileSpec, t);
239                 }
240             }
241         }
242         mTileSpecs.clear();
243         mTileSpecs.addAll(tileSpecs);
244         mTiles.clear();
245         mTiles.putAll(newTiles);
246         if (mCallback != null) {
247             mCallback.onTilesChanged();
248         }
249     }
250 
createTile(String tileSpec)251     protected QSTile<?> createTile(String tileSpec) {
252         if (tileSpec.equals("wifi")) return new WifiTile(this);
253         else if (tileSpec.equals("bt")) return new BluetoothTile(this);
254         else if (tileSpec.equals("inversion")) return new ColorInversionTile(this);
255         else if (tileSpec.equals("cell")) return new CellularTile(this);
256         else if (tileSpec.equals("airplane")) return new AirplaneModeTile(this);
257         else if (tileSpec.equals("dnd")) return new DndTile(this);
258         else if (tileSpec.equals("rotation")) return new RotationLockTile(this);
259         else if (tileSpec.equals("flashlight")) return new FlashlightTile(this);
260         else if (tileSpec.equals("location")) return new LocationTile(this);
261         else if (tileSpec.equals("cast")) return new CastTile(this);
262         else if (tileSpec.equals("hotspot")) return new HotspotTile(this);
263         else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec);
264         else throw new IllegalArgumentException("Bad tile spec: " + tileSpec);
265     }
266 
loadTileSpecs(String tileList)267     protected List<String> loadTileSpecs(String tileList) {
268         final Resources res = mContext.getResources();
269         final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
270         if (tileList == null) {
271             tileList = res.getString(R.string.quick_settings_tiles);
272             if (DEBUG) Log.d(TAG, "Loaded tile specs from config: " + tileList);
273         } else {
274             if (DEBUG) Log.d(TAG, "Loaded tile specs from setting: " + tileList);
275         }
276         final ArrayList<String> tiles = new ArrayList<String>();
277         boolean addedDefault = false;
278         for (String tile : tileList.split(",")) {
279             tile = tile.trim();
280             if (tile.isEmpty()) continue;
281             if (tile.equals("default")) {
282                 if (!addedDefault) {
283                     tiles.addAll(Arrays.asList(defaultTileList.split(",")));
284                     addedDefault = true;
285                 }
286             } else {
287                 tiles.add(tile);
288             }
289         }
290         return tiles;
291     }
292 }
293