blob: 6d434b19d3a38b7c741fabf93e09db6f8686abf9 [file] [log] [blame]
John Spurlockaf8d6c42014-05-07 17:49:08 -04001/*
Jason Monke5b770e2017-03-03 21:49:29 -05002 * Copyright (C) 2017 The Android Open Source Project
John Spurlockaf8d6c42014-05-07 17:49:08 -04003 *
Jason Monke5b770e2017-03-03 21:49:29 -05004 * 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
John Spurlockaf8d6c42014-05-07 17:49:08 -04006 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
Jason Monke5b770e2017-03-03 21:49:29 -05009 * 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.
John Spurlockaf8d6c42014-05-07 17:49:08 -040013 */
14
Jason Monke5b770e2017-03-03 21:49:29 -050015package com.android.systemui.qs;
John Spurlockaf8d6c42014-05-07 17:49:08 -040016
Jason Monkba2318e2015-12-08 09:04:23 -050017import android.app.ActivityManager;
Jason Monk7e53f202016-01-28 10:40:20 -050018import android.content.ComponentName;
John Spurlockaf8d6c42014-05-07 17:49:08 -040019import android.content.Context;
20import android.content.Intent;
John Spurlockbceed062014-08-10 18:04:16 -040021import android.content.res.Resources;
Dan Sandler1e5d0122019-06-06 23:35:22 -040022import android.os.Build;
Jason Monk7e53f202016-01-28 10:40:20 -050023import android.os.Handler;
Jason Monk30b64fa2018-12-27 13:19:34 -050024import android.os.Looper;
Jason Monk7e53f202016-01-28 10:40:20 -050025import android.os.UserHandle;
Sudheer Shankaad790492016-06-03 10:48:27 -070026import android.os.UserManager;
Jason Monkba2318e2015-12-08 09:04:23 -050027import android.provider.Settings;
Jason Monk7e53f202016-01-28 10:40:20 -050028import android.provider.Settings.Secure;
Jason Monka3453b8b2016-06-17 12:42:59 -040029import android.service.quicksettings.Tile;
Jason Monkba2318e2015-12-08 09:04:23 -050030import android.text.TextUtils;
John Spurlockbceed062014-08-10 18:04:16 -040031import android.util.Log;
Winsonc0d70582016-01-29 10:24:39 -080032
Fabian Kozynski00d494d2019-04-04 09:53:50 -040033import com.android.systemui.DumpController;
34import com.android.systemui.Dumpable;
John Spurlockbceed062014-08-10 18:04:16 -040035import com.android.systemui.R;
Jason Monk5d577202018-12-26 15:43:06 -050036import com.android.systemui.SysUiServiceProvider;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000037import com.android.systemui.broadcast.BroadcastDispatcher;
Dave Mankofff4736812019-10-18 17:25:50 -040038import com.android.systemui.dagger.qualifiers.BgLooper;
39import com.android.systemui.dagger.qualifiers.MainHandler;
Jason Monk702e2eb2017-03-03 16:53:44 -050040import com.android.systemui.plugins.PluginListener;
Jason Monk702e2eb2017-03-03 16:53:44 -050041import com.android.systemui.plugins.qs.QSFactory;
Jason Monk702e2eb2017-03-03 16:53:44 -050042import com.android.systemui.plugins.qs.QSTile;
Gus Prevasab336792018-11-14 13:52:20 -050043import com.android.systemui.plugins.qs.QSTileView;
Jason Monkd5a204f2015-12-21 08:50:01 -050044import com.android.systemui.qs.external.CustomTile;
Jason Monk7e53f202016-01-28 10:40:20 -050045import com.android.systemui.qs.external.TileLifecycleManager;
Jason Monkd5a204f2015-12-21 08:50:01 -050046import com.android.systemui.qs.external.TileServices;
Jason Monk702e2eb2017-03-03 16:53:44 -050047import com.android.systemui.qs.tileimpl.QSFactoryImpl;
Gus Prevasab336792018-11-14 13:52:20 -050048import com.android.systemui.shared.plugins.PluginManager;
Jason Monke5b770e2017-03-03 21:49:29 -050049import com.android.systemui.statusbar.phone.AutoTileManager;
50import com.android.systemui.statusbar.phone.StatusBar;
51import com.android.systemui.statusbar.phone.StatusBarIconController;
Jason Monk5e745172015-06-02 19:14:44 -040052import com.android.systemui.tuner.TunerService;
53import com.android.systemui.tuner.TunerService.Tunable;
Dan Sandler1e5d0122019-06-06 23:35:22 -040054import com.android.systemui.util.leak.GarbageMonitor;
John Spurlockaf8d6c42014-05-07 17:49:08 -040055
Fabian Kozynski00d494d2019-04-04 09:53:50 -040056import java.io.FileDescriptor;
57import java.io.PrintWriter;
John Spurlockaf8d6c42014-05-07 17:49:08 -040058import java.util.ArrayList;
John Spurlockbceed062014-08-10 18:04:16 -040059import java.util.Arrays;
60import java.util.Collection;
61import java.util.LinkedHashMap;
John Spurlockaf8d6c42014-05-07 17:49:08 -040062import java.util.List;
Amin Shaikha062beb2018-07-25 11:21:54 -040063import java.util.function.Predicate;
John Spurlockaf8d6c42014-05-07 17:49:08 -040064
Jason Monk5d577202018-12-26 15:43:06 -050065import javax.inject.Inject;
Jason Monka26641f2018-12-27 14:20:53 -050066import javax.inject.Provider;
Jason Monk5d577202018-12-26 15:43:06 -050067import javax.inject.Singleton;
68
John Spurlockaf8d6c42014-05-07 17:49:08 -040069/** Platform implementation of the quick settings tile host **/
Jason Monk5d577202018-12-26 15:43:06 -050070@Singleton
Fabian Kozynski00d494d2019-04-04 09:53:50 -040071public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, Dumpable {
John Spurlockbceed062014-08-10 18:04:16 -040072 private static final String TAG = "QSTileHost";
73 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
74
Jason Monkbaade752016-08-25 15:57:14 -040075 public static final String TILES_SETTING = Secure.QS_TILES;
John Spurlockaf8d6c42014-05-07 17:49:08 -040076
77 private final Context mContext;
Jason Monk702e2eb2017-03-03 16:53:44 -050078 private final LinkedHashMap<String, QSTile> mTiles = new LinkedHashMap<>();
Jason Monk5e745172015-06-02 19:14:44 -040079 protected final ArrayList<String> mTileSpecs = new ArrayList<>();
Jason Monkd5a204f2015-12-21 08:50:01 -050080 private final TileServices mServices;
Jason Monk30b64fa2018-12-27 13:19:34 -050081 private final TunerService mTunerService;
82 private final PluginManager mPluginManager;
Fabian Kozynski00d494d2019-04-04 09:53:50 -040083 private final DumpController mDumpController;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000084 private final BroadcastDispatcher mBroadcastDispatcher;
John Spurlockaf8d6c42014-05-07 17:49:08 -040085
Jason Monkbbadff82015-11-06 15:47:26 -050086 private final List<Callback> mCallbacks = new ArrayList<>();
Jason Monka26641f2018-12-27 14:20:53 -050087 private AutoTileManager mAutoTiles;
Jason Monk9c7844c2017-01-18 15:21:53 -050088 private final StatusBarIconController mIconController;
Jason Monk702e2eb2017-03-03 16:53:44 -050089 private final ArrayList<QSFactory> mQsFactories = new ArrayList<>();
Jason Monk1ffa11b2016-03-08 14:44:23 -050090 private int mCurrentUser;
Jason Monk5d577202018-12-26 15:43:06 -050091 private StatusBar mStatusBar;
John Spurlockbceed062014-08-10 18:04:16 -040092
Fabian Kozynski67ffcf82019-09-05 16:32:12 -040093 private QSColorController mQSColorController = QSColorController.Companion.getInstance();
94
Jason Monk5d577202018-12-26 15:43:06 -050095 @Inject
96 public QSTileHost(Context context,
97 StatusBarIconController iconController,
98 QSFactoryImpl defaultFactory,
Dave Mankofff4736812019-10-18 17:25:50 -040099 @MainHandler Handler mainHandler,
100 @BgLooper Looper bgLooper,
Jason Monk30b64fa2018-12-27 13:19:34 -0500101 PluginManager pluginManager,
Jason Monka26641f2018-12-27 14:20:53 -0500102 TunerService tunerService,
Fabian Kozynski00d494d2019-04-04 09:53:50 -0400103 Provider<AutoTileManager> autoTiles,
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000104 DumpController dumpController,
105 BroadcastDispatcher broadcastDispatcher) {
Jason Monk9c7844c2017-01-18 15:21:53 -0500106 mIconController = iconController;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400107 mContext = context;
Jason Monk30b64fa2018-12-27 13:19:34 -0500108 mTunerService = tunerService;
109 mPluginManager = pluginManager;
Fabian Kozynski00d494d2019-04-04 09:53:50 -0400110 mDumpController = dumpController;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000111 mBroadcastDispatcher = broadcastDispatcher;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400112
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000113 mServices = new TileServices(this, bgLooper, mBroadcastDispatcher);
Jason Monkd5a204f2015-12-21 08:50:01 -0500114
Jason Monk5d577202018-12-26 15:43:06 -0500115 defaultFactory.setHost(this);
116 mQsFactories.add(defaultFactory);
Jason Monk30b64fa2018-12-27 13:19:34 -0500117 pluginManager.addPluginListener(this, QSFactory.class, true);
Ned Burns66b6e372019-07-26 13:45:42 -0400118 mDumpController.registerDumpable(TAG, this);
Jason Monk702e2eb2017-03-03 16:53:44 -0500119
Jason Monk5d577202018-12-26 15:43:06 -0500120 mainHandler.post(() -> {
121 // This is technically a hack to avoid circular dependency of
122 // QSTileHost -> XXXTile -> QSTileHost. Posting ensures creation
123 // finishes before creating any tiles.
Jason Monk30b64fa2018-12-27 13:19:34 -0500124 tunerService.addTunable(this, TILES_SETTING);
Jason Monka26641f2018-12-27 14:20:53 -0500125 // AutoTileManager can modify mTiles so make sure mTiles has already been initialized.
126 mAutoTiles = autoTiles.get();
Jason Monk5d577202018-12-26 15:43:06 -0500127 });
Fabian Kozynski67ffcf82019-09-05 16:32:12 -0400128
129 mQSColorController.initQSTileHost(this);
Jason Monk5e745172015-06-02 19:14:44 -0400130 }
John Spurlockbceed062014-08-10 18:04:16 -0400131
Jason Monk9c7844c2017-01-18 15:21:53 -0500132 public StatusBarIconController getIconController() {
133 return mIconController;
Jason Monkca894a02016-01-12 15:30:22 -0500134 }
135
Jason Monk5e745172015-06-02 19:14:44 -0400136 public void destroy() {
Jason Monk88529052016-11-04 13:29:58 -0400137 mTiles.values().forEach(tile -> tile.destroy());
Jason Monkc3f42c12016-02-05 12:33:13 -0500138 mAutoTiles.destroy();
Jason Monk30b64fa2018-12-27 13:19:34 -0500139 mTunerService.removeTunable(this);
Jason Monk88529052016-11-04 13:29:58 -0400140 mServices.destroy();
Jason Monk30b64fa2018-12-27 13:19:34 -0500141 mPluginManager.removePluginListener(this);
Ned Burns66b6e372019-07-26 13:45:42 -0400142 mDumpController.unregisterDumpable(this);
Fabian Kozynski67ffcf82019-09-05 16:32:12 -0400143
144 mQSColorController.destroy();
Jason Monk702e2eb2017-03-03 16:53:44 -0500145 }
146
147 @Override
148 public void onPluginConnected(QSFactory plugin, Context pluginContext) {
149 // Give plugins priority over creation so they can override if they wish.
150 mQsFactories.add(0, plugin);
Jason Monk30b64fa2018-12-27 13:19:34 -0500151 String value = mTunerService.getValue(TILES_SETTING);
Jason Monk702e2eb2017-03-03 16:53:44 -0500152 // Force remove and recreate of all tiles.
153 onTuningChanged(TILES_SETTING, "");
154 onTuningChanged(TILES_SETTING, value);
155 }
156
157 @Override
158 public void onPluginDisconnected(QSFactory plugin) {
159 mQsFactories.remove(plugin);
160 // Force remove and recreate of all tiles.
Jason Monk30b64fa2018-12-27 13:19:34 -0500161 String value = mTunerService.getValue(TILES_SETTING);
Jason Monk702e2eb2017-03-03 16:53:44 -0500162 onTuningChanged(TILES_SETTING, "");
163 onTuningChanged(TILES_SETTING, value);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400164 }
165
166 @Override
Jason Monkbbadff82015-11-06 15:47:26 -0500167 public void addCallback(Callback callback) {
168 mCallbacks.add(callback);
John Spurlockbceed062014-08-10 18:04:16 -0400169 }
170
171 @Override
Jason Monk46dbfb42016-02-25 14:59:20 -0500172 public void removeCallback(Callback callback) {
173 mCallbacks.remove(callback);
174 }
175
176 @Override
Jason Monk702e2eb2017-03-03 16:53:44 -0500177 public Collection<QSTile> getTiles() {
John Spurlockbceed062014-08-10 18:04:16 -0400178 return mTiles.values();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400179 }
180
181 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400182 public void warn(String message, Throwable t) {
183 // already logged
184 }
185
186 @Override
187 public void collapsePanels() {
Jason Monk5d577202018-12-26 15:43:06 -0500188 if (mStatusBar == null) {
189 mStatusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
190 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400191 mStatusBar.postAnimateCollapsePanels();
192 }
193
194 @Override
Yoshinori Hiranoc673fbc2017-04-14 11:29:38 +0900195 public void forceCollapsePanels() {
Jason Monk5d577202018-12-26 15:43:06 -0500196 if (mStatusBar == null) {
197 mStatusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
198 }
Yoshinori Hiranoc673fbc2017-04-14 11:29:38 +0900199 mStatusBar.postAnimateForceCollapsePanels();
200 }
201
202 @Override
Jason Monkba2318e2015-12-08 09:04:23 -0500203 public void openPanels() {
Jason Monk5d577202018-12-26 15:43:06 -0500204 if (mStatusBar == null) {
205 mStatusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
206 }
Jason Monkba2318e2015-12-08 09:04:23 -0500207 mStatusBar.postAnimateOpenPanels();
208 }
209
210 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400211 public Context getContext() {
212 return mContext;
213 }
214
Jason Monkbbadff82015-11-06 15:47:26 -0500215
Jason Monkd5a204f2015-12-21 08:50:01 -0500216 public TileServices getTileServices() {
217 return mServices;
218 }
219
Jason Monk8c09ac72017-03-16 11:53:40 -0400220 public int indexOf(String spec) {
221 return mTileSpecs.indexOf(spec);
222 }
223
Jason Monk5e745172015-06-02 19:14:44 -0400224 @Override
225 public void onTuningChanged(String key, String newValue) {
226 if (!TILES_SETTING.equals(key)) {
227 return;
228 }
Fabian Kozynski23e000f2019-09-06 15:22:24 -0400229 Log.d(TAG, "Recreating tiles");
Sudheer Shankaad790492016-06-03 10:48:27 -0700230 if (newValue == null && UserManager.isDeviceInDemoMode(mContext)) {
231 newValue = mContext.getResources().getString(R.string.quick_settings_tiles_retail_mode);
232 }
Jason Monkbbadff82015-11-06 15:47:26 -0500233 final List<String> tileSpecs = loadTileSpecs(mContext, newValue);
Jason Monk1ffa11b2016-03-08 14:44:23 -0500234 int currentUser = ActivityManager.getCurrentUser();
235 if (tileSpecs.equals(mTileSpecs) && currentUser == mCurrentUser) return;
Jason Monk88529052016-11-04 13:29:58 -0400236 mTiles.entrySet().stream().filter(tile -> !tileSpecs.contains(tile.getKey())).forEach(
237 tile -> {
Fabian Kozynski23e000f2019-09-06 15:22:24 -0400238 Log.d(TAG, "Destroying tile: " + tile.getKey());
Jason Monk88529052016-11-04 13:29:58 -0400239 tile.getValue().destroy();
240 });
Jason Monk702e2eb2017-03-03 16:53:44 -0500241 final LinkedHashMap<String, QSTile> newTiles = new LinkedHashMap<>();
John Spurlockbceed062014-08-10 18:04:16 -0400242 for (String tileSpec : tileSpecs) {
Jason Monk702e2eb2017-03-03 16:53:44 -0500243 QSTile tile = mTiles.get(tileSpec);
Jason Monk1ffa11b2016-03-08 14:44:23 -0500244 if (tile != null && (!(tile instanceof CustomTile)
245 || ((CustomTile) tile).getUser() == currentUser)) {
Akitaka Kimuraefd1c542016-09-27 20:06:00 +0900246 if (tile.isAvailable()) {
247 if (DEBUG) Log.d(TAG, "Adding " + tile);
248 tile.removeCallbacks();
Jason Monkf120cf32016-12-06 11:34:12 -0500249 if (!(tile instanceof CustomTile) && mCurrentUser != currentUser) {
250 tile.userSwitch(currentUser);
251 }
Akitaka Kimuraefd1c542016-09-27 20:06:00 +0900252 newTiles.put(tileSpec, tile);
253 } else {
254 tile.destroy();
Fabian Kozynski23e000f2019-09-06 15:22:24 -0400255 Log.d(TAG, "Destroying not available tile: " + tileSpec);
Justin Klaassendd32d902016-07-31 10:25:36 -0700256 }
John Spurlockbceed062014-08-10 18:04:16 -0400257 } else {
Fabian Kozynski23e000f2019-09-06 15:22:24 -0400258 Log.d(TAG, "Creating tile: " + tileSpec);
John Spurlockbceed062014-08-10 18:04:16 -0400259 try {
Jason Monk1ffa11b2016-03-08 14:44:23 -0500260 tile = createTile(tileSpec);
Jason Monk88529052016-11-04 13:29:58 -0400261 if (tile != null) {
262 if (tile.isAvailable()) {
263 tile.setTileSpec(tileSpec);
264 newTiles.put(tileSpec, tile);
265 } else {
266 tile.destroy();
Fabian Kozynski23e000f2019-09-06 15:22:24 -0400267 Log.d(TAG, "Destroying not available tile: " + tileSpec);
Jason Monk88529052016-11-04 13:29:58 -0400268 }
Jason Monkba2318e2015-12-08 09:04:23 -0500269 }
John Spurlockbceed062014-08-10 18:04:16 -0400270 } catch (Throwable t) {
271 Log.w(TAG, "Error creating tile for spec: " + tileSpec, t);
272 }
273 }
274 }
Jason Monk1ffa11b2016-03-08 14:44:23 -0500275 mCurrentUser = currentUser;
Fabian Kozynski6ff5c182019-06-20 14:57:47 -0400276 List<String> currentSpecs = new ArrayList(mTileSpecs);
Jason Monk11a77442015-05-12 19:29:02 -0400277 mTileSpecs.clear();
278 mTileSpecs.addAll(tileSpecs);
John Spurlockbceed062014-08-10 18:04:16 -0400279 mTiles.clear();
280 mTiles.putAll(newTiles);
Fabian Kozynski6ff5c182019-06-20 14:57:47 -0400281 if (newTiles.isEmpty() && !tileSpecs.isEmpty()) {
282 // If we didn't manage to create any tiles, set it to empty (default)
Fabian Kozynski23e000f2019-09-06 15:22:24 -0400283 Log.d(TAG, "No valid tiles on tuning changed. Setting to default.");
Fabian Kozynski6ff5c182019-06-20 14:57:47 -0400284 changeTiles(currentSpecs, loadTileSpecs(mContext, ""));
285 } else {
286 for (int i = 0; i < mCallbacks.size(); i++) {
287 mCallbacks.get(i).onTilesChanged();
288 }
John Spurlockbceed062014-08-10 18:04:16 -0400289 }
Fabian Kozynski67ffcf82019-09-05 16:32:12 -0400290
291 mQSColorController.applyColorToAllTiles();
John Spurlockbceed062014-08-10 18:04:16 -0400292 }
293
Jason Monkbbadff82015-11-06 15:47:26 -0500294 @Override
Amin Shaikha062beb2018-07-25 11:21:54 -0400295 public void removeTile(String spec) {
296 changeTileSpecs(tileSpecs-> tileSpecs.remove(spec));
Jason Monkba2318e2015-12-08 09:04:23 -0500297 }
298
arangelov5fe95982018-08-17 18:43:31 +0100299 @Override
300 public void unmarkTileAsAutoAdded(String spec) {
Jason Monka26641f2018-12-27 14:20:53 -0500301 if (mAutoTiles != null) mAutoTiles.unmarkTileAsAutoAdded(spec);
arangelov5fe95982018-08-17 18:43:31 +0100302 }
303
Jason Monkc3f42c12016-02-05 12:33:13 -0500304 public void addTile(String spec) {
Amin Shaikha062beb2018-07-25 11:21:54 -0400305 changeTileSpecs(tileSpecs-> tileSpecs.add(spec));
306 }
307
308 private void changeTileSpecs(Predicate<List<String>> changeFunction) {
Ricky Waib96c1eac2016-06-02 11:42:16 +0100309 final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
Amin Shaikha062beb2018-07-25 11:21:54 -0400310 TILES_SETTING, ActivityManager.getCurrentUser());
Ricky Waib96c1eac2016-06-02 11:42:16 +0100311 final List<String> tileSpecs = loadTileSpecs(mContext, setting);
Amin Shaikha062beb2018-07-25 11:21:54 -0400312 if (changeFunction.test(tileSpecs)) {
313 Settings.Secure.putStringForUser(mContext.getContentResolver(), TILES_SETTING,
Ricky Waib96c1eac2016-06-02 11:42:16 +0100314 TextUtils.join(",", tileSpecs), ActivityManager.getCurrentUser());
Amin Shaikha062beb2018-07-25 11:21:54 -0400315 }
Jason Monkc3f42c12016-02-05 12:33:13 -0500316 }
317
Jason Monk7e53f202016-01-28 10:40:20 -0500318 public void addTile(ComponentName tile) {
319 List<String> newSpecs = new ArrayList<>(mTileSpecs);
320 newSpecs.add(0, CustomTile.toSpec(tile));
321 changeTiles(mTileSpecs, newSpecs);
322 }
323
324 public void removeTile(ComponentName tile) {
325 List<String> newSpecs = new ArrayList<>(mTileSpecs);
326 newSpecs.remove(CustomTile.toSpec(tile));
327 changeTiles(mTileSpecs, newSpecs);
328 }
329
330 public void changeTiles(List<String> previousTiles, List<String> newTiles) {
331 final int NP = previousTiles.size();
332 final int NA = newTiles.size();
333 for (int i = 0; i < NP; i++) {
334 String tileSpec = previousTiles.get(i);
335 if (!tileSpec.startsWith(CustomTile.PREFIX)) continue;
336 if (!newTiles.contains(tileSpec)) {
Jason Monka3453b8b2016-06-17 12:42:59 -0400337 ComponentName component = CustomTile.getComponentFromSpec(tileSpec);
338 Intent intent = new Intent().setComponent(component);
Jason Monk7e53f202016-01-28 10:40:20 -0500339 TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
Jason Monkee68fd82016-06-23 13:12:23 -0400340 mContext, mServices, new Tile(), intent,
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000341 new UserHandle(ActivityManager.getCurrentUser()),
342 mBroadcastDispatcher);
Jason Monk7e53f202016-01-28 10:40:20 -0500343 lifecycleManager.onStopListening();
344 lifecycleManager.onTileRemoved();
Jason Monkbaade752016-08-25 15:57:14 -0400345 TileLifecycleManager.setTileAdded(mContext, component, false);
Jason Monk7e53f202016-01-28 10:40:20 -0500346 lifecycleManager.flushMessagesAndUnbind();
347 }
348 }
349 if (DEBUG) Log.d(TAG, "saveCurrentTiles " + newTiles);
350 Secure.putStringForUser(getContext().getContentResolver(), QSTileHost.TILES_SETTING,
351 TextUtils.join(",", newTiles), ActivityManager.getCurrentUser());
352 }
353
Jason Monk702e2eb2017-03-03 16:53:44 -0500354 public QSTile createTile(String tileSpec) {
355 for (int i = 0; i < mQsFactories.size(); i++) {
356 QSTile t = mQsFactories.get(i).createTile(tileSpec);
357 if (t != null) {
358 return t;
359 }
Jason Monk2b37190f2016-01-06 10:19:04 -0500360 }
Jason Monk702e2eb2017-03-03 16:53:44 -0500361 return null;
362 }
363
364 public QSTileView createTileView(QSTile tile, boolean collapsedView) {
365 for (int i = 0; i < mQsFactories.size(); i++) {
366 QSTileView view = mQsFactories.get(i).createTileView(tile, collapsedView);
367 if (view != null) {
368 return view;
369 }
370 }
371 throw new RuntimeException("Default factory didn't create view for " + tile.getTileSpec());
John Spurlockbceed062014-08-10 18:04:16 -0400372 }
373
Amin Shaikha062beb2018-07-25 11:21:54 -0400374 protected static List<String> loadTileSpecs(Context context, String tileList) {
Jason Monkbbadff82015-11-06 15:47:26 -0500375 final Resources res = context.getResources();
John Spurlockbceed062014-08-10 18:04:16 -0400376 final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
Fabian Kozynski7f370dd2018-12-05 10:41:07 -0500377 if (TextUtils.isEmpty(tileList)) {
John Spurlockbceed062014-08-10 18:04:16 -0400378 tileList = res.getString(R.string.quick_settings_tiles);
379 if (DEBUG) Log.d(TAG, "Loaded tile specs from config: " + tileList);
380 } else {
381 if (DEBUG) Log.d(TAG, "Loaded tile specs from setting: " + tileList);
382 }
383 final ArrayList<String> tiles = new ArrayList<String>();
384 boolean addedDefault = false;
385 for (String tile : tileList.split(",")) {
386 tile = tile.trim();
387 if (tile.isEmpty()) continue;
388 if (tile.equals("default")) {
389 if (!addedDefault) {
390 tiles.addAll(Arrays.asList(defaultTileList.split(",")));
Dan Sandler1e5d0122019-06-06 23:35:22 -0400391 if (Build.IS_DEBUGGABLE
392 && GarbageMonitor.MemoryTile.ADD_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
393 tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
394 }
John Spurlockbceed062014-08-10 18:04:16 -0400395 addedDefault = true;
396 }
397 } else {
398 tiles.add(tile);
399 }
400 }
401 return tiles;
402 }
Fabian Kozynski00d494d2019-04-04 09:53:50 -0400403
404 @Override
405 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
406 pw.println("QSTileHost:");
407 mTiles.values().stream().filter(obj -> obj instanceof Dumpable)
408 .forEach(o -> ((Dumpable) o).dump(fd, pw, args));
409 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400410}