blob: 97b6b0e67efc84fa8a267372da4d1146071a0d24 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.android_scripting.facade.wifi;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static com.googlecode.android_scripting.jsonrpc.JsonBuilder.build;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.DhcpInfo;
import android.net.MacAddress;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.Uri;
import android.net.wifi.EasyConnectStatusCallback;
import android.net.wifi.ScanResult;
import android.net.wifi.SoftApCapability;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SoftApInfo;
import android.net.wifi.WifiClient;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import android.net.wifi.WifiManager.WifiLock;
import android.net.wifi.WifiNetworkSpecifier;
import android.net.wifi.WifiNetworkSuggestion;
import android.net.wifi.WpsInfo;
import android.net.wifi.hotspot2.ConfigParser;
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.ProvisioningCallback;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.PatternMatcher;
import android.os.connectivity.WifiActivityEnergyInfo;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.Base64;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.facade.EventFacade;
import com.googlecode.android_scripting.facade.FacadeManager;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcOptional;
import com.googlecode.android_scripting.rpc.RpcParameter;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
/**
* WifiManager functions.
*/
// TODO: make methods handle various wifi states properly
// e.g. wifi connection result will be null when flight mode is on
public class WifiManagerFacade extends RpcReceiver {
private static final String mEventType = "WifiManager";
// MIME type for passpoint config.
private static final String TYPE_WIFICONFIG = "application/x-wifi-config";
private static final int TIMEOUT_MILLIS = 5000;
private final Service mService;
private final WifiManager mWifi;
private final ConnectivityManager mCm;
private final EventFacade mEventFacade;
private final IntentFilter mScanFilter;
private final IntentFilter mStateChangeFilter;
private final IntentFilter mTetherFilter;
private final IntentFilter mNetworkSuggestionStateChangeFilter;
private final WifiScanReceiver mScanResultsAvailableReceiver;
private final WifiScanResultsReceiver mWifiScanResultsReceiver;
private final WifiStateChangeReceiver mStateChangeReceiver;
private final WifiNetworkSuggestionStateChangeReceiver mNetworkSuggestionStateChangeReceiver;
private final HandlerThread mCallbackHandlerThread;
private final Object mCallbackLock = new Object();
private final Map<NetworkSpecifier, NetworkCallback> mNetworkCallbacks = new HashMap<>();
private boolean mTrackingWifiStateChange;
private boolean mTrackingTetherStateChange;
private boolean mTrackingNetworkSuggestionStateChange;
@GuardedBy("mCallbackLock")
private NetworkRequestUserSelectionCallback mNetworkRequestUserSelectionCallback;
private final SparseArray<SoftApCallbackImp> mSoftapCallbacks;
private final BroadcastReceiver mTetherStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(action)) {
Log.d("Wifi AP state changed.");
int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE,
WifiManager.WIFI_AP_STATE_FAILED);
if (state == WifiManager.WIFI_AP_STATE_ENABLED) {
mEventFacade.postEvent("WifiManagerApEnabled", null);
} else if (state == WifiManager.WIFI_AP_STATE_DISABLED) {
mEventFacade.postEvent("WifiManagerApDisabled", null);
}
} else if (ConnectivityManager.ACTION_TETHER_STATE_CHANGED.equals(action)) {
Log.d("Tether state changed.");
ArrayList<String> available = intent.getStringArrayListExtra(
ConnectivityManager.EXTRA_AVAILABLE_TETHER);
ArrayList<String> active = intent.getStringArrayListExtra(
ConnectivityManager.EXTRA_ACTIVE_TETHER);
ArrayList<String> errored = intent.getStringArrayListExtra(
ConnectivityManager.EXTRA_ERRORED_TETHER);
Bundle msg = new Bundle();
msg.putStringArrayList("AVAILABLE_TETHER", available);
msg.putStringArrayList("ACTIVE_TETHER", active);
msg.putStringArrayList("ERRORED_TETHER", errored);
mEventFacade.postEvent("TetherStateChanged", msg);
}
}
};
private final NetworkRequestMatchCallback mNetworkRequestMatchCallback =
new NetworkRequestMatchCallback() {
private static final String EVENT_TAG = mEventType + "NetworkRequestMatchCallback";
@Override
public void onUserSelectionCallbackRegistration(
NetworkRequestUserSelectionCallback userSelectionCallback) {
synchronized (mCallbackLock) {
mNetworkRequestUserSelectionCallback = userSelectionCallback;
}
}
@Override
public void onAbort() {
mEventFacade.postEvent(EVENT_TAG + "OnAbort", null);
}
@Override
public void onMatch(List<ScanResult> scanResults) {
mEventFacade.postEvent(EVENT_TAG + "OnMatch", scanResults);
}
@Override
public void onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration) {
mEventFacade.postEvent(EVENT_TAG + "OnUserSelectionConnectSuccess",
wifiConfiguration);
}
@Override
public void onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration) {
mEventFacade.postEvent(EVENT_TAG + "OnUserSelectionConnectFailure",
wifiConfiguration);
}
};
private final class NetworkCallbackImpl extends NetworkCallback {
private static final String EVENT_TAG = mEventType + "NetworkCallback";
@Override
public void onAvailable(Network network) {
mEventFacade.postEvent(EVENT_TAG + "OnAvailable", mWifi.getConnectionInfo());
}
@Override
public void onUnavailable() {
mEventFacade.postEvent(EVENT_TAG + "OnUnavailable", null);
}
@Override
public void onLost(Network network) {
mEventFacade.postEvent(EVENT_TAG + "OnLost", null);
}
};
private static class SoftApCallbackImp implements WifiManager.SoftApCallback {
// A monotonic increasing counter for softap callback ids.
private static int sCount = 0;
private final int mId;
private final EventFacade mEventFacade;
private final String mEventStr;
SoftApCallbackImp(EventFacade eventFacade) {
sCount++;
mId = sCount;
mEventFacade = eventFacade;
mEventStr = mEventType + "SoftApCallback-" + mId + "-";
}
@Override
public void onStateChanged(int state, int failureReason) {
Bundle msg = new Bundle();
msg.putInt("State", state);
msg.putInt("FailureReason", failureReason);
mEventFacade.postEvent(mEventStr + "OnStateChanged", msg);
}
@Override
public void onConnectedClientsChanged(List<WifiClient> clients) {
ArrayList<String> macAddresses = new ArrayList<>();
clients.forEach(x -> macAddresses.add(x.getMacAddress().toString()));
Bundle msg = new Bundle();
msg.putInt("NumClients", clients.size());
msg.putStringArrayList("MacAddresses", macAddresses);
mEventFacade.postEvent(mEventStr + "OnNumClientsChanged", msg);
mEventFacade.postEvent(mEventStr + "OnConnectedClientsChanged", clients);
}
@Override
public void onInfoChanged(SoftApInfo softApInfo) {
mEventFacade.postEvent(mEventStr + "OnInfoChanged", softApInfo);
}
@Override
public void onCapabilityChanged(SoftApCapability softApCapability) {
mEventFacade.postEvent(mEventStr + "OnCapabilityChanged", softApCapability);
}
@Override
public void onBlockedClientConnecting(WifiClient client, int blockedReason) {
Bundle msg = new Bundle();
msg.putString("WifiClient", client.getMacAddress().toString());
msg.putInt("BlockedReason", blockedReason);
mEventFacade.postEvent(mEventStr + "OnBlockedClientConnecting", msg);
}
};
private WifiLock mLock = null;
private boolean mIsConnected = false;
public WifiManagerFacade(FacadeManager manager) {
super(manager);
mService = manager.getService();
mWifi = (WifiManager) mService.getSystemService(Context.WIFI_SERVICE);
mCm = (ConnectivityManager) mService.getSystemService(Context.CONNECTIVITY_SERVICE);
mEventFacade = manager.getReceiver(EventFacade.class);
mCallbackHandlerThread = new HandlerThread("WifiManagerFacade");
mScanFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
mStateChangeFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mStateChangeFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
mStateChangeFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
mStateChangeFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
mStateChangeFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY - 1);
mTetherFilter = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
mTetherFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
mNetworkSuggestionStateChangeFilter = new IntentFilter(
WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);
mScanResultsAvailableReceiver = new WifiScanReceiver(mEventFacade);
mWifiScanResultsReceiver = new WifiScanResultsReceiver(mEventFacade);
mStateChangeReceiver = new WifiStateChangeReceiver();
mNetworkSuggestionStateChangeReceiver = new WifiNetworkSuggestionStateChangeReceiver();
mTrackingWifiStateChange = false;
mTrackingTetherStateChange = false;
mTrackingNetworkSuggestionStateChange = false;
mCallbackHandlerThread.start();
mSoftapCallbacks = new SparseArray<>();
}
private void makeLock(int wifiMode) {
if (mLock == null) {
mLock = mWifi.createWifiLock(wifiMode, "sl4a");
mLock.acquire();
}
}
/**
* Handle Broadcast receiver for Scan Result
*
* @parm eventFacade Object of EventFacade
*/
class WifiScanReceiver extends BroadcastReceiver {
private final EventFacade mEventFacade;
WifiScanReceiver(EventFacade eventFacade) {
mEventFacade = eventFacade;
}
@Override
public void onReceive(Context c, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
if (!intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)) {
Log.w("Wifi connection scan failed, ignoring.");
mEventFacade.postEvent(mEventType + "ScanFailure", null);
} else {
Bundle mResults = new Bundle();
Log.d("Wifi connection scan finished, results available.");
mResults.putLong("Timestamp", System.currentTimeMillis() / 1000);
mEventFacade.postEvent(mEventType + "ScanResultsAvailable", mResults);
}
mService.unregisterReceiver(mScanResultsAvailableReceiver);
}
}
}
class WifiScanResultsReceiver extends WifiManager.ScanResultsCallback {
private final EventFacade mEventFacade;
WifiScanResultsReceiver(EventFacade eventFacade) {
mEventFacade = eventFacade;
}
@Override
public void onScanResultsAvailable() {
Bundle mResults = new Bundle();
Log.d("Wifi connection scan finished, results available.");
mResults.putLong("Timestamp", System.currentTimeMillis() / 1000);
mEventFacade.postEvent(mEventType + "ScanResultsCallbackOnSuccess", mResults);
mWifi.unregisterScanResultsCallback(mWifiScanResultsReceiver);
}
}
class WifiActionListener implements WifiManager.ActionListener {
private final EventFacade mEventFacade;
private final String TAG;
public WifiActionListener(EventFacade eventFacade, String tag) {
mEventFacade = eventFacade;
this.TAG = tag;
}
@Override
public void onSuccess() {
Log.d("WifiActionListener onSuccess called for " + mEventType + TAG + "OnSuccess");
mEventFacade.postEvent(mEventType + TAG + "OnSuccess", null);
}
@Override
public void onFailure(int reason) {
Log.d("WifiActionListener onFailure called for" + mEventType);
Bundle msg = new Bundle();
msg.putInt("reason", reason);
mEventFacade.postEvent(mEventType + TAG + "OnFailure", msg);
}
}
public class WifiStateChangeReceiver extends BroadcastReceiver {
String mCachedWifiInfo = "";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
Log.d("Wifi network state changed.");
NetworkInfo nInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
Log.d("NetworkInfo " + nInfo);
// If network info is of type wifi, send wifi events.
if (nInfo.getType() == ConnectivityManager.TYPE_WIFI) {
if (nInfo.getDetailedState().equals(DetailedState.CONNECTED)) {
WifiInfo wInfo = mWifi.getConnectionInfo();
String bssid = wInfo.getBSSID();
if (bssid != null && !mCachedWifiInfo.equals(wInfo.toString())) {
Log.d("WifiNetworkConnected");
mEventFacade.postEvent("WifiNetworkConnected", wInfo);
}
mCachedWifiInfo = wInfo.toString();
} else {
if (nInfo.getDetailedState().equals(DetailedState.DISCONNECTED)) {
if (!mCachedWifiInfo.equals("")) {
mCachedWifiInfo = "";
mEventFacade.postEvent("WifiNetworkDisconnected", null);
}
}
}
}
} else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
Log.d("Supplicant connection state changed.");
mIsConnected = intent
.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false);
Bundle msg = new Bundle();
msg.putBoolean("Connected", mIsConnected);
mEventFacade.postEvent("SupplicantConnectionChanged", msg);
} else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
int state = intent.getIntExtra(
WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED);
Log.d("Wifi state changed to " + state);
boolean enabled;
if (state == WifiManager.WIFI_STATE_DISABLED) {
enabled = false;
} else if (state == WifiManager.WIFI_STATE_ENABLED) {
enabled = true;
} else {
// we only care about enabled/disabled.
Log.v("Ignoring intermediate wifi state change event...");
return;
}
Bundle msg = new Bundle();
msg.putBoolean("enabled", enabled);
mEventFacade.postEvent("WifiStateChanged", msg);
}
}
}
public class WifiNetworkSuggestionStateChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
WifiNetworkSuggestion networkSuggestion =
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_SUGGESTION);
mEventFacade.postEvent(
"WifiNetworkSuggestionPostConnection",
networkSuggestion.wifiConfiguration.SSID);
}
}
}
public class WifiWpsCallback extends WifiManager.WpsCallback {
private static final String tag = "WifiWps";
@Override
public void onStarted(String pin) {
Bundle msg = new Bundle();
msg.putString("pin", pin);
mEventFacade.postEvent(tag + "OnStarted", msg);
}
@Override
public void onSucceeded() {
Log.d("Wps op succeeded");
mEventFacade.postEvent(tag + "OnSucceeded", null);
}
@Override
public void onFailed(int reason) {
Bundle msg = new Bundle();
msg.putInt("reason", reason);
mEventFacade.postEvent(tag + "OnFailed", msg);
}
}
private void applyingkeyMgmt(WifiConfiguration config, ScanResult result) {
if (result.capabilities.contains("WEP")) {
config.allowedKeyManagement.set(KeyMgmt.NONE);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
} else if (result.capabilities.contains("PSK")) {
config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
} else if (result.capabilities.contains("EAP")) {
// this is probably wrong, as we don't have a way to enter the enterprise config
config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
} else {
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
}
}
private WifiConfiguration genWifiConfig(JSONObject j) throws JSONException {
if (j == null) {
return null;
}
WifiConfiguration config = new WifiConfiguration();
if (j.has("SSID")) {
config.SSID = "\"" + j.getString("SSID") + "\"";
} else if (j.has("ssid")) {
config.SSID = "\"" + j.getString("ssid") + "\"";
}
if (j.has("password")) {
String security;
// Check if new security type SAE (WPA3) is present. Default to PSK
if (j.has("security")) {
if (TextUtils.equals(j.getString("security"), "SAE")) {
config.allowedKeyManagement.set(KeyMgmt.SAE);
config.requirePmf = true;
} else {
config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
}
} else {
config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
}
config.preSharedKey = "\"" + j.getString("password") + "\"";
} else if (j.has("preSharedKey")) {
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
config.preSharedKey = j.getString("preSharedKey");
} else {
if (j.has("security")) {
if (TextUtils.equals(j.getString("security"), "OWE")) {
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
config.requirePmf = true;
} else {
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
}
} else {
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
}
}
if (j.has("BSSID")) {
config.BSSID = j.getString("BSSID");
}
if (j.has("hiddenSSID")) {
config.hiddenSSID = j.getBoolean("hiddenSSID");
}
if (j.has("priority")) {
config.priority = j.getInt("priority");
}
if (j.has("apBand")) {
config.apBand = j.getInt("apBand");
}
if (j.has("wepKeys")) {
// Looks like we only support static WEP.
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
JSONArray keys = j.getJSONArray("wepKeys");
String[] wepKeys = new String[keys.length()];
for (int i = 0; i < keys.length(); i++) {
wepKeys[i] = keys.getString(i);
}
config.wepKeys = wepKeys;
}
if (j.has("wepTxKeyIndex")) {
config.wepTxKeyIndex = j.getInt("wepTxKeyIndex");
}
if (j.has("meteredOverride")) {
config.meteredOverride = j.getInt("meteredOverride");
}
if (j.has("macRand")) {
config.macRandomizationSetting = j.getInt("macRand");
}
if (j.has("carrierId")) {
config.carrierId = j.getInt("carrierId");
}
return config;
}
private WifiEnterpriseConfig genWifiEnterpriseConfig(JSONObject j) throws JSONException,
GeneralSecurityException {
WifiEnterpriseConfig eConfig = new WifiEnterpriseConfig();
if (j.has(WifiEnterpriseConfig.EAP_KEY)) {
int eap = j.getInt(WifiEnterpriseConfig.EAP_KEY);
eConfig.setEapMethod(eap);
}
if (j.has(WifiEnterpriseConfig.PHASE2_KEY)) {
int p2Method = j.getInt(WifiEnterpriseConfig.PHASE2_KEY);
eConfig.setPhase2Method(p2Method);
}
if (j.has(WifiEnterpriseConfig.CA_CERT_KEY)) {
String certStr = j.getString(WifiEnterpriseConfig.CA_CERT_KEY);
Log.v("CA Cert String is " + certStr);
eConfig.setCaCertificate(strToX509Cert(certStr));
}
if (j.has(WifiEnterpriseConfig.CLIENT_CERT_KEY)
&& j.has(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY)) {
String certStr = j.getString(WifiEnterpriseConfig.CLIENT_CERT_KEY);
String keyStr = j.getString(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY);
Log.v("Client Cert String is " + certStr);
Log.v("Client Key String is " + keyStr);
X509Certificate cert = strToX509Cert(certStr);
PrivateKey privKey = strToPrivateKey(keyStr);
Log.v("Cert is " + cert);
Log.v("Private Key is " + privKey);
eConfig.setClientKeyEntry(privKey, cert);
}
if (j.has(WifiEnterpriseConfig.IDENTITY_KEY)) {
String identity = j.getString(WifiEnterpriseConfig.IDENTITY_KEY);
Log.v("Setting identity to " + identity);
eConfig.setIdentity(identity);
}
if (j.has(WifiEnterpriseConfig.PASSWORD_KEY)) {
String pwd = j.getString(WifiEnterpriseConfig.PASSWORD_KEY);
Log.v("Setting password to " + pwd);
eConfig.setPassword(pwd);
}
if (j.has(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY)) {
String altSub = j.getString(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY);
Log.v("Setting Alt Subject to " + altSub);
eConfig.setAltSubjectMatch(altSub);
}
if (j.has(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY)) {
String domSuffix = j.getString(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY);
Log.v("Setting Domain Suffix Match to " + domSuffix);
eConfig.setDomainSuffixMatch(domSuffix);
}
if (j.has(WifiEnterpriseConfig.REALM_KEY)) {
String realm = j.getString(WifiEnterpriseConfig.REALM_KEY);
Log.v("Setting Domain Suffix Match to " + realm);
eConfig.setRealm(realm);
}
if (j.has(WifiEnterpriseConfig.OCSP)) {
int ocsp = j.getInt(WifiEnterpriseConfig.OCSP);
Log.v("Setting OCSP to " + ocsp);
eConfig.setOcsp(ocsp);
}
return eConfig;
}
private WifiConfiguration genWifiConfigWithEnterpriseConfig(JSONObject j) throws JSONException,
GeneralSecurityException {
if (j == null) {
return null;
}
WifiConfiguration config = new WifiConfiguration();
config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
if (j.has("security")) {
if (TextUtils.equals(j.getString("security"), "SUITE_B_192")) {
config.allowedKeyManagement.set(KeyMgmt.SUITE_B_192);
config.requirePmf = true;
}
}
if (j.has("SSID")) {
config.SSID = "\"" + j.getString("SSID") + "\"";
} else if (j.has("ssid")) {
config.SSID = "\"" + j.getString("ssid") + "\"";
}
if (j.has("FQDN")) {
config.FQDN = j.getString("FQDN");
}
if (j.has("providerFriendlyName")) {
config.providerFriendlyName = j.getString("providerFriendlyName");
}
if (j.has("roamingConsortiumIds")) {
JSONArray ids = j.getJSONArray("roamingConsortiumIds");
long[] rIds = new long[ids.length()];
for (int i = 0; i < ids.length(); i++) {
rIds[i] = ids.getLong(i);
}
config.roamingConsortiumIds = rIds;
}
if (j.has("carrierId")) {
config.carrierId = j.getInt("carrierId");
}
config.enterpriseConfig = genWifiEnterpriseConfig(j);
return config;
}
private NetworkSpecifier genWifiNetworkSpecifier(JSONObject j) throws JSONException,
GeneralSecurityException {
if (j == null) {
return null;
}
WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();
if (j.has("SSID")) {
builder = builder.setSsid(j.getString("SSID"));
} else if (j.has("ssidPattern")) {
builder = builder.setSsidPattern(
new PatternMatcher(j.getString("ssidPattern"),
PatternMatcher.PATTERN_ADVANCED_GLOB));
}
if (j.has("BSSID")) {
builder = builder.setBssid(MacAddress.fromString(j.getString("BSSID")));
} else if (j.has("bssidPattern")) {
builder = builder.setBssidPattern(
MacAddress.fromString(j.getJSONArray("bssidPattern").getString(0)),
MacAddress.fromString(j.getJSONArray("bssidPattern").getString(1)));
}
if (j.has("hiddenSSID")) {
builder = builder.setIsHiddenSsid(j.getBoolean("hiddenSSID"));
}
if (j.has("isEnhancedOpen")) {
builder = builder.setIsEnhancedOpen(j.getBoolean("isEnhancedOpen"));
}
boolean isWpa3 = false;
if (j.has("isWpa3") && j.getBoolean("isWpa3")) {
isWpa3 = true;
}
if (j.has("password") && !j.has(WifiEnterpriseConfig.EAP_KEY)) {
if (!isWpa3) {
builder = builder.setWpa2Passphrase(j.getString("password"));
} else {
builder = builder.setWpa3Passphrase(j.getString("password"));
}
}
if (j.has(WifiEnterpriseConfig.EAP_KEY)) {
if (!isWpa3) {
builder = builder.setWpa2EnterpriseConfig(genWifiEnterpriseConfig(j));
} else {
builder = builder.setWpa3EnterpriseConfig(genWifiEnterpriseConfig(j));
}
}
return builder.build();
}
private WifiNetworkSuggestion genWifiNetworkSuggestion(JSONObject j) throws JSONException,
GeneralSecurityException, IOException {
if (j == null) {
return null;
}
WifiNetworkSuggestion.Builder builder = new WifiNetworkSuggestion.Builder();
if (j.has("isAppInteractionRequired")) {
builder = builder.setIsAppInteractionRequired(j.getBoolean("isAppInteractionRequired"));
}
if (j.has("isUserInteractionRequired")) {
builder = builder.setIsUserInteractionRequired(
j.getBoolean("isUserInteractionRequired"));
}
if (j.has("isMetered")) {
builder = builder.setIsMetered(j.getBoolean("isMetered"));
}
if (j.has("priority")) {
builder = builder.setPriority(j.getInt("priority"));
}
if (j.has("carrierId")) {
builder.setCarrierId(j.getInt("carrierId"));
}
if (j.has("enableAutojoin")) {
builder.setIsInitialAutojoinEnabled(j.getBoolean("enableAutojoin"));
}
if (j.has("untrusted")) {
builder.setUntrusted(j.getBoolean("untrusted"));
}
if (j.has("profile")) {
builder = builder.setPasspointConfig(genWifiPasspointConfig(j));
} else {
if (j.has("SSID")) {
builder = builder.setSsid(j.getString("SSID"));
}
if (j.has("BSSID")) {
builder = builder.setBssid(MacAddress.fromString(j.getString("BSSID")));
}
if (j.has("hiddenSSID")) {
builder = builder.setIsHiddenSsid(j.getBoolean("hiddenSSID"));
}
if (j.has("isEnhancedOpen")) {
builder = builder.setIsEnhancedOpen(j.getBoolean("isEnhancedOpen"));
}
boolean isWpa3 = false;
if (j.has("isWpa3") && j.getBoolean("isWpa3")) {
isWpa3 = true;
}
if (j.has("password") && !j.has(WifiEnterpriseConfig.EAP_KEY)) {
if (!isWpa3) {
builder = builder.setWpa2Passphrase(j.getString("password"));
} else {
builder = builder.setWpa3Passphrase(j.getString("password"));
}
}
if (j.has(WifiEnterpriseConfig.EAP_KEY)) {
if (!isWpa3) {
builder = builder.setWpa2EnterpriseConfig(genWifiEnterpriseConfig(j));
} else {
builder = builder.setWpa3EnterpriseConfig(genWifiEnterpriseConfig(j));
}
}
}
return builder.build();
}
private List<WifiNetworkSuggestion> genWifiNetworkSuggestions(
JSONArray jsonNetworkSuggestionsArray) throws JSONException, GeneralSecurityException,
IOException {
if (jsonNetworkSuggestionsArray == null) {
return null;
}
List<WifiNetworkSuggestion> networkSuggestions = new ArrayList<>();
for (int i = 0; i < jsonNetworkSuggestionsArray.length(); i++) {
networkSuggestions.add(
genWifiNetworkSuggestion(jsonNetworkSuggestionsArray.getJSONObject(i)));
}
return networkSuggestions;
}
private boolean matchScanResult(ScanResult result, String id) {
if (result.BSSID.equals(id) || result.SSID.equals(id)) {
return true;
}
return false;
}
private WpsInfo parseWpsInfo(String infoStr) throws JSONException {
if (infoStr == null) {
return null;
}
JSONObject j = new JSONObject(infoStr);
WpsInfo info = new WpsInfo();
if (j.has("setup")) {
info.setup = j.getInt("setup");
}
if (j.has("BSSID")) {
info.BSSID = j.getString("BSSID");
}
if (j.has("pin")) {
info.pin = j.getString("pin");
}
return info;
}
private byte[] base64StrToBytes(String input) {
return Base64.decode(input, Base64.DEFAULT);
}
private X509Certificate strToX509Cert(String certStr) throws CertificateException {
byte[] certBytes = base64StrToBytes(certStr);
InputStream certStream = new ByteArrayInputStream(certBytes);
CertificateFactory cf = CertificateFactory.getInstance("X509");
return (X509Certificate) cf.generateCertificate(certStream);
}
private PrivateKey strToPrivateKey(String key) throws NoSuchAlgorithmException,
InvalidKeySpecException {
byte[] keyBytes = base64StrToBytes(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey priv = fact.generatePrivate(keySpec);
return priv;
}
private PublicKey strToPublicKey(String key) throws NoSuchAlgorithmException,
InvalidKeySpecException {
byte[] keyBytes = base64StrToBytes(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pub = fact.generatePublic(keySpec);
return pub;
}
private WifiConfiguration wifiConfigurationFromScanResult(ScanResult result) {
if (result == null)
return null;
WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"" + result.SSID + "\"";
applyingkeyMgmt(config, result);
config.BSSID = result.BSSID;
return config;
}
@Rpc(description = "test.")
public String wifiTest(
@RpcParameter(name = "certString") String certString) throws CertificateException, IOException {
// TODO(angli): Make this work. Convert a X509Certificate back to a string.
X509Certificate caCert = strToX509Cert(certString);
caCert.getEncoded();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(caCert);
byte[] data = bos.toByteArray();
bos.close();
return Base64.encodeToString(data, Base64.DEFAULT);
}
@Rpc(description = "Add a network.")
@Deprecated
public Integer wifiAddNetwork(@RpcParameter(name = "wifiConfig") JSONObject wifiConfig)
throws JSONException {
return wifiaddOrUpdateNetwork(wifiConfig);
}
@Rpc(description = "Add or update a network.")
public Integer wifiaddOrUpdateNetwork(@RpcParameter(name = "wifiConfig") JSONObject wifiConfig)
throws JSONException {
return mWifi.addNetwork(genWifiConfig(wifiConfig));
}
@Rpc(description = "Cancel Wi-fi Protected Setup.")
public void wifiCancelWps() throws JSONException {
WifiWpsCallback listener = new WifiWpsCallback();
mWifi.cancelWps(listener);
}
@Rpc(description = "Checks Wifi state.", returns = "True if Wifi is enabled.")
public Boolean wifiCheckState() {
return mWifi.getWifiState() == WifiManager.WIFI_STATE_ENABLED;
}
/**
* @deprecated Use {@link #wifiConnectByConfig(config)} instead.
*/
@Rpc(description = "Connects to the network with the given configuration")
@Deprecated
public Boolean wifiConnect(@RpcParameter(name = "config") JSONObject config)
throws JSONException {
try {
wifiConnectByConfig(config);
} catch (GeneralSecurityException e) {
String msg = "Caught GeneralSecurityException with the provided"
+ "configuration";
throw new RuntimeException(msg);
}
return true;
}
/**
* @deprecated Use {@link #wifiConnectByConfig(config)} instead.
*/
@Rpc(description = "Connects to the network with the given configuration")
@Deprecated
public Boolean wifiEnterpriseConnect(@RpcParameter(name = "config")
JSONObject config) throws JSONException, GeneralSecurityException {
try {
wifiConnectByConfig(config);
} catch (GeneralSecurityException e) {
throw e;
}
return true;
}
/**
* Connects to a wifi network using configuration.
* @param config JSONObject Dictionary of wifi connection parameters
* @throws JSONException
* @throws GeneralSecurityException
*/
@Rpc(description = "Connects to the network with the given configuration")
public void wifiConnectByConfig(@RpcParameter(name = "config") JSONObject config)
throws JSONException, GeneralSecurityException {
WifiConfiguration wifiConfig;
WifiActionListener listener;
// Check if this is 802.1x or 802.11x config.
if (config.has(WifiEnterpriseConfig.EAP_KEY)) {
wifiConfig = genWifiConfigWithEnterpriseConfig(config);
} else {
wifiConfig = genWifiConfig(config);
}
listener = new WifiActionListener(mEventFacade,
WifiConstants.WIFI_CONNECT_BY_CONFIG_CALLBACK);
mWifi.connect(wifiConfig, listener);
}
/**
* Gets the Wi-Fi factory MAC addresses.
* @return An array of String represnting Wi-Fi MAC addresses,
* Or an empty Srting if failed.
*/
@Rpc(description = "Gets the Wi-Fi factory MAC addresses", returns = "An array of String, representing the MAC address")
public String[] wifigetFactorymacAddresses(){
return mWifi.getFactoryMacAddresses();
}
@Rpc(description = "Gets the randomized MAC address", returns = "A MAC address or null")
public MacAddress wifigetRandomizedMacAddress(@RpcParameter(name = "config") JSONObject config)
throws JSONException{
List<WifiConfiguration> configList = mWifi.getConfiguredNetworks();
for(WifiConfiguration WifiConfig : configList){
String ssid = WifiConfig.SSID;
ssid = ssid.replace("\"", "");
if (ssid.equals(config.getString("SSID"))){
return WifiConfig.getRandomizedMacAddress();
}
}
Log.d("Did not find a matching object in wifiManager.");
return null;
}
/**
* Generate a Passpoint configuration from JSON config.
* @param config JSON config containing base64 encoded Passpoint profile
*/
@Rpc(description = "Generate Passpoint configuration", returns = "PasspointConfiguration object")
public PasspointConfiguration genWifiPasspointConfig(@RpcParameter(
name = "config") JSONObject config)
throws JSONException,CertificateException, IOException {
String profileStr = "";
if (config == null) {
return null;
}
if (config.has("profile")) {
profileStr = config.getString("profile");
}
return ConfigParser.parsePasspointConfig(TYPE_WIFICONFIG,
profileStr.getBytes());
}
/**
* Add or update a Passpoint configuration.
* @param config base64 encoded message containing Passpoint profile
* @throws JSONException
*/
@Rpc(description = "Add or update a Passpoint configuration")
public void addUpdatePasspointConfig(@RpcParameter(
name = "config") JSONObject config)
throws JSONException,CertificateException, IOException {
PasspointConfiguration passpointConfig = genWifiPasspointConfig(config);
mWifi.addOrUpdatePasspointConfiguration(passpointConfig);
}
/**
* Remove a Passpoint configuration.
* @param fqdn The FQDN of the passpoint configuration to be removed
* @return true on success; false otherwise
*/
@Rpc(description = "Remove a Passpoint configuration")
public void removePasspointConfig(
@RpcParameter(name = "fqdn") String fqdn) {
mWifi.removePasspointConfiguration(fqdn);
}
/**
* Get list of Passpoint configurations.
* @return A list of FQDNs of the Passpoint configurations
*/
@Rpc(description = "Return the list of installed Passpoint configurations", returns = "A list of Passpoint configurations")
public List<String> getPasspointConfigs() {
List<String> fqdnList = new ArrayList<String>();
for(PasspointConfiguration passpoint :
mWifi.getPasspointConfigurations()) {
fqdnList.add(passpoint.getHomeSp().getFqdn());
}
return fqdnList;
}
private class ProvisioningCallbackFacade extends ProvisioningCallback {
private final EventFacade mEventFacade;
ProvisioningCallbackFacade(EventFacade eventFacade) {
mEventFacade = eventFacade;
}
@Override
public void onProvisioningFailure(int status) {
Log.v("Provisioning Failure " + status);
Bundle msg = new Bundle();
msg.putString("tag", "failure");
msg.putInt("reason", status);
mEventFacade.postEvent("onProvisioningCallback", msg);
}
@Override
public void onProvisioningStatus(int status) {
Log.v("Provisioning status " + status);
Bundle msg = new Bundle();
msg.putString("tag", "status");
msg.putInt("status", status);
mEventFacade.postEvent("onProvisioningCallback", msg);
}
@Override
public void onProvisioningComplete() {
Log.v("Provisioning Complete");
Bundle msg = new Bundle();
msg.putString("tag", "success");
mEventFacade.postEvent("onProvisioningCallback", msg);
}
}
private OsuProvider buildTestOsuProvider(JSONObject config) {
String osuServiceDescription = "Google Passpoint Test Service";
List<Integer> osuMethodList =
Arrays.asList(OsuProvider.METHOD_SOAP_XML_SPP);
try {
if (!config.has("osuSSID")) {
Log.e("missing osuSSID from the config");
return null;
}
String osuSsid = config.getString("osuSSID");
if (!config.has("osuUri")) {
Log.e("missing osuUri from the config");
return null;
}
Uri osuServerUri = Uri.parse(config.getString("osuUri"));
Log.v("OSU Server URI " + osuServerUri.toString());
if (!config.has("osuFriendlyName")) {
Log.e("missing osuFriendlyName from the config");
return null;
}
String osuFriendlyName = config.getString("osuFriendlyName");
if (config.has("description")) {
osuServiceDescription = config.getString("description");
}
Map<String, String> osuFriendlyNames = new HashMap<>();
osuFriendlyNames.put("eng", osuFriendlyName);
return new OsuProvider(osuSsid, osuFriendlyNames, osuServiceDescription,
osuServerUri, null, osuMethodList);
} catch (JSONException e) {
Log.e("JSON Parsing error: " + e);
return null;
}
}
/**
* Start subscription provisioning
*/
@Rpc(description = "Starts subscription provisioning flow")
public void startSubscriptionProvisioning(
@RpcParameter(name = "configJson") JSONObject configJson) {
ProvisioningCallback callback = new ProvisioningCallbackFacade(mEventFacade);
mWifi.startSubscriptionProvisioning(buildTestOsuProvider(configJson),
mService.getMainExecutor(), callback);
}
/**
* Connects to a wifi network using networkId.
* @param networkId the network identity for the network in the supplicant
*/
@Rpc(description = "Connects to the network with the given networkId")
public void wifiConnectByNetworkId(
@RpcParameter(name = "networkId") Integer networkId) {
WifiActionListener listener;
listener = new WifiActionListener(mEventFacade,
WifiConstants.WIFI_CONNECT_BY_NETID_CALLBACK);
mWifi.connect(networkId, listener);
}
@Rpc(description = "Disconnects from the currently active access point.", returns = "True if the operation succeeded.")
public Boolean wifiDisconnect() {
return mWifi.disconnect();
}
@Rpc(description = "Enable/disable autojoin scan and switch network when connected.")
public Boolean wifiSetEnableAutoJoinWhenAssociated(@RpcParameter(name = "enable") Boolean enable) {
return mWifi.setEnableAutoJoinWhenAssociated(enable);
}
@Rpc(description = "Enable a configured network. Initiate a connection if disableOthers is true", returns = "True if the operation succeeded.")
public Boolean wifiEnableNetwork(@RpcParameter(name = "netId") Integer netId,
@RpcParameter(name = "disableOthers") Boolean disableOthers) {
return mWifi.enableNetwork(netId, disableOthers);
}
@Rpc(description = "Enable WiFi verbose logging.")
public void wifiEnableVerboseLogging(@RpcParameter(name = "level") Integer level) {
mWifi.setVerboseLoggingEnabled(level > 0);
}
@Rpc(description = "Resets all WifiManager settings.")
public void wifiFactoryReset() {
mWifi.factoryReset();
}
/**
* Forget a wifi network by networkId.
*
* @param networkId Id of wifi network
*/
@Rpc(description = "Forget a wifi network by networkId")
public void wifiForgetNetwork(@RpcParameter(name = "wifiSSID") Integer networkId) {
WifiActionListener listener = new WifiActionListener(mEventFacade,
WifiConstants.WIFI_FORGET_NETWORK_CALLBACK);
mWifi.forget(networkId, listener);
}
/**
* User disconnect network.
*
* @param ssid SSID of wifi network
*/
@Rpc(description = "Disconnect a wifi network by SSID")
public void wifiUserDisconnectNetwork(@RpcParameter(name = "ssid") String ssid) {
mWifi.disableEphemeralNetwork("\"" + ssid + "\"");
mWifi.disconnect();
}
/**
* User disconnect passpoint network.
*
* @param fqdn FQDN of the passpoint network
*/
@Rpc(description = "Disconnect a wifi network by FQDN")
public void wifiUserDisconnectPasspointNetwork(@RpcParameter(name = "fqdn") String fqdn) {
mWifi.disableEphemeralNetwork(fqdn);
mWifi.disconnect();
}
/**
* Get SoftAp Configuration with SoftApConfiguration.
*/
@Rpc(description = "Gets the Wi-Fi AP Configuration.")
public SoftApConfiguration wifiGetApConfiguration() {
return mWifi.getSoftApConfiguration();
}
/**
* Get SoftAp Configuration with WifiConfiguration.
*
* Used to test deprecated API to check backward compatible
*/
@Rpc(description = "Gets the Wi-Fi AP Configuration with WifiConfiguration.")
public WifiConfiguration wifiGetApConfigurationWithWifiConfiguration() {
return mWifi.getWifiApConfiguration();
}
@Rpc(description = "Return a list of all the configured wifi networks.")
public List<WifiConfiguration> wifiGetConfiguredNetworks() {
return mWifi.getConfiguredNetworks();
}
@Rpc(description = "Returns information about the currently active access point.")
public WifiInfo wifiGetConnectionInfo() {
return mWifi.getConnectionInfo();
}
@Rpc(description = "Returns wifi activity and energy usage info.")
public WifiActivityEnergyInfo wifiGetControllerActivityEnergyInfo() {
WifiActivityEnergyInfo[] mutable = {null};
CountDownLatch latch = new CountDownLatch(1);
mWifi.getWifiActivityEnergyInfoAsync(new Executor() {
@Override
public void execute(Runnable runnable) {
runnable.run();
}
}, info -> {
mutable[0] = info;
latch.countDown();
});
boolean completedSuccessfully = false;
try {
completedSuccessfully = latch.await(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Log.w("Interrupted while awaiting for WifiManager.getWifiActivityEnergyInfoAsync()");
}
if (completedSuccessfully) {
return mutable[0];
} else {
Log.w("WifiManager.getWifiActivityEnergyInfoAsync() timed out after "
+ TIMEOUT_MILLIS + " milliseconds");
return null;
}
}
@Rpc(description = "Get the country code used by WiFi.")
public String wifiGetCountryCode() {
return mWifi.getCountryCode();
}
@Rpc(description = "Get the current network.")
public Network wifiGetCurrentNetwork() {
return mWifi.getCurrentNetwork();
}
@Rpc(description = "Get the info from last successful DHCP request.")
public DhcpInfo wifiGetDhcpInfo() {
return mWifi.getDhcpInfo();
}
@Rpc(description = "Get setting for Framework layer autojoin enable status.")
public Boolean wifiGetEnableAutoJoinWhenAssociated() {
return mWifi.getEnableAutoJoinWhenAssociated();
}
@Rpc(description = "Get privileged configured networks.")
public List<WifiConfiguration> wifiGetPrivilegedConfiguredNetworks() {
return mWifi.getPrivilegedConfiguredNetworks();
}
@Rpc(description = "Returns the list of access points found during the most recent Wifi scan.")
public List<ScanResult> wifiGetScanResults() {
return mWifi.getScanResults();
}
@Rpc(description = "Get the current level of WiFi verbose logging.")
public Integer wifiGetVerboseLoggingLevel() {
return mWifi.isVerboseLoggingEnabled() ? 1 : 0;
}
@Rpc(description = "true if this adapter supports 5 GHz band.")
public Boolean wifiIs5GHzBandSupported() {
return mWifi.is5GHzBandSupported();
}
@Rpc(description = "true if this adapter supports multiple simultaneous connections.")
public Boolean wifiIsAdditionalStaSupported() {
return mWifi.isAdditionalStaSupported();
}
@Rpc(description = "Return true if WiFi is enabled.")
public Boolean wifiGetisWifiEnabled() {
return mWifi.isWifiEnabled();
}
@Rpc(description = "Return whether Wi-Fi AP is enabled or disabled.")
public Boolean wifiIsApEnabled() {
return mWifi.isWifiApEnabled();
}
@Rpc(description = "Check if Device-to-AP RTT is supported.")
public Boolean wifiIsDeviceToApRttSupported() {
return mWifi.isDeviceToApRttSupported();
}
@Rpc(description = "Check if Device-to-device RTT is supported.")
public Boolean wifiIsDeviceToDeviceRttSupported() {
return mWifi.isDeviceToDeviceRttSupported();
}
/**
* @return true if chipset supports 5GHz band and false otherwise.
*/
@Rpc(description = "Check if the chipset supports 5GHz frequency band.")
public Boolean is5GhzBandSupported() {
return mWifi.is5GHzBandSupported();
}
/**
* @return true if chipset supports 6GHz band and false otherwise.
*/
@Rpc(description = "Check if the chipset supports 6GHz frequency band.")
public Boolean is6GhzBandSupported() {
return mWifi.is6GHzBandSupported();
}
@Rpc(description = "Check if this adapter supports advanced power/performance counters.")
public Boolean wifiIsEnhancedPowerReportingSupported() {
return mWifi.isEnhancedPowerReportingSupported();
}
@Rpc(description = "Check if multicast is enabled.")
public Boolean wifiIsMulticastEnabled() {
return mWifi.isMulticastEnabled();
}
@Rpc(description = "true if this adapter supports Wi-Fi Aware APIs.")
public Boolean wifiIsAwareSupported() {
return mWifi.isWifiAwareSupported();
}
@Rpc(description = "true if this adapter supports Off Channel Tunnel Directed Link Setup.")
public Boolean wifiIsOffChannelTdlsSupported() {
return mWifi.isOffChannelTdlsSupported();
}
@Rpc(description = "true if this adapter supports WifiP2pManager (Wi-Fi Direct).")
public Boolean wifiIsP2pSupported() {
return mWifi.isP2pSupported();
}
@Rpc(description = "true if this adapter supports passpoint.")
public Boolean wifiIsPasspointSupported() {
return mWifi.isPasspointSupported();
}
@Rpc(description = "true if this adapter supports portable Wi-Fi hotspot.")
public Boolean wifiIsPortableHotspotSupported() {
return mWifi.isPortableHotspotSupported();
}
@Rpc(description = "true if this adapter supports offloaded connectivity scan.")
public Boolean wifiIsPreferredNetworkOffloadSupported() {
return mWifi.isPreferredNetworkOffloadSupported();
}
@Rpc(description = "Check if wifi scanner is supported on this device.")
public Boolean wifiIsScannerSupported() {
return mWifi.isWifiScannerSupported();
}
@Rpc(description = "Check if tdls is supported on this device.")
public Boolean wifiIsTdlsSupported() {
return mWifi.isTdlsSupported();
}
/**
* @return true if this device supports WPA3-Personal SAE
*/
@Rpc(description = "Check if WPA3-Personal SAE is supported on this device.")
public Boolean wifiIsWpa3SaeSupported() {
return mWifi.isWpa3SaeSupported();
}
/**
* @return true if this device supports WPA3-Enterprise Suite-B-192
*/
@Rpc(description = "Check if WPA3-Enterprise Suite-B-192 is supported on this device.")
public Boolean wifiIsWpa3SuiteBSupported() {
return mWifi.isWpa3SuiteBSupported();
}
/**
* @return true if this device supports Wi-Fi Enhanced Open (OWE)
*/
@Rpc(description = "Check if Enhanced Open (OWE) is supported on this device.")
public Boolean wifiIsEnhancedOpenSupported() {
return mWifi.isEnhancedOpenSupported();
}
/**
* @return true if this device supports Wi-Fi Device Provisioning Protocol (Easy-connect)
*/
@Rpc(description = "Check if Easy Connect (DPP) is supported on this device.")
public Boolean wifiIsEasyConnectSupported() {
return mWifi.isEasyConnectSupported();
}
@Rpc(description = "Acquires a full Wifi lock.")
public void wifiLockAcquireFull() {
makeLock(WifiManager.WIFI_MODE_FULL);
}
@Rpc(description = "Acquires a scan only Wifi lock.")
public void wifiLockAcquireScanOnly() {
makeLock(WifiManager.WIFI_MODE_SCAN_ONLY);
}
@Rpc(description = "Releases a previously acquired Wifi lock.")
public void wifiLockRelease() {
if (mLock != null) {
mLock.release();
mLock = null;
}
}
@Rpc(description = "Reassociates with the currently active access point.", returns = "True if the operation succeeded.")
public Boolean wifiReassociate() {
return mWifi.reassociate();
}
@Rpc(description = "Reconnects to the currently active access point.", returns = "True if the operation succeeded.")
public Boolean wifiReconnect() {
return mWifi.reconnect();
}
@Rpc(description = "Remove a configured network.", returns = "True if the operation succeeded.")
public Boolean wifiRemoveNetwork(@RpcParameter(name = "netId") Integer netId) {
return mWifi.removeNetwork(netId);
}
private SoftApConfiguration createSoftApConfiguration(JSONObject configJson)
throws JSONException {
if (configJson == null) {
return null;
}
SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
if (configJson.has("SSID")) {
configBuilder.setSsid(configJson.getString("SSID"));
}
if (configJson.has("password")) {
String pwd = configJson.getString("password");
// Check if new security type SAE (WPA3) is present. Default to PSK
if (configJson.has("security")) {
String securityType = configJson.getString("security");
if (TextUtils.equals(securityType, "WPA2_PSK")) {
configBuilder.setPassphrase(pwd, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
} else if (TextUtils.equals(securityType, "WPA3_SAE_TRANSITION")) {
configBuilder.setPassphrase(pwd,
SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION);
} else if (TextUtils.equals(securityType, "WPA3_SAE")) {
configBuilder.setPassphrase(pwd, SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
}
} else {
configBuilder.setPassphrase(pwd, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
}
}
if (configJson.has("BSSID")) {
configBuilder.setBssid(MacAddress.fromString(configJson.getString("BSSID")));
}
if (configJson.has("hiddenSSID")) {
configBuilder.setHiddenSsid(configJson.getBoolean("hiddenSSID"));
}
if (configJson.has("apBand")) {
configBuilder.setBand(configJson.getInt("apBand"));
}
if (configJson.has("apChannel") && configJson.has("apBand")) {
configBuilder.setChannel(configJson.getInt("apChannel"), configJson.getInt("apBand"));
}
if (configJson.has("MaxNumberOfClients")) {
configBuilder.setMaxNumberOfClients(configJson.getInt("MaxNumberOfClients"));
}
if (configJson.has("ShutdownTimeoutMillis")) {
configBuilder.setShutdownTimeoutMillis(configJson.getLong("ShutdownTimeoutMillis"));
}
if (configJson.has("AutoShutdownEnabled")) {
configBuilder.setAutoShutdownEnabled(configJson.getBoolean("AutoShutdownEnabled"));
}
if (configJson.has("ClientControlByUserEnabled")) {
configBuilder.setClientControlByUserEnabled(
configJson.getBoolean("ClientControlByUserEnabled"));
}
List allowedClientList = new ArrayList<>();
if (configJson.has("AllowedClientList")) {
JSONArray allowedList = configJson.getJSONArray("AllowedClientList");
for (int i = 0; i < allowedList.length(); i++) {
allowedClientList.add(MacAddress.fromString(allowedList.getString(i)));
}
}
List blockedClientList = new ArrayList<>();
if (configJson.has("BlockedClientList")) {
JSONArray blockedList = configJson.getJSONArray("BlockedClientList");
for (int j = 0; j < blockedList.length(); j++) {
blockedClientList.add(MacAddress.fromString(blockedList.getString(j)));
}
}
configBuilder.setAllowedClientList(allowedClientList);
configBuilder.setBlockedClientList(blockedClientList);
return configBuilder.build();
}
private WifiConfiguration createSoftApWifiConfiguration(JSONObject configJson)
throws JSONException {
WifiConfiguration config = genWifiConfig(configJson);
// Need to strip of extra quotation marks for SSID and password.
String ssid = config.SSID;
if (ssid != null) {
config.SSID = ssid.substring(1, ssid.length() - 1);
}
config.allowedKeyManagement.clear();
String pwd = config.preSharedKey;
if (pwd != null) {
config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
config.preSharedKey = pwd.substring(1, pwd.length() - 1);
} else {
config.allowedKeyManagement.set(KeyMgmt.NONE);
}
return config;
}
/**
* Set SoftAp Configuration with SoftApConfiguration.
*/
@Rpc(description = "Set configuration for soft AP.")
public Boolean wifiSetWifiApConfiguration(
@RpcParameter(name = "configJson") JSONObject configJson) throws JSONException {
return mWifi.setSoftApConfiguration(createSoftApConfiguration(configJson));
}
/**
* Set SoftAp Configuration with WifiConfiguration.
*
* Used to test deprecated API to check backward compatible.
*/
@Rpc(description = "Set configuration for soft AP with WifiConfig.")
public Boolean wifiSetWifiApConfigurationWithWifiConfiguration(
@RpcParameter(name = "configJson") JSONObject configJson) throws JSONException {
return mWifi.setWifiApConfiguration(createSoftApWifiConfiguration(configJson));
}
/**
* Register softap callback.
*
* @return the id associated with the {@link SoftApCallbackImp}
* used for registering callback.
*/
@Rpc(description = "Register softap callback function.",
returns = "Id of the callback associated with registering.")
public Integer registerSoftApCallback() {
SoftApCallbackImp softApCallback = new SoftApCallbackImp(mEventFacade);
mSoftapCallbacks.put(softApCallback.mId, softApCallback);
mWifi.registerSoftApCallback(
new HandlerExecutor(new Handler(mCallbackHandlerThread.getLooper())),
softApCallback);
return softApCallback.mId;
}
/**
* Unregister softap callback role for the {@link SoftApCallbackImp} identified by the given
* {@code callbackId}.
*
* @param callbackId the id associated with the {@link SoftApCallbackImp}
* used for registering callback.
*
*/
@Rpc(description = "Unregister softap callback function.")
public void unregisterSoftApCallback(@RpcParameter(name = "callbackId") Integer callbackId) {
mWifi.unregisterSoftApCallback(mSoftapCallbacks.get(callbackId));
mSoftapCallbacks.delete(callbackId);
}
@Rpc(description = "Enable/disable tdls with a mac address.")
public void wifiSetTdlsEnabledWithMacAddress(
@RpcParameter(name = "remoteMacAddress") String remoteMacAddress,
@RpcParameter(name = "enable") Boolean enable) {
mWifi.setTdlsEnabledWithMacAddress(remoteMacAddress, enable);
}
@Rpc(description = "Starts a scan for Wifi access points.", returns = "True if the scan was initiated successfully.")
public Boolean wifiStartScan() {
mService.registerReceiver(mScanResultsAvailableReceiver, mScanFilter);
return mWifi.startScan();
}
@Rpc(description = "Starts a scan for Wifi access points with scanResultCallback.",
returns = "True if the scan was initiated successfully.")
public Boolean wifiStartScanWithListener() {
mWifi.registerScanResultsCallback(mService.getMainExecutor(), mWifiScanResultsReceiver);
return mWifi.startScan();
}
@Rpc(description = "Start Wi-fi Protected Setup.")
public void wifiStartWps(
@RpcParameter(name = "config", description = "A json string with fields \"setup\", \"BSSID\", and \"pin\"") String config)
throws JSONException {
WpsInfo info = parseWpsInfo(config);
WifiWpsCallback listener = new WifiWpsCallback();
Log.d("Starting wps with: " + info);
mWifi.startWps(info, listener);
}
@Rpc(description = "Start listening for wifi state change related broadcasts.")
public void wifiStartTrackingStateChange() {
mService.registerReceiver(mStateChangeReceiver, mStateChangeFilter);
mTrackingWifiStateChange = true;
}
@Rpc(description = "Stop listening for wifi state change related broadcasts.")
public void wifiStopTrackingStateChange() {
if (mTrackingWifiStateChange == true) {
mService.unregisterReceiver(mStateChangeReceiver);
mTrackingWifiStateChange = false;
}
}
@Rpc(description = "Start listening for tether state change related broadcasts.")
public void wifiStartTrackingTetherStateChange() {
mService.registerReceiver(mTetherStateReceiver, mTetherFilter);
mTrackingTetherStateChange = true;
}
@Rpc(description = "Stop listening for wifi state change related broadcasts.")
public void wifiStopTrackingTetherStateChange() {
if (mTrackingTetherStateChange == true) {
mService.unregisterReceiver(mTetherStateReceiver);
mTrackingTetherStateChange = false;
}
}
@Rpc(description = "Start listening for network suggestion change related broadcasts.")
public void wifiStartTrackingNetworkSuggestionStateChange() {
mService.registerReceiver(
mNetworkSuggestionStateChangeReceiver, mNetworkSuggestionStateChangeFilter);
mTrackingNetworkSuggestionStateChange = true;
}
@Rpc(description = "Stop listening for network suggestion change related broadcasts.")
public void wifiStopTrackingNetworkSuggestionStateChange() {
if (mTrackingNetworkSuggestionStateChange) {
mService.unregisterReceiver(mNetworkSuggestionStateChangeReceiver);
mTrackingNetworkSuggestionStateChange = false;
}
}
@Rpc(description = "Toggle Wifi on and off.", returns = "True if Wifi is enabled.")
public Boolean wifiToggleState(@RpcParameter(name = "enabled") @RpcOptional Boolean enabled) {
if (enabled == null) {
enabled = !wifiCheckState();
}
mWifi.setWifiEnabled(enabled);
return enabled;
}
@Rpc(description = "Toggle Wifi scan always available on and off.", returns = "True if Wifi scan is always available.")
public Boolean wifiToggleScanAlwaysAvailable(
@RpcParameter(name = "enabled") @RpcOptional Boolean enabled)
throws SettingNotFoundException {
boolean isSet = (enabled == null) ? !mWifi.isScanAlwaysAvailable() : enabled;
mWifi.setScanAlwaysAvailable(isSet);
return isSet;
}
@Rpc(description = "Enable/disable WifiConnectivityManager.")
public void wifiEnableWifiConnectivityManager(
@RpcParameter(name = "enable") Boolean enable) {
mWifi.allowAutojoinGlobal(enable);
}
private void wifiRequestNetworkWithSpecifierInternal(NetworkSpecifier wns, int timeoutInMs)
throws GeneralSecurityException {
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_WIFI)
.setNetworkSpecifier(wns)
.build();
NetworkCallback networkCallback = new NetworkCallbackImpl();
if (timeoutInMs != 0) {
mCm.requestNetwork(networkRequest, networkCallback,
new Handler(mCallbackHandlerThread.getLooper()), timeoutInMs);
} else {
mCm.requestNetwork(networkRequest, networkCallback,
new Handler(mCallbackHandlerThread.getLooper()));
}
// Store the callback for release later.
mNetworkCallbacks.put(wns, networkCallback);
}
/**
* Initiates a network request {@link NetworkRequest} using {@link WifiNetworkSpecifier}.
*
* @param wifiNetworkSpecifier JSONObject Dictionary of wifi network specifier parameters
* @throws JSONException
* @throws GeneralSecurityException
*/
@Rpc(description = "Initiates a network request using the provided network specifier")
public void wifiRequestNetworkWithSpecifier(
@RpcParameter(name = "wifiNetworkSpecifier") JSONObject wifiNetworkSpecifier)
throws JSONException, GeneralSecurityException {
wifiRequestNetworkWithSpecifierInternal(genWifiNetworkSpecifier(wifiNetworkSpecifier), 0);
}
/**
* Initiates a network request {@link NetworkRequest} using {@link WifiNetworkSpecifier}.
*
* @param wifiNetworkSpecifier JSONObject Dictionary of wifi network specifier parameters
* @param timeoutInMs Timeout for the request.
* @throws JSONException
* @throws GeneralSecurityException
*/
@Rpc(description = "Initiates a network request using the provided network specifier")
public void wifiRequestNetworkWithSpecifierWithTimeout(
@RpcParameter(name = "wifiNetworkSpecifier") JSONObject wifiNetworkSpecifier,
@RpcParameter(name = "timeout") Integer timeoutInMs)
throws JSONException, GeneralSecurityException {
wifiRequestNetworkWithSpecifierInternal(
genWifiNetworkSpecifier(wifiNetworkSpecifier), timeoutInMs);
}
/**
* Releases network request using {@link WifiNetworkSpecifier}.
*
* @throws JSONException
* @throws GeneralSecurityException
*/
@Rpc(description = "Releases network request corresponding to the network specifier")
public void wifiReleaseNetwork(
@RpcParameter(name = "wifiNetworkSpecifier") JSONObject wifiNetworkSpecifier)
throws JSONException, GeneralSecurityException {
NetworkSpecifier wns = genWifiNetworkSpecifier(wifiNetworkSpecifier);
NetworkCallback networkCallback = mNetworkCallbacks.remove(wns);
if (networkCallback == null) {
throw new IllegalArgumentException("network callback is null");
}
mCm.unregisterNetworkCallback(networkCallback);
}
/**
* Releases all pending network requests.
*
* @throws JSONException
* @throws GeneralSecurityException
*/
@Rpc(description = "Releases all pending network requests")
public void wifiReleaseNetworkAll() {
Iterator<Map.Entry<NetworkSpecifier, NetworkCallback>> it =
mNetworkCallbacks.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<NetworkSpecifier, NetworkCallback> entry = it.next();
NetworkCallback networkCallback = entry.getValue();
it.remove();
mCm.unregisterNetworkCallback(networkCallback);
}
}
/**
* Register network request match callback to simulate the UI flow.
*
* @throws JSONException
* @throws GeneralSecurityException
*/
@Rpc(description = "Register network request match callback")
public void wifiRegisterNetworkRequestMatchCallback()
throws JSONException, GeneralSecurityException {
// Listen for UI interaction callbacks
mWifi.registerNetworkRequestMatchCallback(
new HandlerExecutor(new Handler(mCallbackHandlerThread.getLooper())),
mNetworkRequestMatchCallback);
}
/**
* Triggers connect to a specific wifi network.
*
* @param jsonConfig JSONObject Dictionary of wifi connection parameters
* @throws JSONException
* @throws GeneralSecurityException
*/
@Rpc(description = "Connects to the specified network for the ongoing network request")
public void wifiSendUserSelectionForNetworkRequestMatch(
@RpcParameter(name = "jsonConfig") JSONObject jsonConfig)
throws JSONException, GeneralSecurityException {
synchronized (mCallbackLock) {
if (mNetworkRequestUserSelectionCallback == null) {
throw new IllegalStateException("user callback is null");
}
// Copy the SSID for user selection.
WifiConfiguration config = new WifiConfiguration();
if (jsonConfig.has("SSID")) {
config.SSID = "\"" + jsonConfig.getString("SSID") + "\"";
}
mNetworkRequestUserSelectionCallback.select(config);
}
}
/**
* Rejects network request.
*
* @throws JSONException
* @throws GeneralSecurityException
*/
@Rpc(description = "Rejects ongoing network request")
public void wifiSendUserRejectionForNetworkRequestMatch()
throws JSONException, GeneralSecurityException {
synchronized (mCallbackLock) {
if (mNetworkRequestUserSelectionCallback == null) {
throw new IllegalStateException("user callback is null");
}
mNetworkRequestUserSelectionCallback.reject();
}
}
/**
* Add network suggestions.
* @param wifiNetworkSuggestions Array of JSONObject Dictionary of wifi network suggestion
* parameters
* @throws JSONException
* @throws GeneralSecurityException
*/
@Rpc(description = "Add network suggestions to the platform")
public boolean wifiAddNetworkSuggestions(
@RpcParameter(name = "wifiNetworkSuggestions") JSONArray wifiNetworkSuggestions)
throws JSONException, GeneralSecurityException, IOException {
return mWifi.addNetworkSuggestions(genWifiNetworkSuggestions(wifiNetworkSuggestions))
== WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS;
}
/**
* Remove network suggestions.
* @param wifiNetworkSuggestions Array of JSONObject Dictionary of wifi network suggestion
* parameters
* @throws JSONException
* @throws GeneralSecurityException
*/
@Rpc(description = "Remove network suggestions from the platform")
public boolean wifiRemoveNetworkSuggestions(
@RpcParameter(name = "wifiNetworkSuggestions") JSONArray wifiNetworkSuggestions)
throws JSONException, GeneralSecurityException, IOException {
return mWifi.removeNetworkSuggestions(genWifiNetworkSuggestions(wifiNetworkSuggestions))
== WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS;
}
@Override
public void shutdown() {
wifiReleaseNetworkAll();
wifiLockRelease();
if (mTrackingWifiStateChange == true) {
wifiStopTrackingStateChange();
}
if (mTrackingTetherStateChange == true) {
wifiStopTrackingTetherStateChange();
}
}
private class EasyConnectCallback extends EasyConnectStatusCallback {
private static final String EASY_CONNECT_CALLBACK_TAG = "onDppCallback";
@Override
public void onEnrolleeSuccess(int newWifiConfigurationId) {
Bundle msg = new Bundle();
msg.putString("Type", "onEnrolleeSuccess");
msg.putInt("NetworkId", newWifiConfigurationId);
Log.d("Posting event: onEnrolleeSuccess");
mEventFacade.postEvent(EASY_CONNECT_CALLBACK_TAG, msg);
}
@Override
public void onConfiguratorSuccess(int code) {
Bundle msg = new Bundle();
msg.putString("Type", "onConfiguratorSuccess");
msg.putInt("Status", code);
Log.d("Posting event: onConfiguratorSuccess");
mEventFacade.postEvent(EASY_CONNECT_CALLBACK_TAG, msg);
}
@Override
public void onFailure(int code, String ssid, SparseArray<int[]> channelList,
int[] bandList) {
Bundle msg = new Bundle();
msg.putString("Type", "onFailure");
msg.putInt("Status", code);
Log.d("Posting event: onFailure");
if (ssid != null) {
Log.d("onFailure SSID: " + ssid);
msg.putString("onFailureSsid", ssid);
} else {
msg.putString("onFailureSsid", "");
}
if (channelList != null) {
Log.d("onFailure list of tried channels: " + channelList);
int key;
int index = 0;
JSONObject formattedChannelList = new JSONObject();
// Build a JSON array of classes, with an array of channels for each class.
do {
try {
key = channelList.keyAt(index);
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
break;
}
try {
JSONArray channelsInClassArray = new JSONArray();
int[] output = channelList.get(key);
for (int i = 0; i < output.length; i++) {
channelsInClassArray.put(output[i]);
}
formattedChannelList.put(Integer.toString(key),
build(channelsInClassArray));
} catch (org.json.JSONException e) {
msg.putString("onFailureChannelList", "");
break;
}
index++;
} while (true);
msg.putString("onFailureChannelList", formattedChannelList.toString());
} else {
msg.putString("onFailureChannelList", "");
}
if (bandList != null) {
// Build a JSON array of bands represented as operating classes
Log.d("onFailure list of supported bands: " + bandList);
JSONArray formattedBandList = new JSONArray();
for (int i = 0; i < bandList.length; i++) {
formattedBandList.put(bandList[i]);
}
msg.putString("onFailureBandList", formattedBandList.toString());
} else {
msg.putString("onFailureBandList", "");
}
mEventFacade.postEvent(EASY_CONNECT_CALLBACK_TAG, msg);
}
@Override
public void onProgress(int code) {
Bundle msg = new Bundle();
msg.putString("Type", "onProgress");
msg.putInt("Status", code);
Log.d("Posting event: onProgress");
mEventFacade.postEvent(EASY_CONNECT_CALLBACK_TAG, msg);
}
}
/**
* Start Easy Connect (DPP) in Initiator-Configurator role: Send Wi-Fi configuration to a peer
*
* @param enrolleeUri Peer URI
* @param selectedNetworkId Wi-Fi configuration ID
*/
@Rpc(description = "Easy Connect Initiator-Configurator: Send Wi-Fi configuration to peer")
public void startEasyConnectAsConfiguratorInitiator(@RpcParameter(name = "enrolleeUri") String
enrolleeUri, @RpcParameter(name = "selectedNetworkId") Integer selectedNetworkId,
@RpcParameter(name = "netRole") String netRole)
throws JSONException {
EasyConnectCallback dppStatusCallback = new EasyConnectCallback();
int netRoleInternal;
if (netRole.equals("ap")) {
netRoleInternal = WifiManager.EASY_CONNECT_NETWORK_ROLE_AP;
} else {
netRoleInternal = WifiManager.EASY_CONNECT_NETWORK_ROLE_STA;
}
// Start Easy Connect
mWifi.startEasyConnectAsConfiguratorInitiator(enrolleeUri, selectedNetworkId,
netRoleInternal, mService.getMainExecutor(), dppStatusCallback);
}
/**
* Start Easy Connect (DPP) in Initiator-Enrollee role: Receive Wi-Fi configuration from a peer
*
* @param configuratorUri
*/
@Rpc(description = "Easy Connect Initiator-Enrollee: Receive Wi-Fi configuration from peer")
public void startEasyConnectAsEnrolleeInitiator(@RpcParameter(name = "configuratorUri") String
configuratorUri) {
EasyConnectCallback dppStatusCallback = new EasyConnectCallback();
// Start Easy Connect
mWifi.startEasyConnectAsEnrolleeInitiator(configuratorUri, mService.getMainExecutor(),
dppStatusCallback);
}
/**
* Stop Easy Connect (DPP) session
*
*/
@Rpc(description = "Stop Easy Connect session")
public void stopEasyConnectSession() {
// Stop Easy Connect
mWifi.stopEasyConnectSession();
}
/**
* Enable/Disable auto join for target network
*/
@Rpc(description = "Set network auto join enable/disable")
public void wifiEnableAutojoin(@RpcParameter(name = "netId") Integer netId,
@RpcParameter(name = "enableAutojoin") Boolean enableAutojoin) {
mWifi.allowAutojoin(netId, enableAutojoin);
}
/**
* Enable/Disable auto join for target Passpoint network
*/
@Rpc(description = "Set passpoint network auto join enable/disable")
public void wifiEnableAutojoinPasspoint(@RpcParameter(name = "FQDN") String fqdn,
@RpcParameter(name = "enableAutojoin") Boolean enableAutojoin) {
mWifi.allowAutojoinPasspoint(fqdn, enableAutojoin);
}
}