SupplicantStaIfaceHal.java revision 82c5c5f2ee520a1066cf5d6421885bb53bbfe269
13ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar/* 23ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * Copyright (C) 2017 The Android Open Source Project 33ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * 43ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * Licensed under the Apache License, Version 2.0 (the "License"); 53ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * you may not use this file except in compliance with the License. 63ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * You may obtain a copy of the License at 73ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * 83ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * http://www.apache.org/licenses/LICENSE-2.0 93ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * 103ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * Unless required by applicable law or agreed to in writing, software 113ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * distributed under the License is distributed on an "AS IS" BASIS, 123ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * See the License for the specific language governing permissions and 143ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * limitations under the License. 153ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar */ 163ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarpackage com.android.server.wifi; 173ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 183ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQP3GPPNetwork; 193ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPDomName; 203ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPIPAddrAvailability; 213ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPNAIRealm; 223ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPRoamingConsortium; 233ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPVenueName; 243ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSConnCapability; 253ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSFriendlyName; 263ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSOSUProviders; 273ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSWANMetrics; 283ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 293ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.content.Context; 303ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.hardware.wifi.supplicant.V1_0.ISupplicant; 313ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.hardware.wifi.supplicant.V1_0.ISupplicantIface; 323ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.hardware.wifi.supplicant.V1_0.ISupplicantNetwork; 3387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarimport android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface; 343ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; 353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork; 363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.hardware.wifi.supplicant.V1_0.IfaceType; 373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.hardware.wifi.supplicant.V1_0.SupplicantStatus; 383ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode; 393ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.hardware.wifi.supplicant.V1_0.WpsConfigMethods; 403ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.hidl.manager.V1_0.IServiceManager; 413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.hidl.manager.V1_0.IServiceNotification; 4287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarimport android.net.IpConfiguration; 433ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.net.wifi.SupplicantState; 443ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.net.wifi.WifiConfiguration; 453ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.net.wifi.WifiSsid; 463ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.os.RemoteException; 473ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.util.Log; 483ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport android.util.SparseArray; 493ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 503ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport com.android.server.wifi.hotspot2.AnqpEvent; 5187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarimport com.android.server.wifi.hotspot2.IconEvent; 523ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport com.android.server.wifi.hotspot2.WnmData; 533ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport com.android.server.wifi.hotspot2.anqp.ANQPElement; 543ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport com.android.server.wifi.hotspot2.anqp.ANQPParser; 553ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport com.android.server.wifi.hotspot2.anqp.Constants; 563ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport com.android.server.wifi.util.NativeUtil; 573ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 583ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport java.io.IOException; 593ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport java.nio.BufferUnderflowException; 6087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarimport java.nio.ByteBuffer; 613ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport java.nio.ByteOrder; 623ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport java.util.ArrayList; 633ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport java.util.HashMap; 643ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport java.util.List; 653ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport java.util.Map; 663ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport java.util.regex.Matcher; 673ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarimport java.util.regex.Pattern; 683ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 693ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar/** 703ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * Hal calls for bring up/shut down of the supplicant daemon and for 713ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * sending requests to the supplicant daemon 723ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar */ 733ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarpublic class SupplicantStaIfaceHal { 743ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private static final boolean DBG = false; 753ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private static final String TAG = "SupplicantStaIfaceHal"; 763ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private static final String SERVICE_MANAGER_NAME = "manager"; 773ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar /** 783ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * Regex pattern for extracting the wps device type bytes. 793ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * Matches a strings like the following: "<categ>-<OUI>-<subcateg>"; 803ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar */ 813ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private static final Pattern WPS_DEVICE_TYPE_PATTERN = 823ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Pattern.compile("^(\\d{1,2})-([0-9a-fA-F]{8})-(\\d{1,2})$"); 833ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 843ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private IServiceManager mIServiceManager = null; 853ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar // Supplicant HAL interface objects 863ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private ISupplicant mISupplicant; 873ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private ISupplicantStaIface mISupplicantStaIface; 883ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private String mIfaceName; 893ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar // Currently configured network in wpa_supplicant 903ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private SupplicantStaNetworkHal mCurrentNetwork; 913ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar // Currently configured network's framework network Id. 923ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private int mFrameworkNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 933ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private final Object mLock = new Object(); 943ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private final Context mContext; 953ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private final WifiMonitor mWifiMonitor; 963ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 973ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar public SupplicantStaIfaceHal(Context context, WifiMonitor monitor) { 983ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mContext = context; 993ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mWifiMonitor = monitor; 1003ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1013ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 1023ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar /** 1033ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * Registers a service notification for the ISupplicant service, which triggers intialization of 1043ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * the ISupplicantStaIface 1053ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * @return true if the service notification was successfully registered 1063ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar */ 1073ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar public boolean initialize() { 1083ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (DBG) Log.i(TAG, "Registering ISupplicant service ready callback."); 1093ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar synchronized (mLock) { 1103ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mISupplicant = null; 1113ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mISupplicantStaIface = null; 1123ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (mIServiceManager != null) { 1133ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar // Already have an IServiceManager and serviceNotification registered, don't 1143ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar // don't register another. 1153ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return true; 1163ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1173ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar try { 1183ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mIServiceManager = getServiceManagerMockable(); 1193ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (mIServiceManager == null) { 1203ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "Failed to get HIDL Service Manager"); 1213ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return false; 1223ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1233ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (!mIServiceManager.linkToDeath(cookie -> { 1243ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.wtf(TAG, "IServiceManager died: cookie=" + cookie); 1253ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar synchronized (mLock) { 1263ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar supplicantServiceDiedHandler(); 1273ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mIServiceManager = null; // Will need to register a new ServiceNotification 1283ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 12987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar }, 0)) { 1303ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.wtf(TAG, "Error on linkToDeath on IServiceManager"); 1313ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar supplicantServiceDiedHandler(); 1323ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mIServiceManager = null; // Will need to register a new ServiceNotification 1333ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return false; 1343ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar IServiceNotification serviceNotificationCb = new IServiceNotification.Stub() { 1363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar public void onRegistration(String fqName, String name, boolean preexisting) { 1373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar synchronized (mLock) { 1383ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (DBG) { 1393ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName 1403ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar + ", " + name + " preexisting=" + preexisting); 1413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1423ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (!initSupplicantService() || !initSupplicantStaIface()) { 1433ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "initalizing ISupplicantIfaces failed."); 1443ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar supplicantServiceDiedHandler(); 1453ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } else { 1463ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.i(TAG, "Completed initialization of ISupplicant interfaces."); 1473ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1483ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1493ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1503ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar }; 1513ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar /* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it 1523ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar exists */ 1533ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (!mIServiceManager.registerForNotifications(ISupplicant.kInterfaceName, 1543ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar "", serviceNotificationCb)) { 1553ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "Failed to register for notifications to " 1563ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar + ISupplicant.kInterfaceName); 1573ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mIServiceManager = null; // Will need to register a new ServiceNotification 1583ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return false; 1593ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1603ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } catch (RemoteException e) { 1613ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "Exception while trying to register a listener for ISupplicant service: " 1623ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar + e); 1633ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar supplicantServiceDiedHandler(); 1643ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1653ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return true; 1663ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1673ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1683ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 1693ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private boolean initSupplicantService() { 1703ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar synchronized (mLock) { 17187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar try { 1723ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mISupplicant = getSupplicantMockable(); 1733ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } catch (RemoteException e) { 1743ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "ISupplicant.getService exception: " + e); 1753ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return false; 1763ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1773ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (mISupplicant == null) { 1783ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "Got null ISupplicant service. Stopping supplicant HIDL startup"); 1793ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return false; 18087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 1813ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1823ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return true; 1833ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1843ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 1853ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private boolean initSupplicantStaIface() { 1863ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar synchronized (mLock) { 1873ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar /** List all supplicant Ifaces */ 1883ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList<>(); 18987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar try { 1903ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mISupplicant.listInterfaces((SupplicantStatus status, 1913ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar ArrayList<ISupplicant.IfaceInfo> ifaces) -> { 1923ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (status.code != SupplicantStatusCode.SUCCESS) { 1933ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "Getting Supplicant Interfaces failed: " + status.code); 1943ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return; 1953ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 1963ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar supplicantIfaces.addAll(ifaces); 1973ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar }); 19887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } catch (RemoteException e) { 1993ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "ISupplicant.listInterfaces exception: " + e); 2003ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return false; 2013ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2023ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (supplicantIfaces.size() == 0) { 2033ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "Got zero HIDL supplicant ifaces. Stopping supplicant HIDL startup."); 2043ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return false; 2053ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2063ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Mutable<ISupplicantIface> supplicantIface = new Mutable<>(); 2073ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Mutable<String> ifaceName = new Mutable<>(); 2083ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar for (ISupplicant.IfaceInfo ifaceInfo : supplicantIfaces) { 2093ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (ifaceInfo.type == IfaceType.STA) { 2103ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar try { 2113ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mISupplicant.getInterface(ifaceInfo, 2123ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar (SupplicantStatus status, ISupplicantIface iface) -> { 2133ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (status.code != SupplicantStatusCode.SUCCESS) { 2143ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "Failed to get ISupplicantIface " + status.code); 2153ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return; 2163ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2173ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar supplicantIface.value = iface; 2183ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar }); 2193ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } catch (RemoteException e) { 2203ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "ISupplicant.getInterface exception: " + e); 2213ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return false; 2223ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2233ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar ifaceName.value = ifaceInfo.name; 2243ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar break; 2253ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 22687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 2273ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (supplicantIface.value == null) { 2283ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar Log.e(TAG, "initSupplicantStaIface got null iface"); 2293ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return false; 2303ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2313ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mISupplicantStaIface = getStaIfaceMockable(supplicantIface.value); 2323ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mIfaceName = ifaceName.value; 2333ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (!registerCallback(new SupplicantStaIfaceHalCallback())) { 2343ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return false; 2353ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2363ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return true; 2373ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2383ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2393ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 2403ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private void supplicantServiceDiedHandler() { 2413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar synchronized (mLock) { 2423ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mISupplicant = null; 2433ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar mISupplicantStaIface = null; 2443ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2453ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2463ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 2473ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar /** 2483ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * Signals whether Initialization completed successfully. Only necessary for testing, is not 2493ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * needed to guard calls etc. 2503ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar */ 2513ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar public boolean isInitializationComplete() { 2523ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return mISupplicantStaIface != null; 2533ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2543ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 2553ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar /** 2563ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * Wrapper functions to access static HAL methods, created to be mockable in unit tests 2573ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar */ 2583ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar protected IServiceManager getServiceManagerMockable() throws RemoteException { 2593ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return IServiceManager.getService(SERVICE_MANAGER_NAME); 2603ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2613ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 2623ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar protected ISupplicant getSupplicantMockable() throws RemoteException { 2633ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return ISupplicant.getService(); 2643ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2653ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 2663ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar protected ISupplicantStaIface getStaIfaceMockable(ISupplicantIface iface) { 2673ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return ISupplicantStaIface.asInterface(iface.asBinder()); 2683ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2693ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 2703ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar /** 2713ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * Add a network configuration to wpa_supplicant. 2723ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * 2733ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * @param config Config corresponding to the network. 2743ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * @return SupplicantStaNetwork of the added network in wpa_supplicant. 2753ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar */ 2763ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar private SupplicantStaNetworkHal addNetwork(WifiConfiguration config) { 2773ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar logi("addSupplicantStaNetwork via HIDL"); 2783ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (config == null) { 2793ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar loge("Cannot add NULL network!"); 2803ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return null; 2813ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2823ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar SupplicantStaNetworkHal network = addNetwork(); 2833ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (network == null) { 2843ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar loge("Failed to add a network!"); 2853ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return null; 2863ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2873ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar if (network.saveWifiConfiguration(config)) { 2883ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return network; 2893ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } else { 2903ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar loge("Failed to save variables for: " + config.configKey()); 2913ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar return null; 2923ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2933ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar } 2943ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar 2953ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar /** 2963ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * Add the provided network configuration to wpa_supplicant and initiate connection to it. 2973ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * This method does the following: 2983ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * 1. Triggers disconnect command to wpa_supplicant (if |shouldDisconnect| is true). 2993ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * 2. Remove any existing network in wpa_supplicant. 3003ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar * 3. Add a new network to wpa_supplicant. 30187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * 4. Save the provided configuration to wpa_supplicant. 30287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * 5. Select the new network in wpa_supplicant. 30387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * 30487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * @param config WifiConfiguration parameters for the provided network. 30587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * @param shouldDisconnect whether to trigger a disconnection or not. 30687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * @return {@code true} if it succeeds, {@code false} otherwise 30787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar */ 30887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar public boolean connectToNetwork(WifiConfiguration config, boolean shouldDisconnect) { 30987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar mFrameworkNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 31087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar mCurrentNetwork = null; 31187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar logd("connectToNetwork " + config.configKey() 31287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar + " (shouldDisconnect " + shouldDisconnect + ")"); 31387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (shouldDisconnect && !disconnect()) { 31487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar loge("Failed to trigger disconnect"); 31587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return false; 31687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 31787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (!removeAllNetworks()) { 31887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar loge("Failed to remove existing networks"); 31987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return false; 32087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 32187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar mCurrentNetwork = addNetwork(config); 32287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (mCurrentNetwork == null) { 32387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar loge("Failed to add/save network configuration: " + config.configKey()); 32487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return false; 32587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 32687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (!mCurrentNetwork.select()) { 32787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar loge("Failed to select network configuration: " + config.configKey()); 32887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return false; 32987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 33087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar mFrameworkNetworkId = config.networkId; 33187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return true; 33287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 33387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 33487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /** 33587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * Initiates roaming to the already configured network in wpa_supplicant. If the network 33687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * configuration provided does not match the already configured network, then this triggers 33787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * a new connection attempt (instead of roam). 33887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * 1. First check if we're attempting to connect to the same network as we currently have 33987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * configured. 34087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * 2. Set the new bssid for the network in wpa_supplicant. 34187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * 3. Trigger reassociate command to wpa_supplicant. 34287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * 34387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * @param config WifiConfiguration parameters for the provided network. 34487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * @return {@code true} if it succeeds, {@code false} otherwise 34587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar */ 34687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar public boolean roamToNetwork(WifiConfiguration config) { 34787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (mFrameworkNetworkId != config.networkId || mCurrentNetwork == null) { 34887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Log.w(TAG, "Cannot roam to a different network, initiate new connection. " 34987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar + "Current network ID: " + mFrameworkNetworkId); 35087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return connectToNetwork(config, false); 35187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 35287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar String bssid = config.getNetworkSelectionStatus().getNetworkSelectionBSSID(); 35387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar logd("roamToNetwork" + config.configKey() + " (bssid " + bssid + ")"); 35487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (!mCurrentNetwork.setBssid(bssid)) { 35587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar loge("Failed to set new bssid on network: " + config.configKey()); 35687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return false; 35787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 35887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (!reassociate()) { 35987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar loge("Failed to trigger reassociate"); 36087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return false; 36187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 36287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return true; 36387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 36487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 36587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /** 36687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * Load all the configured networks from wpa_supplicant. 36787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * 36887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * @param configs Map of configuration key to configuration objects corresponding to all 36987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * the networks. 37087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf 37187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar * @return true if succeeds, false otherwise. 37287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar */ 37387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar public boolean loadNetworks(Map<String, WifiConfiguration> configs, 37487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar SparseArray<Map<String, String>> networkExtras) { 37587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar List<Integer> networkIds = listNetworks(); 37687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (networkIds == null) { 37787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Log.e(TAG, "Failed to list networks"); 37887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return false; 37987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 38087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar for (Integer networkId : networkIds) { 38187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar SupplicantStaNetworkHal network = getNetwork(networkId); 38287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (network == null) { 38387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Log.e(TAG, "Failed to get network with ID: " + networkId); 38487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return false; 38587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 38687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar WifiConfiguration config = new WifiConfiguration(); 38787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Map<String, String> networkExtra = new HashMap<>(); 38887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (!network.loadWifiConfiguration(config, networkExtra)) { 38987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Log.e(TAG, "Failed to load wifi configuration for network with ID: " + networkId); 39087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return false; 39187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 39287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar // Set the default IP assignments. 39387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar config.setIpAssignment(IpConfiguration.IpAssignment.DHCP); 39487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar config.setProxySettings(IpConfiguration.ProxySettings.NONE); 39587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 39687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar networkExtras.put(networkId, networkExtra); 397 String configKey = networkExtra.get(SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY); 398 final WifiConfiguration duplicateConfig = configs.put(configKey, config); 399 if (duplicateConfig != null) { 400 // The network is already known. Overwrite the duplicate entry. 401 Log.i(TAG, "Replacing duplicate network: " + duplicateConfig.networkId); 402 removeNetwork(duplicateConfig.networkId); 403 networkExtras.remove(duplicateConfig.networkId); 404 } 405 } 406 return true; 407 } 408 409 /** 410 * Remove all networks from supplicant 411 */ 412 public boolean removeAllNetworks() { 413 synchronized (mLock) { 414 ArrayList<Integer> networks = listNetworks(); 415 if (networks == null) { 416 Log.e(TAG, "removeAllNetworks failed, got null networks"); 417 return false; 418 } 419 for (int id : networks) { 420 if (!removeNetwork(id)) { 421 Log.e(TAG, "removeAllNetworks failed to remove network: " + id); 422 return false; 423 } 424 } 425 } 426 return true; 427 } 428 429 /** 430 * Set the currently configured network's bssid. 431 * 432 * @param bssidStr Bssid to set in the form of "XX:XX:XX:XX:XX:XX" 433 * @return true if succeeds, false otherwise. 434 */ 435 public boolean setCurrentNetworkBssid(String bssidStr) { 436 if (mCurrentNetwork == null) return false; 437 return mCurrentNetwork.setBssid(bssidStr); 438 } 439 440 /** 441 * Get the currently configured network's WPS NFC token. 442 * 443 * @return Hex string corresponding to the WPS NFC token. 444 */ 445 public String getCurrentNetworkWpsNfcConfigurationToken() { 446 if (mCurrentNetwork == null) return null; 447 return mCurrentNetwork.getWpsNfcConfigurationToken(); 448 } 449 450 /** 451 * Adds a new network. 452 * 453 * @return The ISupplicantNetwork object for the new network, or null if the call fails 454 */ 455 private SupplicantStaNetworkHal addNetwork() { 456 synchronized (mLock) { 457 final String methodStr = "addNetwork"; 458 if (DBG) Log.i(TAG, methodStr); 459 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 460 Mutable<ISupplicantNetwork> newNetwork = new Mutable<>(); 461 try { 462 mISupplicantStaIface.addNetwork((SupplicantStatus status, 463 ISupplicantNetwork network) -> { 464 if (checkStatusAndLogFailure(status, methodStr)) { 465 newNetwork.value = network; 466 } 467 }); 468 } catch (RemoteException e) { 469 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e); 470 supplicantServiceDiedHandler(); 471 } 472 if (newNetwork.value != null) { 473 return getStaNetworkMockable( 474 ISupplicantStaNetwork.asInterface(newNetwork.value.asBinder())); 475 } else { 476 return null; 477 } 478 } 479 } 480 481 /** 482 * Remove network from supplicant with network Id 483 * 484 * @return true if request is sent successfully, false otherwise. 485 */ 486 private boolean removeNetwork(int id) { 487 synchronized (mLock) { 488 final String methodStr = "removeNetwork"; 489 if (DBG) Log.i(TAG, methodStr); 490 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 491 try { 492 SupplicantStatus status = mISupplicantStaIface.removeNetwork(id); 493 return checkStatusAndLogFailure(status, methodStr); 494 } catch (RemoteException e) { 495 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 496 supplicantServiceDiedHandler(); 497 return false; 498 } 499 } 500 } 501 502 /** 503 * Use this to mock the creation of SupplicantStaNetworkHal instance. 504 * 505 * @param iSupplicantStaNetwork ISupplicantStaNetwork instance retrieved from HIDL. 506 * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if 507 * the call fails 508 */ 509 protected SupplicantStaNetworkHal getStaNetworkMockable( 510 ISupplicantStaNetwork iSupplicantStaNetwork) { 511 return new SupplicantStaNetworkHal( 512 iSupplicantStaNetwork, mIfaceName, mContext, mWifiMonitor); 513 } 514 515 /** 516 * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if 517 * the call fails 518 */ 519 private SupplicantStaNetworkHal getNetwork(int id) { 520 synchronized (mLock) { 521 final String methodStr = "getNetwork"; 522 if (DBG) Log.i(TAG, methodStr); 523 Mutable<ISupplicantNetwork> gotNetwork = new Mutable<>(); 524 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 525 try { 526 mISupplicantStaIface.getNetwork(id, (SupplicantStatus status, 527 ISupplicantNetwork network) -> { 528 if (checkStatusAndLogFailure(status, methodStr)) { 529 gotNetwork.value = network; 530 } 531 }); 532 } catch (RemoteException e) { 533 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e); 534 supplicantServiceDiedHandler(); 535 } 536 if (gotNetwork.value != null) { 537 return getStaNetworkMockable( 538 ISupplicantStaNetwork.asInterface(gotNetwork.value.asBinder())); 539 } else { 540 return null; 541 } 542 } 543 } 544 545 /** See ISupplicantStaNetwork.hal for documentation */ 546 private boolean registerCallback(ISupplicantStaIfaceCallback callback) { 547 synchronized (mLock) { 548 final String methodStr = "registerCallback"; 549 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 550 try { 551 SupplicantStatus status = mISupplicantStaIface.registerCallback(callback); 552 return checkStatusAndLogFailure(status, methodStr); 553 } catch (RemoteException e) { 554 supplicantServiceDiedHandler(); 555 return false; 556 } 557 } 558 } 559 560 /** 561 * @return a list of SupplicantNetworkID ints for all networks controlled by supplicant, returns 562 * null if the call fails 563 */ 564 private java.util.ArrayList<Integer> listNetworks() { 565 synchronized (mLock) { 566 final String methodStr = "listNetworks"; 567 if (DBG) Log.i(TAG, methodStr); 568 Mutable<ArrayList<Integer>> networkIdList = new Mutable<>(); 569 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 570 try { 571 mISupplicantStaIface.listNetworks((SupplicantStatus status, 572 java.util.ArrayList<Integer> networkIds) -> { 573 if (checkStatusAndLogFailure(status, methodStr)) { 574 networkIdList.value = networkIds; 575 } 576 }); 577 } catch (RemoteException e) { 578 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e); 579 supplicantServiceDiedHandler(); 580 } 581 return networkIdList.value; 582 } 583 } 584 585 /** 586 * Set WPS device name. 587 * 588 * @param name String to be set. 589 * @return true if request is sent successfully, false otherwise. 590 */ 591 public boolean setWpsDeviceName(String name) { 592 synchronized (mLock) { 593 final String methodStr = "setWpsDeviceName"; 594 if (DBG) Log.i(TAG, methodStr); 595 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 596 try { 597 SupplicantStatus status = mISupplicantStaIface.setWpsDeviceName(name); 598 return checkStatusAndLogFailure(status, methodStr); 599 } catch (RemoteException e) { 600 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 601 supplicantServiceDiedHandler(); 602 return false; 603 } 604 } 605 } 606 607 /** 608 * Set WPS device type. 609 * 610 * @param typeStr Type specified as a string. Used format: <categ>-<OUI>-<subcateg> 611 * @return true if request is sent successfully, false otherwise. 612 */ 613 public boolean setWpsDeviceType(String typeStr) { 614 Matcher match = WPS_DEVICE_TYPE_PATTERN.matcher(typeStr); 615 if (!match.find() || match.groupCount() != 3) { 616 Log.e(TAG, "Malformed WPS device type " + typeStr); 617 return false; 618 } 619 short categ = Short.parseShort(match.group(1)); 620 byte[] oui = NativeUtil.hexStringToByteArray(match.group(2)); 621 short subCateg = Short.parseShort(match.group(3)); 622 623 byte[] bytes = new byte[8]; 624 ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN); 625 byteBuffer.putShort(categ); 626 byteBuffer.put(oui); 627 byteBuffer.putShort(subCateg); 628 return setWpsDeviceType(bytes); 629 } 630 631 private boolean setWpsDeviceType(byte[/* 8 */] type) { 632 synchronized (mLock) { 633 final String methodStr = "setWpsDeviceType"; 634 if (DBG) Log.i(TAG, methodStr); 635 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 636 try { 637 SupplicantStatus status = mISupplicantStaIface.setWpsDeviceType(type); 638 return checkStatusAndLogFailure(status, methodStr); 639 } catch (RemoteException e) { 640 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 641 supplicantServiceDiedHandler(); 642 return false; 643 } 644 } 645 } 646 647 /** 648 * Set WPS manufacturer. 649 * 650 * @param manufacturer String to be set. 651 * @return true if request is sent successfully, false otherwise. 652 */ 653 public boolean setWpsManufacturer(String manufacturer) { 654 synchronized (mLock) { 655 final String methodStr = "setWpsManufacturer"; 656 if (DBG) Log.i(TAG, methodStr); 657 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 658 try { 659 SupplicantStatus status = mISupplicantStaIface.setWpsManufacturer(manufacturer); 660 return checkStatusAndLogFailure(status, methodStr); 661 } catch (RemoteException e) { 662 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 663 supplicantServiceDiedHandler(); 664 return false; 665 } 666 } 667 } 668 669 /** 670 * Set WPS model name. 671 * 672 * @param modelName String to be set. 673 * @return true if request is sent successfully, false otherwise. 674 */ 675 public boolean setWpsModelName(String modelName) { 676 synchronized (mLock) { 677 final String methodStr = "setWpsModelName"; 678 if (DBG) Log.i(TAG, methodStr); 679 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 680 try { 681 SupplicantStatus status = mISupplicantStaIface.setWpsModelName(modelName); 682 return checkStatusAndLogFailure(status, methodStr); 683 } catch (RemoteException e) { 684 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 685 supplicantServiceDiedHandler(); 686 return false; 687 } 688 } 689 } 690 691 /** 692 * Set WPS model number. 693 * 694 * @param modelNumber String to be set. 695 * @return true if request is sent successfully, false otherwise. 696 */ 697 public boolean setWpsModelNumber(String modelNumber) { 698 synchronized (mLock) { 699 final String methodStr = "setWpsModelNumber"; 700 if (DBG) Log.i(TAG, methodStr); 701 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 702 try { 703 SupplicantStatus status = mISupplicantStaIface.setWpsModelNumber(modelNumber); 704 return checkStatusAndLogFailure(status, methodStr); 705 } catch (RemoteException e) { 706 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 707 supplicantServiceDiedHandler(); 708 return false; 709 } 710 } 711 } 712 713 /** 714 * Set WPS serial number. 715 * 716 * @param serialNumber String to be set. 717 * @return true if request is sent successfully, false otherwise. 718 */ 719 public boolean setWpsSerialNumber(String serialNumber) { 720 synchronized (mLock) { 721 final String methodStr = "setWpsSerialNumber"; 722 if (DBG) Log.i(TAG, methodStr); 723 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 724 try { 725 SupplicantStatus status = mISupplicantStaIface.setWpsSerialNumber(serialNumber); 726 return checkStatusAndLogFailure(status, methodStr); 727 } catch (RemoteException e) { 728 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 729 supplicantServiceDiedHandler(); 730 return false; 731 } 732 } 733 } 734 735 /** 736 * Set WPS config methods 737 * 738 * @param configMethodsStr List of config methods. 739 * @return true if request is sent successfully, false otherwise. 740 */ 741 public boolean setWpsConfigMethods(String configMethodsStr) { 742 short configMethodsMask = 0; 743 String[] configMethodsStrArr = configMethodsStr.split("\\s+"); 744 for (int i = 0; i < configMethodsStrArr.length; i++) { 745 configMethodsMask |= stringToWpsConfigMethod(configMethodsStrArr[i]); 746 } 747 return setWpsConfigMethods(configMethodsMask); 748 } 749 750 private boolean setWpsConfigMethods(short configMethods) { 751 synchronized (mLock) { 752 final String methodStr = "setWpsConfigMethods"; 753 if (DBG) Log.i(TAG, methodStr); 754 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 755 try { 756 SupplicantStatus status = mISupplicantStaIface.setWpsConfigMethods(configMethods); 757 return checkStatusAndLogFailure(status, methodStr); 758 } catch (RemoteException e) { 759 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 760 supplicantServiceDiedHandler(); 761 return false; 762 } 763 } 764 } 765 766 /** 767 * Trigger a reassociation even if the iface is currently connected. 768 * 769 * @return true if request is sent successfully, false otherwise. 770 */ 771 public boolean reassociate() { 772 synchronized (mLock) { 773 final String methodStr = "reassociate"; 774 if (DBG) Log.i(TAG, methodStr); 775 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 776 try { 777 SupplicantStatus status = mISupplicantStaIface.reassociate(); 778 return checkStatusAndLogFailure(status, methodStr); 779 } catch (RemoteException e) { 780 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 781 supplicantServiceDiedHandler(); 782 return false; 783 } 784 } 785 } 786 787 /** 788 * Trigger a reconnection if the iface is disconnected. 789 * 790 * @return true if request is sent successfully, false otherwise. 791 */ 792 public boolean reconnect() { 793 synchronized (mLock) { 794 final String methodStr = "reconnect"; 795 if (DBG) Log.i(TAG, methodStr); 796 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 797 try { 798 SupplicantStatus status = mISupplicantStaIface.reconnect(); 799 return checkStatusAndLogFailure(status, methodStr); 800 } catch (RemoteException e) { 801 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 802 supplicantServiceDiedHandler(); 803 return false; 804 } 805 } 806 } 807 808 /** 809 * Trigger a disconnection from the currently connected network. 810 * 811 * @return true if request is sent successfully, false otherwise. 812 */ 813 public boolean disconnect() { 814 synchronized (mLock) { 815 final String methodStr = "disconnect"; 816 if (DBG) Log.i(TAG, methodStr); 817 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 818 try { 819 SupplicantStatus status = mISupplicantStaIface.disconnect(); 820 return checkStatusAndLogFailure(status, methodStr); 821 } catch (RemoteException e) { 822 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 823 supplicantServiceDiedHandler(); 824 return false; 825 } 826 } 827 } 828 829 /** 830 * Enable or disable power save mode. 831 * 832 * @param enable true to enable, false to disable. 833 * @return true if request is sent successfully, false otherwise. 834 */ 835 public boolean setPowerSave(boolean enable) { 836 synchronized (mLock) { 837 final String methodStr = "setPowerSave"; 838 if (DBG) Log.i(TAG, methodStr); 839 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 840 try { 841 SupplicantStatus status = mISupplicantStaIface.setPowerSave(enable); 842 return checkStatusAndLogFailure(status, methodStr); 843 } catch (RemoteException e) { 844 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 845 supplicantServiceDiedHandler(); 846 return false; 847 } 848 } 849 } 850 851 /** 852 * Initiate TDLS discover with the specified AP. 853 * 854 * @param macAddress MAC Address of the AP. 855 * @return true if request is sent successfully, false otherwise. 856 */ 857 public boolean initiateTdlsDiscover(String macAddress) { 858 return initiateTdlsDiscover(NativeUtil.macAddressToByteArray(macAddress)); 859 } 860 /** See ISupplicantStaIface.hal for documentation */ 861 private boolean initiateTdlsDiscover(byte[/* 6 */] macAddress) { 862 synchronized (mLock) { 863 final String methodStr = "initiateTdlsDiscover"; 864 if (DBG) Log.i(TAG, methodStr); 865 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 866 try { 867 SupplicantStatus status = mISupplicantStaIface.initiateTdlsDiscover(macAddress); 868 return checkStatusAndLogFailure(status, methodStr); 869 } catch (RemoteException e) { 870 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 871 supplicantServiceDiedHandler(); 872 return false; 873 } 874 } 875 } 876 877 /** 878 * Initiate TDLS setup with the specified AP. 879 * 880 * @param macAddress MAC Address of the AP. 881 * @return true if request is sent successfully, false otherwise. 882 */ 883 public boolean initiateTdlsSetup(String macAddress) { 884 return initiateTdlsSetup(NativeUtil.macAddressToByteArray(macAddress)); 885 } 886 /** See ISupplicantStaIface.hal for documentation */ 887 private boolean initiateTdlsSetup(byte[/* 6 */] macAddress) { 888 synchronized (mLock) { 889 final String methodStr = "initiateTdlsSetup"; 890 if (DBG) Log.i(TAG, methodStr); 891 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 892 try { 893 SupplicantStatus status = mISupplicantStaIface.initiateTdlsSetup(macAddress); 894 return checkStatusAndLogFailure(status, methodStr); 895 } catch (RemoteException e) { 896 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 897 supplicantServiceDiedHandler(); 898 return false; 899 } 900 } 901 } 902 903 /** 904 * Initiate TDLS teardown with the specified AP. 905 * @param macAddress MAC Address of the AP. 906 * @return true if request is sent successfully, false otherwise. 907 */ 908 public boolean initiateTdlsTeardown(String macAddress) { 909 return initiateTdlsTeardown(NativeUtil.macAddressToByteArray(macAddress)); 910 } 911 912 /** See ISupplicantStaIface.hal for documentation */ 913 private boolean initiateTdlsTeardown(byte[/* 6 */] macAddress) { 914 synchronized (mLock) { 915 final String methodStr = "initiateTdlsTeardown"; 916 if (DBG) Log.i(TAG, methodStr); 917 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 918 try { 919 SupplicantStatus status = mISupplicantStaIface.initiateTdlsTeardown(macAddress); 920 return checkStatusAndLogFailure(status, methodStr); 921 } catch (RemoteException e) { 922 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 923 supplicantServiceDiedHandler(); 924 return false; 925 } 926 } 927 } 928 929 /** 930 * Request the specified ANQP elements |elements| from the specified AP |bssid|. 931 * 932 * @param bssid BSSID of the AP 933 * @param infoElements ANQP elements to be queried. Refer to ISupplicantStaIface.AnqpInfoId. 934 * @param hs20SubTypes HS subtypes to be queried. Refer to ISupplicantStaIface.Hs20AnqpSubTypes. 935 * @return true if request is sent successfully, false otherwise. 936 */ 937 public boolean initiateAnqpQuery(String bssid, ArrayList<Short> infoElements, 938 ArrayList<Integer> hs20SubTypes) { 939 return initiateAnqpQuery( 940 NativeUtil.macAddressToByteArray(bssid), infoElements, hs20SubTypes); 941 } 942 943 /** See ISupplicantStaIface.hal for documentation */ 944 private boolean initiateAnqpQuery(byte[/* 6 */] macAddress, 945 java.util.ArrayList<Short> infoElements, java.util.ArrayList<Integer> subTypes) { 946 synchronized (mLock) { 947 final String methodStr = "initiateAnqpQuery"; 948 if (DBG) Log.i(TAG, methodStr); 949 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 950 try { 951 SupplicantStatus status = mISupplicantStaIface.initiateAnqpQuery(macAddress, 952 infoElements, subTypes); 953 return checkStatusAndLogFailure(status, methodStr); 954 } catch (RemoteException e) { 955 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 956 supplicantServiceDiedHandler(); 957 return false; 958 } 959 } 960 } 961 962 /** 963 * Request the specified ANQP ICON from the specified AP |bssid|. 964 * 965 * @param bssid BSSID of the AP 966 * @param fileName Name of the file to request. 967 * @return true if request is sent successfully, false otherwise. 968 */ 969 public boolean initiateHs20IconQuery(String bssid, String fileName) { 970 return initiateHs20IconQuery(NativeUtil.macAddressToByteArray(bssid), fileName); 971 } 972 973 /** See ISupplicantStaIface.hal for documentation */ 974 private boolean initiateHs20IconQuery(byte[/* 6 */] macAddress, String fileName) { 975 synchronized (mLock) { 976 final String methodStr = "initiateHs20IconQuery"; 977 if (DBG) Log.i(TAG, methodStr); 978 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 979 try { 980 SupplicantStatus status = mISupplicantStaIface.initiateHs20IconQuery(macAddress, 981 fileName); 982 return checkStatusAndLogFailure(status, methodStr); 983 } catch (RemoteException e) { 984 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 985 supplicantServiceDiedHandler(); 986 return false; 987 } 988 } 989 } 990 991 /** 992 * Makes a callback to HIDL to getMacAddress from supplicant 993 * 994 * @return string containing the MAC address, or null on a failed call 995 */ 996 public String getMacAddress() { 997 synchronized (mLock) { 998 final String methodStr = "getMacAddress"; 999 if (DBG) Log.i(TAG, methodStr); 1000 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 1001 Mutable<String> gotMac = new Mutable<>(); 1002 try { 1003 mISupplicantStaIface.getMacAddress((SupplicantStatus status, 1004 byte[/* 6 */] macAddr) -> { 1005 if (checkStatusAndLogFailure(status, methodStr)) { 1006 gotMac.value = NativeUtil.macAddressFromByteArray(macAddr); 1007 } 1008 }); 1009 } catch (RemoteException e) { 1010 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e); 1011 supplicantServiceDiedHandler(); 1012 } 1013 return gotMac.value; 1014 } 1015 } 1016 1017 /** 1018 * Start using the added RX filters. 1019 * 1020 * @return true if request is sent successfully, false otherwise. 1021 */ 1022 public boolean startRxFilter() { 1023 synchronized (mLock) { 1024 final String methodStr = "startRxFilter"; 1025 if (DBG) Log.i(TAG, methodStr); 1026 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1027 try { 1028 SupplicantStatus status = mISupplicantStaIface.startRxFilter(); 1029 return checkStatusAndLogFailure(status, methodStr); 1030 } catch (RemoteException e) { 1031 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1032 supplicantServiceDiedHandler(); 1033 return false; 1034 } 1035 } 1036 } 1037 1038 /** 1039 * Stop using the added RX filters. 1040 * 1041 * @return true if request is sent successfully, false otherwise. 1042 */ 1043 public boolean stopRxFilter() { 1044 synchronized (mLock) { 1045 final String methodStr = "stopRxFilter"; 1046 if (DBG) Log.i(TAG, methodStr); 1047 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1048 try { 1049 SupplicantStatus status = mISupplicantStaIface.stopRxFilter(); 1050 return checkStatusAndLogFailure(status, methodStr); 1051 } catch (RemoteException e) { 1052 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1053 supplicantServiceDiedHandler(); 1054 return false; 1055 } 1056 } 1057 } 1058 1059 public static final byte RX_FILTER_TYPE_V4_MULTICAST = 1060 ISupplicantStaIface.RxFilterType.V6_MULTICAST; 1061 public static final byte RX_FILTER_TYPE_V6_MULTICAST = 1062 ISupplicantStaIface.RxFilterType.V6_MULTICAST; 1063 /** 1064 * Add an RX filter. 1065 * 1066 * @param type one of {@link #RX_FILTER_TYPE_V4_MULTICAST} or 1067 * {@link #RX_FILTER_TYPE_V6_MULTICAST} values. 1068 * @return true if request is sent successfully, false otherwise. 1069 */ 1070 private boolean addRxFilter(byte type) { 1071 synchronized (mLock) { 1072 final String methodStr = "addRxFilter"; 1073 if (DBG) Log.i(TAG, methodStr); 1074 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1075 try { 1076 SupplicantStatus status = mISupplicantStaIface.addRxFilter(type); 1077 return checkStatusAndLogFailure(status, methodStr); 1078 } catch (RemoteException e) { 1079 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1080 supplicantServiceDiedHandler(); 1081 return false; 1082 } 1083 } 1084 } 1085 1086 /** 1087 * Remove an RX filter. 1088 * 1089 * @param type one of {@link #RX_FILTER_TYPE_V4_MULTICAST} or 1090 * {@link #RX_FILTER_TYPE_V6_MULTICAST} values. 1091 * @return true if request is sent successfully, false otherwise. 1092 */ 1093 private boolean removeRxFilter(byte type) { 1094 synchronized (mLock) { 1095 final String methodStr = "removeRxFilter"; 1096 if (DBG) Log.i(TAG, methodStr); 1097 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1098 try { 1099 SupplicantStatus status = mISupplicantStaIface.removeRxFilter(type); 1100 return checkStatusAndLogFailure(status, methodStr); 1101 } catch (RemoteException e) { 1102 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1103 supplicantServiceDiedHandler(); 1104 return false; 1105 } 1106 } 1107 } 1108 1109 public static final byte BT_COEX_MODE_ENABLED = ISupplicantStaIface.BtCoexistenceMode.ENABLED; 1110 public static final byte BT_COEX_MODE_DISABLED = ISupplicantStaIface.BtCoexistenceMode.DISABLED; 1111 public static final byte BT_COEX_MODE_SENSE = ISupplicantStaIface.BtCoexistenceMode.SENSE; 1112 /** 1113 * Set Bt co existense mode. 1114 * 1115 * @param mode one of the above {@link #BT_COEX_MODE_ENABLED}, {@link #BT_COEX_MODE_DISABLED} 1116 * or {@link #BT_COEX_MODE_SENSE} values. 1117 * @return true if request is sent successfully, false otherwise. 1118 */ 1119 public boolean setBtCoexistenceMode(byte mode) { 1120 synchronized (mLock) { 1121 final String methodStr = "setBtCoexistenceMode"; 1122 if (DBG) Log.i(TAG, methodStr); 1123 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1124 try { 1125 SupplicantStatus status = mISupplicantStaIface.setBtCoexistenceMode(mode); 1126 return checkStatusAndLogFailure(status, methodStr); 1127 } catch (RemoteException e) { 1128 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1129 supplicantServiceDiedHandler(); 1130 return false; 1131 } 1132 } 1133 } 1134 1135 /** Enable or disable BT coexistence mode. 1136 * 1137 * @param enable true to enable, false to disable. 1138 * @return true if request is sent successfully, false otherwise. 1139 */ 1140 public boolean setBtCoexistenceScanModeEnabled(boolean enable) { 1141 synchronized (mLock) { 1142 final String methodStr = "setBtCoexistenceScanModeEnabled"; 1143 if (DBG) Log.i(TAG, methodStr); 1144 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1145 try { 1146 SupplicantStatus status = 1147 mISupplicantStaIface.setBtCoexistenceScanModeEnabled(enable); 1148 return checkStatusAndLogFailure(status, methodStr); 1149 } catch (RemoteException e) { 1150 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1151 supplicantServiceDiedHandler(); 1152 return false; 1153 } 1154 } 1155 } 1156 1157 /** 1158 * Enable or disable suspend mode optimizations. 1159 * 1160 * @param enable true to enable, false otherwise. 1161 * @return true if request is sent successfully, false otherwise. 1162 */ 1163 public boolean setSuspendModeEnabled(boolean enable) { 1164 synchronized (mLock) { 1165 final String methodStr = "setSuspendModeEnabled"; 1166 if (DBG) Log.i(TAG, methodStr); 1167 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1168 try { 1169 SupplicantStatus status = mISupplicantStaIface.setSuspendModeEnabled(enable); 1170 return checkStatusAndLogFailure(status, methodStr); 1171 } catch (RemoteException e) { 1172 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1173 supplicantServiceDiedHandler(); 1174 return false; 1175 } 1176 } 1177 } 1178 1179 /** 1180 * Set country code. 1181 * 1182 * @param codeStr 2 byte ASCII string. For ex: US, CA. 1183 * @return true if request is sent successfully, false otherwise. 1184 */ 1185 public boolean setCountryCode(String codeStr) { 1186 return setCountryCode(NativeUtil.stringToByteArray(codeStr)); 1187 } 1188 1189 /** See ISupplicantStaIface.hal for documentation */ 1190 private boolean setCountryCode(byte[/* 2 */] code) { 1191 synchronized (mLock) { 1192 final String methodStr = "setCountryCode"; 1193 if (DBG) Log.i(TAG, methodStr); 1194 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1195 try { 1196 SupplicantStatus status = mISupplicantStaIface.setCountryCode(code); 1197 return checkStatusAndLogFailure(status, methodStr); 1198 } catch (RemoteException e) { 1199 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1200 supplicantServiceDiedHandler(); 1201 return false; 1202 } 1203 } 1204 } 1205 1206 /** 1207 * Start WPS pin registrar operation with the specified peer and pin. 1208 * 1209 * @param bssidStr BSSID of the peer. 1210 * @param pin Pin to be used. 1211 * @return true if request is sent successfully, false otherwise. 1212 */ 1213 public boolean startWpsRegistrar(String bssidStr, String pin) { 1214 return startWpsRegistrar(NativeUtil.macAddressToByteArray(bssidStr), pin); 1215 } 1216 1217 /** See ISupplicantStaIface.hal for documentation */ 1218 private boolean startWpsRegistrar(byte[/* 6 */] bssid, String pin) { 1219 synchronized (mLock) { 1220 final String methodStr = "startWpsRegistrar"; 1221 if (DBG) Log.i(TAG, methodStr); 1222 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1223 try { 1224 SupplicantStatus status = mISupplicantStaIface.startWpsRegistrar(bssid, pin); 1225 return checkStatusAndLogFailure(status, methodStr); 1226 } catch (RemoteException e) { 1227 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1228 supplicantServiceDiedHandler(); 1229 return false; 1230 } 1231 } 1232 } 1233 1234 /** 1235 * Start WPS pin display operation with the specified peer. 1236 * 1237 * @param bssidStr BSSID of the peer. 1238 * @return true if request is sent successfully, false otherwise. 1239 */ 1240 public boolean startWpsPbc(String bssidStr) { 1241 return startWpsPbc(NativeUtil.macAddressToByteArray(bssidStr)); 1242 } 1243 1244 /** See ISupplicantStaIface.hal for documentation */ 1245 private boolean startWpsPbc(byte[/* 6 */] bssid) { 1246 synchronized (mLock) { 1247 final String methodStr = "startWpsPbc"; 1248 if (DBG) Log.i(TAG, methodStr); 1249 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1250 try { 1251 SupplicantStatus status = mISupplicantStaIface.startWpsPbc(bssid); 1252 return checkStatusAndLogFailure(status, methodStr); 1253 } catch (RemoteException e) { 1254 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1255 supplicantServiceDiedHandler(); 1256 return false; 1257 } 1258 } 1259 } 1260 1261 /** 1262 * Start WPS pin keypad operation with the specified pin. 1263 * 1264 * @param pin Pin to be used. 1265 * @return true if request is sent successfully, false otherwise. 1266 */ 1267 public boolean startWpsPinKeypad(String pin) { 1268 synchronized (mLock) { 1269 final String methodStr = "startWpsPinKeypad"; 1270 if (DBG) Log.i(TAG, methodStr); 1271 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1272 try { 1273 SupplicantStatus status = mISupplicantStaIface.startWpsPinKeypad(pin); 1274 return checkStatusAndLogFailure(status, methodStr); 1275 } catch (RemoteException e) { 1276 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1277 supplicantServiceDiedHandler(); 1278 return false; 1279 } 1280 } 1281 } 1282 1283 /** 1284 * Start WPS pin display operation with the specified peer. 1285 * 1286 * @param bssidStr BSSID of the peer. 1287 * @return new pin generated on success, null otherwise. 1288 */ 1289 public String startWpsPinDisplay(String bssidStr) { 1290 return startWpsPinDisplay(NativeUtil.macAddressToByteArray(bssidStr)); 1291 } 1292 1293 /** See ISupplicantStaIface.hal for documentation */ 1294 private String startWpsPinDisplay(byte[/* 6 */] bssid) { 1295 synchronized (mLock) { 1296 final String methodStr = "startWpsPinDisplay"; 1297 if (DBG) Log.i(TAG, methodStr); 1298 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null; 1299 final Mutable<String> gotPin = new Mutable<>(); 1300 try { 1301 mISupplicantStaIface.startWpsPinDisplay(bssid, 1302 (SupplicantStatus status, String pin) -> { 1303 if (checkStatusAndLogFailure(status, methodStr)) { 1304 gotPin.value = pin; 1305 } 1306 }); 1307 } catch (RemoteException e) { 1308 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1309 supplicantServiceDiedHandler(); 1310 } 1311 return gotPin.value; 1312 } 1313 } 1314 1315 /** 1316 * Cancels any ongoing WPS requests. 1317 * 1318 * @return true if request is sent successfully, false otherwise. 1319 */ 1320 public boolean cancelWps() { 1321 synchronized (mLock) { 1322 final String methodStr = "cancelWps"; 1323 if (DBG) Log.i(TAG, methodStr); 1324 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1325 try { 1326 SupplicantStatus status = mISupplicantStaIface.cancelWps(); 1327 return checkStatusAndLogFailure(status, methodStr); 1328 } catch (RemoteException e) { 1329 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1330 supplicantServiceDiedHandler(); 1331 return false; 1332 } 1333 } 1334 } 1335 1336 /** 1337 * Sets whether to use external sim for SIM/USIM processing. 1338 * 1339 * @param useExternalSim true to enable, false otherwise. 1340 * @return true if request is sent successfully, false otherwise. 1341 */ 1342 public boolean setExternalSim(boolean useExternalSim) { 1343 synchronized (mLock) { 1344 final String methodStr = "setExternalSim"; 1345 if (DBG) Log.i(TAG, methodStr); 1346 if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false; 1347 try { 1348 SupplicantStatus status = mISupplicantStaIface.setExternalSim(useExternalSim); 1349 return checkStatusAndLogFailure(status, methodStr); 1350 } catch (RemoteException e) { 1351 Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e); 1352 supplicantServiceDiedHandler(); 1353 return false; 1354 } 1355 } 1356 } 1357 1358 public static final int LOG_LEVEL_EXCESSIVE = ISupplicant.DebugLevel.EXCESSIVE; 1359 public static final int LOG_LEVEL_MSGDUMP = ISupplicant.DebugLevel.MSGDUMP; 1360 public static final int LOG_LEVEL_DEBUG = ISupplicant.DebugLevel.DEBUG; 1361 public static final int LOG_LEVEL_INFO = ISupplicant.DebugLevel.INFO; 1362 public static final int LOG_LEVEL_WARNING = ISupplicant.DebugLevel.WARNING; 1363 public static final int LOG_LEVEL_ERROR = ISupplicant.DebugLevel.ERROR; 1364 /** 1365 * Set the debug log level for wpa_supplicant 1366 * @param level One of the above {@link #LOG_LEVEL_EXCESSIVE} - {@link #LOG_LEVEL_ERROR} value. 1367 * @return true if request is sent successfully, false otherwise. 1368 */ 1369 public boolean setLogLevel(int level) { 1370 return setDebugParams(level, false, false); 1371 } 1372 1373 /** See ISupplicant.hal for documentation */ 1374 private boolean setDebugParams(int level, boolean showTimestamp, boolean showKeys) { 1375 synchronized (mLock) { 1376 final String methodStr = "setDebugParams"; 1377 if (DBG) Log.i(TAG, methodStr); 1378 if (!checkSupplicantAndLogFailure(methodStr)) return false; 1379 try { 1380 SupplicantStatus status = 1381 mISupplicant.setDebugParams(level, showTimestamp, showKeys); 1382 return checkStatusAndLogFailure(status, methodStr); 1383 } catch (RemoteException e) { 1384 Log.e(TAG, "ISupplicant." + methodStr + ": exception:" + e); 1385 supplicantServiceDiedHandler(); 1386 return false; 1387 } 1388 } 1389 } 1390 1391 /** 1392 * Set concurrency priority between P2P & STA operations. 1393 * 1394 * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations, 1395 * false otherwise. 1396 * @return true if request is sent successfully, false otherwise. 1397 */ 1398 public boolean setConcurrencyPriority(boolean isStaHigherPriority) { 1399 if (isStaHigherPriority) { 1400 return setConcurrencyPriority(IfaceType.STA); 1401 } else { 1402 return setConcurrencyPriority(IfaceType.P2P); 1403 } 1404 } 1405 1406 /** See ISupplicant.hal for documentation */ 1407 private boolean setConcurrencyPriority(int type) { 1408 synchronized (mLock) { 1409 final String methodStr = "setConcurrencyPriority"; 1410 if (DBG) Log.i(TAG, methodStr); 1411 if (!checkSupplicantAndLogFailure(methodStr)) return false; 1412 try { 1413 SupplicantStatus status = mISupplicant.setConcurrencyPriority(type); 1414 return checkStatusAndLogFailure(status, methodStr); 1415 } catch (RemoteException e) { 1416 Log.e(TAG, "ISupplicant." + methodStr + ": exception:" + e); 1417 supplicantServiceDiedHandler(); 1418 return false; 1419 } 1420 } 1421 } 1422 1423 /** 1424 * Returns false if Supplicant is null, and logs failure to call methodStr 1425 */ 1426 private boolean checkSupplicantAndLogFailure(final String methodStr) { 1427 if (DBG) Log.i(TAG, methodStr); 1428 if (mISupplicant == null) { 1429 Log.e(TAG, "Can't call " + methodStr + ", ISupplicant is null"); 1430 return false; 1431 } 1432 return true; 1433 } 1434 1435 /** 1436 * Returns false if SupplicantStaIface is null, and logs failure to call methodStr 1437 */ 1438 private boolean checkSupplicantStaIfaceAndLogFailure(final String methodStr) { 1439 if (DBG) Log.i(TAG, methodStr); 1440 if (mISupplicantStaIface == null) { 1441 Log.e(TAG, "Can't call " + methodStr + ", ISupplicantStaIface is null"); 1442 return false; 1443 } 1444 return true; 1445 } 1446 1447 /** 1448 * Returns true if provided status code is SUCCESS, logs debug message and returns false 1449 * otherwise 1450 */ 1451 private static boolean checkStatusAndLogFailure(SupplicantStatus status, 1452 final String methodStr) { 1453 if (DBG) Log.i(TAG, methodStr); 1454 if (status.code != SupplicantStatusCode.SUCCESS) { 1455 Log.e(TAG, methodStr + " failed: " + supplicantStatusCodeToString(status.code) + ", " 1456 + status.debugMessage); 1457 return false; 1458 } 1459 return true; 1460 } 1461 1462 /** 1463 * Converts SupplicantStatus code values to strings for debug logging 1464 * TODO(b/34811152) Remove this, or make it more break resistance 1465 */ 1466 public static String supplicantStatusCodeToString(int code) { 1467 switch (code) { 1468 case 0: 1469 return "SUCCESS"; 1470 case 1: 1471 return "FAILURE_UNKNOWN"; 1472 case 2: 1473 return "FAILURE_ARGS_INVALID"; 1474 case 3: 1475 return "FAILURE_IFACE_INVALID"; 1476 case 4: 1477 return "FAILURE_IFACE_UNKNOWN"; 1478 case 5: 1479 return "FAILURE_IFACE_EXISTS"; 1480 case 6: 1481 return "FAILURE_IFACE_DISABLED"; 1482 case 7: 1483 return "FAILURE_IFACE_NOT_DISCONNECTED"; 1484 case 8: 1485 return "FAILURE_NETWORK_INVALID"; 1486 case 9: 1487 return "FAILURE_NETWORK_UNKNOWN"; 1488 default: 1489 return "??? UNKNOWN_CODE"; 1490 } 1491 } 1492 1493 1494 /** 1495 * Converts the Wps config method string to the equivalent enum value. 1496 */ 1497 private static short stringToWpsConfigMethod(String configMethod) { 1498 switch (configMethod) { 1499 case "usba": 1500 return WpsConfigMethods.USBA; 1501 case "ethernet": 1502 return WpsConfigMethods.ETHERNET; 1503 case "label": 1504 return WpsConfigMethods.LABEL; 1505 case "display": 1506 return WpsConfigMethods.DISPLAY; 1507 case "int_nfc_token": 1508 return WpsConfigMethods.INT_NFC_TOKEN; 1509 case "ext_nfc_token": 1510 return WpsConfigMethods.EXT_NFC_TOKEN; 1511 case "nfc_interface": 1512 return WpsConfigMethods.NFC_INTERFACE; 1513 case "push_button": 1514 return WpsConfigMethods.PUSHBUTTON; 1515 case "keypad": 1516 return WpsConfigMethods.KEYPAD; 1517 case "virtual_push_button": 1518 return WpsConfigMethods.VIRT_PUSHBUTTON; 1519 case "physical_push_button": 1520 return WpsConfigMethods.PHY_PUSHBUTTON; 1521 case "p2ps": 1522 return WpsConfigMethods.P2PS; 1523 case "virtual_display": 1524 return WpsConfigMethods.VIRT_DISPLAY; 1525 case "physical_display": 1526 return WpsConfigMethods.PHY_DISPLAY; 1527 default: 1528 throw new IllegalArgumentException( 1529 "Invalid WPS config method: " + configMethod); 1530 } 1531 } 1532 1533 /** 1534 * Converts the supplicant state received from HIDL to the equivalent framework state. 1535 */ 1536 private static SupplicantState supplicantHidlStateToFrameworkState(int state) { 1537 switch (state) { 1538 case ISupplicantStaIfaceCallback.State.DISCONNECTED: 1539 return SupplicantState.DISCONNECTED; 1540 case ISupplicantStaIfaceCallback.State.IFACE_DISABLED: 1541 return SupplicantState.INTERFACE_DISABLED; 1542 case ISupplicantStaIfaceCallback.State.INACTIVE: 1543 return SupplicantState.INACTIVE; 1544 case ISupplicantStaIfaceCallback.State.SCANNING: 1545 return SupplicantState.SCANNING; 1546 case ISupplicantStaIfaceCallback.State.AUTHENTICATING: 1547 return SupplicantState.AUTHENTICATING; 1548 case ISupplicantStaIfaceCallback.State.ASSOCIATING: 1549 return SupplicantState.ASSOCIATING; 1550 case ISupplicantStaIfaceCallback.State.ASSOCIATED: 1551 return SupplicantState.ASSOCIATED; 1552 case ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE: 1553 return SupplicantState.FOUR_WAY_HANDSHAKE; 1554 case ISupplicantStaIfaceCallback.State.GROUP_HANDSHAKE: 1555 return SupplicantState.GROUP_HANDSHAKE; 1556 case ISupplicantStaIfaceCallback.State.COMPLETED: 1557 return SupplicantState.COMPLETED; 1558 default: 1559 throw new IllegalArgumentException("Invalid state: " + state); 1560 } 1561 } 1562 1563 private static class Mutable<E> { 1564 public E value; 1565 1566 Mutable() { 1567 value = null; 1568 } 1569 1570 Mutable(E value) { 1571 this.value = value; 1572 } 1573 } 1574 1575 private class SupplicantStaIfaceHalCallback extends ISupplicantStaIfaceCallback.Stub { 1576 /** 1577 * Parses the provided payload into an ANQP element. 1578 * 1579 * @param infoID Element type. 1580 * @param payload Raw payload bytes. 1581 * @return AnqpElement instance on success, null on failure. 1582 */ 1583 private ANQPElement parseAnqpElement(Constants.ANQPElementType infoID, 1584 ArrayList<Byte> payload) { 1585 try { 1586 return Constants.getANQPElementID(infoID) != null 1587 ? ANQPParser.parseElement( 1588 infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload))) 1589 : ANQPParser.parseHS20Element( 1590 infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload))); 1591 } catch (IOException | BufferUnderflowException e) { 1592 Log.e(TAG, "Failed parsing ANQP element payload: " + infoID, e); 1593 return null; 1594 } 1595 } 1596 1597 /** 1598 * Parse the ANQP element data and add to the provided elements map if successful. 1599 * 1600 * @param elementsMap Map to add the parsed out element to. 1601 * @param infoID Element type. 1602 * @param payload Raw payload bytes. 1603 */ 1604 private void addAnqpElementToMap(Map<Constants.ANQPElementType, ANQPElement> elementsMap, 1605 Constants.ANQPElementType infoID, 1606 ArrayList<Byte> payload) { 1607 if (payload == null || payload.isEmpty()) return; 1608 ANQPElement element = parseAnqpElement(infoID, payload); 1609 if (element != null) { 1610 elementsMap.put(infoID, element); 1611 } 1612 } 1613 1614 /** 1615 * Helper utility to convert the bssid bytes to long. 1616 */ 1617 private Long toLongBssid(byte[] bssidBytes) { 1618 try { 1619 return ByteBufferReader.readInteger( 1620 ByteBuffer.wrap(bssidBytes), ByteOrder.BIG_ENDIAN, bssidBytes.length); 1621 } catch (BufferUnderflowException | IllegalArgumentException e) { 1622 return 0L; 1623 } 1624 } 1625 1626 @Override 1627 public void onNetworkAdded(int id) { 1628 } 1629 1630 @Override 1631 public void onNetworkRemoved(int id) { 1632 } 1633 1634 @Override 1635 public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, 1636 ArrayList<Byte> ssid) { 1637 SupplicantState newSupplicantState = supplicantHidlStateToFrameworkState(newState); 1638 WifiSsid wifiSsid = 1639 WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid)); 1640 String bssidStr = NativeUtil.macAddressFromByteArray(bssid); 1641 mWifiMonitor.broadcastSupplicantStateChangeEvent( 1642 mIfaceName, mFrameworkNetworkId, wifiSsid, bssidStr, newSupplicantState); 1643 if (newSupplicantState == SupplicantState.ASSOCIATED) { 1644 mWifiMonitor.broadcastAssociationSuccesfulEvent(mIfaceName, bssidStr); 1645 } else if (newSupplicantState == SupplicantState.COMPLETED) { 1646 mWifiMonitor.broadcastNetworkConnectionEvent( 1647 mIfaceName, mFrameworkNetworkId, bssidStr); 1648 } 1649 } 1650 1651 @Override 1652 public void onAnqpQueryDone(byte[/* 6 */] bssid, 1653 ISupplicantStaIfaceCallback.AnqpData data, 1654 ISupplicantStaIfaceCallback.Hs20AnqpData hs20Data) { 1655 Map<Constants.ANQPElementType, ANQPElement> elementsMap = new HashMap<>(); 1656 addAnqpElementToMap(elementsMap, ANQPVenueName, data.venueName); 1657 addAnqpElementToMap(elementsMap, ANQPRoamingConsortium, data.roamingConsortium); 1658 addAnqpElementToMap(elementsMap, ANQPIPAddrAvailability, data.ipAddrTypeAvailability); 1659 addAnqpElementToMap(elementsMap, ANQPNAIRealm, data.naiRealm); 1660 addAnqpElementToMap(elementsMap, ANQP3GPPNetwork, data.anqp3gppCellularNetwork); 1661 addAnqpElementToMap(elementsMap, ANQPDomName, data.domainName); 1662 addAnqpElementToMap(elementsMap, HSFriendlyName, hs20Data.operatorFriendlyName); 1663 addAnqpElementToMap(elementsMap, HSWANMetrics, hs20Data.wanMetrics); 1664 addAnqpElementToMap(elementsMap, HSConnCapability, hs20Data.connectionCapability); 1665 addAnqpElementToMap(elementsMap, HSOSUProviders, hs20Data.osuProvidersList); 1666 mWifiMonitor.broadcastAnqpDoneEvent( 1667 mIfaceName, new AnqpEvent(toLongBssid(bssid), elementsMap)); 1668 } 1669 1670 @Override 1671 public void onHs20IconQueryDone(byte[/* 6 */] bssid, String fileName, 1672 ArrayList<Byte> data) { 1673 mWifiMonitor.broadcastIconDoneEvent( 1674 mIfaceName, 1675 new IconEvent(toLongBssid(bssid), fileName, data.size(), 1676 NativeUtil.byteArrayFromArrayList(data))); 1677 } 1678 1679 @Override 1680 public void onHs20SubscriptionRemediation(byte[/* 6 */] bssid, byte osuMethod, String url) { 1681 mWifiMonitor.broadcastWnmEvent( 1682 mIfaceName, new WnmData(toLongBssid(bssid), url, osuMethod)); 1683 } 1684 1685 @Override 1686 public void onHs20DeauthImminentNotice(byte[/* 6 */] bssid, int reasonCode, 1687 int reAuthDelayInSec, String url) { 1688 mWifiMonitor.broadcastWnmEvent( 1689 mIfaceName, 1690 new WnmData(toLongBssid(bssid), url, reasonCode == WnmData.ESS, 1691 reAuthDelayInSec)); 1692 } 1693 1694 @Override 1695 public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, int reasonCode) { 1696 } 1697 1698 @Override 1699 public void onAssociationRejected(byte[/* 6 */] bssid, int statusCode) { 1700 } 1701 1702 @Override 1703 public void onAuthenticationTimeout(byte[/* 6 */] bssid) { 1704 } 1705 1706 @Override 1707 public void onEapFailure() { 1708 } 1709 1710 @Override 1711 public void onWpsEventSuccess() { 1712 } 1713 1714 @Override 1715 public void onWpsEventFail(byte[/* 6 */] bssid, short configError, short errorInd) { 1716 } 1717 1718 @Override 1719 public void onWpsEventPbcOverlap() { 1720 } 1721 1722 @Override 1723 public void onExtRadioWorkStart(int id) { 1724 } 1725 1726 @Override 1727 public void onExtRadioWorkTimeout(int id) { 1728 } 1729 } 1730 1731 private void logd(String s) { 1732 Log.d(TAG, s); 1733 } 1734 1735 private void logi(String s) { 1736 Log.i(TAG, s); 1737 } 1738 1739 private void loge(String s) { 1740 Log.e(TAG, s); 1741 } 1742} 1743