blob: 9b1e72a1648b352c0bf94cce9234711a281aa346 [file] [log] [blame]
Jason Monkda68f592015-01-07 10:55:58 -05001/*
2 * Copyright (C) 2015 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 */
16package com.android.systemui.statusbar.policy;
17
18import android.content.Context;
19import android.content.Intent;
20import android.net.NetworkCapabilities;
21import android.net.NetworkInfo;
22import android.net.wifi.WifiConfiguration;
23import android.net.wifi.WifiInfo;
24import android.net.wifi.WifiManager;
25import android.os.Handler;
26import android.os.Message;
27import android.os.Messenger;
28import android.util.Log;
29
30import com.android.internal.annotations.VisibleForTesting;
31import com.android.internal.util.AsyncChannel;
Jason Monk07b75fe2015-05-14 16:47:03 -040032import com.android.systemui.statusbar.policy.NetworkController.IconState;
Jason Monkda68f592015-01-07 10:55:58 -050033
34import java.util.List;
35import java.util.Objects;
36
37
38public class WifiSignalController extends
39 SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
40 private final WifiManager mWifiManager;
41 private final AsyncChannel mWifiChannel;
42 private final boolean mHasMobileData;
43
44 public WifiSignalController(Context context, boolean hasMobileData,
Jason Monk07b75fe2015-05-14 16:47:03 -040045 CallbackHandler callbackHandler, NetworkControllerImpl networkController) {
Jason Monkda68f592015-01-07 10:55:58 -050046 super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
Jason Monk07b75fe2015-05-14 16:47:03 -040047 callbackHandler, networkController);
Jason Monkda68f592015-01-07 10:55:58 -050048 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
49 mHasMobileData = hasMobileData;
50 Handler handler = new WifiHandler();
51 mWifiChannel = new AsyncChannel();
52 Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger();
53 if (wifiMessenger != null) {
54 mWifiChannel.connect(context, handler, wifiMessenger);
55 }
56 // WiFi only has one state.
57 mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
58 "Wi-Fi Icons",
59 WifiIcons.WIFI_SIGNAL_STRENGTH,
60 WifiIcons.QS_WIFI_SIGNAL_STRENGTH,
61 AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH,
62 WifiIcons.WIFI_NO_NETWORK,
63 WifiIcons.QS_WIFI_NO_NETWORK,
64 WifiIcons.WIFI_NO_NETWORK,
65 WifiIcons.QS_WIFI_NO_NETWORK,
66 AccessibilityContentDescriptions.WIFI_NO_CONNECTION
67 );
68 }
69
70 @Override
71 protected WifiState cleanState() {
72 return new WifiState();
73 }
74
75 @Override
76 public void notifyListeners() {
77 // only show wifi in the cluster if connected or if wifi-only
78 boolean wifiVisible = mCurrentState.enabled
79 && (mCurrentState.connected || !mHasMobileData);
80 String wifiDesc = wifiVisible ? mCurrentState.ssid : null;
81 boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
82 String contentDescription = getStringIfExists(getContentDescription());
Jason Monkda68f592015-01-07 10:55:58 -050083
Jason Monk07b75fe2015-05-14 16:47:03 -040084 IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);
85 IconState qsIcon = new IconState(mCurrentState.connected, getQsCurrentIconId(),
86 contentDescription);
87 mCallbackHandler.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
88 ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
89 wifiDesc);
Jason Monkda68f592015-01-07 10:55:58 -050090 }
91
92 /**
93 * Extract wifi state directly from broadcasts about changes in wifi state.
94 */
95 public void handleBroadcast(Intent intent) {
96 String action = intent.getAction();
97 if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
98 mCurrentState.enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
99 WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
100 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
101 final NetworkInfo networkInfo = (NetworkInfo)
102 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
103 mCurrentState.connected = networkInfo != null && networkInfo.isConnected();
104 // If Connected grab the signal strength and ssid.
105 if (mCurrentState.connected) {
106 // try getting it out of the intent first
107 WifiInfo info = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) != null
108 ? (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO)
109 : mWifiManager.getConnectionInfo();
110 if (info != null) {
111 mCurrentState.ssid = getSsid(info);
112 } else {
113 mCurrentState.ssid = null;
114 }
115 } else if (!mCurrentState.connected) {
116 mCurrentState.ssid = null;
117 }
118 } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
119 // Default to -200 as its below WifiManager.MIN_RSSI.
120 mCurrentState.rssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
121 mCurrentState.level = WifiManager.calculateSignalLevel(
122 mCurrentState.rssi, WifiIcons.WIFI_LEVEL_COUNT);
123 }
124
125 notifyListenersIfNecessary();
126 }
127
128 private String getSsid(WifiInfo info) {
129 String ssid = info.getSSID();
130 if (ssid != null) {
131 return ssid;
132 }
133 // OK, it's not in the connectionInfo; we have to go hunting for it
134 List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
135 int length = networks.size();
136 for (int i = 0; i < length; i++) {
137 if (networks.get(i).networkId == info.getNetworkId()) {
138 return networks.get(i).SSID;
139 }
140 }
141 return null;
142 }
143
144 @VisibleForTesting
145 void setActivity(int wifiActivity) {
146 mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
147 || wifiActivity == WifiManager.DATA_ACTIVITY_IN;
148 mCurrentState.activityOut = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
149 || wifiActivity == WifiManager.DATA_ACTIVITY_OUT;
150 notifyListenersIfNecessary();
151 }
152
153 /**
154 * Handler to receive the data activity on wifi.
155 */
156 private class WifiHandler extends Handler {
157 @Override
158 public void handleMessage(Message msg) {
159 switch (msg.what) {
160 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
161 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
162 mWifiChannel.sendMessage(Message.obtain(this,
163 AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
164 } else {
165 Log.e(mTag, "Failed to connect to wifi");
166 }
167 break;
168 case WifiManager.DATA_ACTIVITY_NOTIFICATION:
169 setActivity(msg.arg1);
170 break;
171 default:
172 // Ignore
173 break;
174 }
175 }
176 }
177
178 static class WifiState extends SignalController.State {
179 String ssid;
180
181 @Override
182 public void copyFrom(State s) {
183 super.copyFrom(s);
184 WifiState state = (WifiState) s;
185 ssid = state.ssid;
186 }
187
188 @Override
189 protected void toString(StringBuilder builder) {
190 super.toString(builder);
191 builder.append(',').append("ssid=").append(ssid);
192 }
193
194 @Override
195 public boolean equals(Object o) {
196 return super.equals(o)
197 && Objects.equals(((WifiState) o).ssid, ssid);
198 }
199 }
200}