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