WifiTile.java revision d2263cd9db36d5f74a124c5ffaf8594ef702408f
1/*
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;
21import android.content.res.Resources;
22import android.provider.Settings;
23import android.util.Log;
24import android.view.View;
25import android.view.ViewGroup;
26
27import com.android.systemui.R;
28import com.android.systemui.qs.QSDetailItems;
29import com.android.systemui.qs.QSDetailItems.Item;
30import com.android.systemui.qs.QSTile;
31import com.android.systemui.qs.QSTileView;
32import com.android.systemui.qs.SignalTileView;
33import com.android.systemui.statusbar.policy.NetworkController;
34import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
35import com.android.systemui.statusbar.policy.NetworkController.AccessPointController.AccessPoint;
36import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
37
38/** Quick settings tile: Wifi **/
39public class WifiTile extends QSTile<QSTile.SignalState> {
40    private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
41
42    private final NetworkController mController;
43    private final AccessPointController mWifiController;
44    private final WifiDetailAdapter mDetailAdapter;
45    private final QSTile.SignalState mStateBeforeClick = newTileState();
46
47    public WifiTile(Host host) {
48        super(host);
49        mController = host.getNetworkController();
50        mWifiController = mController.getAccessPointController();
51        mDetailAdapter = new WifiDetailAdapter();
52    }
53
54    @Override
55    public boolean supportsDualTargets() {
56        return true;
57    }
58
59    @Override
60    protected SignalState newTileState() {
61        return new SignalState();
62    }
63
64    @Override
65    public void setListening(boolean listening) {
66        if (listening) {
67            mController.addNetworkSignalChangedCallback(mCallback);
68            mWifiController.addAccessPointCallback(mDetailAdapter);
69        } else {
70            mController.removeNetworkSignalChangedCallback(mCallback);
71            mWifiController.removeAccessPointCallback(mDetailAdapter);
72        }
73    }
74
75    @Override
76    public DetailAdapter getDetailAdapter() {
77        return mDetailAdapter;
78    }
79
80    @Override
81    public QSTileView createTileView(Context context) {
82        return new SignalTileView(context);
83    }
84
85    @Override
86    protected void handleClick() {
87        mState.copyTo(mStateBeforeClick);
88        mController.setWifiEnabled(!mState.enabled);
89    }
90
91    @Override
92    protected void handleSecondaryClick() {
93        if (!mWifiController.canConfigWifi()) {
94            mHost.startSettingsActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
95            return;
96        }
97        if (!mState.enabled) {
98            mController.setWifiEnabled(true);
99            mState.enabled = true;
100        }
101        showDetail(true);
102    }
103
104    @Override
105    protected void handleUpdateState(SignalState state, Object arg) {
106        state.visible = true;
107        if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg);
108        if (arg == null) return;
109        CallbackInfo cb = (CallbackInfo) arg;
110
111        boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
112        boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.enabledDesc == null);
113        boolean enabledChanging = state.enabled != cb.enabled;
114        if (enabledChanging) {
115            mDetailAdapter.setItemsVisible(cb.enabled);
116            fireToggleStateChanged(cb.enabled);
117        }
118        state.enabled = cb.enabled;
119        state.connected = wifiConnected;
120        state.activityIn = cb.enabled && cb.activityIn;
121        state.activityOut = cb.enabled && cb.activityOut;
122        state.filter = true;
123        final String signalContentDescription;
124        final Resources r = mContext.getResources();
125        if (!state.enabled) {
126            state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_disabled);
127            state.label = r.getString(R.string.quick_settings_wifi_label);
128            signalContentDescription = r.getString(R.string.accessibility_wifi_off);
129        } else if (wifiConnected) {
130            state.icon = ResourceIcon.get(cb.wifiSignalIconId);
131            state.label = removeDoubleQuotes(cb.enabledDesc);
132            signalContentDescription = cb.wifiSignalContentDescription;
133        } else if (wifiNotConnected) {
134            state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_0);
135            state.label = r.getString(R.string.quick_settings_wifi_label);
136            signalContentDescription = r.getString(R.string.accessibility_no_wifi);
137        } else {
138            state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_no_network);
139            state.label = r.getString(R.string.quick_settings_wifi_label);
140            signalContentDescription = r.getString(R.string.accessibility_wifi_off);
141        }
142        state.contentDescription = mContext.getString(
143                R.string.accessibility_quick_settings_wifi,
144                signalContentDescription);
145        String wifiName = state.label;
146        if (state.connected) {
147            wifiName = r.getString(R.string.accessibility_wifi_name, state.label);
148        }
149        state.dualLabelContentDescription = wifiName;
150    }
151
152    @Override
153    protected boolean shouldAnnouncementBeDelayed() {
154        return mStateBeforeClick.enabled == mState.enabled;
155    }
156
157    @Override
158    protected String composeChangeAnnouncement() {
159        if (mState.enabled) {
160            return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_on);
161        } else {
162            return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_off);
163        }
164    }
165
166    private static String removeDoubleQuotes(String string) {
167        if (string == null) return null;
168        final int length = string.length();
169        if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
170            return string.substring(1, length - 1);
171        }
172        return string;
173    }
174
175    private static final class CallbackInfo {
176        boolean enabled;
177        boolean connected;
178        int wifiSignalIconId;
179        String enabledDesc;
180        boolean activityIn;
181        boolean activityOut;
182        String wifiSignalContentDescription;
183
184        @Override
185        public String toString() {
186            return new StringBuilder("CallbackInfo[")
187                .append("enabled=").append(enabled)
188                .append(",connected=").append(connected)
189                .append(",wifiSignalIconId=").append(wifiSignalIconId)
190                .append(",enabledDesc=").append(enabledDesc)
191                .append(",activityIn=").append(activityIn)
192                .append(",activityOut=").append(activityOut)
193                .append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
194                .append(']').toString();
195        }
196    }
197
198    private final NetworkSignalChangedCallback mCallback = new NetworkSignalChangedCallback() {
199        @Override
200        public void onWifiSignalChanged(boolean enabled, boolean connected, int wifiSignalIconId,
201                boolean activityIn, boolean activityOut,
202                String wifiSignalContentDescriptionId, String description) {
203            if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled);
204            final CallbackInfo info = new CallbackInfo();
205            info.enabled = enabled;
206            info.connected = connected;
207            info.wifiSignalIconId = wifiSignalIconId;
208            info.enabledDesc = description;
209            info.activityIn = activityIn;
210            info.activityOut = activityOut;
211            info.wifiSignalContentDescription = wifiSignalContentDescriptionId;
212            refreshState(info);
213        }
214
215        @Override
216        public void onMobileDataSignalChanged(boolean enabled,
217                int mobileSignalIconId,
218                String mobileSignalContentDescriptionId, int dataTypeIconId,
219                boolean activityIn, boolean activityOut,
220                String dataTypeContentDescriptionId, String description, boolean noSim,
221                boolean isDataTypeIconWide) {
222            // noop
223        }
224
225        @Override
226        public void onAirplaneModeChanged(boolean enabled) {
227            // noop
228        }
229
230        @Override
231        public void onMobileDataEnabled(boolean enabled) {
232            // noop
233        }
234    };
235
236    private final class WifiDetailAdapter implements DetailAdapter,
237            NetworkController.AccessPointController.AccessPointCallback, QSDetailItems.Callback {
238
239        private QSDetailItems mItems;
240        private AccessPoint[] mAccessPoints;
241
242        @Override
243        public int getTitle() {
244            return R.string.quick_settings_wifi_label;
245        }
246
247        public Intent getSettingsIntent() {
248            return WIFI_SETTINGS;
249        }
250
251        @Override
252        public Boolean getToggleState() {
253            return mState.enabled;
254        }
255
256        @Override
257        public void setToggleState(boolean state) {
258            if (DEBUG) Log.d(TAG, "setToggleState " + state);
259            mController.setWifiEnabled(state);
260            showDetail(false);
261        }
262
263        @Override
264        public View createDetailView(Context context, View convertView, ViewGroup parent) {
265            if (DEBUG) Log.d(TAG, "createDetailView convertView=" + (convertView != null));
266            mAccessPoints = null;
267            mWifiController.scanForAccessPoints();
268            fireScanStateChanged(true);
269            mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
270            mItems.setTagSuffix("Wifi");
271            mItems.setCallback(this);
272            mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
273                    R.string.quick_settings_wifi_detail_empty_text);
274            updateItems();
275            setItemsVisible(mState.enabled);
276            return mItems;
277        }
278
279        @Override
280        public void onAccessPointsChanged(final AccessPoint[] accessPoints) {
281            mAccessPoints = accessPoints;
282            updateItems();
283            if (accessPoints != null && accessPoints.length > 0) {
284                fireScanStateChanged(false);
285            }
286        }
287
288        @Override
289        public void onDetailItemClick(Item item) {
290            if (item == null || item.tag == null) return;
291            final AccessPoint ap = (AccessPoint) item.tag;
292            if (!ap.isConnected) {
293                if (mWifiController.connect(ap)) {
294                    mHost.collapsePanels();
295                }
296            }
297            showDetail(false);
298        }
299
300        @Override
301        public void onDetailItemDisconnect(Item item) {
302            // noop
303        }
304
305        public void setItemsVisible(boolean visible) {
306            if (mItems == null) return;
307            mItems.setItemsVisible(visible);
308        }
309
310        private void updateItems() {
311            if (mItems == null) return;
312            Item[] items = null;
313            if (mAccessPoints != null) {
314                items = new Item[mAccessPoints.length];
315                for (int i = 0; i < mAccessPoints.length; i++) {
316                    final AccessPoint ap = mAccessPoints[i];
317                    final Item item = new Item();
318                    item.tag = ap;
319                    item.icon = ap.iconId;
320                    item.line1 = ap.ssid;
321                    if (ap.isConnected) {
322                        item.line2 = mContext.getString(R.string.quick_settings_connected);
323                    }
324                    items[i] = item;
325                }
326            }
327            mItems.setItems(items);
328        }
329    };
330}
331