blob: c3610d93e1933ec5ebffd9bed6dbd682da0d280b [file] [log] [blame]
Jason Monk62b63a02016-02-02 15:15:31 -05001/*
2 * Copyright (C) 2016 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.qs.customize;
18
Jason Monkb53b6c52016-02-24 17:25:49 -050019import android.Manifest.permission;
Jason Monk62b63a02016-02-02 15:15:31 -050020import android.app.ActivityManager;
21import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
24import android.content.pm.PackageManager;
25import android.content.pm.ResolveInfo;
26import android.graphics.drawable.Drawable;
27import android.os.AsyncTask;
28import android.os.Handler;
29import android.os.Looper;
30import android.service.quicksettings.TileService;
31import com.android.systemui.R;
32import com.android.systemui.qs.QSTile;
33import com.android.systemui.qs.QSTile.DrawableIcon;
34import com.android.systemui.qs.external.CustomTile;
35import com.android.systemui.statusbar.phone.QSTileHost;
36
37import java.util.ArrayList;
38import java.util.Collection;
39import java.util.List;
40
41public class TileQueryHelper {
42
43 private static final String TAG = "TileQueryHelper";
44
45 private final ArrayList<TileInfo> mTiles = new ArrayList<>();
Jason Monke24194f2016-02-05 14:55:05 -050046 private final ArrayList<String> mSpecs = new ArrayList<>();
Jason Monk62b63a02016-02-02 15:15:31 -050047 private final Context mContext;
48 private TileStateListener mListener;
49
50 public TileQueryHelper(Context context, QSTileHost host) {
51 mContext = context;
52 addSystemTiles(host);
53 // TODO: Live?
54 }
55
56 private void addSystemTiles(QSTileHost host) {
Jason Monk5dbd4aa2016-02-07 13:13:39 -050057 boolean hasColorMod = host.getNightModeController().isEnabled();
Jason Monk62b63a02016-02-02 15:15:31 -050058 String possible = mContext.getString(R.string.quick_settings_tiles_default)
Jason Monk5dbd4aa2016-02-07 13:13:39 -050059 + ",hotspot,inversion,saver,work,cast" + (hasColorMod ? ",night" : "");
Jason Monk62b63a02016-02-02 15:15:31 -050060 String[] possibleTiles = possible.split(",");
61 final Handler qsHandler = new Handler(host.getLooper());
62 final Handler mainHandler = new Handler(Looper.getMainLooper());
63 for (int i = 0; i < possibleTiles.length; i++) {
64 final String spec = possibleTiles[i];
65 final QSTile<?> tile = host.createTile(spec);
Jason Monkc3f42c12016-02-05 12:33:13 -050066 if (tile == null || !tile.isAvailable()) {
Jason Monk62b63a02016-02-02 15:15:31 -050067 continue;
68 }
69 tile.setListening(true);
70 tile.clearState();
71 tile.refreshState();
72 tile.setListening(false);
73 qsHandler.post(new Runnable() {
74 @Override
75 public void run() {
76 final QSTile.State state = tile.newTileState();
77 tile.getState().copyTo(state);
78 mainHandler.post(new Runnable() {
79 @Override
80 public void run() {
Jason Monke24194f2016-02-05 14:55:05 -050081 addTile(spec, state);
Jason Monk62b63a02016-02-02 15:15:31 -050082 mListener.onTilesChanged(mTiles);
83 }
84 });
85 }
86 });
87 }
88 qsHandler.post(new Runnable() {
89 @Override
90 public void run() {
91 new QueryTilesTask().execute();
92 }
93 });
94 }
95
96 public void setListener(TileStateListener listener) {
97 mListener = listener;
98 }
99
Jason Monke24194f2016-02-05 14:55:05 -0500100 private void addTile(String spec, QSTile.State state) {
101 if (mSpecs.contains(spec)) {
102 return;
103 }
Jason Monk62b63a02016-02-02 15:15:31 -0500104 TileInfo info = new TileInfo();
105 info.state = state;
106 info.spec = spec;
Jason Monke24194f2016-02-05 14:55:05 -0500107 mTiles.add(info);
108 mSpecs.add(spec);
Jason Monk62b63a02016-02-02 15:15:31 -0500109 }
110
Jason Monke24194f2016-02-05 14:55:05 -0500111 private void addTile(String spec, Drawable drawable, CharSequence label, Context context) {
Jason Monk62b63a02016-02-02 15:15:31 -0500112 QSTile.State state = new QSTile.State();
113 state.label = label;
114 state.contentDescription = label;
115 state.icon = new DrawableIcon(drawable);
Jason Monke24194f2016-02-05 14:55:05 -0500116 addTile(spec, state);
Jason Monk62b63a02016-02-02 15:15:31 -0500117 }
118
119 public static class TileInfo {
120 public String spec;
121 public QSTile.State state;
122 }
123
124 private class QueryTilesTask extends AsyncTask<Void, Void, Collection<TileInfo>> {
125 @Override
126 protected Collection<TileInfo> doInBackground(Void... params) {
127 List<TileInfo> tiles = new ArrayList<>();
128 PackageManager pm = mContext.getPackageManager();
129 List<ResolveInfo> services = pm.queryIntentServicesAsUser(
130 new Intent(TileService.ACTION_QS_TILE), 0, ActivityManager.getCurrentUser());
131 for (ResolveInfo info : services) {
132 String packageName = info.serviceInfo.packageName;
133 ComponentName componentName = new ComponentName(packageName, info.serviceInfo.name);
134 String spec = CustomTile.toSpec(componentName);
135 Drawable icon = info.serviceInfo.loadIcon(pm);
Jason Monkb53b6c52016-02-24 17:25:49 -0500136 if (!permission.BIND_QUICK_SETTINGS_TILE.equals(info.serviceInfo.permission)) {
137 continue;
138 }
Jason Monk62b63a02016-02-02 15:15:31 -0500139 if (icon != null) {
140 icon.mutate();
141 icon.setTint(mContext.getColor(android.R.color.white));
142 }
143 CharSequence label = info.serviceInfo.loadLabel(pm);
Jason Monke24194f2016-02-05 14:55:05 -0500144 addTile(spec, icon, label != null ? label.toString() : "null", mContext);
Jason Monk62b63a02016-02-02 15:15:31 -0500145 }
146 return tiles;
147 }
148
149 @Override
150 protected void onPostExecute(Collection<TileInfo> result) {
151 mTiles.addAll(result);
152 mListener.onTilesChanged(mTiles);
153 }
154 }
155
156 public interface TileStateListener {
157 void onTilesChanged(List<TileInfo> tiles);
158 }
159}