blob: bbc885691b313c0920eaabe8d9b96f46504365de [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 Monk62b63a02016-02-02 15:15:31 -050057 String possible = mContext.getString(R.string.quick_settings_tiles_default)
Jason Monk1b0afeb2016-03-03 18:25:54 -050058 + ",hotspot,inversion,saver,work,cast,night";
Jason Monk62b63a02016-02-02 15:15:31 -050059 String[] possibleTiles = possible.split(",");
60 final Handler qsHandler = new Handler(host.getLooper());
61 final Handler mainHandler = new Handler(Looper.getMainLooper());
62 for (int i = 0; i < possibleTiles.length; i++) {
63 final String spec = possibleTiles[i];
64 final QSTile<?> tile = host.createTile(spec);
Jason Monkc3f42c12016-02-05 12:33:13 -050065 if (tile == null || !tile.isAvailable()) {
Jason Monk62b63a02016-02-02 15:15:31 -050066 continue;
67 }
68 tile.setListening(true);
69 tile.clearState();
70 tile.refreshState();
71 tile.setListening(false);
72 qsHandler.post(new Runnable() {
73 @Override
74 public void run() {
75 final QSTile.State state = tile.newTileState();
76 tile.getState().copyTo(state);
Jason Monk39c98e62016-03-16 09:18:35 -040077 // Ignore the current state and get the generic label instead.
78 state.label = tile.getTileLabel();
Jason Monk62b63a02016-02-02 15:15:31 -050079 mainHandler.post(new Runnable() {
80 @Override
81 public void run() {
Jason Monke24194f2016-02-05 14:55:05 -050082 addTile(spec, state);
Jason Monk62b63a02016-02-02 15:15:31 -050083 mListener.onTilesChanged(mTiles);
84 }
85 });
86 }
87 });
88 }
89 qsHandler.post(new Runnable() {
90 @Override
91 public void run() {
Jason Monkcb654cb2016-02-25 15:43:07 -050092 mainHandler.post(new Runnable() {
93 @Override
94 public void run() {
95 new QueryTilesTask().execute();
96 }
97 });
Jason Monk62b63a02016-02-02 15:15:31 -050098 }
99 });
100 }
101
102 public void setListener(TileStateListener listener) {
103 mListener = listener;
104 }
105
Jason Monke24194f2016-02-05 14:55:05 -0500106 private void addTile(String spec, QSTile.State state) {
107 if (mSpecs.contains(spec)) {
108 return;
109 }
Jason Monk62b63a02016-02-02 15:15:31 -0500110 TileInfo info = new TileInfo();
111 info.state = state;
112 info.spec = spec;
Jason Monke24194f2016-02-05 14:55:05 -0500113 mTiles.add(info);
114 mSpecs.add(spec);
Jason Monk62b63a02016-02-02 15:15:31 -0500115 }
116
Jason Monke24194f2016-02-05 14:55:05 -0500117 private void addTile(String spec, Drawable drawable, CharSequence label, Context context) {
Jason Monk62b63a02016-02-02 15:15:31 -0500118 QSTile.State state = new QSTile.State();
119 state.label = label;
120 state.contentDescription = label;
121 state.icon = new DrawableIcon(drawable);
Jason Monke24194f2016-02-05 14:55:05 -0500122 addTile(spec, state);
Jason Monk62b63a02016-02-02 15:15:31 -0500123 }
124
125 public static class TileInfo {
126 public String spec;
127 public QSTile.State state;
128 }
129
130 private class QueryTilesTask extends AsyncTask<Void, Void, Collection<TileInfo>> {
131 @Override
132 protected Collection<TileInfo> doInBackground(Void... params) {
133 List<TileInfo> tiles = new ArrayList<>();
134 PackageManager pm = mContext.getPackageManager();
135 List<ResolveInfo> services = pm.queryIntentServicesAsUser(
136 new Intent(TileService.ACTION_QS_TILE), 0, ActivityManager.getCurrentUser());
137 for (ResolveInfo info : services) {
138 String packageName = info.serviceInfo.packageName;
139 ComponentName componentName = new ComponentName(packageName, info.serviceInfo.name);
140 String spec = CustomTile.toSpec(componentName);
141 Drawable icon = info.serviceInfo.loadIcon(pm);
Jason Monkb53b6c52016-02-24 17:25:49 -0500142 if (!permission.BIND_QUICK_SETTINGS_TILE.equals(info.serviceInfo.permission)) {
143 continue;
144 }
Jason Monk62b63a02016-02-02 15:15:31 -0500145 if (icon != null) {
146 icon.mutate();
147 icon.setTint(mContext.getColor(android.R.color.white));
148 }
149 CharSequence label = info.serviceInfo.loadLabel(pm);
Jason Monke24194f2016-02-05 14:55:05 -0500150 addTile(spec, icon, label != null ? label.toString() : "null", mContext);
Jason Monk62b63a02016-02-02 15:15:31 -0500151 }
152 return tiles;
153 }
154
155 @Override
156 protected void onPostExecute(Collection<TileInfo> result) {
157 mTiles.addAll(result);
158 mListener.onTilesChanged(mTiles);
159 }
160 }
161
162 public interface TileStateListener {
163 void onTilesChanged(List<TileInfo> tiles);
164 }
165}