WificondControl.java revision f4b53ff21ce0aa25131222d0cd15cc4a5e8c0c4f
1/* 2 * Copyright (C) 2017 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.server.wifi; 18 19import android.net.wifi.IApInterface; 20import android.net.wifi.IClientInterface; 21import android.net.wifi.IWifiScannerImpl; 22import android.net.wifi.IWificond; 23import android.net.wifi.ScanResult; 24import android.net.wifi.WifiSsid; 25import android.os.Binder; 26import android.os.RemoteException; 27import android.util.Log; 28 29import com.android.server.wifi.hotspot2.NetworkDetail; 30import com.android.server.wifi.util.InformationElementUtil; 31import com.android.server.wifi.util.NativeUtil; 32import com.android.server.wifi.wificond.NativeScanResult; 33 34import java.util.ArrayList; 35 36/** 37 * This class provides methods for WifiNative to send control commands to wificond. 38 * NOTE: This class should only be used from WifiNative. 39 */ 40public class WificondControl { 41 42 private static final String TAG = "WificondControl"; 43 private static final int MAC_ADDR_LEN = 6; 44 private IWificond mWificond; 45 private IClientInterface mClientInterface; 46 private IApInterface mApInterface; 47 private IWifiScannerImpl mWificondScanner; 48 private WifiInjector mWifiInjector; 49 50 WificondControl(WifiInjector wifiInjector) { 51 mWifiInjector = wifiInjector; 52 } 53 54 /** 55 * Setup driver for client mode via wificond. 56 * @return An IClientInterface as wificond client interface binder handler. 57 * Returns null on failure. 58 */ 59 public IClientInterface setupDriverForClientMode() { 60 mWificond = mWifiInjector.makeWificond(); 61 if (mWificond == null) { 62 Log.e(TAG, "Failed to get reference to wificond"); 63 return null; 64 } 65 66 IClientInterface clientInterface = null; 67 try { 68 clientInterface = mWificond.createClientInterface(); 69 } catch (RemoteException e1) { 70 Log.e(TAG, "Failed to get IClientInterface due to remote exception"); 71 return null; 72 } 73 74 if (clientInterface == null) { 75 Log.e(TAG, "Could not get IClientInterface instance from wificond"); 76 return null; 77 } 78 Binder.allowBlocking(clientInterface.asBinder()); 79 80 // Refresh Handlers 81 mClientInterface = clientInterface; 82 try { 83 mWificondScanner = mClientInterface.getWifiScannerImpl(); 84 } catch (RemoteException e) { 85 Log.e(TAG, "Failed to refresh wificond scanner due to remote exception"); 86 } 87 88 return clientInterface; 89 } 90 91 /** 92 * Setup driver for softAp mode via wificond. 93 * @return An IApInterface as wificond Ap interface binder handler. 94 * Returns null on failure. 95 */ 96 public IApInterface setupDriverForSoftApMode() { 97 mWificond = mWifiInjector.makeWificond(); 98 if (mWificond == null) { 99 Log.e(TAG, "Failed to get reference to wificond"); 100 return null; 101 } 102 103 IApInterface apInterface = null; 104 try { 105 apInterface = mWificond.createApInterface(); 106 } catch (RemoteException e1) { 107 Log.e(TAG, "Failed to get IApInterface due to remote exception"); 108 return null; 109 } 110 111 if (apInterface == null) { 112 Log.e(TAG, "Could not get IApInterface instance from wificond"); 113 return null; 114 } 115 Binder.allowBlocking(apInterface.asBinder()); 116 117 // Refresh Handlers 118 mApInterface = apInterface; 119 mWificondScanner = null; 120 121 return apInterface; 122 } 123 124 /** 125 * Teardown all interfaces configured in wificond. 126 * @return Returns true on success. 127 */ 128 public boolean tearDownInterfaces() { 129 // Explicitly refresh the wificodn handler because |tearDownInterfaces()| 130 // could be used to cleanup before we setup any interfaces. 131 mWificond = mWifiInjector.makeWificond(); 132 if (mWificond == null) { 133 Log.e(TAG, "Failed to get reference to wificond"); 134 return false; 135 } 136 137 try { 138 mWificond.tearDownInterfaces(); 139 return true; 140 } catch (RemoteException e) { 141 Log.e(TAG, "Failed to tear down interfaces due to remote exception"); 142 } 143 return false; 144 } 145 146 /** 147 * Disable wpa_supplicant via wificond. 148 * @return Returns true on success. 149 */ 150 public boolean disableSupplicant() { 151 if (mClientInterface == null) { 152 Log.e(TAG, "No valid wificond client interface handler"); 153 return false; 154 } 155 try { 156 return mClientInterface.disableSupplicant(); 157 } catch (RemoteException e) { 158 Log.e(TAG, "Failed to disable supplicant due to remote exception"); 159 } 160 return false; 161 } 162 163 /** 164 * Enable wpa_supplicant via wificond. 165 * @return Returns true on success. 166 */ 167 public boolean enableSupplicant() { 168 if (mClientInterface == null) { 169 Log.e(TAG, "No valid wificond client interface handler"); 170 return false; 171 } 172 173 try { 174 return mClientInterface.enableSupplicant(); 175 } catch (RemoteException e) { 176 Log.e(TAG, "Failed to enable supplicant due to remote exception"); 177 } 178 return false; 179 } 180 181 /** 182 * Request signal polling to wificond. 183 * Returns an SignalPollResult object. 184 * Returns null on failure. 185 */ 186 public WifiNative.SignalPollResult signalPoll() { 187 if (mClientInterface == null) { 188 Log.e(TAG, "No valid wificond client interface handler"); 189 return null; 190 } 191 192 int[] resultArray; 193 try { 194 resultArray = mClientInterface.signalPoll(); 195 if (resultArray == null || resultArray.length != 3) { 196 Log.e(TAG, "Invalid signal poll result from wificond"); 197 return null; 198 } 199 } catch (RemoteException e) { 200 Log.e(TAG, "Failed to do signal polling due to remote exception"); 201 return null; 202 } 203 WifiNative.SignalPollResult pollResult = new WifiNative.SignalPollResult(); 204 pollResult.currentRssi = resultArray[0]; 205 pollResult.txBitrate = resultArray[1]; 206 pollResult.associationFrequency = resultArray[2]; 207 return pollResult; 208 } 209 210 /** 211 * Fetch TX packet counters on current connection from wificond. 212 * Returns an TxPacketCounters object. 213 * Returns null on failure. 214 */ 215 public WifiNative.TxPacketCounters getTxPacketCounters() { 216 if (mClientInterface == null) { 217 Log.e(TAG, "No valid wificond client interface handler"); 218 return null; 219 } 220 221 int[] resultArray; 222 try { 223 resultArray = mClientInterface.getPacketCounters(); 224 if (resultArray == null || resultArray.length != 2) { 225 Log.e(TAG, "Invalid signal poll result from wificond"); 226 return null; 227 } 228 } catch (RemoteException e) { 229 Log.e(TAG, "Failed to do signal polling due to remote exception"); 230 return null; 231 } 232 WifiNative.TxPacketCounters counters = new WifiNative.TxPacketCounters(); 233 counters.txSucceeded = resultArray[0]; 234 counters.txFailed = resultArray[1]; 235 return counters; 236 } 237 238 /** 239 * Fetch the latest scan result from kernel via wificond. 240 * @return Returns an ArrayList of ScanDetail. 241 * Returns an empty ArrayList on failure. 242 */ 243 public ArrayList<ScanDetail> getScanResults() { 244 ArrayList<ScanDetail> results = new ArrayList<>(); 245 if (mWificondScanner == null) { 246 Log.e(TAG, "No valid wificond scanner interface handler"); 247 return results; 248 } 249 try { 250 NativeScanResult[] nativeResults = mWificondScanner.getScanResults(); 251 for (NativeScanResult result : nativeResults) { 252 WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(new String(result.ssid)); 253 String bssid = NativeUtil.macAddressFromByteArray(result.bssid); 254 ScanResult.InformationElement[] ies = 255 InformationElementUtil.parseInformationElements(result.infoElement); 256 InformationElementUtil.Capabilities capabilities = 257 new InformationElementUtil.Capabilities(); 258 capabilities.from(ies, result.capability); 259 String flags = capabilities.generateCapabilitiesString(); 260 NetworkDetail networkDetail = 261 new NetworkDetail(bssid, ies, null, result.frequency); 262 263 if (!wifiSsid.toString().equals(networkDetail.getTrimmedSSID())) { 264 Log.e(TAG, "Inconsistent SSID on BSSID: " + bssid); 265 continue; 266 } 267 ScanDetail scanDetail = new ScanDetail(networkDetail, wifiSsid, bssid, flags, 268 result.signalMbm / 100, result.frequency, result.tsf, ies, null); 269 results.add(scanDetail); 270 } 271 } catch (RemoteException e1) { 272 Log.e(TAG, "Failed to create ScanDetail ArrayList"); 273 } 274 return results; 275 } 276} 277