blob: 6b3e87183d23ea23b500612e5712e7e923c69b25 [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.qs.tiles;
18
John Spurlock1e6eb172014-07-13 11:59:50 -040019import android.content.Context;
John Spurlockaf8d6c42014-05-07 17:49:08 -040020import android.content.Intent;
John Spurlockaf8d6c42014-05-07 17:49:08 -040021import android.provider.Settings;
John Spurlock1e6eb172014-07-13 11:59:50 -040022import android.util.Log;
John Spurlockaf8d6c42014-05-07 17:49:08 -040023import android.view.View;
John Spurlock1e6eb172014-07-13 11:59:50 -040024import android.view.View.OnAttachStateChangeListener;
25import android.view.ViewGroup;
John Spurlockaf8d6c42014-05-07 17:49:08 -040026
John Spurlockaf8d6c42014-05-07 17:49:08 -040027import com.android.systemui.R;
John Spurlock1e6eb172014-07-13 11:59:50 -040028import com.android.systemui.qs.QSDetailItems;
29import com.android.systemui.qs.QSDetailItems.Item;
John Spurlockaf8d6c42014-05-07 17:49:08 -040030import com.android.systemui.qs.QSTile;
31import com.android.systemui.statusbar.policy.CastController;
John Spurlock1e6eb172014-07-13 11:59:50 -040032import com.android.systemui.statusbar.policy.CastController.CastDevice;
John Spurlock657c62c2014-07-22 12:18:09 -040033import com.android.systemui.statusbar.policy.KeyguardMonitor;
John Spurlock1e6eb172014-07-13 11:59:50 -040034
35import java.util.LinkedHashMap;
36import java.util.Set;
John Spurlockaf8d6c42014-05-07 17:49:08 -040037
38/** Quick settings tile: Cast **/
39public class CastTile extends QSTile<QSTile.BooleanState> {
Jeff Brown18492622014-08-19 17:51:47 -070040 private static final Intent CAST_SETTINGS =
41 new Intent(Settings.ACTION_CAST_SETTINGS);
John Spurlockaf8d6c42014-05-07 17:49:08 -040042
43 private final CastController mController;
John Spurlock1e6eb172014-07-13 11:59:50 -040044 private final CastDetailAdapter mDetailAdapter;
John Spurlock657c62c2014-07-22 12:18:09 -040045 private final KeyguardMonitor mKeyguard;
46 private final Callback mCallback = new Callback();
John Spurlockaf8d6c42014-05-07 17:49:08 -040047
John Spurlockaf8d6c42014-05-07 17:49:08 -040048 public CastTile(Host host) {
49 super(host);
50 mController = host.getCastController();
John Spurlock1e6eb172014-07-13 11:59:50 -040051 mDetailAdapter = new CastDetailAdapter();
John Spurlock657c62c2014-07-22 12:18:09 -040052 mKeyguard = host.getKeyguardMonitor();
John Spurlock1e6eb172014-07-13 11:59:50 -040053 }
54
55 @Override
56 public DetailAdapter getDetailAdapter() {
57 return mDetailAdapter;
John Spurlockaf8d6c42014-05-07 17:49:08 -040058 }
59
60 @Override
61 protected BooleanState newTileState() {
62 return new BooleanState();
63 }
64
65 @Override
John Spurlockccb6b9a2014-05-17 15:54:40 -040066 public void setListening(boolean listening) {
John Spurlockaf8d6c42014-05-07 17:49:08 -040067 if (mController == null) return;
John Spurlock1e6eb172014-07-13 11:59:50 -040068 if (DEBUG) Log.d(TAG, "setListening " + listening);
John Spurlockccb6b9a2014-05-17 15:54:40 -040069 if (listening) {
70 mController.addCallback(mCallback);
John Spurlock657c62c2014-07-22 12:18:09 -040071 mKeyguard.addCallback(mCallback);
John Spurlockccb6b9a2014-05-17 15:54:40 -040072 } else {
John Spurlock1e6eb172014-07-13 11:59:50 -040073 mController.setDiscovering(false);
John Spurlockccb6b9a2014-05-17 15:54:40 -040074 mController.removeCallback(mCallback);
John Spurlock657c62c2014-07-22 12:18:09 -040075 mKeyguard.removeCallback(mCallback);
John Spurlockccb6b9a2014-05-17 15:54:40 -040076 }
John Spurlockaf8d6c42014-05-07 17:49:08 -040077 }
78
79 @Override
80 protected void handleUserSwitch(int newUserId) {
81 super.handleUserSwitch(newUserId);
82 if (mController == null) return;
83 mController.setCurrentUserId(newUserId);
84 }
85
86 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -040087 protected void handleClick() {
John Spurlock1e6eb172014-07-13 11:59:50 -040088 showDetail(true);
John Spurlockaf8d6c42014-05-07 17:49:08 -040089 }
90
91 @Override
92 protected void handleUpdateState(BooleanState state, Object arg) {
John Spurlock657c62c2014-07-22 12:18:09 -040093 state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
John Spurlock1e6eb172014-07-13 11:59:50 -040094 state.label = mContext.getString(R.string.quick_settings_cast_title);
95 state.value = false;
96 final Set<CastDevice> devices = mController.getCastDevices();
97 boolean connecting = false;
98 for (CastDevice device : devices) {
99 if (device.state == CastDevice.STATE_CONNECTED) {
100 state.value = true;
101 state.label = getDeviceName(device);
102 } else if (device.state == CastDevice.STATE_CONNECTING) {
103 connecting = true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400104 }
105 }
John Spurlock1e6eb172014-07-13 11:59:50 -0400106 if (!state.value && connecting) {
107 state.label = mContext.getString(R.string.quick_settings_connecting);
108 }
John Spurlock83e28482014-05-18 17:20:05 -0400109 state.iconId = state.value ? R.drawable.ic_qs_cast_on : R.drawable.ic_qs_cast_off;
John Spurlock1e6eb172014-07-13 11:59:50 -0400110 mDetailAdapter.updateItems(devices);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400111 }
112
John Spurlock1e6eb172014-07-13 11:59:50 -0400113 private String getDeviceName(CastDevice device) {
114 return device.name != null ? device.name
115 : mContext.getString(R.string.quick_settings_cast_device_default_name);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400116 }
117
John Spurlock657c62c2014-07-22 12:18:09 -0400118 private final class Callback implements CastController.Callback, KeyguardMonitor.Callback {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400119 @Override
John Spurlock1e6eb172014-07-13 11:59:50 -0400120 public void onCastDevicesChanged() {
121 refreshState();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400122 }
John Spurlock657c62c2014-07-22 12:18:09 -0400123
124 @Override
125 public void onKeyguardChanged() {
126 refreshState();
127 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400128 };
John Spurlock76c43b92014-05-13 21:10:51 -0400129
John Spurlock1e6eb172014-07-13 11:59:50 -0400130 private final class CastDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
131 private final LinkedHashMap<String, CastDevice> mVisibleOrder = new LinkedHashMap<>();
132
133 private QSDetailItems mItems;
134
John Spurlock76c43b92014-05-13 21:10:51 -0400135 @Override
John Spurlock1e6eb172014-07-13 11:59:50 -0400136 public int getTitle() {
137 return R.string.quick_settings_cast_title;
John Spurlock76c43b92014-05-13 21:10:51 -0400138 }
John Spurlock1e6eb172014-07-13 11:59:50 -0400139
140 @Override
141 public Boolean getToggleState() {
142 return null;
143 }
144
145 @Override
146 public Intent getSettingsIntent() {
Jeff Brown18492622014-08-19 17:51:47 -0700147 return CAST_SETTINGS;
John Spurlock1e6eb172014-07-13 11:59:50 -0400148 }
149
150 @Override
151 public void setToggleState(boolean state) {
152 // noop
153 }
154
155 @Override
156 public View createDetailView(Context context, View convertView, ViewGroup parent) {
157 mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
158 mItems.setTagSuffix("Cast");
159 if (convertView == null) {
160 if (DEBUG) Log.d(TAG, "addOnAttachStateChangeListener");
161 mItems.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
162 @Override
163 public void onViewAttachedToWindow(View v) {
164 if (DEBUG) Log.d(TAG, "onViewAttachedToWindow");
165 }
166
167 @Override
168 public void onViewDetachedFromWindow(View v) {
169 if (DEBUG) Log.d(TAG, "onViewDetachedFromWindow");
170 mVisibleOrder.clear();
171 }
172 });
173 }
174 mItems.setEmptyState(R.drawable.ic_qs_cast_detail_empty,
175 R.string.quick_settings_cast_detail_empty_text);
176 mItems.setCallback(this);
177 updateItems(mController.getCastDevices());
178 mController.setDiscovering(true);
179 return mItems;
180 }
181
182 private void updateItems(Set<CastDevice> devices) {
183 if (mItems == null) return;
184 Item[] items = null;
185 if (devices != null && !devices.isEmpty()) {
186 // if we are connected, simply show that device
187 for (CastDevice device : devices) {
188 if (device.state == CastDevice.STATE_CONNECTED) {
189 final Item item = new Item();
190 item.icon = R.drawable.ic_qs_cast_on;
191 item.line1 = getDeviceName(device);
192 item.line2 = mContext.getString(R.string.quick_settings_connected);
193 item.tag = device;
194 item.canDisconnect = true;
195 items = new Item[] { item };
196 break;
197 }
198 }
199 // otherwise list all available devices, and don't move them around
200 if (items == null) {
201 for (CastDevice device : devices) {
202 mVisibleOrder.put(device.id, device);
203 }
204 items = new Item[devices.size()];
205 int i = 0;
206 for (String id : mVisibleOrder.keySet()) {
207 final CastDevice device = mVisibleOrder.get(id);
208 if (!devices.contains(device)) continue;
209 final Item item = new Item();
210 item.icon = R.drawable.ic_qs_cast_off;
211 item.line1 = getDeviceName(device);
212 if (device.state == CastDevice.STATE_CONNECTING) {
213 item.line2 = mContext.getString(R.string.quick_settings_connecting);
214 }
215 item.tag = device;
216 items[i++] = item;
217 }
218 }
219 }
220 mItems.setItems(items);
221 }
222
223 @Override
224 public void onDetailItemClick(Item item) {
225 if (item == null || item.tag == null) return;
226 final CastDevice device = (CastDevice) item.tag;
227 mController.startCasting(device);
228 }
229
230 @Override
231 public void onDetailItemDisconnect(Item item) {
232 if (item == null || item.tag == null) return;
233 mController.stopCasting();
234 }
235 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400236}