blob: 8fd6bbfacba56bdf2ed7312328907639d2876fcc [file] [log] [blame]
John Spurlockaf8d6c42014-05-07 17:49:08 -04001/*
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
17package com.android.systemui.statusbar.phone;
18
Jason Monkba2318e2015-12-08 09:04:23 -050019import android.app.ActivityManager;
Adrian Roos62692b22015-09-11 17:46:23 -070020import android.app.PendingIntent;
Jason Monk7e53f202016-01-28 10:40:20 -050021import android.content.ComponentName;
John Spurlockaf8d6c42014-05-07 17:49:08 -040022import android.content.Context;
23import android.content.Intent;
John Spurlockbceed062014-08-10 18:04:16 -040024import android.content.res.Resources;
Jason Monk7e53f202016-01-28 10:40:20 -050025import android.os.Handler;
John Spurlockaf8d6c42014-05-07 17:49:08 -040026import android.os.HandlerThread;
27import android.os.Looper;
Jason Monk5e745172015-06-02 19:14:44 -040028import android.os.Process;
Jason Monk7e53f202016-01-28 10:40:20 -050029import android.os.UserHandle;
Sudheer Shankaad790492016-06-03 10:48:27 -070030import android.os.UserManager;
Jason Monkba2318e2015-12-08 09:04:23 -050031import android.provider.Settings;
Jason Monk7e53f202016-01-28 10:40:20 -050032import android.provider.Settings.Secure;
Jason Monka3453b8b2016-06-17 12:42:59 -040033import android.service.quicksettings.Tile;
Jason Monkba2318e2015-12-08 09:04:23 -050034import android.text.TextUtils;
John Spurlockbceed062014-08-10 18:04:16 -040035import android.util.Log;
Jason Monkca894a02016-01-12 15:30:22 -050036import android.view.View;
Winsonc0d70582016-01-29 10:24:39 -080037
John Spurlockbceed062014-08-10 18:04:16 -040038import com.android.systemui.R;
John Spurlockaf8d6c42014-05-07 17:49:08 -040039import com.android.systemui.qs.QSTile;
Jason Monkd5a204f2015-12-21 08:50:01 -050040import com.android.systemui.qs.external.CustomTile;
Jason Monk7e53f202016-01-28 10:40:20 -050041import com.android.systemui.qs.external.TileLifecycleManager;
Jason Monkd5a204f2015-12-21 08:50:01 -050042import com.android.systemui.qs.external.TileServices;
Jason Monkbbadff82015-11-06 15:47:26 -050043import com.android.systemui.qs.tiles.AirplaneModeTile;
44import com.android.systemui.qs.tiles.BatteryTile;
45import com.android.systemui.qs.tiles.BluetoothTile;
46import com.android.systemui.qs.tiles.CastTile;
47import com.android.systemui.qs.tiles.CellularTile;
48import com.android.systemui.qs.tiles.ColorInversionTile;
Jason Monk9a4ce132016-01-21 15:27:17 -050049import com.android.systemui.qs.tiles.DataSaverTile;
Jason Monkbbadff82015-11-06 15:47:26 -050050import com.android.systemui.qs.tiles.DndTile;
51import com.android.systemui.qs.tiles.FlashlightTile;
52import com.android.systemui.qs.tiles.HotspotTile;
53import com.android.systemui.qs.tiles.IntentTile;
54import com.android.systemui.qs.tiles.LocationTile;
Justin Klaassen13790902016-06-21 20:28:12 -070055import com.android.systemui.qs.tiles.NightDisplayTile;
Jason Monkbbadff82015-11-06 15:47:26 -050056import com.android.systemui.qs.tiles.RotationLockTile;
57import com.android.systemui.qs.tiles.UserTile;
58import com.android.systemui.qs.tiles.WifiTile;
Rubin Xu1205fb12015-11-04 17:45:03 +000059import com.android.systemui.qs.tiles.WorkModeTile;
Jason Monkbbadff82015-11-06 15:47:26 -050060import com.android.systemui.statusbar.policy.BatteryController;
61import com.android.systemui.statusbar.policy.BluetoothController;
62import com.android.systemui.statusbar.policy.CastController;
Jason Monk46dbfb42016-02-25 14:59:20 -050063import com.android.systemui.statusbar.policy.NextAlarmController;
Jason Monkbbadff82015-11-06 15:47:26 -050064import com.android.systemui.statusbar.policy.FlashlightController;
65import com.android.systemui.statusbar.policy.HotspotController;
66import com.android.systemui.statusbar.policy.KeyguardMonitor;
67import com.android.systemui.statusbar.policy.LocationController;
68import com.android.systemui.statusbar.policy.NetworkController;
69import com.android.systemui.statusbar.policy.RotationLockController;
70import com.android.systemui.statusbar.policy.SecurityController;
71import com.android.systemui.statusbar.policy.UserInfoController;
72import com.android.systemui.statusbar.policy.UserSwitcherController;
73import com.android.systemui.statusbar.policy.ZenModeController;
Jason Monk5e745172015-06-02 19:14:44 -040074import com.android.systemui.tuner.TunerService;
75import com.android.systemui.tuner.TunerService.Tunable;
John Spurlockaf8d6c42014-05-07 17:49:08 -040076
77import java.util.ArrayList;
John Spurlockbceed062014-08-10 18:04:16 -040078import java.util.Arrays;
79import java.util.Collection;
80import java.util.LinkedHashMap;
John Spurlockaf8d6c42014-05-07 17:49:08 -040081import java.util.List;
John Spurlockbceed062014-08-10 18:04:16 -040082import java.util.Map;
John Spurlockaf8d6c42014-05-07 17:49:08 -040083
84/** Platform implementation of the quick settings tile host **/
Xiaohui Chen311b98e2016-03-30 11:55:54 -070085public class QSTileHost implements QSTile.Host, Tunable {
John Spurlockbceed062014-08-10 18:04:16 -040086 private static final String TAG = "QSTileHost";
87 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
88
Jason Monkbaade752016-08-25 15:57:14 -040089 public static final String TILES_SETTING = Secure.QS_TILES;
John Spurlockaf8d6c42014-05-07 17:49:08 -040090
91 private final Context mContext;
92 private final PhoneStatusBar mStatusBar;
John Spurlockbceed062014-08-10 18:04:16 -040093 private final LinkedHashMap<String, QSTile<?>> mTiles = new LinkedHashMap<>();
Jason Monk5e745172015-06-02 19:14:44 -040094 protected final ArrayList<String> mTileSpecs = new ArrayList<>();
John Spurlockaf8d6c42014-05-07 17:49:08 -040095 private final BluetoothController mBluetooth;
96 private final LocationController mLocation;
97 private final RotationLockController mRotation;
98 private final NetworkController mNetwork;
99 private final ZenModeController mZen;
Jason Monk51e4dc02014-07-22 12:00:47 -0400100 private final HotspotController mHotspot;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400101 private final CastController mCast;
102 private final Looper mLooper;
Adrian Roosb83777b2014-06-30 15:11:53 +0200103 private final FlashlightController mFlashlight;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200104 private final UserSwitcherController mUserSwitcherController;
Jason Monkabe19742015-09-29 09:47:06 -0400105 private final UserInfoController mUserInfoController;
John Spurlock657c62c2014-07-22 12:18:09 -0400106 private final KeyguardMonitor mKeyguard;
Jason Monk3d5f5512014-07-25 11:17:28 -0400107 private final SecurityController mSecurity;
Jason Monkabe19742015-09-29 09:47:06 -0400108 private final BatteryController mBattery;
Jason Monk66c89c12016-01-06 08:51:26 -0500109 private final StatusBarIconController mIconController;
Jason Monkd5a204f2015-12-21 08:50:01 -0500110 private final TileServices mServices;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400111
Jason Monkbbadff82015-11-06 15:47:26 -0500112 private final List<Callback> mCallbacks = new ArrayList<>();
Jason Monkc3f42c12016-02-05 12:33:13 -0500113 private final AutoTileManager mAutoTiles;
114 private final ManagedProfileController mProfileController;
Jason Monk46dbfb42016-02-25 14:59:20 -0500115 private final NextAlarmController mNextAlarmController;
Jason Monk88529052016-11-04 13:29:58 -0400116 private final HandlerThread mHandlerThread;
Jason Monkca894a02016-01-12 15:30:22 -0500117 private View mHeader;
Jason Monk1ffa11b2016-03-08 14:44:23 -0500118 private int mCurrentUser;
John Spurlockbceed062014-08-10 18:04:16 -0400119
John Spurlockaf8d6c42014-05-07 17:49:08 -0400120 public QSTileHost(Context context, PhoneStatusBar statusBar,
Jason Monk46dbfb42016-02-25 14:59:20 -0500121 BluetoothController bluetooth, LocationController location,
122 RotationLockController rotation, NetworkController network,
123 ZenModeController zen, HotspotController hotspot,
124 CastController cast, FlashlightController flashlight,
125 UserSwitcherController userSwitcher, UserInfoController userInfo,
126 KeyguardMonitor keyguard, SecurityController security,
127 BatteryController battery, StatusBarIconController iconController,
128 NextAlarmController nextAlarmController) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400129 mContext = context;
130 mStatusBar = statusBar;
131 mBluetooth = bluetooth;
132 mLocation = location;
133 mRotation = rotation;
134 mNetwork = network;
135 mZen = zen;
Jason Monk51e4dc02014-07-22 12:00:47 -0400136 mHotspot = hotspot;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400137 mCast = cast;
Adrian Roosb83777b2014-06-30 15:11:53 +0200138 mFlashlight = flashlight;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200139 mUserSwitcherController = userSwitcher;
Jason Monkabe19742015-09-29 09:47:06 -0400140 mUserInfoController = userInfo;
John Spurlock657c62c2014-07-22 12:18:09 -0400141 mKeyguard = keyguard;
Jason Monk3d5f5512014-07-25 11:17:28 -0400142 mSecurity = security;
Jason Monkabe19742015-09-29 09:47:06 -0400143 mBattery = battery;
Jason Monk66c89c12016-01-06 08:51:26 -0500144 mIconController = iconController;
Jason Monk46dbfb42016-02-25 14:59:20 -0500145 mNextAlarmController = nextAlarmController;
Jason Monkc3f42c12016-02-05 12:33:13 -0500146 mProfileController = new ManagedProfileController(this);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400147
Jason Monk88529052016-11-04 13:29:58 -0400148 mHandlerThread = new HandlerThread(QSTileHost.class.getSimpleName(),
Jorim Jaggi1ecd7cd2014-11-03 16:18:03 +0100149 Process.THREAD_PRIORITY_BACKGROUND);
Jason Monk88529052016-11-04 13:29:58 -0400150 mHandlerThread.start();
151 mLooper = mHandlerThread.getLooper();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400152
Jason Monkd5a204f2015-12-21 08:50:01 -0500153 mServices = new TileServices(this, mLooper);
154
Jason Monk5e745172015-06-02 19:14:44 -0400155 TunerService.get(mContext).addTunable(this, TILES_SETTING);
Rubin Xucedcd282016-02-15 14:44:44 +0000156 // AutoTileManager can modify mTiles so make sure mTiles has already been initialized.
157 mAutoTiles = new AutoTileManager(context, this);
Jason Monk5e745172015-06-02 19:14:44 -0400158 }
John Spurlockbceed062014-08-10 18:04:16 -0400159
Jason Monk46dbfb42016-02-25 14:59:20 -0500160 public NextAlarmController getNextAlarmController() {
161 return mNextAlarmController;
162 }
163
Jason Monkca894a02016-01-12 15:30:22 -0500164 public void setHeaderView(View view) {
165 mHeader = view;
166 }
167
Jason Monkdeba7a42015-12-08 16:14:10 -0500168 public PhoneStatusBar getPhoneStatusBar() {
Jason Monkc34befb2015-10-07 16:40:02 -0400169 return mStatusBar;
170 }
171
Jason Monk5e745172015-06-02 19:14:44 -0400172 public void destroy() {
Jason Monk88529052016-11-04 13:29:58 -0400173 mHandlerThread.quitSafely();
174 mTiles.values().forEach(tile -> tile.destroy());
Jason Monkc3f42c12016-02-05 12:33:13 -0500175 mAutoTiles.destroy();
Jason Monk5e745172015-06-02 19:14:44 -0400176 TunerService.get(mContext).removeTunable(this);
Jason Monk88529052016-11-04 13:29:58 -0400177 mServices.destroy();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400178 }
179
180 @Override
Jason Monkbbadff82015-11-06 15:47:26 -0500181 public void addCallback(Callback callback) {
182 mCallbacks.add(callback);
John Spurlockbceed062014-08-10 18:04:16 -0400183 }
184
185 @Override
Jason Monk46dbfb42016-02-25 14:59:20 -0500186 public void removeCallback(Callback callback) {
187 mCallbacks.remove(callback);
188 }
189
190 @Override
John Spurlockbceed062014-08-10 18:04:16 -0400191 public Collection<QSTile<?>> getTiles() {
192 return mTiles.values();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400193 }
194
195 @Override
Jason Monkee43cdf2015-06-19 14:20:46 -0400196 public void startActivityDismissingKeyguard(final Intent intent) {
197 mStatusBar.postStartActivityDismissingKeyguard(intent, 0);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400198 }
199
200 @Override
Adrian Roos62692b22015-09-11 17:46:23 -0700201 public void startActivityDismissingKeyguard(PendingIntent intent) {
202 mStatusBar.postStartActivityDismissingKeyguard(intent);
203 }
204
205 @Override
Jason Monkba2318e2015-12-08 09:04:23 -0500206 public void startRunnableDismissingKeyguard(Runnable runnable) {
207 mStatusBar.postQSRunnableDismissingKeyguard(runnable);
208 }
209
210 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400211 public void warn(String message, Throwable t) {
212 // already logged
213 }
214
Jason Monk8b54cad2016-04-19 11:38:03 -0400215 public void animateToggleQSExpansion() {
Jason Monkca894a02016-01-12 15:30:22 -0500216 // TODO: Better path to animated panel expansion.
Jason Monkc33f3282016-05-23 14:40:27 -0400217 mHeader.callOnClick();
Jason Monkca894a02016-01-12 15:30:22 -0500218 }
219
John Spurlockaf8d6c42014-05-07 17:49:08 -0400220 @Override
221 public void collapsePanels() {
222 mStatusBar.postAnimateCollapsePanels();
223 }
224
225 @Override
Jason Monkba2318e2015-12-08 09:04:23 -0500226 public void openPanels() {
227 mStatusBar.postAnimateOpenPanels();
228 }
229
230 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400231 public Looper getLooper() {
232 return mLooper;
233 }
234
235 @Override
236 public Context getContext() {
237 return mContext;
238 }
239
240 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400241 public BluetoothController getBluetoothController() {
242 return mBluetooth;
243 }
244
245 @Override
246 public LocationController getLocationController() {
247 return mLocation;
248 }
249
250 @Override
251 public RotationLockController getRotationLockController() {
252 return mRotation;
253 }
254
255 @Override
256 public NetworkController getNetworkController() {
257 return mNetwork;
258 }
259
260 @Override
261 public ZenModeController getZenModeController() {
262 return mZen;
263 }
264
265 @Override
Jason Monk51e4dc02014-07-22 12:00:47 -0400266 public HotspotController getHotspotController() {
267 return mHotspot;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400268 }
269
270 @Override
271 public CastController getCastController() {
272 return mCast;
273 }
John Spurlock86005342014-05-23 11:58:00 -0400274
275 @Override
John Spurlock657c62c2014-07-22 12:18:09 -0400276 public FlashlightController getFlashlightController() {
277 return mFlashlight;
John Spurlock86005342014-05-23 11:58:00 -0400278 }
Adrian Roosb83777b2014-06-30 15:11:53 +0200279
280 @Override
John Spurlock657c62c2014-07-22 12:18:09 -0400281 public KeyguardMonitor getKeyguardMonitor() {
282 return mKeyguard;
Adrian Roosb83777b2014-06-30 15:11:53 +0200283 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200284
Jason Monkabe19742015-09-29 09:47:06 -0400285 @Override
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200286 public UserSwitcherController getUserSwitcherController() {
287 return mUserSwitcherController;
288 }
Jason Monk3d5f5512014-07-25 11:17:28 -0400289
Jason Monkabe19742015-09-29 09:47:06 -0400290 @Override
291 public UserInfoController getUserInfoController() {
292 return mUserInfoController;
293 }
294
295 @Override
296 public BatteryController getBatteryController() {
297 return mBattery;
298 }
299
Jason Monk3d5f5512014-07-25 11:17:28 -0400300 public SecurityController getSecurityController() {
301 return mSecurity;
302 }
Jason Monkbbadff82015-11-06 15:47:26 -0500303
Jason Monkd5a204f2015-12-21 08:50:01 -0500304 public TileServices getTileServices() {
305 return mServices;
306 }
307
Jason Monk66c89c12016-01-06 08:51:26 -0500308 public StatusBarIconController getIconController() {
309 return mIconController;
310 }
311
Jason Monkc3f42c12016-02-05 12:33:13 -0500312 public ManagedProfileController getManagedProfileController() {
313 return mProfileController;
314 }
315
Jason Monk5e745172015-06-02 19:14:44 -0400316 @Override
317 public void onTuningChanged(String key, String newValue) {
318 if (!TILES_SETTING.equals(key)) {
319 return;
320 }
John Spurlockbceed062014-08-10 18:04:16 -0400321 if (DEBUG) Log.d(TAG, "Recreating tiles");
Sudheer Shankaad790492016-06-03 10:48:27 -0700322 if (newValue == null && UserManager.isDeviceInDemoMode(mContext)) {
323 newValue = mContext.getResources().getString(R.string.quick_settings_tiles_retail_mode);
324 }
Jason Monkbbadff82015-11-06 15:47:26 -0500325 final List<String> tileSpecs = loadTileSpecs(mContext, newValue);
Jason Monk1ffa11b2016-03-08 14:44:23 -0500326 int currentUser = ActivityManager.getCurrentUser();
327 if (tileSpecs.equals(mTileSpecs) && currentUser == mCurrentUser) return;
Jason Monk88529052016-11-04 13:29:58 -0400328 mTiles.entrySet().stream().filter(tile -> !tileSpecs.contains(tile.getKey())).forEach(
329 tile -> {
330 if (DEBUG) Log.d(TAG, "Destroying tile: " + tile.getKey());
331 tile.getValue().destroy();
332 });
John Spurlockbceed062014-08-10 18:04:16 -0400333 final LinkedHashMap<String, QSTile<?>> newTiles = new LinkedHashMap<>();
334 for (String tileSpec : tileSpecs) {
Jason Monk1ffa11b2016-03-08 14:44:23 -0500335 QSTile<?> tile = mTiles.get(tileSpec);
336 if (tile != null && (!(tile instanceof CustomTile)
337 || ((CustomTile) tile).getUser() == currentUser)) {
Akitaka Kimuraefd1c542016-09-27 20:06:00 +0900338 if (tile.isAvailable()) {
339 if (DEBUG) Log.d(TAG, "Adding " + tile);
340 tile.removeCallbacks();
Jason Monkf120cf32016-12-06 11:34:12 -0500341 if (!(tile instanceof CustomTile) && mCurrentUser != currentUser) {
342 tile.userSwitch(currentUser);
343 }
Akitaka Kimuraefd1c542016-09-27 20:06:00 +0900344 newTiles.put(tileSpec, tile);
345 } else {
346 tile.destroy();
Justin Klaassendd32d902016-07-31 10:25:36 -0700347 }
John Spurlockbceed062014-08-10 18:04:16 -0400348 } else {
349 if (DEBUG) Log.d(TAG, "Creating tile: " + tileSpec);
350 try {
Jason Monk1ffa11b2016-03-08 14:44:23 -0500351 tile = createTile(tileSpec);
Jason Monk88529052016-11-04 13:29:58 -0400352 if (tile != null) {
353 if (tile.isAvailable()) {
354 tile.setTileSpec(tileSpec);
355 newTiles.put(tileSpec, tile);
356 } else {
357 tile.destroy();
358 }
Jason Monkba2318e2015-12-08 09:04:23 -0500359 }
John Spurlockbceed062014-08-10 18:04:16 -0400360 } catch (Throwable t) {
361 Log.w(TAG, "Error creating tile for spec: " + tileSpec, t);
362 }
363 }
364 }
Jason Monk1ffa11b2016-03-08 14:44:23 -0500365 mCurrentUser = currentUser;
Jason Monk11a77442015-05-12 19:29:02 -0400366 mTileSpecs.clear();
367 mTileSpecs.addAll(tileSpecs);
John Spurlockbceed062014-08-10 18:04:16 -0400368 mTiles.clear();
369 mTiles.putAll(newTiles);
Jason Monkbbadff82015-11-06 15:47:26 -0500370 for (int i = 0; i < mCallbacks.size(); i++) {
371 mCallbacks.get(i).onTilesChanged();
John Spurlockbceed062014-08-10 18:04:16 -0400372 }
373 }
374
Jason Monkbbadff82015-11-06 15:47:26 -0500375 @Override
Jason Monkba2318e2015-12-08 09:04:23 -0500376 public void removeTile(String tileSpec) {
377 ArrayList<String> specs = new ArrayList<>(mTileSpecs);
378 specs.remove(tileSpec);
379 Settings.Secure.putStringForUser(mContext.getContentResolver(), TILES_SETTING,
380 TextUtils.join(",", specs), ActivityManager.getCurrentUser());
381 }
382
Jason Monkc3f42c12016-02-05 12:33:13 -0500383 public void addTile(String spec) {
Ricky Waib96c1eac2016-06-02 11:42:16 +0100384 final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
385 TILES_SETTING, ActivityManager.getCurrentUser());
386 final List<String> tileSpecs = loadTileSpecs(mContext, setting);
387 if (tileSpecs.contains(spec)) {
Jason Monkc3f42c12016-02-05 12:33:13 -0500388 return;
389 }
Ricky Waib96c1eac2016-06-02 11:42:16 +0100390 tileSpecs.add(spec);
Jason Monkc3f42c12016-02-05 12:33:13 -0500391 Settings.Secure.putStringForUser(mContext.getContentResolver(), TILES_SETTING,
Ricky Waib96c1eac2016-06-02 11:42:16 +0100392 TextUtils.join(",", tileSpecs), ActivityManager.getCurrentUser());
Jason Monkc3f42c12016-02-05 12:33:13 -0500393 }
394
Jason Monk7e53f202016-01-28 10:40:20 -0500395 public void addTile(ComponentName tile) {
396 List<String> newSpecs = new ArrayList<>(mTileSpecs);
397 newSpecs.add(0, CustomTile.toSpec(tile));
398 changeTiles(mTileSpecs, newSpecs);
399 }
400
401 public void removeTile(ComponentName tile) {
402 List<String> newSpecs = new ArrayList<>(mTileSpecs);
403 newSpecs.remove(CustomTile.toSpec(tile));
404 changeTiles(mTileSpecs, newSpecs);
405 }
406
407 public void changeTiles(List<String> previousTiles, List<String> newTiles) {
408 final int NP = previousTiles.size();
409 final int NA = newTiles.size();
410 for (int i = 0; i < NP; i++) {
411 String tileSpec = previousTiles.get(i);
412 if (!tileSpec.startsWith(CustomTile.PREFIX)) continue;
413 if (!newTiles.contains(tileSpec)) {
Jason Monka3453b8b2016-06-17 12:42:59 -0400414 ComponentName component = CustomTile.getComponentFromSpec(tileSpec);
415 Intent intent = new Intent().setComponent(component);
Jason Monk7e53f202016-01-28 10:40:20 -0500416 TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
Jason Monkee68fd82016-06-23 13:12:23 -0400417 mContext, mServices, new Tile(), intent,
Jason Monka3453b8b2016-06-17 12:42:59 -0400418 new UserHandle(ActivityManager.getCurrentUser()));
Jason Monk7e53f202016-01-28 10:40:20 -0500419 lifecycleManager.onStopListening();
420 lifecycleManager.onTileRemoved();
Jason Monkbaade752016-08-25 15:57:14 -0400421 TileLifecycleManager.setTileAdded(mContext, component, false);
Jason Monk7e53f202016-01-28 10:40:20 -0500422 lifecycleManager.flushMessagesAndUnbind();
423 }
424 }
425 if (DEBUG) Log.d(TAG, "saveCurrentTiles " + newTiles);
426 Secure.putStringForUser(getContext().getContentResolver(), QSTileHost.TILES_SETTING,
427 TextUtils.join(",", newTiles), ActivityManager.getCurrentUser());
428 }
429
Jason Monk5db8a412015-10-21 15:16:23 -0700430 public QSTile<?> createTile(String tileSpec) {
Jason Monkc3f42c12016-02-05 12:33:13 -0500431 if (tileSpec.equals("wifi")) return new WifiTile(this);
432 else if (tileSpec.equals("bt")) return new BluetoothTile(this);
433 else if (tileSpec.equals("cell")) return new CellularTile(this);
434 else if (tileSpec.equals("dnd")) return new DndTile(this);
John Spurlockbceed062014-08-10 18:04:16 -0400435 else if (tileSpec.equals("inversion")) return new ColorInversionTile(this);
John Spurlockbceed062014-08-10 18:04:16 -0400436 else if (tileSpec.equals("airplane")) return new AirplaneModeTile(this);
Rubin Xu1205fb12015-11-04 17:45:03 +0000437 else if (tileSpec.equals("work")) return new WorkModeTile(this);
John Spurlockbceed062014-08-10 18:04:16 -0400438 else if (tileSpec.equals("rotation")) return new RotationLockTile(this);
439 else if (tileSpec.equals("flashlight")) return new FlashlightTile(this);
440 else if (tileSpec.equals("location")) return new LocationTile(this);
441 else if (tileSpec.equals("cast")) return new CastTile(this);
442 else if (tileSpec.equals("hotspot")) return new HotspotTile(this);
Jason Monkabe19742015-09-29 09:47:06 -0400443 else if (tileSpec.equals("user")) return new UserTile(this);
444 else if (tileSpec.equals("battery")) return new BatteryTile(this);
Jason Monk9a4ce132016-01-21 15:27:17 -0500445 else if (tileSpec.equals("saver")) return new DataSaverTile(this);
Justin Klaassen13790902016-06-21 20:28:12 -0700446 else if (tileSpec.equals("night")) return new NightDisplayTile(this);
Jason Monkcaf37622015-08-18 12:33:50 -0400447 // Intent tiles.
John Spurlockbceed062014-08-10 18:04:16 -0400448 else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec);
Jason Monk5db8a412015-10-21 15:16:23 -0700449 else if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(this,tileSpec);
Jason Monk2b37190f2016-01-06 10:19:04 -0500450 else {
451 Log.w(TAG, "Bad tile spec: " + tileSpec);
452 return null;
453 }
John Spurlockbceed062014-08-10 18:04:16 -0400454 }
455
Xiaohui Chen311b98e2016-03-30 11:55:54 -0700456 protected List<String> loadTileSpecs(Context context, String tileList) {
Jason Monkbbadff82015-11-06 15:47:26 -0500457 final Resources res = context.getResources();
John Spurlockbceed062014-08-10 18:04:16 -0400458 final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
John Spurlockbceed062014-08-10 18:04:16 -0400459 if (tileList == null) {
460 tileList = res.getString(R.string.quick_settings_tiles);
461 if (DEBUG) Log.d(TAG, "Loaded tile specs from config: " + tileList);
462 } else {
463 if (DEBUG) Log.d(TAG, "Loaded tile specs from setting: " + tileList);
464 }
465 final ArrayList<String> tiles = new ArrayList<String>();
466 boolean addedDefault = false;
467 for (String tile : tileList.split(",")) {
468 tile = tile.trim();
469 if (tile.isEmpty()) continue;
470 if (tile.equals("default")) {
471 if (!addedDefault) {
472 tiles.addAll(Arrays.asList(defaultTileList.split(",")));
473 addedDefault = true;
474 }
475 } else {
476 tiles.add(tile);
477 }
478 }
479 return tiles;
480 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400481}