blob: 70746c746976b594433487811db6793b6bc8fe9c [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
Jason Monkd52356a2015-01-28 10:40:41 -050019import java.util.List;
20
John Spurlockaf8d6c42014-05-07 17:49:08 -040021import android.content.Context;
22import android.content.Intent;
23import android.content.res.Resources;
24import android.provider.Settings;
John Spurlockccb6b9a2014-05-17 15:54:40 -040025import android.util.Log;
John Spurlock7f8f22a2014-07-02 18:54:17 -040026import android.view.View;
John Spurlock7f8f22a2014-07-02 18:54:17 -040027import android.view.ViewGroup;
John Spurlockaf8d6c42014-05-07 17:49:08 -040028
Jason Monkd52356a2015-01-28 10:40:41 -050029import com.android.settingslib.wifi.AccessPoint;
John Spurlockaf8d6c42014-05-07 17:49:08 -040030import com.android.systemui.R;
John Spurlock486b78e2014-07-07 08:37:56 -040031import com.android.systemui.qs.QSDetailItems;
32import com.android.systemui.qs.QSDetailItems.Item;
John Spurlockaf8d6c42014-05-07 17:49:08 -040033import com.android.systemui.qs.QSTile;
34import com.android.systemui.qs.QSTileView;
35import com.android.systemui.qs.SignalTileView;
36import com.android.systemui.statusbar.policy.NetworkController;
Jason Monkd2263cd2014-11-10 14:22:56 -050037import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
John Spurlockaf8d6c42014-05-07 17:49:08 -040038import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
39
40/** Quick settings tile: Wifi **/
41public class WifiTile extends QSTile<QSTile.SignalState> {
42 private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
43
44 private final NetworkController mController;
Jason Monkd2263cd2014-11-10 14:22:56 -050045 private final AccessPointController mWifiController;
John Spurlock7f8f22a2014-07-02 18:54:17 -040046 private final WifiDetailAdapter mDetailAdapter;
Selim Cinek4fda7b22014-08-18 22:07:25 +020047 private final QSTile.SignalState mStateBeforeClick = newTileState();
John Spurlockaf8d6c42014-05-07 17:49:08 -040048
49 public WifiTile(Host host) {
50 super(host);
51 mController = host.getNetworkController();
Jason Monkd2263cd2014-11-10 14:22:56 -050052 mWifiController = mController.getAccessPointController();
John Spurlock7f8f22a2014-07-02 18:54:17 -040053 mDetailAdapter = new WifiDetailAdapter();
John Spurlockccb6b9a2014-05-17 15:54:40 -040054 }
55
56 @Override
57 public boolean supportsDualTargets() {
58 return true;
John Spurlockaf8d6c42014-05-07 17:49:08 -040059 }
60
61 @Override
62 protected SignalState newTileState() {
63 return new SignalState();
64 }
65
66 @Override
John Spurlockccb6b9a2014-05-17 15:54:40 -040067 public void setListening(boolean listening) {
68 if (listening) {
69 mController.addNetworkSignalChangedCallback(mCallback);
Jason Monkd2263cd2014-11-10 14:22:56 -050070 mWifiController.addAccessPointCallback(mDetailAdapter);
John Spurlockccb6b9a2014-05-17 15:54:40 -040071 } else {
72 mController.removeNetworkSignalChangedCallback(mCallback);
Jason Monkd2263cd2014-11-10 14:22:56 -050073 mWifiController.removeAccessPointCallback(mDetailAdapter);
John Spurlockccb6b9a2014-05-17 15:54:40 -040074 }
John Spurlockaf8d6c42014-05-07 17:49:08 -040075 }
76
77 @Override
John Spurlock7f8f22a2014-07-02 18:54:17 -040078 public DetailAdapter getDetailAdapter() {
79 return mDetailAdapter;
80 }
81
82 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -040083 public QSTileView createTileView(Context context) {
84 return new SignalTileView(context);
85 }
86
87 @Override
88 protected void handleClick() {
Selim Cinek4fda7b22014-08-18 22:07:25 +020089 mState.copyTo(mStateBeforeClick);
John Spurlockaf8d6c42014-05-07 17:49:08 -040090 mController.setWifiEnabled(!mState.enabled);
91 }
92
93 @Override
94 protected void handleSecondaryClick() {
Jason Monkd2263cd2014-11-10 14:22:56 -050095 if (!mWifiController.canConfigWifi()) {
Jason Monk5d325072014-10-27 11:38:47 -040096 mHost.startSettingsActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
97 return;
98 }
99 if (!mState.enabled) {
100 mController.setWifiEnabled(true);
101 mState.enabled = true;
102 }
103 showDetail(true);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400104 }
105
106 @Override
107 protected void handleUpdateState(SignalState state, Object arg) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400108 state.visible = true;
John Spurlockccb6b9a2014-05-17 15:54:40 -0400109 if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg);
110 if (arg == null) return;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400111 CallbackInfo cb = (CallbackInfo) arg;
112
113 boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
114 boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.enabledDesc == null);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400115 boolean enabledChanging = state.enabled != cb.enabled;
116 if (enabledChanging) {
John Spurlock486b78e2014-07-07 08:37:56 -0400117 mDetailAdapter.setItemsVisible(cb.enabled);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400118 fireToggleStateChanged(cb.enabled);
119 }
John Spurlock3d09bbd2014-05-22 12:20:16 -0400120 state.enabled = cb.enabled;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400121 state.connected = wifiConnected;
122 state.activityIn = cb.enabled && cb.activityIn;
123 state.activityOut = cb.enabled && cb.activityOut;
John Spurlock899f4392014-06-11 10:59:11 -0400124 state.filter = true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400125 final String signalContentDescription;
126 final Resources r = mContext.getResources();
John Spurlockc1d48a52014-08-01 12:12:32 -0400127 if (!state.enabled) {
John Spurlock2d695812014-10-30 13:25:21 -0400128 state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_disabled);
John Spurlockc1d48a52014-08-01 12:12:32 -0400129 state.label = r.getString(R.string.quick_settings_wifi_label);
130 signalContentDescription = r.getString(R.string.accessibility_wifi_off);
131 } else if (wifiConnected) {
John Spurlock2d695812014-10-30 13:25:21 -0400132 state.icon = ResourceIcon.get(cb.wifiSignalIconId);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400133 state.label = removeDoubleQuotes(cb.enabledDesc);
134 signalContentDescription = cb.wifiSignalContentDescription;
135 } else if (wifiNotConnected) {
John Spurlock2d695812014-10-30 13:25:21 -0400136 state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_0);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400137 state.label = r.getString(R.string.quick_settings_wifi_label);
138 signalContentDescription = r.getString(R.string.accessibility_no_wifi);
139 } else {
John Spurlock2d695812014-10-30 13:25:21 -0400140 state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_no_network);
John Spurlock012d4a22014-06-04 00:40:18 -0400141 state.label = r.getString(R.string.quick_settings_wifi_label);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400142 signalContentDescription = r.getString(R.string.accessibility_wifi_off);
143 }
144 state.contentDescription = mContext.getString(
145 R.string.accessibility_quick_settings_wifi,
Selim Cineke5557a92014-08-15 19:59:23 +0200146 signalContentDescription);
147 String wifiName = state.label;
148 if (state.connected) {
149 wifiName = r.getString(R.string.accessibility_wifi_name, state.label);
150 }
151 state.dualLabelContentDescription = wifiName;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400152 }
153
Selim Cinek4fda7b22014-08-18 22:07:25 +0200154 @Override
155 protected boolean shouldAnnouncementBeDelayed() {
156 return mStateBeforeClick.enabled == mState.enabled;
157 }
158
159 @Override
160 protected String composeChangeAnnouncement() {
161 if (mState.enabled) {
162 return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_on);
163 } else {
164 return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_off);
165 }
166 }
167
John Spurlockaf8d6c42014-05-07 17:49:08 -0400168 private static String removeDoubleQuotes(String string) {
169 if (string == null) return null;
170 final int length = string.length();
171 if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
172 return string.substring(1, length - 1);
173 }
174 return string;
175 }
176
177 private static final class CallbackInfo {
178 boolean enabled;
John Spurlockd5cd2fd2014-07-27 11:36:33 -0400179 boolean connected;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400180 int wifiSignalIconId;
181 String enabledDesc;
182 boolean activityIn;
183 boolean activityOut;
184 String wifiSignalContentDescription;
John Spurlockccb6b9a2014-05-17 15:54:40 -0400185
186 @Override
187 public String toString() {
188 return new StringBuilder("CallbackInfo[")
189 .append("enabled=").append(enabled)
John Spurlockd5cd2fd2014-07-27 11:36:33 -0400190 .append(",connected=").append(connected)
John Spurlockccb6b9a2014-05-17 15:54:40 -0400191 .append(",wifiSignalIconId=").append(wifiSignalIconId)
192 .append(",enabledDesc=").append(enabledDesc)
193 .append(",activityIn=").append(activityIn)
194 .append(",activityOut=").append(activityOut)
195 .append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
196 .append(']').toString();
197 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400198 }
199
200 private final NetworkSignalChangedCallback mCallback = new NetworkSignalChangedCallback() {
201 @Override
John Spurlockd5cd2fd2014-07-27 11:36:33 -0400202 public void onWifiSignalChanged(boolean enabled, boolean connected, int wifiSignalIconId,
John Spurlockaf8d6c42014-05-07 17:49:08 -0400203 boolean activityIn, boolean activityOut,
204 String wifiSignalContentDescriptionId, String description) {
John Spurlockccb6b9a2014-05-17 15:54:40 -0400205 if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400206 final CallbackInfo info = new CallbackInfo();
207 info.enabled = enabled;
John Spurlockd5cd2fd2014-07-27 11:36:33 -0400208 info.connected = connected;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400209 info.wifiSignalIconId = wifiSignalIconId;
210 info.enabledDesc = description;
211 info.activityIn = activityIn;
212 info.activityOut = activityOut;
213 info.wifiSignalContentDescription = wifiSignalContentDescriptionId;
214 refreshState(info);
215 }
216
217 @Override
218 public void onMobileDataSignalChanged(boolean enabled,
219 int mobileSignalIconId,
220 String mobileSignalContentDescriptionId, int dataTypeIconId,
221 boolean activityIn, boolean activityOut,
Jason Monkb5746272014-11-12 16:50:31 -0500222 String dataTypeContentDescriptionId, String description,
Jorim Jaggic737b9b2014-09-08 23:57:20 +0200223 boolean isDataTypeIconWide) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400224 // noop
225 }
226
Jason Monkb5746272014-11-12 16:50:31 -0500227 public void onNoSimVisibleChanged(boolean noSims) {
228 // noop
229 }
230
John Spurlockaf8d6c42014-05-07 17:49:08 -0400231 @Override
232 public void onAirplaneModeChanged(boolean enabled) {
233 // noop
234 }
John Spurlockb98f7472014-07-08 17:09:42 -0400235
236 @Override
237 public void onMobileDataEnabled(boolean enabled) {
238 // noop
239 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400240 };
John Spurlock7f8f22a2014-07-02 18:54:17 -0400241
242 private final class WifiDetailAdapter implements DetailAdapter,
Jason Monkd2263cd2014-11-10 14:22:56 -0500243 NetworkController.AccessPointController.AccessPointCallback, QSDetailItems.Callback {
John Spurlock7f8f22a2014-07-02 18:54:17 -0400244
John Spurlock486b78e2014-07-07 08:37:56 -0400245 private QSDetailItems mItems;
John Spurlock7f8f22a2014-07-02 18:54:17 -0400246 private AccessPoint[] mAccessPoints;
247
248 @Override
249 public int getTitle() {
250 return R.string.quick_settings_wifi_label;
251 }
252
253 public Intent getSettingsIntent() {
254 return WIFI_SETTINGS;
255 }
256
257 @Override
258 public Boolean getToggleState() {
259 return mState.enabled;
260 }
261
262 @Override
263 public void setToggleState(boolean state) {
264 if (DEBUG) Log.d(TAG, "setToggleState " + state);
265 mController.setWifiEnabled(state);
266 showDetail(false);
267 }
268
269 @Override
270 public View createDetailView(Context context, View convertView, ViewGroup parent) {
John Spurlock486b78e2014-07-07 08:37:56 -0400271 if (DEBUG) Log.d(TAG, "createDetailView convertView=" + (convertView != null));
272 mAccessPoints = null;
Jason Monkd2263cd2014-11-10 14:22:56 -0500273 mWifiController.scanForAccessPoints();
John Spurlock486b78e2014-07-07 08:37:56 -0400274 fireScanStateChanged(true);
275 mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
276 mItems.setTagSuffix("Wifi");
277 mItems.setCallback(this);
278 mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
279 R.string.quick_settings_wifi_detail_empty_text);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400280 updateItems();
John Spurlock486b78e2014-07-07 08:37:56 -0400281 setItemsVisible(mState.enabled);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400282 return mItems;
283 }
284
285 @Override
Jason Monkd52356a2015-01-28 10:40:41 -0500286 public void onAccessPointsChanged(final List<AccessPoint> accessPoints) {
287 mAccessPoints = accessPoints.toArray(new AccessPoint[accessPoints.size()]);
John Spurlock486b78e2014-07-07 08:37:56 -0400288 updateItems();
Jason Monkd52356a2015-01-28 10:40:41 -0500289 if (accessPoints != null && accessPoints.size() > 0) {
John Spurlock486b78e2014-07-07 08:37:56 -0400290 fireScanStateChanged(false);
291 }
John Spurlock7f8f22a2014-07-02 18:54:17 -0400292 }
293
John Spurlock486b78e2014-07-07 08:37:56 -0400294 @Override
Jason Monk17f3c3f2015-01-14 10:13:22 -0500295 public void onSettingsActivityTriggered(Intent settingsIntent) {
296 mHost.startSettingsActivity(settingsIntent);
297 }
298
299 @Override
John Spurlock486b78e2014-07-07 08:37:56 -0400300 public void onDetailItemClick(Item item) {
301 if (item == null || item.tag == null) return;
302 final AccessPoint ap = (AccessPoint) item.tag;
Jason Monkd52356a2015-01-28 10:40:41 -0500303 if (!ap.isActive()) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500304 if (mWifiController.connect(ap)) {
Jason Monk5d325072014-10-27 11:38:47 -0400305 mHost.collapsePanels();
306 }
John Spurlock486b78e2014-07-07 08:37:56 -0400307 }
308 showDetail(false);
309 }
310
311 @Override
312 public void onDetailItemDisconnect(Item item) {
313 // noop
314 }
315
316 public void setItemsVisible(boolean visible) {
317 if (mItems == null) return;
318 mItems.setItemsVisible(visible);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400319 }
320
321 private void updateItems() {
322 if (mItems == null) return;
John Spurlock486b78e2014-07-07 08:37:56 -0400323 Item[] items = null;
324 if (mAccessPoints != null) {
325 items = new Item[mAccessPoints.length];
326 for (int i = 0; i < mAccessPoints.length; i++) {
327 final AccessPoint ap = mAccessPoints[i];
328 final Item item = new Item();
329 item.tag = ap;
Jason Monkd52356a2015-01-28 10:40:41 -0500330 item.icon = mWifiController.getIcon(ap);
331 item.line1 = ap.getSsid();
332 item.line2 = ap.getSummary();
333 item.overlay = ap.getSecurity() != AccessPoint.SECURITY_NONE
Jason Monkb27ec6d32014-12-01 17:50:16 -0500334 ? mContext.getDrawable(R.drawable.qs_ic_wifi_lock)
335 : null;
John Spurlock486b78e2014-07-07 08:37:56 -0400336 items[i] = item;
337 }
John Spurlock7f8f22a2014-07-02 18:54:17 -0400338 }
John Spurlock486b78e2014-07-07 08:37:56 -0400339 mItems.setItems(items);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400340 }
341 };
John Spurlockaf8d6c42014-05-07 17:49:08 -0400342}