blob: 65154f2bad347aa8c5b6dca69c2b9e28b18c8fc2 [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
19import android.content.Context;
20import android.content.Intent;
Jason Monkba2318e2015-12-08 09:04:23 -050021import android.content.pm.PackageManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040022import android.content.res.Resources;
23import android.provider.Settings;
John Spurlockccb6b9a2014-05-17 15:54:40 -040024import android.util.Log;
John Spurlock7f8f22a2014-07-02 18:54:17 -040025import android.view.View;
John Spurlock7f8f22a2014-07-02 18:54:17 -040026import android.view.ViewGroup;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050027
Chris Wren457a21c2015-05-06 17:50:34 -040028import com.android.internal.logging.MetricsLogger;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050029import com.android.internal.logging.MetricsProto.MetricsEvent;
Jason Monkd52356a2015-01-28 10:40:41 -050030import com.android.settingslib.wifi.AccessPoint;
John Spurlockaf8d6c42014-05-07 17:49:08 -040031import com.android.systemui.R;
John Spurlock486b78e2014-07-07 08:37:56 -040032import com.android.systemui.qs.QSDetailItems;
33import com.android.systemui.qs.QSDetailItems.Item;
Jason Monkdc35dcb2015-12-04 16:36:15 -050034import com.android.systemui.qs.QSIconView;
John Spurlockaf8d6c42014-05-07 17:49:08 -040035import com.android.systemui.qs.QSTile;
John Spurlockaf8d6c42014-05-07 17:49:08 -040036import com.android.systemui.qs.SignalTileView;
37import com.android.systemui.statusbar.policy.NetworkController;
Jason Monkd2263cd2014-11-10 14:22:56 -050038import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
Jason Monk07b75fe2015-05-14 16:47:03 -040039import com.android.systemui.statusbar.policy.NetworkController.IconState;
Jason Monk07b75fe2015-05-14 16:47:03 -040040import com.android.systemui.statusbar.policy.SignalCallbackAdapter;
41
42import java.util.List;
John Spurlockaf8d6c42014-05-07 17:49:08 -040043
44/** Quick settings tile: Wifi **/
45public class WifiTile extends QSTile<QSTile.SignalState> {
46 private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
47
48 private final NetworkController mController;
Jason Monkd2263cd2014-11-10 14:22:56 -050049 private final AccessPointController mWifiController;
John Spurlock7f8f22a2014-07-02 18:54:17 -040050 private final WifiDetailAdapter mDetailAdapter;
Selim Cinek4fda7b22014-08-18 22:07:25 +020051 private final QSTile.SignalState mStateBeforeClick = newTileState();
John Spurlockaf8d6c42014-05-07 17:49:08 -040052
Jason Monkf1179612015-09-23 11:11:00 -040053 protected final WifiSignalCallback mSignalCallback = new WifiSignalCallback();
Jason Monk878c0932015-07-21 10:18:01 -040054
Jason Monkdc35dcb2015-12-04 16:36:15 -050055 public WifiTile(Host host) {
John Spurlockaf8d6c42014-05-07 17:49:08 -040056 super(host);
57 mController = host.getNetworkController();
Jason Monkd2263cd2014-11-10 14:22:56 -050058 mWifiController = mController.getAccessPointController();
John Spurlock7f8f22a2014-07-02 18:54:17 -040059 mDetailAdapter = new WifiDetailAdapter();
John Spurlockccb6b9a2014-05-17 15:54:40 -040060 }
61
62 @Override
Jason Monk62b63a02016-02-02 15:15:31 -050063 public SignalState newTileState() {
John Spurlockaf8d6c42014-05-07 17:49:08 -040064 return new SignalState();
65 }
66
67 @Override
John Spurlockccb6b9a2014-05-17 15:54:40 -040068 public void setListening(boolean listening) {
69 if (listening) {
Jason Monk07b75fe2015-05-14 16:47:03 -040070 mController.addSignalCallback(mSignalCallback);
John Spurlockccb6b9a2014-05-17 15:54:40 -040071 } else {
Jason Monk07b75fe2015-05-14 16:47:03 -040072 mController.removeSignalCallback(mSignalCallback);
Jason Monk0d6a1c42015-04-20 16:38:51 -040073 }
74 }
75
76 @Override
77 public void setDetailListening(boolean listening) {
78 if (listening) {
79 mWifiController.addAccessPointCallback(mDetailAdapter);
80 } else {
Jason Monkd2263cd2014-11-10 14:22:56 -050081 mWifiController.removeAccessPointCallback(mDetailAdapter);
John Spurlockccb6b9a2014-05-17 15:54:40 -040082 }
John Spurlockaf8d6c42014-05-07 17:49:08 -040083 }
84
85 @Override
John Spurlock7f8f22a2014-07-02 18:54:17 -040086 public DetailAdapter getDetailAdapter() {
87 return mDetailAdapter;
88 }
89
90 @Override
Jason Monkdc35dcb2015-12-04 16:36:15 -050091 public QSIconView createTileView(Context context) {
John Spurlockaf8d6c42014-05-07 17:49:08 -040092 return new SignalTileView(context);
93 }
94
95 @Override
Jason Monk76c67aa2016-02-19 14:49:42 -050096 public Intent getLongClickIntent() {
97 return WIFI_SETTINGS;
98 }
99
100 @Override
Jason Monkdc35dcb2015-12-04 16:36:15 -0500101 protected void handleSecondaryClick() {
102 // Secondary clicks are header clicks, just toggle.
Selim Cinek4fda7b22014-08-18 22:07:25 +0200103 mState.copyTo(mStateBeforeClick);
Chris Wren9e7283f2015-05-08 17:23:47 -0400104 MetricsLogger.action(mContext, getMetricsCategory(), !mState.enabled);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400105 mController.setWifiEnabled(!mState.enabled);
106 }
107
108 @Override
Jason Monkdc35dcb2015-12-04 16:36:15 -0500109 protected void handleClick() {
Jason Monkd2263cd2014-11-10 14:22:56 -0500110 if (!mWifiController.canConfigWifi()) {
Jason Monkee43cdf2015-06-19 14:20:46 -0400111 mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_WIFI_SETTINGS));
Jason Monk5d325072014-10-27 11:38:47 -0400112 return;
113 }
114 if (!mState.enabled) {
115 mController.setWifiEnabled(true);
116 mState.enabled = true;
117 }
118 showDetail(true);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400119 }
120
121 @Override
Jason Monk39c98e62016-03-16 09:18:35 -0400122 public CharSequence getTileLabel() {
123 return mContext.getString(R.string.quick_settings_wifi_label);
124 }
125
126 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400127 protected void handleUpdateState(SignalState state, Object arg) {
John Spurlockccb6b9a2014-05-17 15:54:40 -0400128 if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400129 CallbackInfo cb = (CallbackInfo) arg;
Jason Monk878c0932015-07-21 10:18:01 -0400130 if (cb == null) {
131 cb = mSignalCallback.mInfo;
132 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400133
134 boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
135 boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.enabledDesc == null);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400136 boolean enabledChanging = state.enabled != cb.enabled;
137 if (enabledChanging) {
John Spurlock486b78e2014-07-07 08:37:56 -0400138 mDetailAdapter.setItemsVisible(cb.enabled);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400139 fireToggleStateChanged(cb.enabled);
140 }
John Spurlock3d09bbd2014-05-22 12:20:16 -0400141 state.enabled = cb.enabled;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400142 state.connected = wifiConnected;
143 state.activityIn = cb.enabled && cb.activityIn;
144 state.activityOut = cb.enabled && cb.activityOut;
John Spurlock899f4392014-06-11 10:59:11 -0400145 state.filter = true;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400146 final String signalContentDescription;
147 final Resources r = mContext.getResources();
John Spurlockc1d48a52014-08-01 12:12:32 -0400148 if (!state.enabled) {
John Spurlock2d695812014-10-30 13:25:21 -0400149 state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_disabled);
John Spurlockc1d48a52014-08-01 12:12:32 -0400150 state.label = r.getString(R.string.quick_settings_wifi_label);
151 signalContentDescription = r.getString(R.string.accessibility_wifi_off);
152 } else if (wifiConnected) {
John Spurlock2d695812014-10-30 13:25:21 -0400153 state.icon = ResourceIcon.get(cb.wifiSignalIconId);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400154 state.label = removeDoubleQuotes(cb.enabledDesc);
155 signalContentDescription = cb.wifiSignalContentDescription;
156 } else if (wifiNotConnected) {
Jason Monk7d0e5982015-07-08 12:09:52 -0400157 state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_full_0);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400158 state.label = r.getString(R.string.quick_settings_wifi_label);
159 signalContentDescription = r.getString(R.string.accessibility_no_wifi);
160 } else {
John Spurlock2d695812014-10-30 13:25:21 -0400161 state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_no_network);
John Spurlock012d4a22014-06-04 00:40:18 -0400162 state.label = r.getString(R.string.quick_settings_wifi_label);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400163 signalContentDescription = r.getString(R.string.accessibility_wifi_off);
164 }
165 state.contentDescription = mContext.getString(
166 R.string.accessibility_quick_settings_wifi,
Selim Cineke5557a92014-08-15 19:59:23 +0200167 signalContentDescription);
Jason Monkbbadff82015-11-06 15:47:26 -0500168 CharSequence wifiName = state.label;
Selim Cineke5557a92014-08-15 19:59:23 +0200169 if (state.connected) {
170 wifiName = r.getString(R.string.accessibility_wifi_name, state.label);
171 }
172 state.dualLabelContentDescription = wifiName;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400173 }
174
Selim Cinek4fda7b22014-08-18 22:07:25 +0200175 @Override
Chris Wren457a21c2015-05-06 17:50:34 -0400176 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500177 return MetricsEvent.QS_WIFI;
Chris Wren457a21c2015-05-06 17:50:34 -0400178 }
179
180 @Override
Selim Cinek4fda7b22014-08-18 22:07:25 +0200181 protected boolean shouldAnnouncementBeDelayed() {
182 return mStateBeforeClick.enabled == mState.enabled;
183 }
184
185 @Override
186 protected String composeChangeAnnouncement() {
187 if (mState.enabled) {
188 return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_on);
189 } else {
190 return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_off);
191 }
192 }
193
Jason Monkc3f42c12016-02-05 12:33:13 -0500194 @Override
195 public boolean isAvailable() {
196 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
197 }
198
John Spurlockaf8d6c42014-05-07 17:49:08 -0400199 private static String removeDoubleQuotes(String string) {
200 if (string == null) return null;
201 final int length = string.length();
202 if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
203 return string.substring(1, length - 1);
204 }
205 return string;
206 }
207
Jason Monkf1179612015-09-23 11:11:00 -0400208 protected static final class CallbackInfo {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400209 boolean enabled;
John Spurlockd5cd2fd2014-07-27 11:36:33 -0400210 boolean connected;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400211 int wifiSignalIconId;
212 String enabledDesc;
213 boolean activityIn;
214 boolean activityOut;
215 String wifiSignalContentDescription;
John Spurlockccb6b9a2014-05-17 15:54:40 -0400216
217 @Override
218 public String toString() {
219 return new StringBuilder("CallbackInfo[")
220 .append("enabled=").append(enabled)
John Spurlockd5cd2fd2014-07-27 11:36:33 -0400221 .append(",connected=").append(connected)
John Spurlockccb6b9a2014-05-17 15:54:40 -0400222 .append(",wifiSignalIconId=").append(wifiSignalIconId)
223 .append(",enabledDesc=").append(enabledDesc)
224 .append(",activityIn=").append(activityIn)
225 .append(",activityOut=").append(activityOut)
226 .append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
227 .append(']').toString();
228 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400229 }
230
Jason Monkf1179612015-09-23 11:11:00 -0400231 protected final class WifiSignalCallback extends SignalCallbackAdapter {
Jason Monk878c0932015-07-21 10:18:01 -0400232 final CallbackInfo mInfo = new CallbackInfo();
233
John Spurlockaf8d6c42014-05-07 17:49:08 -0400234 @Override
Jason Monk07b75fe2015-05-14 16:47:03 -0400235 public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
236 boolean activityIn, boolean activityOut, String description) {
John Spurlockccb6b9a2014-05-17 15:54:40 -0400237 if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled);
Jason Monk878c0932015-07-21 10:18:01 -0400238 mInfo.enabled = enabled;
239 mInfo.connected = qsIcon.visible;
240 mInfo.wifiSignalIconId = qsIcon.icon;
241 mInfo.enabledDesc = description;
242 mInfo.activityIn = activityIn;
243 mInfo.activityOut = activityOut;
244 mInfo.wifiSignalContentDescription = qsIcon.contentDescription;
245 refreshState(mInfo);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400246 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400247 };
John Spurlock7f8f22a2014-07-02 18:54:17 -0400248
249 private final class WifiDetailAdapter implements DetailAdapter,
Jason Monkd2263cd2014-11-10 14:22:56 -0500250 NetworkController.AccessPointController.AccessPointCallback, QSDetailItems.Callback {
John Spurlock7f8f22a2014-07-02 18:54:17 -0400251
John Spurlock486b78e2014-07-07 08:37:56 -0400252 private QSDetailItems mItems;
John Spurlock7f8f22a2014-07-02 18:54:17 -0400253 private AccessPoint[] mAccessPoints;
254
255 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -0500256 public CharSequence getTitle() {
257 return mContext.getString(R.string.quick_settings_wifi_label);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400258 }
259
260 public Intent getSettingsIntent() {
261 return WIFI_SETTINGS;
262 }
263
264 @Override
265 public Boolean getToggleState() {
266 return mState.enabled;
267 }
268
269 @Override
270 public void setToggleState(boolean state) {
271 if (DEBUG) Log.d(TAG, "setToggleState " + state);
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500272 MetricsLogger.action(mContext, MetricsEvent.QS_WIFI_TOGGLE, state);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400273 mController.setWifiEnabled(state);
274 showDetail(false);
275 }
276
277 @Override
Chris Wren457a21c2015-05-06 17:50:34 -0400278 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500279 return MetricsEvent.QS_WIFI_DETAILS;
Chris Wren457a21c2015-05-06 17:50:34 -0400280 }
281
282 @Override
John Spurlock7f8f22a2014-07-02 18:54:17 -0400283 public View createDetailView(Context context, View convertView, ViewGroup parent) {
John Spurlock486b78e2014-07-07 08:37:56 -0400284 if (DEBUG) Log.d(TAG, "createDetailView convertView=" + (convertView != null));
285 mAccessPoints = null;
Jason Monkd2263cd2014-11-10 14:22:56 -0500286 mWifiController.scanForAccessPoints();
John Spurlock486b78e2014-07-07 08:37:56 -0400287 fireScanStateChanged(true);
288 mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
289 mItems.setTagSuffix("Wifi");
290 mItems.setCallback(this);
291 mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
292 R.string.quick_settings_wifi_detail_empty_text);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400293 updateItems();
John Spurlock486b78e2014-07-07 08:37:56 -0400294 setItemsVisible(mState.enabled);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400295 return mItems;
296 }
297
298 @Override
Jason Monkd52356a2015-01-28 10:40:41 -0500299 public void onAccessPointsChanged(final List<AccessPoint> accessPoints) {
300 mAccessPoints = accessPoints.toArray(new AccessPoint[accessPoints.size()]);
John Spurlock486b78e2014-07-07 08:37:56 -0400301 updateItems();
Jason Monkd52356a2015-01-28 10:40:41 -0500302 if (accessPoints != null && accessPoints.size() > 0) {
John Spurlock486b78e2014-07-07 08:37:56 -0400303 fireScanStateChanged(false);
304 }
John Spurlock7f8f22a2014-07-02 18:54:17 -0400305 }
306
John Spurlock486b78e2014-07-07 08:37:56 -0400307 @Override
Jason Monk17f3c3f2015-01-14 10:13:22 -0500308 public void onSettingsActivityTriggered(Intent settingsIntent) {
Jason Monkee43cdf2015-06-19 14:20:46 -0400309 mHost.startActivityDismissingKeyguard(settingsIntent);
Jason Monk17f3c3f2015-01-14 10:13:22 -0500310 }
311
312 @Override
John Spurlock486b78e2014-07-07 08:37:56 -0400313 public void onDetailItemClick(Item item) {
314 if (item == null || item.tag == null) return;
315 final AccessPoint ap = (AccessPoint) item.tag;
Jason Monkd52356a2015-01-28 10:40:41 -0500316 if (!ap.isActive()) {
Jason Monkd2263cd2014-11-10 14:22:56 -0500317 if (mWifiController.connect(ap)) {
Jason Monk5d325072014-10-27 11:38:47 -0400318 mHost.collapsePanels();
319 }
John Spurlock486b78e2014-07-07 08:37:56 -0400320 }
321 showDetail(false);
322 }
323
324 @Override
325 public void onDetailItemDisconnect(Item item) {
326 // noop
327 }
328
329 public void setItemsVisible(boolean visible) {
330 if (mItems == null) return;
331 mItems.setItemsVisible(visible);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400332 }
333
334 private void updateItems() {
335 if (mItems == null) return;
John Spurlock486b78e2014-07-07 08:37:56 -0400336 Item[] items = null;
337 if (mAccessPoints != null) {
338 items = new Item[mAccessPoints.length];
339 for (int i = 0; i < mAccessPoints.length; i++) {
340 final AccessPoint ap = mAccessPoints[i];
341 final Item item = new Item();
342 item.tag = ap;
Jason Monkd52356a2015-01-28 10:40:41 -0500343 item.icon = mWifiController.getIcon(ap);
344 item.line1 = ap.getSsid();
Jason Monk283c8b72015-05-26 12:54:12 -0400345 item.line2 = ap.isActive() ? ap.getSummary() : null;
Jason Monkd52356a2015-01-28 10:40:41 -0500346 item.overlay = ap.getSecurity() != AccessPoint.SECURITY_NONE
Jason Monkb27ec6d32014-12-01 17:50:16 -0500347 ? mContext.getDrawable(R.drawable.qs_ic_wifi_lock)
348 : null;
John Spurlock486b78e2014-07-07 08:37:56 -0400349 items[i] = item;
350 }
John Spurlock7f8f22a2014-07-02 18:54:17 -0400351 }
John Spurlock486b78e2014-07-07 08:37:56 -0400352 mItems.setItems(items);
John Spurlock7f8f22a2014-07-02 18:54:17 -0400353 }
354 };
John Spurlockaf8d6c42014-05-07 17:49:08 -0400355}