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 17 package com.googlecode.android_scripting.facade.wifi; 18 19 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 20 21 import android.app.Service; 22 import android.content.BroadcastReceiver; 23 import android.content.ContentResolver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.net.ConnectivityManager; 28 import android.net.ConnectivityManager.NetworkCallback; 29 import android.net.DhcpInfo; 30 import android.net.MacAddress; 31 import android.net.Network; 32 import android.net.NetworkInfo; 33 import android.net.NetworkInfo.DetailedState; 34 import android.net.NetworkRequest; 35 import android.net.NetworkSpecifier; 36 import android.net.Uri; 37 import android.net.wifi.EasyConnectStatusCallback; 38 import android.net.wifi.ScanResult; 39 import android.net.wifi.WifiActivityEnergyInfo; 40 import android.net.wifi.WifiConfiguration; 41 import android.net.wifi.WifiConfiguration.AuthAlgorithm; 42 import android.net.wifi.WifiConfiguration.KeyMgmt; 43 import android.net.wifi.WifiEnterpriseConfig; 44 import android.net.wifi.WifiInfo; 45 import android.net.wifi.WifiManager; 46 import android.net.wifi.WifiManager.NetworkRequestMatchCallback; 47 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback; 48 import android.net.wifi.WifiManager.WifiLock; 49 import android.net.wifi.WifiNetworkSpecifier; 50 import android.net.wifi.WifiNetworkSuggestion; 51 import android.net.wifi.WifiSsid; 52 import android.net.wifi.WpsInfo; 53 import android.net.wifi.hotspot2.ConfigParser; 54 import android.net.wifi.hotspot2.OsuProvider; 55 import android.net.wifi.hotspot2.PasspointConfiguration; 56 import android.net.wifi.hotspot2.ProvisioningCallback; 57 import android.os.Bundle; 58 import android.os.Handler; 59 import android.os.HandlerThread; 60 import android.os.PatternMatcher; 61 import android.provider.Settings.Global; 62 import android.provider.Settings.SettingNotFoundException; 63 import android.text.TextUtils; 64 import android.util.Base64; 65 import android.util.SparseArray; 66 67 import com.android.internal.annotations.GuardedBy; 68 69 import com.googlecode.android_scripting.Log; 70 import com.googlecode.android_scripting.facade.EventFacade; 71 import com.googlecode.android_scripting.facade.FacadeManager; 72 import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 73 import com.googlecode.android_scripting.rpc.Rpc; 74 import com.googlecode.android_scripting.rpc.RpcOptional; 75 import com.googlecode.android_scripting.rpc.RpcParameter; 76 77 import org.json.JSONArray; 78 import org.json.JSONException; 79 import org.json.JSONObject; 80 81 import java.io.ByteArrayInputStream; 82 import java.io.ByteArrayOutputStream; 83 import java.io.IOException; 84 import java.io.InputStream; 85 import java.io.ObjectOutput; 86 import java.io.ObjectOutputStream; 87 import java.nio.charset.StandardCharsets; 88 import java.security.GeneralSecurityException; 89 import java.security.KeyFactory; 90 import java.security.NoSuchAlgorithmException; 91 import java.security.PrivateKey; 92 import java.security.PublicKey; 93 import java.security.cert.CertificateException; 94 import java.security.cert.CertificateFactory; 95 import java.security.cert.X509Certificate; 96 import java.security.spec.InvalidKeySpecException; 97 import java.security.spec.PKCS8EncodedKeySpec; 98 import java.security.spec.X509EncodedKeySpec; 99 import java.util.ArrayList; 100 import java.util.Arrays; 101 import java.util.HashMap; 102 import java.util.Iterator; 103 import java.util.List; 104 import java.util.Map; 105 106 /** 107 * WifiManager functions. 108 */ 109 // TODO: make methods handle various wifi states properly 110 // e.g. wifi connection result will be null when flight mode is on 111 public class WifiManagerFacade extends RpcReceiver { 112 private final static String mEventType = "WifiManager"; 113 // MIME type for passpoint config. 114 private final static String TYPE_WIFICONFIG = "application/x-wifi-config"; 115 private final Service mService; 116 private final WifiManager mWifi; 117 private final ConnectivityManager mCm; 118 private final EventFacade mEventFacade; 119 120 private final IntentFilter mScanFilter; 121 private final IntentFilter mStateChangeFilter; 122 private final IntentFilter mTetherFilter; 123 private final IntentFilter mNetworkSuggestionStateChangeFilter; 124 private final WifiScanReceiver mScanResultsAvailableReceiver; 125 private final WifiStateChangeReceiver mStateChangeReceiver; 126 private final WifiNetworkSuggestionStateChangeReceiver mNetworkSuggestionStateChangeReceiver; 127 private final HandlerThread mCallbackHandlerThread; 128 private final Object mCallbackLock = new Object(); 129 private final Map<NetworkSpecifier, NetworkCallback> mNetworkCallbacks = new HashMap<>(); 130 private boolean mTrackingWifiStateChange; 131 private boolean mTrackingTetherStateChange; 132 private boolean mTrackingNetworkSuggestionStateChange; 133 @GuardedBy("mCallbackLock") 134 private NetworkRequestUserSelectionCallback mNetworkRequestUserSelectionCallback; 135 private final SparseArray<SoftApCallbackImp> mSoftapCallbacks; 136 137 private final BroadcastReceiver mTetherStateReceiver = new BroadcastReceiver() { 138 @Override 139 public void onReceive(Context context, Intent intent) { 140 String action = intent.getAction(); 141 if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(action)) { 142 Log.d("Wifi AP state changed."); 143 int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 144 WifiManager.WIFI_AP_STATE_FAILED); 145 if (state == WifiManager.WIFI_AP_STATE_ENABLED) { 146 mEventFacade.postEvent("WifiManagerApEnabled", null); 147 } else if (state == WifiManager.WIFI_AP_STATE_DISABLED) { 148 mEventFacade.postEvent("WifiManagerApDisabled", null); 149 } 150 } else if (ConnectivityManager.ACTION_TETHER_STATE_CHANGED.equals(action)) { 151 Log.d("Tether state changed."); 152 ArrayList<String> available = intent.getStringArrayListExtra( 153 ConnectivityManager.EXTRA_AVAILABLE_TETHER); 154 ArrayList<String> active = intent.getStringArrayListExtra( 155 ConnectivityManager.EXTRA_ACTIVE_TETHER); 156 ArrayList<String> errored = intent.getStringArrayListExtra( 157 ConnectivityManager.EXTRA_ERRORED_TETHER); 158 Bundle msg = new Bundle(); 159 msg.putStringArrayList("AVAILABLE_TETHER", available); 160 msg.putStringArrayList("ACTIVE_TETHER", active); 161 msg.putStringArrayList("ERRORED_TETHER", errored); 162 mEventFacade.postEvent("TetherStateChanged", msg); 163 } 164 } 165 }; 166 167 private final NetworkRequestMatchCallback mNetworkRequestMatchCallback = 168 new NetworkRequestMatchCallback() { 169 private static final String EVENT_TAG = mEventType + "NetworkRequestMatchCallback"; 170 171 @Override 172 public void onUserSelectionCallbackRegistration( 173 NetworkRequestUserSelectionCallback userSelectionCallback) { 174 synchronized (mCallbackLock) { 175 mNetworkRequestUserSelectionCallback = userSelectionCallback; 176 } 177 } 178 179 @Override 180 public void onAbort() { 181 mEventFacade.postEvent(EVENT_TAG + "OnAbort", null); 182 } 183 184 @Override 185 public void onMatch(List<ScanResult> scanResults) { 186 mEventFacade.postEvent(EVENT_TAG + "OnMatch", scanResults); 187 } 188 189 @Override 190 public void onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration) { 191 mEventFacade.postEvent(EVENT_TAG + "OnUserSelectionConnectSuccess", 192 wifiConfiguration); 193 } 194 195 @Override 196 public void onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration) { 197 mEventFacade.postEvent(EVENT_TAG + "OnUserSelectionConnectFailure", 198 wifiConfiguration); 199 } 200 }; 201 202 private final class NetworkCallbackImpl extends NetworkCallback { 203 private static final String EVENT_TAG = mEventType + "NetworkCallback"; 204 205 @Override 206 public void onAvailable(Network network) { 207 mEventFacade.postEvent(EVENT_TAG + "OnAvailable", mWifi.getConnectionInfo()); 208 } 209 210 @Override 211 public void onUnavailable() { 212 mEventFacade.postEvent(EVENT_TAG + "OnUnavailable", null); 213 } 214 215 @Override 216 public void onLost(Network network) { 217 mEventFacade.postEvent(EVENT_TAG + "OnLost", null); 218 } 219 }; 220 221 private static class SoftApCallbackImp implements WifiManager.SoftApCallback { 222 // A monotonic increasing counter for softap callback ids. 223 private static int sCount = 0; 224 225 private final int mId; 226 private final EventFacade mEventFacade; 227 private final String mEventStr; 228 229 SoftApCallbackImp(EventFacade eventFacade) { 230 sCount++; 231 mId = sCount; 232 mEventFacade = eventFacade; 233 mEventStr = mEventType + "SoftApCallback-" + mId + "-"; 234 } 235 236 @Override 237 public void onStateChanged(int state, int failureReason) { 238 Bundle msg = new Bundle(); 239 msg.putInt("State", state); 240 msg.putInt("FailureReason", failureReason); 241 mEventFacade.postEvent(mEventStr + "OnStateChanged", msg); 242 } 243 244 @Override 245 public void onNumClientsChanged(int numClients) { 246 Bundle msg = new Bundle(); 247 msg.putInt("NumClients", numClients); 248 mEventFacade.postEvent(mEventStr + "OnNumClientsChanged", msg); 249 } 250 }; 251 252 private WifiLock mLock = null; 253 private boolean mIsConnected = false; 254 255 public WifiManagerFacade(FacadeManager manager) { 256 super(manager); 257 mService = manager.getService(); 258 mWifi = (WifiManager) mService.getSystemService(Context.WIFI_SERVICE); 259 mCm = (ConnectivityManager) mService.getSystemService(Context.CONNECTIVITY_SERVICE); 260 mEventFacade = manager.getReceiver(EventFacade.class); 261 mCallbackHandlerThread = new HandlerThread("WifiManagerFacade"); 262 263 mScanFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 264 mStateChangeFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION); 265 mStateChangeFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); 266 mStateChangeFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 267 mStateChangeFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 268 mStateChangeFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY - 1); 269 270 mTetherFilter = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 271 mTetherFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); 272 273 mNetworkSuggestionStateChangeFilter = new IntentFilter( 274 WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION); 275 276 mScanResultsAvailableReceiver = new WifiScanReceiver(mEventFacade); 277 mStateChangeReceiver = new WifiStateChangeReceiver(); 278 mNetworkSuggestionStateChangeReceiver = new WifiNetworkSuggestionStateChangeReceiver(); 279 mTrackingWifiStateChange = false; 280 mTrackingTetherStateChange = false; 281 mTrackingNetworkSuggestionStateChange = false; 282 mCallbackHandlerThread.start(); 283 mSoftapCallbacks = new SparseArray<>(); 284 } 285 286 private void makeLock(int wifiMode) { 287 if (mLock == null) { 288 mLock = mWifi.createWifiLock(wifiMode, "sl4a"); 289 mLock.acquire(); 290 } 291 } 292 293 /** 294 * Handle Broadcast receiver for Scan Result 295 * 296 * @parm eventFacade Object of EventFacade 297 */ 298 class WifiScanReceiver extends BroadcastReceiver { 299 private final EventFacade mEventFacade; 300 301 WifiScanReceiver(EventFacade eventFacade) { 302 mEventFacade = eventFacade; 303 } 304 305 @Override 306 public void onReceive(Context c, Intent intent) { 307 String action = intent.getAction(); 308 if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { 309 if (!intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)) { 310 Log.w("Wifi connection scan failed, ignoring."); 311 mEventFacade.postEvent(mEventType + "ScanFailure", null); 312 } else { 313 Bundle mResults = new Bundle(); 314 Log.d("Wifi connection scan finished, results available."); 315 mResults.putLong("Timestamp", System.currentTimeMillis() / 1000); 316 mEventFacade.postEvent(mEventType + "ScanResultsAvailable", mResults); 317 } 318 mService.unregisterReceiver(mScanResultsAvailableReceiver); 319 } 320 } 321 } 322 323 class WifiActionListener implements WifiManager.ActionListener { 324 private final EventFacade mEventFacade; 325 private final String TAG; 326 327 public WifiActionListener(EventFacade eventFacade, String tag) { 328 mEventFacade = eventFacade; 329 this.TAG = tag; 330 } 331 332 @Override 333 public void onSuccess() { 334 Log.d("WifiActionListener onSuccess called for " + mEventType + TAG + "OnSuccess"); 335 mEventFacade.postEvent(mEventType + TAG + "OnSuccess", null); 336 } 337 338 @Override 339 public void onFailure(int reason) { 340 Log.d("WifiActionListener onFailure called for" + mEventType); 341 Bundle msg = new Bundle(); 342 msg.putInt("reason", reason); 343 mEventFacade.postEvent(mEventType + TAG + "OnFailure", msg); 344 } 345 } 346 347 public class WifiStateChangeReceiver extends BroadcastReceiver { 348 String mCachedWifiInfo = ""; 349 350 @Override 351 public void onReceive(Context context, Intent intent) { 352 String action = intent.getAction(); 353 if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 354 Log.d("Wifi network state changed."); 355 NetworkInfo nInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 356 Log.d("NetworkInfo " + nInfo); 357 // If network info is of type wifi, send wifi events. 358 if (nInfo.getType() == ConnectivityManager.TYPE_WIFI) { 359 if (nInfo.getDetailedState().equals(DetailedState.CONNECTED)) { 360 WifiInfo wInfo = mWifi.getConnectionInfo(); 361 String bssid = wInfo.getBSSID(); 362 if (bssid != null && !mCachedWifiInfo.equals(wInfo.toString())) { 363 Log.d("WifiNetworkConnected"); 364 mEventFacade.postEvent("WifiNetworkConnected", wInfo); 365 } 366 mCachedWifiInfo = wInfo.toString(); 367 } else { 368 if (nInfo.getDetailedState().equals(DetailedState.DISCONNECTED)) { 369 if (!mCachedWifiInfo.equals("")) { 370 mCachedWifiInfo = ""; 371 mEventFacade.postEvent("WifiNetworkDisconnected", null); 372 } 373 } 374 } 375 } 376 } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) { 377 Log.d("Supplicant connection state changed."); 378 mIsConnected = intent 379 .getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false); 380 Bundle msg = new Bundle(); 381 msg.putBoolean("Connected", mIsConnected); 382 mEventFacade.postEvent("SupplicantConnectionChanged", msg); 383 } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 384 int state = intent.getIntExtra( 385 WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED); 386 Log.d("Wifi state changed to " + state); 387 boolean enabled; 388 if (state == WifiManager.WIFI_STATE_DISABLED) { 389 enabled = false; 390 } else if (state == WifiManager.WIFI_STATE_ENABLED) { 391 enabled = true; 392 } else { 393 // we only care about enabled/disabled. 394 Log.v("Ignoring intermediate wifi state change event..."); 395 return; 396 } 397 Bundle msg = new Bundle(); 398 msg.putBoolean("enabled", enabled); 399 mEventFacade.postEvent("WifiStateChanged", msg); 400 } 401 } 402 } 403 404 public class WifiNetworkSuggestionStateChangeReceiver extends BroadcastReceiver { 405 @Override 406 public void onReceive(Context context, Intent intent) { 407 String action = intent.getAction(); 408 if (action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) { 409 WifiNetworkSuggestion networkSuggestion = 410 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_SUGGESTION); 411 mEventFacade.postEvent( 412 "WifiNetworkSuggestionPostConnection", 413 networkSuggestion.wifiConfiguration.SSID); 414 } 415 } 416 } 417 418 public class WifiWpsCallback extends WifiManager.WpsCallback { 419 private static final String tag = "WifiWps"; 420 421 @Override 422 public void onStarted(String pin) { 423 Bundle msg = new Bundle(); 424 msg.putString("pin", pin); 425 mEventFacade.postEvent(tag + "OnStarted", msg); 426 } 427 428 @Override 429 public void onSucceeded() { 430 Log.d("Wps op succeeded"); 431 mEventFacade.postEvent(tag + "OnSucceeded", null); 432 } 433 434 @Override 435 public void onFailed(int reason) { 436 Bundle msg = new Bundle(); 437 msg.putInt("reason", reason); 438 mEventFacade.postEvent(tag + "OnFailed", msg); 439 } 440 } 441 442 private void applyingkeyMgmt(WifiConfiguration config, ScanResult result) { 443 if (result.capabilities.contains("WEP")) { 444 config.allowedKeyManagement.set(KeyMgmt.NONE); 445 config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN); 446 config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED); 447 } else if (result.capabilities.contains("PSK")) { 448 config.allowedKeyManagement.set(KeyMgmt.WPA_PSK); 449 } else if (result.capabilities.contains("EAP")) { 450 // this is probably wrong, as we don't have a way to enter the enterprise config 451 config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); 452 config.allowedKeyManagement.set(KeyMgmt.IEEE8021X); 453 } else { 454 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 455 } 456 } 457 458 private WifiConfiguration genWifiConfig(JSONObject j) throws JSONException { 459 if (j == null) { 460 return null; 461 } 462 WifiConfiguration config = new WifiConfiguration(); 463 if (j.has("SSID")) { 464 config.SSID = "\"" + j.getString("SSID") + "\""; 465 } else if (j.has("ssid")) { 466 config.SSID = "\"" + j.getString("ssid") + "\""; 467 } 468 if (j.has("password")) { 469 String security; 470 471 // Check if new security type SAE (WPA3) is present. Default to PSK 472 if (j.has("security")) { 473 if (TextUtils.equals(j.getString("security"), "SAE")) { 474 config.allowedKeyManagement.set(KeyMgmt.SAE); 475 config.requirePMF = true; 476 } else { 477 config.allowedKeyManagement.set(KeyMgmt.WPA_PSK); 478 } 479 } else { 480 config.allowedKeyManagement.set(KeyMgmt.WPA_PSK); 481 } 482 config.preSharedKey = "\"" + j.getString("password") + "\""; 483 } else if (j.has("preSharedKey")) { 484 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); 485 config.preSharedKey = j.getString("preSharedKey"); 486 } else { 487 if (j.has("security")) { 488 if (TextUtils.equals(j.getString("security"), "OWE")) { 489 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE); 490 config.requirePMF = true; 491 } else { 492 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 493 } 494 } else { 495 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 496 } 497 } 498 if (j.has("BSSID")) { 499 config.BSSID = j.getString("BSSID"); 500 } 501 if (j.has("hiddenSSID")) { 502 config.hiddenSSID = j.getBoolean("hiddenSSID"); 503 } 504 if (j.has("priority")) { 505 config.priority = j.getInt("priority"); 506 } 507 if (j.has("apBand")) { 508 config.apBand = j.getInt("apBand"); 509 } 510 if (j.has("wepKeys")) { 511 // Looks like we only support static WEP. 512 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 513 config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN); 514 config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED); 515 JSONArray keys = j.getJSONArray("wepKeys"); 516 String[] wepKeys = new String[keys.length()]; 517 for (int i = 0; i < keys.length(); i++) { 518 wepKeys[i] = keys.getString(i); 519 } 520 config.wepKeys = wepKeys; 521 } 522 if (j.has("wepTxKeyIndex")) { 523 config.wepTxKeyIndex = j.getInt("wepTxKeyIndex"); 524 } 525 if (j.has("meteredOverride")) { 526 config.meteredOverride = j.getInt("meteredOverride"); 527 } 528 if (j.has("macRand")) { 529 config.macRandomizationSetting = j.getInt("macRand"); 530 } 531 return config; 532 } 533 534 private WifiEnterpriseConfig genWifiEnterpriseConfig(JSONObject j) throws JSONException, 535 GeneralSecurityException { 536 WifiEnterpriseConfig eConfig = new WifiEnterpriseConfig(); 537 if (j.has(WifiEnterpriseConfig.EAP_KEY)) { 538 int eap = j.getInt(WifiEnterpriseConfig.EAP_KEY); 539 eConfig.setEapMethod(eap); 540 } 541 if (j.has(WifiEnterpriseConfig.PHASE2_KEY)) { 542 int p2Method = j.getInt(WifiEnterpriseConfig.PHASE2_KEY); 543 eConfig.setPhase2Method(p2Method); 544 } 545 if (j.has(WifiEnterpriseConfig.CA_CERT_KEY)) { 546 String certStr = j.getString(WifiEnterpriseConfig.CA_CERT_KEY); 547 Log.v("CA Cert String is " + certStr); 548 eConfig.setCaCertificate(strToX509Cert(certStr)); 549 } 550 if (j.has(WifiEnterpriseConfig.CLIENT_CERT_KEY) 551 && j.has(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY)) { 552 String certStr = j.getString(WifiEnterpriseConfig.CLIENT_CERT_KEY); 553 String keyStr = j.getString(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY); 554 Log.v("Client Cert String is " + certStr); 555 Log.v("Client Key String is " + keyStr); 556 X509Certificate cert = strToX509Cert(certStr); 557 PrivateKey privKey = strToPrivateKey(keyStr); 558 Log.v("Cert is " + cert); 559 Log.v("Private Key is " + privKey); 560 eConfig.setClientKeyEntry(privKey, cert); 561 } 562 if (j.has(WifiEnterpriseConfig.IDENTITY_KEY)) { 563 String identity = j.getString(WifiEnterpriseConfig.IDENTITY_KEY); 564 Log.v("Setting identity to " + identity); 565 eConfig.setIdentity(identity); 566 } 567 if (j.has(WifiEnterpriseConfig.PASSWORD_KEY)) { 568 String pwd = j.getString(WifiEnterpriseConfig.PASSWORD_KEY); 569 Log.v("Setting password to " + pwd); 570 eConfig.setPassword(pwd); 571 } 572 if (j.has(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY)) { 573 String altSub = j.getString(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY); 574 Log.v("Setting Alt Subject to " + altSub); 575 eConfig.setAltSubjectMatch(altSub); 576 } 577 if (j.has(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY)) { 578 String domSuffix = j.getString(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY); 579 Log.v("Setting Domain Suffix Match to " + domSuffix); 580 eConfig.setDomainSuffixMatch(domSuffix); 581 } 582 if (j.has(WifiEnterpriseConfig.REALM_KEY)) { 583 String realm = j.getString(WifiEnterpriseConfig.REALM_KEY); 584 Log.v("Setting Domain Suffix Match to " + realm); 585 eConfig.setRealm(realm); 586 } 587 return eConfig; 588 } 589 590 private WifiConfiguration genWifiConfigWithEnterpriseConfig(JSONObject j) throws JSONException, 591 GeneralSecurityException { 592 if (j == null) { 593 return null; 594 } 595 WifiConfiguration config = new WifiConfiguration(); 596 config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); 597 config.allowedKeyManagement.set(KeyMgmt.IEEE8021X); 598 599 if (j.has("security")) { 600 if (TextUtils.equals(j.getString("security"), "SUITE_B_192")) { 601 config.allowedKeyManagement.set(KeyMgmt.SUITE_B_192); 602 config.requirePMF = true; 603 } 604 } 605 606 if (j.has("SSID")) { 607 config.SSID = "\"" + j.getString("SSID") + "\""; 608 } else if (j.has("ssid")) { 609 config.SSID = "\"" + j.getString("ssid") + "\""; 610 } 611 if (j.has("FQDN")) { 612 config.FQDN = j.getString("FQDN"); 613 } 614 if (j.has("providerFriendlyName")) { 615 config.providerFriendlyName = j.getString("providerFriendlyName"); 616 } 617 if (j.has("roamingConsortiumIds")) { 618 JSONArray ids = j.getJSONArray("roamingConsortiumIds"); 619 long[] rIds = new long[ids.length()]; 620 for (int i = 0; i < ids.length(); i++) { 621 rIds[i] = ids.getLong(i); 622 } 623 config.roamingConsortiumIds = rIds; 624 } 625 config.enterpriseConfig = genWifiEnterpriseConfig(j); 626 return config; 627 } 628 629 private NetworkSpecifier genWifiNetworkSpecifier(JSONObject j) throws JSONException, 630 GeneralSecurityException { 631 if (j == null) { 632 return null; 633 } 634 WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder(); 635 if (j.has("SSID")) { 636 builder = builder.setSsid(j.getString("SSID")); 637 } else if (j.has("ssidPattern")) { 638 builder = builder.setSsidPattern( 639 new PatternMatcher(j.getString("ssidPattern"), 640 PatternMatcher.PATTERN_ADVANCED_GLOB)); 641 } 642 if (j.has("BSSID")) { 643 builder = builder.setBssid(MacAddress.fromString(j.getString("BSSID"))); 644 } else if (j.has("bssidPattern")) { 645 builder = builder.setBssidPattern( 646 MacAddress.fromString(j.getJSONArray("bssidPattern").getString(0)), 647 MacAddress.fromString(j.getJSONArray("bssidPattern").getString(1))); 648 } 649 if (j.has("hiddenSSID")) { 650 builder = builder.setIsHiddenSsid(j.getBoolean("hiddenSSID")); 651 } 652 if (j.has("isEnhancedOpen")) { 653 builder = builder.setIsEnhancedOpen(j.getBoolean("isEnhancedOpen")); 654 } 655 boolean isWpa3 = false; 656 if (j.has("isWpa3") && j.getBoolean("isWpa3")) { 657 isWpa3 = true; 658 } 659 if (j.has("password")) { 660 if (!isWpa3) { 661 builder = builder.setWpa2Passphrase(j.getString("password")); 662 } else { 663 builder = builder.setWpa3Passphrase(j.getString("password")); 664 } 665 } 666 if (j.has(WifiEnterpriseConfig.EAP_KEY)) { 667 if (!isWpa3) { 668 builder = builder.setWpa2EnterpriseConfig(genWifiEnterpriseConfig(j)); 669 } else { 670 builder = builder.setWpa3EnterpriseConfig(genWifiEnterpriseConfig(j)); 671 } 672 } 673 return builder.build(); 674 } 675 676 private WifiNetworkSuggestion genWifiNetworkSuggestion(JSONObject j) throws JSONException, 677 GeneralSecurityException { 678 if (j == null) { 679 return null; 680 } 681 WifiNetworkSuggestion.Builder builder = new WifiNetworkSuggestion.Builder(); 682 if (j.has("SSID")) { 683 builder = builder.setSsid(j.getString("SSID")); 684 } 685 if (j.has("BSSID")) { 686 builder = builder.setBssid(MacAddress.fromString(j.getString("BSSID"))); 687 } 688 if (j.has("hiddenSSID")) { 689 builder = builder.setIsHiddenSsid(j.getBoolean("hiddenSSID")); 690 } 691 if (j.has("isEnhancedOpen")) { 692 builder = builder.setIsEnhancedOpen(j.getBoolean("isEnhancedOpen")); 693 } 694 boolean isWpa3 = false; 695 if (j.has("isWpa3") && j.getBoolean("isWpa3")) { 696 isWpa3 = true; 697 } 698 if (j.has("password")) { 699 if (!isWpa3) { 700 builder = builder.setWpa2Passphrase(j.getString("password")); 701 } else { 702 builder = builder.setWpa3Passphrase(j.getString("password")); 703 } 704 } 705 if (j.has(WifiEnterpriseConfig.EAP_KEY)) { 706 if (!isWpa3) { 707 builder = builder.setWpa2EnterpriseConfig(genWifiEnterpriseConfig(j)); 708 } else { 709 builder = builder.setWpa3EnterpriseConfig(genWifiEnterpriseConfig(j)); 710 } 711 } 712 if (j.has("isAppInteractionRequired")) { 713 builder = builder.setIsAppInteractionRequired(j.getBoolean("isAppInteractionRequired")); 714 } 715 if (j.has("isUserInteractionRequired")) { 716 builder = builder.setIsUserInteractionRequired( 717 j.getBoolean("isUserInteractionRequired")); 718 } 719 if (j.has("isMetered")) { 720 builder = builder.setIsMetered(j.getBoolean("isMetered")); 721 } 722 if (j.has("priority")) { 723 builder = builder.setPriority(j.getInt("priority")); 724 } 725 return builder.build(); 726 } 727 728 private List<WifiNetworkSuggestion> genWifiNetworkSuggestions( 729 JSONArray jsonNetworkSuggestionsArray) throws JSONException, GeneralSecurityException { 730 if (jsonNetworkSuggestionsArray == null) { 731 return null; 732 } 733 List<WifiNetworkSuggestion> networkSuggestions = new ArrayList<>(); 734 for (int i = 0; i < jsonNetworkSuggestionsArray.length(); i++) { 735 networkSuggestions.add( 736 genWifiNetworkSuggestion(jsonNetworkSuggestionsArray.getJSONObject(i))); 737 } 738 return networkSuggestions; 739 } 740 741 private boolean matchScanResult(ScanResult result, String id) { 742 if (result.BSSID.equals(id) || result.SSID.equals(id)) { 743 return true; 744 } 745 return false; 746 } 747 748 private WpsInfo parseWpsInfo(String infoStr) throws JSONException { 749 if (infoStr == null) { 750 return null; 751 } 752 JSONObject j = new JSONObject(infoStr); 753 WpsInfo info = new WpsInfo(); 754 if (j.has("setup")) { 755 info.setup = j.getInt("setup"); 756 } 757 if (j.has("BSSID")) { 758 info.BSSID = j.getString("BSSID"); 759 } 760 if (j.has("pin")) { 761 info.pin = j.getString("pin"); 762 } 763 return info; 764 } 765 766 private byte[] base64StrToBytes(String input) { 767 return Base64.decode(input, Base64.DEFAULT); 768 } 769 770 private X509Certificate strToX509Cert(String certStr) throws CertificateException { 771 byte[] certBytes = base64StrToBytes(certStr); 772 InputStream certStream = new ByteArrayInputStream(certBytes); 773 CertificateFactory cf = CertificateFactory.getInstance("X509"); 774 return (X509Certificate) cf.generateCertificate(certStream); 775 } 776 777 private PrivateKey strToPrivateKey(String key) throws NoSuchAlgorithmException, 778 InvalidKeySpecException { 779 byte[] keyBytes = base64StrToBytes(key); 780 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); 781 KeyFactory fact = KeyFactory.getInstance("RSA"); 782 PrivateKey priv = fact.generatePrivate(keySpec); 783 return priv; 784 } 785 786 private PublicKey strToPublicKey(String key) throws NoSuchAlgorithmException, 787 InvalidKeySpecException { 788 byte[] keyBytes = base64StrToBytes(key); 789 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); 790 KeyFactory fact = KeyFactory.getInstance("RSA"); 791 PublicKey pub = fact.generatePublic(keySpec); 792 return pub; 793 } 794 795 private WifiConfiguration wifiConfigurationFromScanResult(ScanResult result) { 796 if (result == null) 797 return null; 798 WifiConfiguration config = new WifiConfiguration(); 799 config.SSID = "\"" + result.SSID + "\""; 800 applyingkeyMgmt(config, result); 801 config.BSSID = result.BSSID; 802 return config; 803 } 804 805 @Rpc(description = "test.") 806 public String wifiTest( 807 @RpcParameter(name = "certString") String certString) throws CertificateException, IOException { 808 // TODO(angli): Make this work. Convert a X509Certificate back to a string. 809 X509Certificate caCert = strToX509Cert(certString); 810 caCert.getEncoded(); 811 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 812 ObjectOutput out = new ObjectOutputStream(bos); 813 out.writeObject(caCert); 814 byte[] data = bos.toByteArray(); 815 bos.close(); 816 return Base64.encodeToString(data, Base64.DEFAULT); 817 } 818 819 @Rpc(description = "Add a network.") 820 @Deprecated 821 public Integer wifiAddNetwork(@RpcParameter(name = "wifiConfig") JSONObject wifiConfig) 822 throws JSONException { 823 return wifiaddOrUpdateNetwork(wifiConfig); 824 } 825 826 @Rpc(description = "Add or update a network.") 827 public Integer wifiaddOrUpdateNetwork(@RpcParameter(name = "wifiConfig") JSONObject wifiConfig) 828 throws JSONException { 829 return mWifi.addNetwork(genWifiConfig(wifiConfig)); 830 } 831 832 @Rpc(description = "Cancel Wi-fi Protected Setup.") 833 public void wifiCancelWps() throws JSONException { 834 WifiWpsCallback listener = new WifiWpsCallback(); 835 mWifi.cancelWps(listener); 836 } 837 838 @Rpc(description = "Checks Wifi state.", returns = "True if Wifi is enabled.") 839 public Boolean wifiCheckState() { 840 return mWifi.getWifiState() == WifiManager.WIFI_STATE_ENABLED; 841 } 842 843 /** 844 * @deprecated Use {@link #wifiConnectByConfig(config)} instead. 845 */ 846 @Rpc(description = "Connects to the network with the given configuration") 847 @Deprecated 848 public Boolean wifiConnect(@RpcParameter(name = "config") JSONObject config) 849 throws JSONException { 850 try { 851 wifiConnectByConfig(config); 852 } catch (GeneralSecurityException e) { 853 String msg = "Caught GeneralSecurityException with the provided" 854 + "configuration"; 855 throw new RuntimeException(msg); 856 } 857 return true; 858 } 859 860 /** 861 * @deprecated Use {@link #wifiConnectByConfig(config)} instead. 862 */ 863 @Rpc(description = "Connects to the network with the given configuration") 864 @Deprecated 865 public Boolean wifiEnterpriseConnect(@RpcParameter(name = "config") 866 JSONObject config) throws JSONException, GeneralSecurityException { 867 try { 868 wifiConnectByConfig(config); 869 } catch (GeneralSecurityException e) { 870 throw e; 871 } 872 return true; 873 } 874 875 /** 876 * Connects to a wifi network using configuration. 877 * @param config JSONObject Dictionary of wifi connection parameters 878 * @throws JSONException 879 * @throws GeneralSecurityException 880 */ 881 @Rpc(description = "Connects to the network with the given configuration") 882 public void wifiConnectByConfig(@RpcParameter(name = "config") JSONObject config) 883 throws JSONException, GeneralSecurityException { 884 WifiConfiguration wifiConfig; 885 WifiActionListener listener; 886 // Check if this is 802.1x or 802.11x config. 887 if (config.has(WifiEnterpriseConfig.EAP_KEY)) { 888 wifiConfig = genWifiConfigWithEnterpriseConfig(config); 889 } else { 890 wifiConfig = genWifiConfig(config); 891 } 892 listener = new WifiActionListener(mEventFacade, 893 WifiConstants.WIFI_CONNECT_BY_CONFIG_CALLBACK); 894 mWifi.connect(wifiConfig, listener); 895 } 896 897 /** 898 * Gets the Wi-Fi factory MAC addresses. 899 * @return An array of String represnting Wi-Fi MAC addresses, 900 * Or an empty Srting if failed. 901 */ 902 @Rpc(description = "Gets the Wi-Fi factory MAC addresses", returns = "An array of String, representing the MAC address") 903 public String[] wifigetFactorymacAddresses(){ 904 return mWifi.getFactoryMacAddresses(); 905 } 906 907 @Rpc(description = "Gets the randomized MAC address", returns = "A MAC address or null") 908 public MacAddress wifigetRandomizedMacAddress(@RpcParameter(name = "config") JSONObject config) 909 throws JSONException{ 910 List<WifiConfiguration> configList = mWifi.getConfiguredNetworks(); 911 for(WifiConfiguration WifiConfig : configList){ 912 String ssid = WifiConfig.SSID; 913 ssid = ssid.replace("\"", ""); 914 if (ssid.equals(config.getString("SSID"))){ 915 return WifiConfig.getRandomizedMacAddress(); 916 } 917 } 918 Log.d("Did not find a matching object in wifiManager."); 919 return null; 920 } 921 /** 922 * Generate a Passpoint configuration from JSON config. 923 * @param config JSON config containing base64 encoded Passpoint profile 924 */ 925 @Rpc(description = "Generate Passpoint configuration", returns = "PasspointConfiguration object") 926 public PasspointConfiguration genWifiPasspointConfig(@RpcParameter( 927 name = "config") JSONObject config) 928 throws JSONException,CertificateException, IOException { 929 String profileStr = ""; 930 if (config == null) { 931 return null; 932 } 933 if (config.has("profile")) { 934 profileStr = config.getString("profile"); 935 } 936 return ConfigParser.parsePasspointConfig(TYPE_WIFICONFIG, 937 profileStr.getBytes()); 938 } 939 940 /** 941 * Add or update a Passpoint configuration. 942 * @param config base64 encoded message containing Passpoint profile 943 * @throws JSONException 944 */ 945 @Rpc(description = "Add or update a Passpoint configuration") 946 public void addUpdatePasspointConfig(@RpcParameter( 947 name = "config") JSONObject config) 948 throws JSONException,CertificateException, IOException { 949 PasspointConfiguration passpointConfig = genWifiPasspointConfig(config); 950 mWifi.addOrUpdatePasspointConfiguration(passpointConfig); 951 } 952 953 /** 954 * Remove a Passpoint configuration. 955 * @param fqdn The FQDN of the passpoint configuration to be removed 956 * @return true on success; false otherwise 957 */ 958 @Rpc(description = "Remove a Passpoint configuration") 959 public void removePasspointConfig( 960 @RpcParameter(name = "fqdn") String fqdn) { 961 mWifi.removePasspointConfiguration(fqdn); 962 } 963 964 /** 965 * Get list of Passpoint configurations. 966 * @return A list of FQDNs of the Passpoint configurations 967 */ 968 @Rpc(description = "Return the list of installed Passpoint configurations", returns = "A list of Passpoint configurations") 969 public List<String> getPasspointConfigs() { 970 List<String> fqdnList = new ArrayList<String>(); 971 for(PasspointConfiguration passpoint : 972 mWifi.getPasspointConfigurations()) { 973 fqdnList.add(passpoint.getHomeSp().getFqdn()); 974 } 975 return fqdnList; 976 } 977 978 private class ProvisioningCallbackFacade extends ProvisioningCallback { 979 private final EventFacade mEventFacade; 980 981 ProvisioningCallbackFacade(EventFacade eventFacade) { 982 mEventFacade = eventFacade; 983 } 984 985 @Override 986 public void onProvisioningFailure(int status) { 987 Log.v("Provisioning Failure " + status); 988 Bundle msg = new Bundle(); 989 msg.putString("tag", "failure"); 990 msg.putInt("reason", status); 991 mEventFacade.postEvent("onProvisioningCallback", msg); 992 } 993 994 @Override 995 public void onProvisioningStatus(int status) { 996 Log.v("Provisioning status " + status); 997 Bundle msg = new Bundle(); 998 msg.putString("tag", "status"); 999 msg.putInt("status", status); 1000 mEventFacade.postEvent("onProvisioningCallback", msg); 1001 } 1002 1003 @Override 1004 public void onProvisioningComplete() { 1005 Log.v("Provisioning Complete"); 1006 Bundle msg = new Bundle(); 1007 msg.putString("tag", "success"); 1008 mEventFacade.postEvent("onProvisioningCallback", msg); 1009 } 1010 } 1011 1012 private OsuProvider buildTestOsuProvider(JSONObject config) { 1013 String osuServiceDescription = "Google Passpoint Test Service"; 1014 List<Integer> osuMethodList = 1015 Arrays.asList(OsuProvider.METHOD_SOAP_XML_SPP); 1016 1017 try { 1018 if (!config.has("osuSSID")) { 1019 Log.e("missing osuSSID from the config"); 1020 return null; 1021 } 1022 WifiSsid osuSsid = WifiSsid.createFromByteArray( 1023 config.getString("osuSSID").getBytes(StandardCharsets.UTF_8)); 1024 1025 if (!config.has("osuUri")) { 1026 Log.e("missing osuUri from the config"); 1027 return null; 1028 } 1029 Uri osuServerUri = Uri.parse(config.getString("osuUri")); 1030 1031 Log.v("OSU Server URI " + osuServerUri.toString()); 1032 if (!config.has("osuFriendlyName")) { 1033 Log.e("missing osuFriendlyName from the config"); 1034 return null; 1035 } 1036 String osuFriendlyName = config.getString("osuFriendlyName"); 1037 1038 if (config.has("description")) { 1039 osuServiceDescription = config.getString("description"); 1040 } 1041 Map<String, String> osuFriendlyNames = new HashMap<>(); 1042 osuFriendlyNames.put("en", osuFriendlyName); 1043 return new OsuProvider(osuSsid, osuFriendlyNames, osuServiceDescription, 1044 osuServerUri, null, osuMethodList, null); 1045 } catch (JSONException e) { 1046 Log.e("JSON Parsing error: " + e); 1047 return null; 1048 } 1049 } 1050 1051 /** 1052 * Start subscription provisioning 1053 */ 1054 @Rpc(description = "Starts subscription provisioning flow") 1055 public void startSubscriptionProvisioning( 1056 @RpcParameter(name = "configJson") JSONObject configJson) { 1057 ProvisioningCallback callback = new ProvisioningCallbackFacade(mEventFacade); 1058 mWifi.startSubscriptionProvisioning(buildTestOsuProvider(configJson), 1059 mService.getMainExecutor(), callback); 1060 } 1061 1062 /** 1063 * Connects to a wifi network using networkId. 1064 * @param networkId the network identity for the network in the supplicant 1065 */ 1066 @Rpc(description = "Connects to the network with the given networkId") 1067 public void wifiConnectByNetworkId( 1068 @RpcParameter(name = "networkId") Integer networkId) { 1069 WifiActionListener listener; 1070 listener = new WifiActionListener(mEventFacade, 1071 WifiConstants.WIFI_CONNECT_BY_NETID_CALLBACK); 1072 mWifi.connect(networkId, listener); 1073 } 1074 1075 @Rpc(description = "Disconnects from the currently active access point.", returns = "True if the operation succeeded.") 1076 public Boolean wifiDisconnect() { 1077 return mWifi.disconnect(); 1078 } 1079 1080 @Rpc(description = "Enable/disable autojoin scan and switch network when connected.") 1081 public Boolean wifiSetEnableAutoJoinWhenAssociated(@RpcParameter(name = "enable") Boolean enable) { 1082 return mWifi.setEnableAutoJoinWhenAssociated(enable); 1083 } 1084 1085 @Rpc(description = "Enable a configured network. Initiate a connection if disableOthers is true", returns = "True if the operation succeeded.") 1086 public Boolean wifiEnableNetwork(@RpcParameter(name = "netId") Integer netId, 1087 @RpcParameter(name = "disableOthers") Boolean disableOthers) { 1088 return mWifi.enableNetwork(netId, disableOthers); 1089 } 1090 1091 @Rpc(description = "Enable WiFi verbose logging.") 1092 public void wifiEnableVerboseLogging(@RpcParameter(name = "level") Integer level) { 1093 mWifi.enableVerboseLogging(level); 1094 } 1095 1096 @Rpc(description = "Resets all WifiManager settings.") 1097 public void wifiFactoryReset() { 1098 mWifi.factoryReset(); 1099 } 1100 1101 /** 1102 * Forget a wifi network by networkId. 1103 * 1104 * @param networkId Id of wifi network 1105 */ 1106 @Rpc(description = "Forget a wifi network by networkId") 1107 public void wifiForgetNetwork(@RpcParameter(name = "wifiSSID") Integer networkId) { 1108 WifiActionListener listener = new WifiActionListener(mEventFacade, 1109 WifiConstants.WIFI_FORGET_NETWORK_CALLBACK); 1110 mWifi.forget(networkId, listener); 1111 } 1112 1113 /** 1114 * Disable ephemeral network. 1115 * 1116 * @param ssid SSID of wifi network 1117 */ 1118 @Rpc(description = "Forget a wifi network by networkId") 1119 public void wifiDisableEphemeralNetwork(@RpcParameter(name = "ssid") String ssid) { 1120 mWifi.disableEphemeralNetwork("\"" + ssid + "\""); 1121 } 1122 1123 @Rpc(description = "Gets the Wi-Fi AP Configuration.") 1124 public WifiConfiguration wifiGetApConfiguration() { 1125 return mWifi.getWifiApConfiguration(); 1126 } 1127 1128 @Rpc(description = "Return a list of all the configured wifi networks.") 1129 public List<WifiConfiguration> wifiGetConfiguredNetworks() { 1130 return mWifi.getConfiguredNetworks(); 1131 } 1132 1133 @Rpc(description = "Returns information about the currently active access point.") 1134 public WifiInfo wifiGetConnectionInfo() { 1135 return mWifi.getConnectionInfo(); 1136 } 1137 1138 @Rpc(description = "Returns wifi activity and energy usage info.") 1139 public WifiActivityEnergyInfo wifiGetControllerActivityEnergyInfo() { 1140 return mWifi.getControllerActivityEnergyInfo(); 1141 } 1142 1143 @Rpc(description = "Get the country code used by WiFi.") 1144 public String wifiGetCountryCode() { 1145 return mWifi.getCountryCode(); 1146 } 1147 1148 @Rpc(description = "Get the current network.") 1149 public Network wifiGetCurrentNetwork() { 1150 return mWifi.getCurrentNetwork(); 1151 } 1152 1153 @Rpc(description = "Get the info from last successful DHCP request.") 1154 public DhcpInfo wifiGetDhcpInfo() { 1155 return mWifi.getDhcpInfo(); 1156 } 1157 1158 @Rpc(description = "Get setting for Framework layer autojoin enable status.") 1159 public Boolean wifiGetEnableAutoJoinWhenAssociated() { 1160 return mWifi.getEnableAutoJoinWhenAssociated(); 1161 } 1162 1163 @Rpc(description = "Get privileged configured networks.") 1164 public List<WifiConfiguration> wifiGetPrivilegedConfiguredNetworks() { 1165 return mWifi.getPrivilegedConfiguredNetworks(); 1166 } 1167 1168 @Rpc(description = "Returns the list of access points found during the most recent Wifi scan.") 1169 public List<ScanResult> wifiGetScanResults() { 1170 return mWifi.getScanResults(); 1171 } 1172 1173 @Rpc(description = "Get the current level of WiFi verbose logging.") 1174 public Integer wifiGetVerboseLoggingLevel() { 1175 return mWifi.getVerboseLoggingLevel(); 1176 } 1177 1178 @Rpc(description = "true if this adapter supports 5 GHz band.") 1179 public Boolean wifiIs5GHzBandSupported() { 1180 return mWifi.is5GHzBandSupported(); 1181 } 1182 1183 @Rpc(description = "true if this adapter supports multiple simultaneous connections.") 1184 public Boolean wifiIsAdditionalStaSupported() { 1185 return mWifi.isAdditionalStaSupported(); 1186 } 1187 1188 @Rpc(description = "Return true if WiFi is enabled.") 1189 public Boolean wifiGetisWifiEnabled() { 1190 return mWifi.isWifiEnabled(); 1191 } 1192 1193 @Rpc(description = "Return whether Wi-Fi AP is enabled or disabled.") 1194 public Boolean wifiIsApEnabled() { 1195 return mWifi.isWifiApEnabled(); 1196 } 1197 1198 @Rpc(description = "Check if Device-to-AP RTT is supported.") 1199 public Boolean wifiIsDeviceToApRttSupported() { 1200 return mWifi.isDeviceToApRttSupported(); 1201 } 1202 1203 @Rpc(description = "Check if Device-to-device RTT is supported.") 1204 public Boolean wifiIsDeviceToDeviceRttSupported() { 1205 return mWifi.isDeviceToDeviceRttSupported(); 1206 } 1207 1208 @Rpc(description = "Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz).") 1209 public Boolean wifiIsDualBandSupported() { 1210 return mWifi.isDualBandSupported(); 1211 } 1212 1213 @Rpc(description = "Check if this adapter supports advanced power/performance counters.") 1214 public Boolean wifiIsEnhancedPowerReportingSupported() { 1215 return mWifi.isEnhancedPowerReportingSupported(); 1216 } 1217 1218 @Rpc(description = "Check if multicast is enabled.") 1219 public Boolean wifiIsMulticastEnabled() { 1220 return mWifi.isMulticastEnabled(); 1221 } 1222 1223 @Rpc(description = "true if this adapter supports Wi-Fi Aware APIs.") 1224 public Boolean wifiIsAwareSupported() { 1225 return mWifi.isWifiAwareSupported(); 1226 } 1227 1228 @Rpc(description = "true if this adapter supports Off Channel Tunnel Directed Link Setup.") 1229 public Boolean wifiIsOffChannelTdlsSupported() { 1230 return mWifi.isOffChannelTdlsSupported(); 1231 } 1232 1233 @Rpc(description = "true if this adapter supports WifiP2pManager (Wi-Fi Direct).") 1234 public Boolean wifiIsP2pSupported() { 1235 return mWifi.isP2pSupported(); 1236 } 1237 1238 @Rpc(description = "true if this adapter supports passpoint.") 1239 public Boolean wifiIsPasspointSupported() { 1240 return mWifi.isPasspointSupported(); 1241 } 1242 1243 @Rpc(description = "true if this adapter supports portable Wi-Fi hotspot.") 1244 public Boolean wifiIsPortableHotspotSupported() { 1245 return mWifi.isPortableHotspotSupported(); 1246 } 1247 1248 @Rpc(description = "true if this adapter supports offloaded connectivity scan.") 1249 public Boolean wifiIsPreferredNetworkOffloadSupported() { 1250 return mWifi.isPreferredNetworkOffloadSupported(); 1251 } 1252 1253 @Rpc(description = "Check if wifi scanner is supported on this device.") 1254 public Boolean wifiIsScannerSupported() { 1255 return mWifi.isWifiScannerSupported(); 1256 } 1257 1258 @Rpc(description = "Check if tdls is supported on this device.") 1259 public Boolean wifiIsTdlsSupported() { 1260 return mWifi.isTdlsSupported(); 1261 } 1262 1263 /** 1264 * @return true if this device supports WPA3-Personal SAE 1265 */ 1266 @Rpc(description = "Check if WPA3-Personal SAE is supported on this device.") 1267 public Boolean wifiIsWpa3SaeSupported() { 1268 return mWifi.isWpa3SaeSupported(); 1269 } 1270 /** 1271 * @return true if this device supports WPA3-Enterprise Suite-B-192 1272 */ 1273 @Rpc(description = "Check if WPA3-Enterprise Suite-B-192 is supported on this device.") 1274 public Boolean wifiIsWpa3SuiteBSupported() { 1275 return mWifi.isWpa3SuiteBSupported(); 1276 } 1277 /** 1278 * @return true if this device supports Wi-Fi Enhanced Open (OWE) 1279 */ 1280 @Rpc(description = "Check if Enhanced Open (OWE) is supported on this device.") 1281 public Boolean wifiIsEnhancedOpenSupported() { 1282 return mWifi.isEnhancedOpenSupported(); 1283 } 1284 /** 1285 * @return true if this device supports Wi-Fi Device Provisioning Protocol (Easy-connect) 1286 */ 1287 @Rpc(description = "Check if Easy Connect (DPP) is supported on this device.") 1288 public Boolean wifiIsEasyConnectSupported() { 1289 return mWifi.isEasyConnectSupported(); 1290 } 1291 1292 @Rpc(description = "Acquires a full Wifi lock.") 1293 public void wifiLockAcquireFull() { 1294 makeLock(WifiManager.WIFI_MODE_FULL); 1295 } 1296 1297 @Rpc(description = "Acquires a scan only Wifi lock.") 1298 public void wifiLockAcquireScanOnly() { 1299 makeLock(WifiManager.WIFI_MODE_SCAN_ONLY); 1300 } 1301 1302 @Rpc(description = "Releases a previously acquired Wifi lock.") 1303 public void wifiLockRelease() { 1304 if (mLock != null) { 1305 mLock.release(); 1306 mLock = null; 1307 } 1308 } 1309 1310 @Rpc(description = "Reassociates with the currently active access point.", returns = "True if the operation succeeded.") 1311 public Boolean wifiReassociate() { 1312 return mWifi.reassociate(); 1313 } 1314 1315 @Rpc(description = "Reconnects to the currently active access point.", returns = "True if the operation succeeded.") 1316 public Boolean wifiReconnect() { 1317 return mWifi.reconnect(); 1318 } 1319 1320 @Rpc(description = "Remove a configured network.", returns = "True if the operation succeeded.") 1321 public Boolean wifiRemoveNetwork(@RpcParameter(name = "netId") Integer netId) { 1322 return mWifi.removeNetwork(netId); 1323 } 1324 1325 private WifiConfiguration createSoftApWifiConfiguration(JSONObject configJson) 1326 throws JSONException { 1327 WifiConfiguration config = genWifiConfig(configJson); 1328 // Need to strip of extra quotation marks for SSID and password. 1329 String ssid = config.SSID; 1330 if (ssid != null) { 1331 config.SSID = ssid.substring(1, ssid.length() - 1); 1332 } 1333 1334 config.allowedKeyManagement.clear(); 1335 String pwd = config.preSharedKey; 1336 if (pwd != null) { 1337 config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK); 1338 config.preSharedKey = pwd.substring(1, pwd.length() - 1); 1339 } else { 1340 config.allowedKeyManagement.set(KeyMgmt.NONE); 1341 } 1342 return config; 1343 } 1344 1345 @Rpc(description = "Set configuration for soft AP.") 1346 public Boolean wifiSetWifiApConfiguration( 1347 @RpcParameter(name = "configJson") JSONObject configJson) throws JSONException { 1348 WifiConfiguration config = createSoftApWifiConfiguration(configJson); 1349 return mWifi.setWifiApConfiguration(config); 1350 } 1351 1352 /** 1353 * Register softap callback. 1354 * 1355 * @return the id associated with the {@link SoftApCallbackImp} 1356 * used for registering callback. 1357 */ 1358 @Rpc(description = "Register softap callback function.", 1359 returns = "Id of the callback associated with registering.") 1360 public Integer registerSoftApCallback() { 1361 SoftApCallbackImp softApCallback = new SoftApCallbackImp(mEventFacade); 1362 mSoftapCallbacks.put(softApCallback.mId, softApCallback); 1363 mWifi.registerSoftApCallback(softApCallback, 1364 new Handler(mCallbackHandlerThread.getLooper())); 1365 return softApCallback.mId; 1366 } 1367 1368 /** 1369 * Unregister softap callback role for the {@link SoftApCallbackImp} identified by the given 1370 * {@code callbackId}. 1371 * 1372 * @param callbackId the id associated with the {@link SoftApCallbackImp} 1373 * used for registering callback. 1374 * 1375 */ 1376 @Rpc(description = "Unregister softap callback function.") 1377 public void unregisterSoftApCallback(@RpcParameter(name = "callbackId") Integer callbackId) { 1378 mWifi.unregisterSoftApCallback(mSoftapCallbacks.get(callbackId)); 1379 mSoftapCallbacks.delete(callbackId); 1380 } 1381 1382 @Rpc(description = "Set the country code used by WiFi.") 1383 public void wifiSetCountryCode( 1384 @RpcParameter(name = "country") String country) { 1385 mWifi.setCountryCode(country); 1386 } 1387 1388 @Rpc(description = "Enable/disable tdls with a mac address.") 1389 public void wifiSetTdlsEnabledWithMacAddress( 1390 @RpcParameter(name = "remoteMacAddress") String remoteMacAddress, 1391 @RpcParameter(name = "enable") Boolean enable) { 1392 mWifi.setTdlsEnabledWithMacAddress(remoteMacAddress, enable); 1393 } 1394 1395 @Rpc(description = "Starts a scan for Wifi access points.", returns = "True if the scan was initiated successfully.") 1396 public Boolean wifiStartScan() { 1397 mService.registerReceiver(mScanResultsAvailableReceiver, mScanFilter); 1398 return mWifi.startScan(); 1399 } 1400 1401 @Rpc(description = "Start Wi-fi Protected Setup.") 1402 public void wifiStartWps( 1403 @RpcParameter(name = "config", description = "A json string with fields \"setup\", \"BSSID\", and \"pin\"") String config) 1404 throws JSONException { 1405 WpsInfo info = parseWpsInfo(config); 1406 WifiWpsCallback listener = new WifiWpsCallback(); 1407 Log.d("Starting wps with: " + info); 1408 mWifi.startWps(info, listener); 1409 } 1410 1411 @Rpc(description = "Start listening for wifi state change related broadcasts.") 1412 public void wifiStartTrackingStateChange() { 1413 mService.registerReceiver(mStateChangeReceiver, mStateChangeFilter); 1414 mTrackingWifiStateChange = true; 1415 } 1416 1417 @Rpc(description = "Stop listening for wifi state change related broadcasts.") 1418 public void wifiStopTrackingStateChange() { 1419 if (mTrackingWifiStateChange == true) { 1420 mService.unregisterReceiver(mStateChangeReceiver); 1421 mTrackingWifiStateChange = false; 1422 } 1423 } 1424 1425 @Rpc(description = "Start listening for tether state change related broadcasts.") 1426 public void wifiStartTrackingTetherStateChange() { 1427 mService.registerReceiver(mTetherStateReceiver, mTetherFilter); 1428 mTrackingTetherStateChange = true; 1429 } 1430 1431 @Rpc(description = "Stop listening for wifi state change related broadcasts.") 1432 public void wifiStopTrackingTetherStateChange() { 1433 if (mTrackingTetherStateChange == true) { 1434 mService.unregisterReceiver(mTetherStateReceiver); 1435 mTrackingTetherStateChange = false; 1436 } 1437 } 1438 1439 @Rpc(description = "Start listening for network suggestion change related broadcasts.") 1440 public void wifiStartTrackingNetworkSuggestionStateChange() { 1441 mService.registerReceiver( 1442 mNetworkSuggestionStateChangeReceiver, mNetworkSuggestionStateChangeFilter); 1443 mTrackingNetworkSuggestionStateChange = true; 1444 } 1445 1446 @Rpc(description = "Stop listening for network suggestion change related broadcasts.") 1447 public void wifiStopTrackingNetworkSuggestionStateChange() { 1448 if (mTrackingNetworkSuggestionStateChange) { 1449 mService.unregisterReceiver(mNetworkSuggestionStateChangeReceiver); 1450 mTrackingNetworkSuggestionStateChange = false; 1451 } 1452 } 1453 1454 @Rpc(description = "Toggle Wifi on and off.", returns = "True if Wifi is enabled.") 1455 public Boolean wifiToggleState(@RpcParameter(name = "enabled") @RpcOptional Boolean enabled) { 1456 if (enabled == null) { 1457 enabled = !wifiCheckState(); 1458 } 1459 mWifi.setWifiEnabled(enabled); 1460 return enabled; 1461 } 1462 1463 @Rpc(description = "Toggle Wifi scan always available on and off.", returns = "True if Wifi scan is always available.") 1464 public Boolean wifiToggleScanAlwaysAvailable( 1465 @RpcParameter(name = "enabled") @RpcOptional Boolean enabled) 1466 throws SettingNotFoundException { 1467 ContentResolver cr = mService.getContentResolver(); 1468 int isSet = 0; 1469 if (enabled == null) { 1470 isSet = Global.getInt(cr, Global.WIFI_SCAN_ALWAYS_AVAILABLE); 1471 isSet ^= 1; 1472 } else if (enabled == true) { 1473 isSet = 1; 1474 } 1475 Global.putInt(cr, Global.WIFI_SCAN_ALWAYS_AVAILABLE, isSet); 1476 if (isSet == 1) { 1477 return true; 1478 } 1479 return false; 1480 } 1481 1482 @Rpc(description = "Enable/disable WifiConnectivityManager.") 1483 public void wifiEnableWifiConnectivityManager( 1484 @RpcParameter(name = "enable") Boolean enable) { 1485 mWifi.enableWifiConnectivityManager(enable); 1486 } 1487 1488 private void wifiRequestNetworkWithSpecifierInternal(NetworkSpecifier wns, int timeoutInMs) 1489 throws GeneralSecurityException { 1490 NetworkRequest networkRequest = new NetworkRequest.Builder() 1491 .addTransportType(TRANSPORT_WIFI) 1492 .setNetworkSpecifier(wns) 1493 .build(); 1494 NetworkCallback networkCallback = new NetworkCallbackImpl(); 1495 if (timeoutInMs != 0) { 1496 mCm.requestNetwork(networkRequest, networkCallback, 1497 new Handler(mCallbackHandlerThread.getLooper()), timeoutInMs); 1498 } else { 1499 mCm.requestNetwork(networkRequest, networkCallback, 1500 new Handler(mCallbackHandlerThread.getLooper())); 1501 } 1502 // Store the callback for release later. 1503 mNetworkCallbacks.put(wns, networkCallback); 1504 } 1505 1506 /** 1507 * Initiates a network request {@link NetworkRequest} using {@link WifiNetworkSpecifier}. 1508 * 1509 * @param wifiNetworkSpecifier JSONObject Dictionary of wifi network specifier parameters 1510 * @throws JSONException 1511 * @throws GeneralSecurityException 1512 */ 1513 @Rpc(description = "Initiates a network request using the provided network specifier") 1514 public void wifiRequestNetworkWithSpecifier( 1515 @RpcParameter(name = "wifiNetworkSpecifier") JSONObject wifiNetworkSpecifier) 1516 throws JSONException, GeneralSecurityException { 1517 wifiRequestNetworkWithSpecifierInternal(genWifiNetworkSpecifier(wifiNetworkSpecifier), 0); 1518 } 1519 1520 /** 1521 * Initiates a network request {@link NetworkRequest} using {@link WifiNetworkSpecifier}. 1522 * 1523 * @param wifiNetworkSpecifier JSONObject Dictionary of wifi network specifier parameters 1524 * @param timeoutInMs Timeout for the request. 1525 * @throws JSONException 1526 * @throws GeneralSecurityException 1527 */ 1528 @Rpc(description = "Initiates a network request using the provided network specifier") 1529 public void wifiRequestNetworkWithSpecifierWithTimeout( 1530 @RpcParameter(name = "wifiNetworkSpecifier") JSONObject wifiNetworkSpecifier, 1531 @RpcParameter(name = "timeout") Integer timeoutInMs) 1532 throws JSONException, GeneralSecurityException { 1533 wifiRequestNetworkWithSpecifierInternal( 1534 genWifiNetworkSpecifier(wifiNetworkSpecifier), timeoutInMs); 1535 } 1536 1537 /** 1538 * Releases network request using {@link WifiNetworkSpecifier}. 1539 * 1540 * @throws JSONException 1541 * @throws GeneralSecurityException 1542 */ 1543 @Rpc(description = "Releases network request corresponding to the network specifier") 1544 public void wifiReleaseNetwork( 1545 @RpcParameter(name = "wifiNetworkSpecifier") JSONObject wifiNetworkSpecifier) 1546 throws JSONException, GeneralSecurityException { 1547 NetworkSpecifier wns = genWifiNetworkSpecifier(wifiNetworkSpecifier); 1548 NetworkCallback networkCallback = mNetworkCallbacks.remove(wns); 1549 if (networkCallback == null) { 1550 throw new IllegalArgumentException("network callback is null"); 1551 } 1552 mCm.unregisterNetworkCallback(networkCallback); 1553 } 1554 1555 /** 1556 * Releases all pending network requests. 1557 * 1558 * @throws JSONException 1559 * @throws GeneralSecurityException 1560 */ 1561 @Rpc(description = "Releases all pending network requests") 1562 public void wifiReleaseNetworkAll() { 1563 Iterator<Map.Entry<NetworkSpecifier, NetworkCallback>> it = 1564 mNetworkCallbacks.entrySet().iterator(); 1565 while (it.hasNext()) { 1566 Map.Entry<NetworkSpecifier, NetworkCallback> entry = it.next(); 1567 NetworkCallback networkCallback = entry.getValue(); 1568 it.remove(); 1569 mCm.unregisterNetworkCallback(networkCallback); 1570 } 1571 } 1572 1573 /** 1574 * Register network request match callback to simulate the UI flow. 1575 * 1576 * @throws JSONException 1577 * @throws GeneralSecurityException 1578 */ 1579 @Rpc(description = "Register network request match callback") 1580 public void wifiRegisterNetworkRequestMatchCallback() 1581 throws JSONException, GeneralSecurityException { 1582 // Listen for UI interaction callbacks 1583 mWifi.registerNetworkRequestMatchCallback( 1584 mNetworkRequestMatchCallback, new Handler(mCallbackHandlerThread.getLooper())); 1585 } 1586 1587 /** 1588 * Triggers connect to a specific wifi network. 1589 * 1590 * @param jsonConfig JSONObject Dictionary of wifi connection parameters 1591 * @throws JSONException 1592 * @throws GeneralSecurityException 1593 */ 1594 @Rpc(description = "Connects to the specified network for the ongoing network request") 1595 public void wifiSendUserSelectionForNetworkRequestMatch( 1596 @RpcParameter(name = "jsonConfig") JSONObject jsonConfig) 1597 throws JSONException, GeneralSecurityException { 1598 synchronized (mCallbackLock) { 1599 if (mNetworkRequestUserSelectionCallback == null) { 1600 throw new IllegalStateException("user callback is null"); 1601 } 1602 // Copy the SSID for user selection. 1603 WifiConfiguration config = new WifiConfiguration(); 1604 if (jsonConfig.has("SSID")) { 1605 config.SSID = "\"" + jsonConfig.getString("SSID") + "\""; 1606 } 1607 mNetworkRequestUserSelectionCallback.select(config); 1608 } 1609 } 1610 1611 /** 1612 * Rejects network request. 1613 * 1614 * @throws JSONException 1615 * @throws GeneralSecurityException 1616 */ 1617 @Rpc(description = "Rejects ongoing network request") 1618 public void wifiSendUserRejectionForNetworkRequestMatch() 1619 throws JSONException, GeneralSecurityException { 1620 synchronized (mCallbackLock) { 1621 if (mNetworkRequestUserSelectionCallback == null) { 1622 throw new IllegalStateException("user callback is null"); 1623 } 1624 mNetworkRequestUserSelectionCallback.reject(); 1625 } 1626 } 1627 1628 /** 1629 * Add network suggestions. 1630 1631 * @param wifiNetworkSuggestions Array of JSONObject Dictionary of wifi network suggestion 1632 * parameters 1633 * @throws JSONException 1634 * @throws GeneralSecurityException 1635 */ 1636 @Rpc(description = "Add network suggestions to the platform") 1637 public boolean wifiAddNetworkSuggestions( 1638 @RpcParameter(name = "wifiNetworkSuggestions") JSONArray wifiNetworkSuggestions) 1639 throws JSONException, GeneralSecurityException { 1640 return mWifi.addNetworkSuggestions(genWifiNetworkSuggestions(wifiNetworkSuggestions)) 1641 == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; 1642 } 1643 1644 /** 1645 * Remove network suggestions. 1646 1647 * @param wifiNetworkSuggestions Array of JSONObject Dictionary of wifi network suggestion 1648 * parameters 1649 * @throws JSONException 1650 * @throws GeneralSecurityException 1651 */ 1652 @Rpc(description = "Remove network suggestions from the platform") 1653 public boolean wifiRemoveNetworkSuggestions( 1654 @RpcParameter(name = "wifiNetworkSuggestions") JSONArray wifiNetworkSuggestions) 1655 throws JSONException, GeneralSecurityException { 1656 return mWifi.removeNetworkSuggestions(genWifiNetworkSuggestions(wifiNetworkSuggestions)) 1657 == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; 1658 } 1659 1660 @Override 1661 public void shutdown() { 1662 wifiReleaseNetworkAll(); 1663 wifiLockRelease(); 1664 if (mTrackingWifiStateChange == true) { 1665 wifiStopTrackingStateChange(); 1666 } 1667 if (mTrackingTetherStateChange == true) { 1668 wifiStopTrackingTetherStateChange(); 1669 } 1670 } 1671 1672 private class EasyConnectCallback extends EasyConnectStatusCallback { 1673 private static final String EASY_CONNECT_CALLBACK_TAG = "onDppCallback"; 1674 1675 @Override 1676 public void onEnrolleeSuccess(int newWifiConfigurationId) { 1677 Bundle msg = new Bundle(); 1678 msg.putString("Type", "onEnrolleeSuccess"); 1679 msg.putInt("NetworkId", newWifiConfigurationId); 1680 Log.d("Posting event: onEnrolleeSuccess"); 1681 mEventFacade.postEvent(EASY_CONNECT_CALLBACK_TAG, msg); 1682 } 1683 1684 @Override 1685 public void onConfiguratorSuccess(int code) { 1686 Bundle msg = new Bundle(); 1687 msg.putString("Type", "onConfiguratorSuccess"); 1688 msg.putInt("Status", code); 1689 Log.d("Posting event: onConfiguratorSuccess"); 1690 mEventFacade.postEvent(EASY_CONNECT_CALLBACK_TAG, msg); 1691 } 1692 1693 @Override 1694 public void onFailure(int code) { 1695 Bundle msg = new Bundle(); 1696 msg.putString("Type", "onFailure"); 1697 msg.putInt("Status", code); 1698 Log.d("Posting event: onFailure"); 1699 mEventFacade.postEvent(EASY_CONNECT_CALLBACK_TAG, msg); 1700 } 1701 1702 @Override 1703 public void onProgress(int code) { 1704 Bundle msg = new Bundle(); 1705 msg.putString("Type", "onProgress"); 1706 msg.putInt("Status", code); 1707 Log.d("Posting event: onProgress"); 1708 mEventFacade.postEvent(EASY_CONNECT_CALLBACK_TAG, msg); 1709 } 1710 } 1711 1712 /** 1713 * Start Easy Connect (DPP) in Initiator-Configurator role: Send Wi-Fi configuration to a peer 1714 * 1715 * @param enrolleeUri Peer URI 1716 * @param selectedNetworkId Wi-Fi configuration ID 1717 */ 1718 @Rpc(description = "Easy Connect Initiator-Configurator: Send Wi-Fi configuration to peer") 1719 public void startEasyConnectAsConfiguratorInitiator(@RpcParameter(name = "enrolleeUri") String 1720 enrolleeUri, @RpcParameter(name = "selectedNetworkId") Integer selectedNetworkId, 1721 @RpcParameter(name = "netRole") String netRole) 1722 throws JSONException { 1723 EasyConnectCallback dppStatusCallback = new EasyConnectCallback(); 1724 int netRoleInternal; 1725 1726 if (netRole.equals("ap")) { 1727 netRoleInternal = WifiManager.EASY_CONNECT_NETWORK_ROLE_AP; 1728 } else { 1729 netRoleInternal = WifiManager.EASY_CONNECT_NETWORK_ROLE_STA; 1730 } 1731 1732 // Start Easy Connect 1733 mWifi.startEasyConnectAsConfiguratorInitiator(enrolleeUri, selectedNetworkId, 1734 netRoleInternal, mService.getMainExecutor(), dppStatusCallback); 1735 } 1736 1737 /** 1738 * Start Easy Connect (DPP) in Initiator-Enrollee role: Receive Wi-Fi configuration from a peer 1739 * 1740 * @param configuratorUri 1741 */ 1742 @Rpc(description = "Easy Connect Initiator-Enrollee: Receive Wi-Fi configuration from peer") 1743 public void startEasyConnectAsEnrolleeInitiator(@RpcParameter(name = "configuratorUri") String 1744 configuratorUri) { 1745 EasyConnectCallback dppStatusCallback = new EasyConnectCallback(); 1746 1747 // Start Easy Connect 1748 mWifi.startEasyConnectAsEnrolleeInitiator(configuratorUri, mService.getMainExecutor(), 1749 dppStatusCallback); 1750 } 1751 1752 /** 1753 * Stop Easy Connect (DPP) session 1754 * 1755 */ 1756 @Rpc(description = "Stop Easy Connect session") 1757 public void stopEasyConnectSession() { 1758 // Stop Easy Connect 1759 mWifi.stopEasyConnectSession(); 1760 } 1761 } 1762