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 */
16package com.android.server.wifi;
17
18import android.content.Context;
19import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork;
20import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetworkCallback;
21import android.hardware.wifi.supplicant.V1_0.SupplicantStatus;
22import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode;
23import android.net.wifi.WifiConfiguration;
24import android.net.wifi.WifiEnterpriseConfig;
25import android.os.RemoteException;
26import android.text.TextUtils;
27import android.util.Log;
28import android.util.MutableBoolean;
29
30import com.android.internal.R;
31import com.android.internal.annotations.VisibleForTesting;
32import com.android.internal.util.ArrayUtils;
33import com.android.server.wifi.util.NativeUtil;
34
35import org.json.JSONException;
36import org.json.JSONObject;
37
38import java.io.UnsupportedEncodingException;
39import java.net.URLDecoder;
40import java.net.URLEncoder;
41import java.util.ArrayList;
42import java.util.BitSet;
43import java.util.HashMap;
44import java.util.Iterator;
45import java.util.Map;
46import java.util.regex.Matcher;
47import java.util.regex.Pattern;
48
49
50/**
51 * Wrapper class for ISupplicantStaNetwork HAL calls. Gets and sets supplicant sta network variables
52 * and interacts with networks.
53 * Public fields should be treated as invalid until their 'get' method is called, which will set the
54 * value if it returns true
55 */
56public class SupplicantStaNetworkHal {
57    private static final String TAG = "SupplicantStaNetworkHal";
58    @VisibleForTesting
59    public static final String ID_STRING_KEY_FQDN = "fqdn";
60    @VisibleForTesting
61    public static final String ID_STRING_KEY_CREATOR_UID = "creatorUid";
62    @VisibleForTesting
63    public static final String ID_STRING_KEY_CONFIG_KEY = "configKey";
64
65    /**
66     * Regex pattern for extracting the GSM sim authentication response params from a string.
67     * Matches a strings like the following: "[:<kc_value>:<sres_value>]";
68     */
69    private static final Pattern GSM_AUTH_RESPONSE_PARAMS_PATTERN =
70            Pattern.compile(":([0-9a-fA-F]+):([0-9a-fA-F]+)");
71    /**
72     * Regex pattern for extracting the UMTS sim authentication response params from a string.
73     * Matches a strings like the following: ":<ik_value>:<ck_value>:<res_value>";
74     */
75    private static final Pattern UMTS_AUTH_RESPONSE_PARAMS_PATTERN =
76            Pattern.compile("^:([0-9a-fA-F]+):([0-9a-fA-F]+):([0-9a-fA-F]+)$");
77    /**
78     * Regex pattern for extracting the UMTS sim auts response params from a string.
79     * Matches a strings like the following: ":<auts_value>";
80     */
81    private static final Pattern UMTS_AUTS_RESPONSE_PARAMS_PATTERN =
82            Pattern.compile("^:([0-9a-fA-F]+)$");
83
84    private final Object mLock = new Object();
85    private final String mIfaceName;
86    private final WifiMonitor mWifiMonitor;
87    private ISupplicantStaNetwork mISupplicantStaNetwork;
88    private ISupplicantStaNetworkCallback mISupplicantStaNetworkCallback;
89
90    private boolean mVerboseLoggingEnabled = false;
91    // Indicates whether the system is capable of 802.11r fast BSS transition.
92    private boolean mSystemSupportsFastBssTransition = false;
93
94    // Network variables read from wpa_supplicant.
95    private int mNetworkId;
96    private ArrayList<Byte> mSsid;
97    private byte[/* 6 */] mBssid;
98    private boolean mScanSsid;
99    private int mKeyMgmtMask;
100    private int mProtoMask;
101    private int mAuthAlgMask;
102    private int mGroupCipherMask;
103    private int mPairwiseCipherMask;
104    private String mPskPassphrase;
105    private byte[] mPsk;
106    private ArrayList<Byte> mWepKey;
107    private int mWepTxKeyIdx;
108    private boolean mRequirePmf;
109    private String mIdStr;
110    private int mEapMethod;
111    private int mEapPhase2Method;
112    private ArrayList<Byte> mEapIdentity;
113    private ArrayList<Byte> mEapAnonymousIdentity;
114    private ArrayList<Byte> mEapPassword;
115    private String mEapCACert;
116    private String mEapCAPath;
117    private String mEapClientCert;
118    private String mEapPrivateKeyId;
119    private String mEapSubjectMatch;
120    private String mEapAltSubjectMatch;
121    private boolean mEapEngine;
122    private String mEapEngineID;
123    private String mEapDomainSuffixMatch;
124
125    SupplicantStaNetworkHal(ISupplicantStaNetwork iSupplicantStaNetwork, String ifaceName,
126                            Context context, WifiMonitor monitor) {
127        mISupplicantStaNetwork = iSupplicantStaNetwork;
128        mIfaceName = ifaceName;
129        mWifiMonitor = monitor;
130        mSystemSupportsFastBssTransition =
131                context.getResources().getBoolean(R.bool.config_wifi_fast_bss_transition_enabled);
132    }
133
134    /**
135     * Enable/Disable verbose logging.
136     *
137     * @param enable true to enable, false to disable.
138     */
139    void enableVerboseLogging(boolean enable) {
140        mVerboseLoggingEnabled = enable;
141    }
142
143    /**
144     * Read network variables from wpa_supplicant into the provided WifiConfiguration object.
145     *
146     * @param config        WifiConfiguration object to be populated.
147     * @param networkExtras Map of network extras parsed from wpa_supplicant.
148     * @return true if succeeds, false otherwise.
149     * @throws IllegalArgumentException on malformed configuration params.
150     */
151    public boolean loadWifiConfiguration(WifiConfiguration config,
152                                         Map<String, String> networkExtras) {
153        if (config == null) return false;
154        /** SSID */
155        config.SSID = null;
156        if (getSsid() && !ArrayUtils.isEmpty(mSsid)) {
157            config.SSID = NativeUtil.encodeSsid(mSsid);
158        } else {
159            Log.e(TAG, "failed to read ssid");
160            return false;
161        }
162        /** Network Id */
163        config.networkId = -1;
164        if (getId()) {
165            config.networkId = mNetworkId;
166        } else {
167            Log.e(TAG, "getId failed");
168            return false;
169        }
170        /** BSSID */
171        config.getNetworkSelectionStatus().setNetworkSelectionBSSID(null);
172        if (getBssid() && !ArrayUtils.isEmpty(mBssid)) {
173            config.getNetworkSelectionStatus().setNetworkSelectionBSSID(
174                    NativeUtil.macAddressFromByteArray(mBssid));
175        }
176        /** Scan SSID (Is Hidden Network?) */
177        config.hiddenSSID = false;
178        if (getScanSsid()) {
179            config.hiddenSSID = mScanSsid;
180        }
181        /** Require PMF*/
182        config.requirePMF = false;
183        if (getRequirePmf()) {
184            config.requirePMF = mRequirePmf;
185        }
186        /** WEP keys **/
187        config.wepTxKeyIndex = -1;
188        if (getWepTxKeyIdx()) {
189            config.wepTxKeyIndex = mWepTxKeyIdx;
190        }
191        for (int i = 0; i < 4; i++) {
192            config.wepKeys[i] = null;
193            if (getWepKey(i) && !ArrayUtils.isEmpty(mWepKey)) {
194                config.wepKeys[i] = NativeUtil.bytesToHexOrQuotedAsciiString(mWepKey);
195            }
196        }
197        /** PSK pass phrase */
198        config.preSharedKey = null;
199        if (getPskPassphrase() && !TextUtils.isEmpty(mPskPassphrase)) {
200            config.preSharedKey = NativeUtil.addEnclosingQuotes(mPskPassphrase);
201        } else if (getPsk() && !ArrayUtils.isEmpty(mPsk)) {
202            config.preSharedKey = NativeUtil.hexStringFromByteArray(mPsk);
203        }
204        /** allowedKeyManagement */
205        if (getKeyMgmt()) {
206            BitSet keyMgmtMask = supplicantToWifiConfigurationKeyMgmtMask(mKeyMgmtMask);
207            config.allowedKeyManagement = removeFastTransitionFlags(keyMgmtMask);
208        }
209        /** allowedProtocols */
210        if (getProto()) {
211            config.allowedProtocols =
212                    supplicantToWifiConfigurationProtoMask(mProtoMask);
213        }
214        /** allowedAuthAlgorithms */
215        if (getAuthAlg()) {
216            config.allowedAuthAlgorithms =
217                    supplicantToWifiConfigurationAuthAlgMask(mAuthAlgMask);
218        }
219        /** allowedGroupCiphers */
220        if (getGroupCipher()) {
221            config.allowedGroupCiphers =
222                    supplicantToWifiConfigurationGroupCipherMask(mGroupCipherMask);
223        }
224        /** allowedPairwiseCiphers */
225        if (getPairwiseCipher()) {
226            config.allowedPairwiseCiphers =
227                    supplicantToWifiConfigurationPairwiseCipherMask(mPairwiseCipherMask);
228        }
229        /** metadata: idstr */
230        if (getIdStr() && !TextUtils.isEmpty(mIdStr)) {
231            Map<String, String> metadata = parseNetworkExtra(mIdStr);
232            networkExtras.putAll(metadata);
233        } else {
234            Log.w(TAG, "getIdStr failed or empty");
235        }
236        return loadWifiEnterpriseConfig(config.SSID, config.enterpriseConfig);
237    }
238
239    /**
240     * Save an entire WifiConfiguration to wpa_supplicant via HIDL.
241     *
242     * @param config WifiConfiguration object to be saved.
243     * @return true if succeeds, false otherwise.
244     * @throws IllegalArgumentException on malformed configuration params.
245     */
246    public boolean saveWifiConfiguration(WifiConfiguration config) {
247        if (config == null) return false;
248        /** SSID */
249        if (config.SSID != null) {
250            if (!setSsid(NativeUtil.decodeSsid(config.SSID))) {
251                Log.e(TAG, "failed to set SSID: " + config.SSID);
252                return false;
253            }
254        }
255        /** BSSID */
256        String bssidStr = config.getNetworkSelectionStatus().getNetworkSelectionBSSID();
257        if (bssidStr != null) {
258            byte[] bssid = NativeUtil.macAddressToByteArray(bssidStr);
259            if (!setBssid(bssid)) {
260                Log.e(TAG, "failed to set BSSID: " + bssidStr);
261                return false;
262            }
263        }
264        /** Pre Shared Key. This can either be quoted ASCII passphrase or hex string for raw psk */
265        if (config.preSharedKey != null) {
266            if (config.preSharedKey.startsWith("\"")) {
267                if (!setPskPassphrase(NativeUtil.removeEnclosingQuotes(config.preSharedKey))) {
268                    Log.e(TAG, "failed to set psk passphrase");
269                    return false;
270                }
271            } else {
272                if (!setPsk(NativeUtil.hexStringToByteArray(config.preSharedKey))) {
273                    Log.e(TAG, "failed to set psk");
274                    return false;
275                }
276            }
277        }
278
279        /** Wep Keys */
280        boolean hasSetKey = false;
281        if (config.wepKeys != null) {
282            for (int i = 0; i < config.wepKeys.length; i++) {
283                if (config.wepKeys[i] != null) {
284                    if (!setWepKey(
285                            i, NativeUtil.hexOrQuotedAsciiStringToBytes(config.wepKeys[i]))) {
286                        Log.e(TAG, "failed to set wep_key " + i);
287                        return false;
288                    }
289                    hasSetKey = true;
290                }
291            }
292        }
293        /** Wep Tx Key Idx */
294        if (hasSetKey) {
295            if (!setWepTxKeyIdx(config.wepTxKeyIndex)) {
296                Log.e(TAG, "failed to set wep_tx_keyidx: " + config.wepTxKeyIndex);
297                return false;
298            }
299        }
300        /** HiddenSSID */
301        if (!setScanSsid(config.hiddenSSID)) {
302            Log.e(TAG, config.SSID + ": failed to set hiddenSSID: " + config.hiddenSSID);
303            return false;
304        }
305        /** RequirePMF */
306        if (!setRequirePmf(config.requirePMF)) {
307            Log.e(TAG, config.SSID + ": failed to set requirePMF: " + config.requirePMF);
308            return false;
309        }
310        /** Key Management Scheme */
311        if (config.allowedKeyManagement.cardinality() != 0) {
312            // Add FT flags if supported.
313            BitSet keyMgmtMask = addFastTransitionFlags(config.allowedKeyManagement);
314            if (!setKeyMgmt(wifiConfigurationToSupplicantKeyMgmtMask(keyMgmtMask))) {
315                Log.e(TAG, "failed to set Key Management");
316                return false;
317            }
318        }
319        /** Security Protocol */
320        if (config.allowedProtocols.cardinality() != 0
321                && !setProto(wifiConfigurationToSupplicantProtoMask(config.allowedProtocols))) {
322            Log.e(TAG, "failed to set Security Protocol");
323            return false;
324        }
325        /** Auth Algorithm */
326        if (config.allowedAuthAlgorithms.cardinality() != 0
327                && !setAuthAlg(wifiConfigurationToSupplicantAuthAlgMask(
328                config.allowedAuthAlgorithms))) {
329            Log.e(TAG, "failed to set AuthAlgorithm");
330            return false;
331        }
332        /** Group Cipher */
333        if (config.allowedGroupCiphers.cardinality() != 0
334                && !setGroupCipher(wifiConfigurationToSupplicantGroupCipherMask(
335                config.allowedGroupCiphers))) {
336            Log.e(TAG, "failed to set Group Cipher");
337            return false;
338        }
339        /** Pairwise Cipher*/
340        if (config.allowedPairwiseCiphers.cardinality() != 0
341                && !setPairwiseCipher(wifiConfigurationToSupplicantPairwiseCipherMask(
342                        config.allowedPairwiseCiphers))) {
343            Log.e(TAG, "failed to set PairwiseCipher");
344            return false;
345        }
346        /** metadata: FQDN + ConfigKey + CreatorUid */
347        final Map<String, String> metadata = new HashMap<String, String>();
348        if (config.isPasspoint()) {
349            metadata.put(ID_STRING_KEY_FQDN, config.FQDN);
350        }
351        metadata.put(ID_STRING_KEY_CONFIG_KEY, config.configKey());
352        metadata.put(ID_STRING_KEY_CREATOR_UID, Integer.toString(config.creatorUid));
353        if (!setIdStr(createNetworkExtra(metadata))) {
354            Log.e(TAG, "failed to set id string");
355            return false;
356        }
357        /** UpdateIdentifier */
358        if (config.updateIdentifier != null
359                && !setUpdateIdentifier(Integer.parseInt(config.updateIdentifier))) {
360            Log.e(TAG, "failed to set update identifier");
361            return false;
362        }
363        // Finish here if no EAP config to set
364        if (config.enterpriseConfig != null
365                && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) {
366            if (!saveWifiEnterpriseConfig(config.SSID, config.enterpriseConfig)) {
367                return false;
368            }
369        }
370
371        // Now that the network is configured fully, start listening for callback events.
372        mISupplicantStaNetworkCallback =
373                new SupplicantStaNetworkHalCallback(config.networkId, config.SSID);
374        if (!registerCallback(mISupplicantStaNetworkCallback)) {
375            Log.e(TAG, "Failed to register callback");
376            return false;
377        }
378        return true;
379    }
380
381    /**
382     * Read network variables from wpa_supplicant into the provided WifiEnterpriseConfig object.
383     *
384     * @param ssid SSID of the network. (Used for logging purposes only)
385     * @param eapConfig WifiEnterpriseConfig object to be populated.
386     * @return true if succeeds, false otherwise.
387     */
388    private boolean loadWifiEnterpriseConfig(String ssid, WifiEnterpriseConfig eapConfig) {
389        if (eapConfig == null) return false;
390        /** EAP method */
391        if (getEapMethod()) {
392            eapConfig.setEapMethod(supplicantToWifiConfigurationEapMethod(mEapMethod));
393        } else {
394            // Invalid eap method could be because it's not an enterprise config.
395            Log.e(TAG, "failed to get eap method. Assumimg not an enterprise network");
396            return true;
397        }
398        /** EAP Phase 2 method */
399        if (getEapPhase2Method()) {
400            eapConfig.setPhase2Method(
401                    supplicantToWifiConfigurationEapPhase2Method(mEapPhase2Method));
402        } else {
403            // We cannot have an invalid eap phase 2 method. Return failure.
404            Log.e(TAG, "failed to get eap phase2 method");
405            return false;
406        }
407        /** EAP Identity */
408        if (getEapIdentity() && !ArrayUtils.isEmpty(mEapIdentity)) {
409            eapConfig.setFieldValue(
410                    WifiEnterpriseConfig.IDENTITY_KEY,
411                    NativeUtil.stringFromByteArrayList(mEapIdentity));
412        }
413        /** EAP Anonymous Identity */
414        if (getEapAnonymousIdentity() && !ArrayUtils.isEmpty(mEapAnonymousIdentity)) {
415            eapConfig.setFieldValue(
416                    WifiEnterpriseConfig.ANON_IDENTITY_KEY,
417                    NativeUtil.stringFromByteArrayList(mEapAnonymousIdentity));
418        }
419        /** EAP Password */
420        if (getEapPassword() && !ArrayUtils.isEmpty(mEapPassword)) {
421            eapConfig.setFieldValue(
422                    WifiEnterpriseConfig.PASSWORD_KEY,
423                    NativeUtil.stringFromByteArrayList(mEapPassword));
424        }
425        /** EAP Client Cert */
426        if (getEapClientCert() && !TextUtils.isEmpty(mEapClientCert)) {
427            eapConfig.setFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY, mEapClientCert);
428        }
429        /** EAP CA Cert */
430        if (getEapCACert() && !TextUtils.isEmpty(mEapCACert)) {
431            eapConfig.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, mEapCACert);
432        }
433        /** EAP Subject Match */
434        if (getEapSubjectMatch() && !TextUtils.isEmpty(mEapSubjectMatch)) {
435            eapConfig.setFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY, mEapSubjectMatch);
436        }
437        /** EAP Engine ID */
438        if (getEapEngineID() && !TextUtils.isEmpty(mEapEngineID)) {
439            eapConfig.setFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY, mEapEngineID);
440        }
441        /** EAP Engine. Set this only if the engine id is non null. */
442        if (getEapEngine() && !TextUtils.isEmpty(mEapEngineID)) {
443            eapConfig.setFieldValue(
444                    WifiEnterpriseConfig.ENGINE_KEY,
445                    mEapEngine
446                            ? WifiEnterpriseConfig.ENGINE_ENABLE
447                            : WifiEnterpriseConfig.ENGINE_DISABLE);
448        }
449        /** EAP Private Key */
450        if (getEapPrivateKeyId() && !TextUtils.isEmpty(mEapPrivateKeyId)) {
451            eapConfig.setFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, mEapPrivateKeyId);
452        }
453        /** EAP Alt Subject Match */
454        if (getEapAltSubjectMatch() && !TextUtils.isEmpty(mEapAltSubjectMatch)) {
455            eapConfig.setFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, mEapAltSubjectMatch);
456        }
457        /** EAP Domain Suffix Match */
458        if (getEapDomainSuffixMatch() && !TextUtils.isEmpty(mEapDomainSuffixMatch)) {
459            eapConfig.setFieldValue(
460                    WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, mEapDomainSuffixMatch);
461        }
462        /** EAP CA Path*/
463        if (getEapCAPath() && !TextUtils.isEmpty(mEapCAPath)) {
464            eapConfig.setFieldValue(WifiEnterpriseConfig.CA_PATH_KEY, mEapCAPath);
465        }
466        return true;
467    }
468
469    /**
470     * Save network variables from the provided WifiEnterpriseConfig object to wpa_supplicant.
471     *
472     * @param ssid SSID of the network. (Used for logging purposes only)
473     * @param eapConfig WifiEnterpriseConfig object to be saved.
474     * @return true if succeeds, false otherwise.
475     */
476    private boolean saveWifiEnterpriseConfig(String ssid, WifiEnterpriseConfig eapConfig) {
477        if (eapConfig == null) return false;
478        /** EAP method */
479        if (!setEapMethod(wifiConfigurationToSupplicantEapMethod(eapConfig.getEapMethod()))) {
480            Log.e(TAG, ssid + ": failed to set eap method: " + eapConfig.getEapMethod());
481            return false;
482        }
483        /** EAP Phase 2 method */
484        if (!setEapPhase2Method(wifiConfigurationToSupplicantEapPhase2Method(
485                eapConfig.getPhase2Method()))) {
486            Log.e(TAG, ssid + ": failed to set eap phase 2 method: " + eapConfig.getPhase2Method());
487            return false;
488        }
489        String eapParam = null;
490        /** EAP Identity */
491        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.IDENTITY_KEY);
492        if (!TextUtils.isEmpty(eapParam)
493                && !setEapIdentity(NativeUtil.stringToByteArrayList(eapParam))) {
494            Log.e(TAG, ssid + ": failed to set eap identity: " + eapParam);
495            return false;
496        }
497        /** EAP Anonymous Identity */
498        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY);
499        if (!TextUtils.isEmpty(eapParam)
500                && !setEapAnonymousIdentity(NativeUtil.stringToByteArrayList(eapParam))) {
501            Log.e(TAG, ssid + ": failed to set eap anonymous identity: " + eapParam);
502            return false;
503        }
504        /** EAP Password */
505        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY);
506        if (!TextUtils.isEmpty(eapParam)
507                && !setEapPassword(NativeUtil.stringToByteArrayList(eapParam))) {
508            Log.e(TAG, ssid + ": failed to set eap password");
509            return false;
510        }
511        /** EAP Client Cert */
512        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY);
513        if (!TextUtils.isEmpty(eapParam) && !setEapClientCert(eapParam)) {
514            Log.e(TAG, ssid + ": failed to set eap client cert: " + eapParam);
515            return false;
516        }
517        /** EAP CA Cert */
518        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY);
519        if (!TextUtils.isEmpty(eapParam) && !setEapCACert(eapParam)) {
520            Log.e(TAG, ssid + ": failed to set eap ca cert: " + eapParam);
521            return false;
522        }
523        /** EAP Subject Match */
524        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY);
525        if (!TextUtils.isEmpty(eapParam) && !setEapSubjectMatch(eapParam)) {
526            Log.e(TAG, ssid + ": failed to set eap subject match: " + eapParam);
527            return false;
528        }
529        /** EAP Engine ID */
530        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY);
531        if (!TextUtils.isEmpty(eapParam) && !setEapEngineID(eapParam)) {
532            Log.e(TAG, ssid + ": failed to set eap engine id: " + eapParam);
533            return false;
534        }
535        /** EAP Engine */
536        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_KEY);
537        if (!TextUtils.isEmpty(eapParam) && !setEapEngine(
538                eapParam.equals(WifiEnterpriseConfig.ENGINE_ENABLE) ? true : false)) {
539            Log.e(TAG, ssid + ": failed to set eap engine: " + eapParam);
540            return false;
541        }
542        /** EAP Private Key */
543        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY);
544        if (!TextUtils.isEmpty(eapParam) && !setEapPrivateKeyId(eapParam)) {
545            Log.e(TAG, ssid + ": failed to set eap private key: " + eapParam);
546            return false;
547        }
548        /** EAP Alt Subject Match */
549        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY);
550        if (!TextUtils.isEmpty(eapParam) && !setEapAltSubjectMatch(eapParam)) {
551            Log.e(TAG, ssid + ": failed to set eap alt subject match: " + eapParam);
552            return false;
553        }
554        /** EAP Domain Suffix Match */
555        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY);
556        if (!TextUtils.isEmpty(eapParam) && !setEapDomainSuffixMatch(eapParam)) {
557            Log.e(TAG, ssid + ": failed to set eap domain suffix match: " + eapParam);
558            return false;
559        }
560        /** EAP CA Path*/
561        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.CA_PATH_KEY);
562        if (!TextUtils.isEmpty(eapParam) && !setEapCAPath(eapParam)) {
563            Log.e(TAG, ssid + ": failed to set eap ca path: " + eapParam);
564            return false;
565        }
566
567        /** EAP Proactive Key Caching */
568        eapParam = eapConfig.getFieldValue(WifiEnterpriseConfig.OPP_KEY_CACHING);
569        if (!TextUtils.isEmpty(eapParam)
570                && !setEapProactiveKeyCaching(eapParam.equals("1") ? true : false)) {
571            Log.e(TAG, ssid + ": failed to set proactive key caching: " + eapParam);
572            return false;
573        }
574        return true;
575    }
576
577    /**
578     * Maps WifiConfiguration Key Management BitSet to Supplicant HIDL bitmask int
579     * TODO(b/32571829): Update mapping when fast transition keys are added
580     * @return bitmask int describing the allowed Key Management schemes, readable by the Supplicant
581     *         HIDL hal
582     */
583    private static int wifiConfigurationToSupplicantKeyMgmtMask(BitSet keyMgmt) {
584        int mask = 0;
585        for (int bit = keyMgmt.nextSetBit(0); bit != -1; bit = keyMgmt.nextSetBit(bit + 1)) {
586            switch (bit) {
587                case WifiConfiguration.KeyMgmt.NONE:
588                    mask |= ISupplicantStaNetwork.KeyMgmtMask.NONE;
589                    break;
590                case WifiConfiguration.KeyMgmt.WPA_PSK:
591                    mask |= ISupplicantStaNetwork.KeyMgmtMask.WPA_PSK;
592                    break;
593                case WifiConfiguration.KeyMgmt.WPA_EAP:
594                    mask |= ISupplicantStaNetwork.KeyMgmtMask.WPA_EAP;
595                    break;
596                case WifiConfiguration.KeyMgmt.IEEE8021X:
597                    mask |= ISupplicantStaNetwork.KeyMgmtMask.IEEE8021X;
598                    break;
599                case WifiConfiguration.KeyMgmt.OSEN:
600                    mask |= ISupplicantStaNetwork.KeyMgmtMask.OSEN;
601                    break;
602                case WifiConfiguration.KeyMgmt.FT_PSK:
603                    mask |= ISupplicantStaNetwork.KeyMgmtMask.FT_PSK;
604                    break;
605                case WifiConfiguration.KeyMgmt.FT_EAP:
606                    mask |= ISupplicantStaNetwork.KeyMgmtMask.FT_EAP;
607                    break;
608                case WifiConfiguration.KeyMgmt.WPA2_PSK: // This should never happen
609                default:
610                    throw new IllegalArgumentException(
611                            "Invalid protoMask bit in keyMgmt: " + bit);
612            }
613        }
614        return mask;
615    }
616
617    private static int wifiConfigurationToSupplicantProtoMask(BitSet protoMask) {
618        int mask = 0;
619        for (int bit = protoMask.nextSetBit(0); bit != -1; bit = protoMask.nextSetBit(bit + 1)) {
620            switch (bit) {
621                case WifiConfiguration.Protocol.WPA:
622                    mask |= ISupplicantStaNetwork.ProtoMask.WPA;
623                    break;
624                case WifiConfiguration.Protocol.RSN:
625                    mask |= ISupplicantStaNetwork.ProtoMask.RSN;
626                    break;
627                case WifiConfiguration.Protocol.OSEN:
628                    mask |= ISupplicantStaNetwork.ProtoMask.OSEN;
629                    break;
630                default:
631                    throw new IllegalArgumentException(
632                            "Invalid protoMask bit in wificonfig: " + bit);
633            }
634        }
635        return mask;
636    };
637
638    private static int wifiConfigurationToSupplicantAuthAlgMask(BitSet authAlgMask) {
639        int mask = 0;
640        for (int bit = authAlgMask.nextSetBit(0); bit != -1;
641                bit = authAlgMask.nextSetBit(bit + 1)) {
642            switch (bit) {
643                case WifiConfiguration.AuthAlgorithm.OPEN:
644                    mask |= ISupplicantStaNetwork.AuthAlgMask.OPEN;
645                    break;
646                case WifiConfiguration.AuthAlgorithm.SHARED:
647                    mask |= ISupplicantStaNetwork.AuthAlgMask.SHARED;
648                    break;
649                case WifiConfiguration.AuthAlgorithm.LEAP:
650                    mask |= ISupplicantStaNetwork.AuthAlgMask.LEAP;
651                    break;
652                default:
653                    throw new IllegalArgumentException(
654                            "Invalid authAlgMask bit in wificonfig: " + bit);
655            }
656        }
657        return mask;
658    };
659
660    private static int wifiConfigurationToSupplicantGroupCipherMask(BitSet groupCipherMask) {
661        int mask = 0;
662        for (int bit = groupCipherMask.nextSetBit(0); bit != -1; bit =
663                groupCipherMask.nextSetBit(bit + 1)) {
664            switch (bit) {
665                case WifiConfiguration.GroupCipher.WEP40:
666                    mask |= ISupplicantStaNetwork.GroupCipherMask.WEP40;
667                    break;
668                case WifiConfiguration.GroupCipher.WEP104:
669                    mask |= ISupplicantStaNetwork.GroupCipherMask.WEP104;
670                    break;
671                case WifiConfiguration.GroupCipher.TKIP:
672                    mask |= ISupplicantStaNetwork.GroupCipherMask.TKIP;
673                    break;
674                case WifiConfiguration.GroupCipher.CCMP:
675                    mask |= ISupplicantStaNetwork.GroupCipherMask.CCMP;
676                    break;
677                case WifiConfiguration.GroupCipher.GTK_NOT_USED:
678                    mask |= ISupplicantStaNetwork.GroupCipherMask.GTK_NOT_USED;
679                    break;
680                default:
681                    throw new IllegalArgumentException(
682                            "Invalid GroupCipherMask bit in wificonfig: " + bit);
683            }
684        }
685        return mask;
686    };
687
688    private static int wifiConfigurationToSupplicantPairwiseCipherMask(BitSet pairwiseCipherMask) {
689        int mask = 0;
690        for (int bit = pairwiseCipherMask.nextSetBit(0); bit != -1;
691                bit = pairwiseCipherMask.nextSetBit(bit + 1)) {
692            switch (bit) {
693                case WifiConfiguration.PairwiseCipher.NONE:
694                    mask |= ISupplicantStaNetwork.PairwiseCipherMask.NONE;
695                    break;
696                case WifiConfiguration.PairwiseCipher.TKIP:
697                    mask |= ISupplicantStaNetwork.PairwiseCipherMask.TKIP;
698                    break;
699                case WifiConfiguration.PairwiseCipher.CCMP:
700                    mask |= ISupplicantStaNetwork.PairwiseCipherMask.CCMP;
701                    break;
702                default:
703                    throw new IllegalArgumentException(
704                            "Invalid pairwiseCipherMask bit in wificonfig: " + bit);
705            }
706        }
707        return mask;
708    };
709
710    private static int supplicantToWifiConfigurationEapMethod(int value) {
711        switch (value) {
712            case ISupplicantStaNetwork.EapMethod.PEAP:
713                return WifiEnterpriseConfig.Eap.PEAP;
714            case ISupplicantStaNetwork.EapMethod.TLS:
715                return WifiEnterpriseConfig.Eap.TLS;
716            case ISupplicantStaNetwork.EapMethod.TTLS:
717                return WifiEnterpriseConfig.Eap.TTLS;
718            case ISupplicantStaNetwork.EapMethod.PWD:
719                return WifiEnterpriseConfig.Eap.PWD;
720            case ISupplicantStaNetwork.EapMethod.SIM:
721                return WifiEnterpriseConfig.Eap.SIM;
722            case ISupplicantStaNetwork.EapMethod.AKA:
723                return WifiEnterpriseConfig.Eap.AKA;
724            case ISupplicantStaNetwork.EapMethod.AKA_PRIME:
725                return WifiEnterpriseConfig.Eap.AKA_PRIME;
726            case ISupplicantStaNetwork.EapMethod.WFA_UNAUTH_TLS:
727                return WifiEnterpriseConfig.Eap.UNAUTH_TLS;
728            // WifiEnterpriseConfig.Eap.NONE:
729            default:
730                Log.e(TAG, "invalid eap method value from supplicant: " + value);
731                return -1;
732        }
733    };
734
735    private static int supplicantToWifiConfigurationEapPhase2Method(int value) {
736        switch (value) {
737            case ISupplicantStaNetwork.EapPhase2Method.NONE:
738                return WifiEnterpriseConfig.Phase2.NONE;
739            case ISupplicantStaNetwork.EapPhase2Method.PAP:
740                return WifiEnterpriseConfig.Phase2.PAP;
741            case ISupplicantStaNetwork.EapPhase2Method.MSPAP:
742                return WifiEnterpriseConfig.Phase2.MSCHAP;
743            case ISupplicantStaNetwork.EapPhase2Method.MSPAPV2:
744                return WifiEnterpriseConfig.Phase2.MSCHAPV2;
745            case ISupplicantStaNetwork.EapPhase2Method.GTC:
746                return WifiEnterpriseConfig.Phase2.GTC;
747            case ISupplicantStaNetwork.EapPhase2Method.SIM:
748                return WifiEnterpriseConfig.Phase2.SIM;
749            case ISupplicantStaNetwork.EapPhase2Method.AKA:
750                return WifiEnterpriseConfig.Phase2.AKA;
751            case ISupplicantStaNetwork.EapPhase2Method.AKA_PRIME:
752                return WifiEnterpriseConfig.Phase2.AKA_PRIME;
753            default:
754                Log.e(TAG, "invalid eap phase2 method value from supplicant: " + value);
755                return -1;
756        }
757    };
758
759    private static int supplicantMaskValueToWifiConfigurationBitSet(int supplicantMask,
760                                                             int supplicantValue, BitSet bitset,
761                                                             int bitSetPosition) {
762        bitset.set(bitSetPosition, (supplicantMask & supplicantValue) == supplicantValue);
763        int modifiedSupplicantMask = supplicantMask & ~supplicantValue;
764        return modifiedSupplicantMask;
765    }
766
767    private static BitSet supplicantToWifiConfigurationKeyMgmtMask(int mask) {
768        BitSet bitset = new BitSet();
769        mask = supplicantMaskValueToWifiConfigurationBitSet(
770                mask, ISupplicantStaNetwork.KeyMgmtMask.NONE, bitset,
771                WifiConfiguration.KeyMgmt.NONE);
772        mask = supplicantMaskValueToWifiConfigurationBitSet(
773                mask, ISupplicantStaNetwork.KeyMgmtMask.WPA_PSK, bitset,
774                WifiConfiguration.KeyMgmt.WPA_PSK);
775        mask = supplicantMaskValueToWifiConfigurationBitSet(
776                mask, ISupplicantStaNetwork.KeyMgmtMask.WPA_EAP, bitset,
777                WifiConfiguration.KeyMgmt.WPA_EAP);
778        mask = supplicantMaskValueToWifiConfigurationBitSet(
779                mask, ISupplicantStaNetwork.KeyMgmtMask.IEEE8021X, bitset,
780                WifiConfiguration.KeyMgmt.IEEE8021X);
781        mask = supplicantMaskValueToWifiConfigurationBitSet(
782                mask, ISupplicantStaNetwork.KeyMgmtMask.OSEN, bitset,
783                WifiConfiguration.KeyMgmt.OSEN);
784        mask = supplicantMaskValueToWifiConfigurationBitSet(
785                mask, ISupplicantStaNetwork.KeyMgmtMask.FT_PSK, bitset,
786                WifiConfiguration.KeyMgmt.FT_PSK);
787        mask = supplicantMaskValueToWifiConfigurationBitSet(
788                mask, ISupplicantStaNetwork.KeyMgmtMask.FT_EAP, bitset,
789                WifiConfiguration.KeyMgmt.FT_EAP);
790        if (mask != 0) {
791            throw new IllegalArgumentException(
792                    "invalid key mgmt mask from supplicant: " + mask);
793        }
794        return bitset;
795    }
796
797    private static BitSet supplicantToWifiConfigurationProtoMask(int mask) {
798        BitSet bitset = new BitSet();
799        mask = supplicantMaskValueToWifiConfigurationBitSet(
800                mask, ISupplicantStaNetwork.ProtoMask.WPA, bitset,
801                WifiConfiguration.Protocol.WPA);
802        mask = supplicantMaskValueToWifiConfigurationBitSet(
803                mask, ISupplicantStaNetwork.ProtoMask.RSN, bitset,
804                WifiConfiguration.Protocol.RSN);
805        mask = supplicantMaskValueToWifiConfigurationBitSet(
806                mask, ISupplicantStaNetwork.ProtoMask.OSEN, bitset,
807                WifiConfiguration.Protocol.OSEN);
808        if (mask != 0) {
809            throw new IllegalArgumentException(
810                    "invalid proto mask from supplicant: " + mask);
811        }
812        return bitset;
813    };
814
815    private static BitSet supplicantToWifiConfigurationAuthAlgMask(int mask) {
816        BitSet bitset = new BitSet();
817        mask = supplicantMaskValueToWifiConfigurationBitSet(
818                mask, ISupplicantStaNetwork.AuthAlgMask.OPEN, bitset,
819                WifiConfiguration.AuthAlgorithm.OPEN);
820        mask = supplicantMaskValueToWifiConfigurationBitSet(
821                mask, ISupplicantStaNetwork.AuthAlgMask.SHARED, bitset,
822                WifiConfiguration.AuthAlgorithm.SHARED);
823        mask = supplicantMaskValueToWifiConfigurationBitSet(
824                mask, ISupplicantStaNetwork.AuthAlgMask.LEAP, bitset,
825                WifiConfiguration.AuthAlgorithm.LEAP);
826        if (mask != 0) {
827            throw new IllegalArgumentException(
828                    "invalid auth alg mask from supplicant: " + mask);
829        }
830        return bitset;
831    };
832
833    private static BitSet supplicantToWifiConfigurationGroupCipherMask(int mask) {
834        BitSet bitset = new BitSet();
835        mask = supplicantMaskValueToWifiConfigurationBitSet(
836                mask, ISupplicantStaNetwork.GroupCipherMask.WEP40, bitset,
837                WifiConfiguration.GroupCipher.WEP40);
838        mask = supplicantMaskValueToWifiConfigurationBitSet(
839                mask, ISupplicantStaNetwork.GroupCipherMask.WEP104, bitset,
840                WifiConfiguration.GroupCipher.WEP104);
841        mask = supplicantMaskValueToWifiConfigurationBitSet(
842                mask, ISupplicantStaNetwork.GroupCipherMask.TKIP, bitset,
843                WifiConfiguration.GroupCipher.TKIP);
844        mask = supplicantMaskValueToWifiConfigurationBitSet(
845                mask, ISupplicantStaNetwork.GroupCipherMask.CCMP, bitset,
846                WifiConfiguration.GroupCipher.CCMP);
847        mask = supplicantMaskValueToWifiConfigurationBitSet(
848                mask, ISupplicantStaNetwork.GroupCipherMask.GTK_NOT_USED, bitset,
849                WifiConfiguration.GroupCipher.GTK_NOT_USED);
850        if (mask != 0) {
851            throw new IllegalArgumentException(
852                    "invalid group cipher mask from supplicant: " + mask);
853        }
854        return bitset;
855    };
856
857    private static BitSet supplicantToWifiConfigurationPairwiseCipherMask(int mask) {
858        BitSet bitset = new BitSet();
859        mask = supplicantMaskValueToWifiConfigurationBitSet(
860                mask, ISupplicantStaNetwork.PairwiseCipherMask.NONE, bitset,
861                WifiConfiguration.PairwiseCipher.NONE);
862        mask = supplicantMaskValueToWifiConfigurationBitSet(
863                mask, ISupplicantStaNetwork.PairwiseCipherMask.TKIP, bitset,
864                WifiConfiguration.PairwiseCipher.TKIP);
865        mask = supplicantMaskValueToWifiConfigurationBitSet(
866                mask, ISupplicantStaNetwork.PairwiseCipherMask.CCMP, bitset,
867                WifiConfiguration.PairwiseCipher.CCMP);
868        if (mask != 0) {
869            throw new IllegalArgumentException(
870                    "invalid pairwise cipher mask from supplicant: " + mask);
871        }
872        return bitset;
873    };
874
875    private static int wifiConfigurationToSupplicantEapMethod(int value) {
876        switch (value) {
877            case WifiEnterpriseConfig.Eap.PEAP:
878                return ISupplicantStaNetwork.EapMethod.PEAP;
879            case WifiEnterpriseConfig.Eap.TLS:
880                return ISupplicantStaNetwork.EapMethod.TLS;
881            case WifiEnterpriseConfig.Eap.TTLS:
882                return ISupplicantStaNetwork.EapMethod.TTLS;
883            case WifiEnterpriseConfig.Eap.PWD:
884                return ISupplicantStaNetwork.EapMethod.PWD;
885            case WifiEnterpriseConfig.Eap.SIM:
886                return ISupplicantStaNetwork.EapMethod.SIM;
887            case WifiEnterpriseConfig.Eap.AKA:
888                return ISupplicantStaNetwork.EapMethod.AKA;
889            case WifiEnterpriseConfig.Eap.AKA_PRIME:
890                return ISupplicantStaNetwork.EapMethod.AKA_PRIME;
891            case WifiEnterpriseConfig.Eap.UNAUTH_TLS:
892                return ISupplicantStaNetwork.EapMethod.WFA_UNAUTH_TLS;
893            // WifiEnterpriseConfig.Eap.NONE:
894            default:
895                Log.e(TAG, "invalid eap method value from WifiConfiguration: " + value);
896                return -1;
897        }
898    };
899
900    private static int wifiConfigurationToSupplicantEapPhase2Method(int value) {
901        switch (value) {
902            case WifiEnterpriseConfig.Phase2.NONE:
903                return ISupplicantStaNetwork.EapPhase2Method.NONE;
904            case WifiEnterpriseConfig.Phase2.PAP:
905                return ISupplicantStaNetwork.EapPhase2Method.PAP;
906            case WifiEnterpriseConfig.Phase2.MSCHAP:
907                return ISupplicantStaNetwork.EapPhase2Method.MSPAP;
908            case WifiEnterpriseConfig.Phase2.MSCHAPV2:
909                return ISupplicantStaNetwork.EapPhase2Method.MSPAPV2;
910            case WifiEnterpriseConfig.Phase2.GTC:
911                return ISupplicantStaNetwork.EapPhase2Method.GTC;
912            case WifiEnterpriseConfig.Phase2.SIM:
913                return ISupplicantStaNetwork.EapPhase2Method.SIM;
914            case WifiEnterpriseConfig.Phase2.AKA:
915                return ISupplicantStaNetwork.EapPhase2Method.AKA;
916            case WifiEnterpriseConfig.Phase2.AKA_PRIME:
917                return ISupplicantStaNetwork.EapPhase2Method.AKA_PRIME;
918            default:
919                Log.e(TAG, "invalid eap phase2 method value from WifiConfiguration: " + value);
920                return -1;
921        }
922    };
923
924    /** See ISupplicantNetwork.hal for documentation */
925    private boolean getId() {
926        synchronized (mLock) {
927            final String methodStr = "getId";
928            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
929            try {
930                MutableBoolean statusOk = new MutableBoolean(false);
931                mISupplicantStaNetwork.getId((SupplicantStatus status, int idValue) -> {
932                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
933                    if (statusOk.value) {
934                        this.mNetworkId = idValue;
935                    } else {
936                        checkStatusAndLogFailure(status, methodStr);
937                    }
938                });
939                return statusOk.value;
940            } catch (RemoteException e) {
941                handleRemoteException(e, methodStr);
942                return false;
943            }
944        }
945    }
946
947    /** See ISupplicantStaNetwork.hal for documentation */
948    private boolean registerCallback(ISupplicantStaNetworkCallback callback) {
949        synchronized (mLock) {
950            final String methodStr = "registerCallback";
951            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
952            try {
953                SupplicantStatus status =  mISupplicantStaNetwork.registerCallback(callback);
954                return checkStatusAndLogFailure(status, methodStr);
955            } catch (RemoteException e) {
956                handleRemoteException(e, methodStr);
957                return false;
958            }
959        }
960    }
961
962    /** See ISupplicantStaNetwork.hal for documentation */
963    private boolean setSsid(java.util.ArrayList<Byte> ssid) {
964        synchronized (mLock) {
965            final String methodStr = "setSsid";
966            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
967            try {
968                SupplicantStatus status =  mISupplicantStaNetwork.setSsid(ssid);
969                return checkStatusAndLogFailure(status, methodStr);
970            } catch (RemoteException e) {
971                handleRemoteException(e, methodStr);
972                return false;
973            }
974        }
975    }
976
977    /**
978     * Set the BSSID for this network.
979     *
980     * @param bssidStr MAC address in "XX:XX:XX:XX:XX:XX" form or "any" to reset the mac address.
981     * @return true if it succeeds, false otherwise.
982     */
983    public boolean setBssid(String bssidStr) {
984        try {
985            return setBssid(NativeUtil.macAddressToByteArray(bssidStr));
986        } catch (IllegalArgumentException e) {
987            Log.e(TAG, "Illegal argument " + bssidStr, e);
988            return false;
989        }
990    }
991
992    /** See ISupplicantStaNetwork.hal for documentation */
993    private boolean setBssid(byte[/* 6 */] bssid) {
994        synchronized (mLock) {
995            final String methodStr = "setBssid";
996            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
997            try {
998                SupplicantStatus status =  mISupplicantStaNetwork.setBssid(bssid);
999                return checkStatusAndLogFailure(status, methodStr);
1000            } catch (RemoteException e) {
1001                handleRemoteException(e, methodStr);
1002                return false;
1003            }
1004        }
1005    }
1006    /** See ISupplicantStaNetwork.hal for documentation */
1007    private boolean setScanSsid(boolean enable) {
1008        synchronized (mLock) {
1009            final String methodStr = "setScanSsid";
1010            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1011            try {
1012                SupplicantStatus status =  mISupplicantStaNetwork.setScanSsid(enable);
1013                return checkStatusAndLogFailure(status, methodStr);
1014            } catch (RemoteException e) {
1015                handleRemoteException(e, methodStr);
1016                return false;
1017            }
1018        }
1019    }
1020    /** See ISupplicantStaNetwork.hal for documentation */
1021    private boolean setKeyMgmt(int keyMgmtMask) {
1022        synchronized (mLock) {
1023            final String methodStr = "setKeyMgmt";
1024            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1025            try {
1026                SupplicantStatus status =  mISupplicantStaNetwork.setKeyMgmt(keyMgmtMask);
1027                return checkStatusAndLogFailure(status, methodStr);
1028            } catch (RemoteException e) {
1029                handleRemoteException(e, methodStr);
1030                return false;
1031            }
1032        }
1033    }
1034    /** See ISupplicantStaNetwork.hal for documentation */
1035    private boolean setProto(int protoMask) {
1036        synchronized (mLock) {
1037            final String methodStr = "setProto";
1038            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1039            try {
1040                SupplicantStatus status =  mISupplicantStaNetwork.setProto(protoMask);
1041                return checkStatusAndLogFailure(status, methodStr);
1042            } catch (RemoteException e) {
1043                handleRemoteException(e, methodStr);
1044                return false;
1045            }
1046        }
1047    }
1048    /** See ISupplicantStaNetwork.hal for documentation */
1049    private boolean setAuthAlg(int authAlgMask) {
1050        synchronized (mLock) {
1051            final String methodStr = "setAuthAlg";
1052            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1053            try {
1054                SupplicantStatus status =  mISupplicantStaNetwork.setAuthAlg(authAlgMask);
1055                return checkStatusAndLogFailure(status, methodStr);
1056            } catch (RemoteException e) {
1057                handleRemoteException(e, methodStr);
1058                return false;
1059            }
1060        }
1061    }
1062    /** See ISupplicantStaNetwork.hal for documentation */
1063    private boolean setGroupCipher(int groupCipherMask) {
1064        synchronized (mLock) {
1065            final String methodStr = "setGroupCipher";
1066            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1067            try {
1068                SupplicantStatus status =  mISupplicantStaNetwork.setGroupCipher(groupCipherMask);
1069                return checkStatusAndLogFailure(status, methodStr);
1070            } catch (RemoteException e) {
1071                handleRemoteException(e, methodStr);
1072                return false;
1073            }
1074        }
1075    }
1076    /** See ISupplicantStaNetwork.hal for documentation */
1077    private boolean setPairwiseCipher(int pairwiseCipherMask) {
1078        synchronized (mLock) {
1079            final String methodStr = "setPairwiseCipher";
1080            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1081            try {
1082                SupplicantStatus status =
1083                        mISupplicantStaNetwork.setPairwiseCipher(pairwiseCipherMask);
1084                return checkStatusAndLogFailure(status, methodStr);
1085            } catch (RemoteException e) {
1086                handleRemoteException(e, methodStr);
1087                return false;
1088            }
1089        }
1090    }
1091    /** See ISupplicantStaNetwork.hal for documentation */
1092    private boolean setPskPassphrase(String psk) {
1093        synchronized (mLock) {
1094            final String methodStr = "setPskPassphrase";
1095            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1096            try {
1097                SupplicantStatus status =  mISupplicantStaNetwork.setPskPassphrase(psk);
1098                return checkStatusAndLogFailure(status, methodStr);
1099            } catch (RemoteException e) {
1100                handleRemoteException(e, methodStr);
1101                return false;
1102            }
1103        }
1104    }
1105    /** See ISupplicantStaNetwork.hal for documentation */
1106    private boolean setPsk(byte[] psk) {
1107        synchronized (mLock) {
1108            final String methodStr = "setPsk";
1109            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1110            try {
1111                SupplicantStatus status =  mISupplicantStaNetwork.setPsk(psk);
1112                return checkStatusAndLogFailure(status, methodStr);
1113            } catch (RemoteException e) {
1114                handleRemoteException(e, methodStr);
1115                return false;
1116            }
1117        }
1118    }
1119    /** See ISupplicantStaNetwork.hal for documentation */
1120    private boolean setWepKey(int keyIdx, java.util.ArrayList<Byte> wepKey) {
1121        synchronized (mLock) {
1122            final String methodStr = "setWepKey";
1123            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1124            try {
1125                SupplicantStatus status =  mISupplicantStaNetwork.setWepKey(keyIdx, wepKey);
1126                return checkStatusAndLogFailure(status, methodStr);
1127            } catch (RemoteException e) {
1128                handleRemoteException(e, methodStr);
1129                return false;
1130            }
1131        }
1132    }
1133    /** See ISupplicantStaNetwork.hal for documentation */
1134    private boolean setWepTxKeyIdx(int keyIdx) {
1135        synchronized (mLock) {
1136            final String methodStr = "setWepTxKeyIdx";
1137            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1138            try {
1139                SupplicantStatus status =  mISupplicantStaNetwork.setWepTxKeyIdx(keyIdx);
1140                return checkStatusAndLogFailure(status, methodStr);
1141            } catch (RemoteException e) {
1142                handleRemoteException(e, methodStr);
1143                return false;
1144            }
1145        }
1146    }
1147    /** See ISupplicantStaNetwork.hal for documentation */
1148    private boolean setRequirePmf(boolean enable) {
1149        synchronized (mLock) {
1150            final String methodStr = "setRequirePmf";
1151            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1152            try {
1153                SupplicantStatus status =  mISupplicantStaNetwork.setRequirePmf(enable);
1154                return checkStatusAndLogFailure(status, methodStr);
1155            } catch (RemoteException e) {
1156                handleRemoteException(e, methodStr);
1157                return false;
1158            }
1159        }
1160    }
1161    /** See ISupplicantStaNetwork.hal for documentation */
1162    private boolean setUpdateIdentifier(int identifier) {
1163        synchronized (mLock) {
1164            final String methodStr = "setUpdateIdentifier";
1165            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1166            try {
1167                SupplicantStatus status =  mISupplicantStaNetwork.setUpdateIdentifier(identifier);
1168                return checkStatusAndLogFailure(status, methodStr);
1169            } catch (RemoteException e) {
1170                handleRemoteException(e, methodStr);
1171                return false;
1172            }
1173        }
1174    }
1175    /** See ISupplicantStaNetwork.hal for documentation */
1176    private boolean setEapMethod(int method) {
1177        synchronized (mLock) {
1178            final String methodStr = "setEapMethod";
1179            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1180            try {
1181                SupplicantStatus status =  mISupplicantStaNetwork.setEapMethod(method);
1182                return checkStatusAndLogFailure(status, methodStr);
1183            } catch (RemoteException e) {
1184                handleRemoteException(e, methodStr);
1185                return false;
1186            }
1187        }
1188    }
1189    /** See ISupplicantStaNetwork.hal for documentation */
1190    private boolean setEapPhase2Method(int method) {
1191        synchronized (mLock) {
1192            final String methodStr = "setEapPhase2Method";
1193            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1194            try {
1195                SupplicantStatus status =  mISupplicantStaNetwork.setEapPhase2Method(method);
1196                return checkStatusAndLogFailure(status, methodStr);
1197            } catch (RemoteException e) {
1198                handleRemoteException(e, methodStr);
1199                return false;
1200            }
1201        }
1202    }
1203    /** See ISupplicantStaNetwork.hal for documentation */
1204    private boolean setEapIdentity(java.util.ArrayList<Byte> identity) {
1205        synchronized (mLock) {
1206            final String methodStr = "setEapIdentity";
1207            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1208            try {
1209                SupplicantStatus status =  mISupplicantStaNetwork.setEapIdentity(identity);
1210                return checkStatusAndLogFailure(status, methodStr);
1211            } catch (RemoteException e) {
1212                handleRemoteException(e, methodStr);
1213                return false;
1214            }
1215        }
1216    }
1217    /** See ISupplicantStaNetwork.hal for documentation */
1218    private boolean setEapAnonymousIdentity(java.util.ArrayList<Byte> identity) {
1219        synchronized (mLock) {
1220            final String methodStr = "setEapAnonymousIdentity";
1221            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1222            try {
1223                SupplicantStatus status =  mISupplicantStaNetwork.setEapAnonymousIdentity(identity);
1224                return checkStatusAndLogFailure(status, methodStr);
1225            } catch (RemoteException e) {
1226                handleRemoteException(e, methodStr);
1227                return false;
1228            }
1229        }
1230    }
1231    /** See ISupplicantStaNetwork.hal for documentation */
1232    private boolean setEapPassword(java.util.ArrayList<Byte> password) {
1233        synchronized (mLock) {
1234            final String methodStr = "setEapPassword";
1235            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1236            try {
1237                SupplicantStatus status =  mISupplicantStaNetwork.setEapPassword(password);
1238                return checkStatusAndLogFailure(status, methodStr);
1239            } catch (RemoteException e) {
1240                handleRemoteException(e, methodStr);
1241                return false;
1242            }
1243        }
1244    }
1245    /** See ISupplicantStaNetwork.hal for documentation */
1246    private boolean setEapCACert(String path) {
1247        synchronized (mLock) {
1248            final String methodStr = "setEapCACert";
1249            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1250            try {
1251                SupplicantStatus status =  mISupplicantStaNetwork.setEapCACert(path);
1252                return checkStatusAndLogFailure(status, methodStr);
1253            } catch (RemoteException e) {
1254                handleRemoteException(e, methodStr);
1255                return false;
1256            }
1257        }
1258    }
1259    /** See ISupplicantStaNetwork.hal for documentation */
1260    private boolean setEapCAPath(String path) {
1261        synchronized (mLock) {
1262            final String methodStr = "setEapCAPath";
1263            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1264            try {
1265                SupplicantStatus status =  mISupplicantStaNetwork.setEapCAPath(path);
1266                return checkStatusAndLogFailure(status, methodStr);
1267            } catch (RemoteException e) {
1268                handleRemoteException(e, methodStr);
1269                return false;
1270            }
1271        }
1272    }
1273    /** See ISupplicantStaNetwork.hal for documentation */
1274    private boolean setEapClientCert(String path) {
1275        synchronized (mLock) {
1276            final String methodStr = "setEapClientCert";
1277            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1278            try {
1279                SupplicantStatus status =  mISupplicantStaNetwork.setEapClientCert(path);
1280                return checkStatusAndLogFailure(status, methodStr);
1281            } catch (RemoteException e) {
1282                handleRemoteException(e, methodStr);
1283                return false;
1284            }
1285        }
1286    }
1287    /** See ISupplicantStaNetwork.hal for documentation */
1288    private boolean setEapPrivateKeyId(String id) {
1289        synchronized (mLock) {
1290            final String methodStr = "setEapPrivateKeyId";
1291            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1292            try {
1293                SupplicantStatus status =  mISupplicantStaNetwork.setEapPrivateKeyId(id);
1294                return checkStatusAndLogFailure(status, methodStr);
1295            } catch (RemoteException e) {
1296                handleRemoteException(e, methodStr);
1297                return false;
1298            }
1299        }
1300    }
1301    /** See ISupplicantStaNetwork.hal for documentation */
1302    private boolean setEapSubjectMatch(String match) {
1303        synchronized (mLock) {
1304            final String methodStr = "setEapSubjectMatch";
1305            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1306            try {
1307                SupplicantStatus status =  mISupplicantStaNetwork.setEapSubjectMatch(match);
1308                return checkStatusAndLogFailure(status, methodStr);
1309            } catch (RemoteException e) {
1310                handleRemoteException(e, methodStr);
1311                return false;
1312            }
1313        }
1314    }
1315    /** See ISupplicantStaNetwork.hal for documentation */
1316    private boolean setEapAltSubjectMatch(String match) {
1317        synchronized (mLock) {
1318            final String methodStr = "setEapAltSubjectMatch";
1319            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1320            try {
1321                SupplicantStatus status =  mISupplicantStaNetwork.setEapAltSubjectMatch(match);
1322                return checkStatusAndLogFailure(status, methodStr);
1323            } catch (RemoteException e) {
1324                handleRemoteException(e, methodStr);
1325                return false;
1326            }
1327        }
1328    }
1329    /** See ISupplicantStaNetwork.hal for documentation */
1330    private boolean setEapEngine(boolean enable) {
1331        synchronized (mLock) {
1332            final String methodStr = "setEapEngine";
1333            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1334            try {
1335                SupplicantStatus status =  mISupplicantStaNetwork.setEapEngine(enable);
1336                return checkStatusAndLogFailure(status, methodStr);
1337            } catch (RemoteException e) {
1338                handleRemoteException(e, methodStr);
1339                return false;
1340            }
1341        }
1342    }
1343    /** See ISupplicantStaNetwork.hal for documentation */
1344    private boolean setEapEngineID(String id) {
1345        synchronized (mLock) {
1346            final String methodStr = "setEapEngineID";
1347            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1348            try {
1349                SupplicantStatus status =  mISupplicantStaNetwork.setEapEngineID(id);
1350                return checkStatusAndLogFailure(status, methodStr);
1351            } catch (RemoteException e) {
1352                handleRemoteException(e, methodStr);
1353                return false;
1354            }
1355        }
1356    }
1357    /** See ISupplicantStaNetwork.hal for documentation */
1358    private boolean setEapDomainSuffixMatch(String match) {
1359        synchronized (mLock) {
1360            final String methodStr = "setEapDomainSuffixMatch";
1361            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1362            try {
1363                SupplicantStatus status =  mISupplicantStaNetwork.setEapDomainSuffixMatch(match);
1364                return checkStatusAndLogFailure(status, methodStr);
1365            } catch (RemoteException e) {
1366                handleRemoteException(e, methodStr);
1367                return false;
1368            }
1369        }
1370    }
1371    /** See ISupplicantStaNetwork.hal for documentation */
1372    private boolean setEapProactiveKeyCaching(boolean enable) {
1373        synchronized (mLock) {
1374            final String methodStr = "setEapProactiveKeyCaching";
1375            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1376            try {
1377                SupplicantStatus status =  mISupplicantStaNetwork.setProactiveKeyCaching(enable);
1378                return checkStatusAndLogFailure(status, methodStr);
1379            } catch (RemoteException e) {
1380                handleRemoteException(e, methodStr);
1381                return false;
1382            }
1383        }
1384    }
1385    /** See ISupplicantStaNetwork.hal for documentation */
1386    private boolean setIdStr(String idString) {
1387        synchronized (mLock) {
1388            final String methodStr = "setIdStr";
1389            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1390            try {
1391                SupplicantStatus status =  mISupplicantStaNetwork.setIdStr(idString);
1392                return checkStatusAndLogFailure(status, methodStr);
1393            } catch (RemoteException e) {
1394                handleRemoteException(e, methodStr);
1395                return false;
1396            }
1397        }
1398    }
1399    /** See ISupplicantStaNetwork.hal for documentation */
1400    private boolean getSsid() {
1401        synchronized (mLock) {
1402            final String methodStr = "getSsid";
1403            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1404            try {
1405                MutableBoolean statusOk = new MutableBoolean(false);
1406                mISupplicantStaNetwork.getSsid((SupplicantStatus status,
1407                        java.util.ArrayList<Byte> ssidValue) -> {
1408                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1409                    if (statusOk.value) {
1410                        this.mSsid = ssidValue;
1411                    } else {
1412                        checkStatusAndLogFailure(status, methodStr);
1413                    }
1414                });
1415                return statusOk.value;
1416            } catch (RemoteException e) {
1417                handleRemoteException(e, methodStr);
1418                return false;
1419            }
1420        }
1421    }
1422    /** See ISupplicantStaNetwork.hal for documentation */
1423    private boolean getBssid() {
1424        synchronized (mLock) {
1425            final String methodStr = "getBssid";
1426            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1427            try {
1428                MutableBoolean statusOk = new MutableBoolean(false);
1429                mISupplicantStaNetwork.getBssid((SupplicantStatus status,
1430                        byte[/* 6 */] bssidValue) -> {
1431                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1432                    if (statusOk.value) {
1433                        this.mBssid = bssidValue;
1434                    } else {
1435                        checkStatusAndLogFailure(status, methodStr);
1436                    }
1437                });
1438                return statusOk.value;
1439            } catch (RemoteException e) {
1440                handleRemoteException(e, methodStr);
1441                return false;
1442            }
1443        }
1444    }
1445    /** See ISupplicantStaNetwork.hal for documentation */
1446    private boolean getScanSsid() {
1447        synchronized (mLock) {
1448            final String methodStr = "getScanSsid";
1449            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1450            try {
1451                MutableBoolean statusOk = new MutableBoolean(false);
1452                mISupplicantStaNetwork.getScanSsid((SupplicantStatus status,
1453                        boolean enabledValue) -> {
1454                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1455                    if (statusOk.value) {
1456                        this.mScanSsid = enabledValue;
1457                    } else {
1458                        checkStatusAndLogFailure(status, methodStr);
1459                    }
1460                });
1461                return statusOk.value;
1462            } catch (RemoteException e) {
1463                handleRemoteException(e, methodStr);
1464                return false;
1465            }
1466        }
1467    }
1468    /** See ISupplicantStaNetwork.hal for documentation */
1469    private boolean getKeyMgmt() {
1470        synchronized (mLock) {
1471            final String methodStr = "getKeyMgmt";
1472            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1473            try {
1474                MutableBoolean statusOk = new MutableBoolean(false);
1475                mISupplicantStaNetwork.getKeyMgmt((SupplicantStatus status,
1476                        int keyMgmtMaskValue) -> {
1477                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1478                    if (statusOk.value) {
1479                        this.mKeyMgmtMask = keyMgmtMaskValue;
1480                    } else {
1481                        checkStatusAndLogFailure(status, methodStr);
1482                    }
1483                });
1484                return statusOk.value;
1485            } catch (RemoteException e) {
1486                handleRemoteException(e, methodStr);
1487                return false;
1488            }
1489        }
1490    }
1491    /** See ISupplicantStaNetwork.hal for documentation */
1492    private boolean getProto() {
1493        synchronized (mLock) {
1494            final String methodStr = "getProto";
1495            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1496            try {
1497                MutableBoolean statusOk = new MutableBoolean(false);
1498                mISupplicantStaNetwork.getProto((SupplicantStatus status, int protoMaskValue) -> {
1499                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1500                    if (statusOk.value) {
1501                        this.mProtoMask = protoMaskValue;
1502                    } else {
1503                        checkStatusAndLogFailure(status, methodStr);
1504                    }
1505                });
1506                return statusOk.value;
1507            } catch (RemoteException e) {
1508                handleRemoteException(e, methodStr);
1509                return false;
1510            }
1511        }
1512    }
1513    /** See ISupplicantStaNetwork.hal for documentation */
1514    private boolean getAuthAlg() {
1515        synchronized (mLock) {
1516            final String methodStr = "getAuthAlg";
1517            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1518            try {
1519                MutableBoolean statusOk = new MutableBoolean(false);
1520                mISupplicantStaNetwork.getAuthAlg((SupplicantStatus status,
1521                        int authAlgMaskValue) -> {
1522                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1523                    if (statusOk.value) {
1524                        this.mAuthAlgMask = authAlgMaskValue;
1525                    } else {
1526                        checkStatusAndLogFailure(status, methodStr);
1527                    }
1528                });
1529                return statusOk.value;
1530            } catch (RemoteException e) {
1531                handleRemoteException(e, methodStr);
1532                return false;
1533            }
1534        }
1535    }
1536    /** See ISupplicantStaNetwork.hal for documentation */
1537    private boolean getGroupCipher() {
1538        synchronized (mLock) {
1539            final String methodStr = "getGroupCipher";
1540            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1541            try {
1542                MutableBoolean statusOk = new MutableBoolean(false);
1543                mISupplicantStaNetwork.getGroupCipher((SupplicantStatus status,
1544                        int groupCipherMaskValue) -> {
1545                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1546                    if (statusOk.value) {
1547                        this.mGroupCipherMask = groupCipherMaskValue;
1548                    } else {
1549                        checkStatusAndLogFailure(status, methodStr);
1550                    }
1551                });
1552                return statusOk.value;
1553            } catch (RemoteException e) {
1554                handleRemoteException(e, methodStr);
1555                return false;
1556            }
1557        }
1558    }
1559    /** See ISupplicantStaNetwork.hal for documentation */
1560    private boolean getPairwiseCipher() {
1561        synchronized (mLock) {
1562            final String methodStr = "getPairwiseCipher";
1563            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1564            try {
1565                MutableBoolean statusOk = new MutableBoolean(false);
1566                mISupplicantStaNetwork.getPairwiseCipher((SupplicantStatus status,
1567                        int pairwiseCipherMaskValue) -> {
1568                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1569                    if (statusOk.value) {
1570                        this.mPairwiseCipherMask = pairwiseCipherMaskValue;
1571                    } else {
1572                        checkStatusAndLogFailure(status, methodStr);
1573                    }
1574                });
1575                return statusOk.value;
1576            } catch (RemoteException e) {
1577                handleRemoteException(e, methodStr);
1578                return false;
1579            }
1580        }
1581    }
1582    /** See ISupplicantStaNetwork.hal for documentation */
1583    private boolean getPskPassphrase() {
1584        synchronized (mLock) {
1585            final String methodStr = "getPskPassphrase";
1586            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1587            try {
1588                MutableBoolean statusOk = new MutableBoolean(false);
1589                mISupplicantStaNetwork.getPskPassphrase((SupplicantStatus status,
1590                        String pskValue) -> {
1591                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1592                    if (statusOk.value) {
1593                        this.mPskPassphrase = pskValue;
1594                    } else {
1595                        checkStatusAndLogFailure(status, methodStr);
1596                    }
1597                });
1598                return statusOk.value;
1599            } catch (RemoteException e) {
1600                handleRemoteException(e, methodStr);
1601                return false;
1602            }
1603        }
1604    }
1605    /** See ISupplicantStaNetwork.hal for documentation */
1606    private boolean getPsk() {
1607        synchronized (mLock) {
1608            final String methodStr = "getPsk";
1609            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1610            try {
1611                MutableBoolean statusOk = new MutableBoolean(false);
1612                mISupplicantStaNetwork.getPsk((SupplicantStatus status, byte[] pskValue) -> {
1613                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1614                    if (statusOk.value) {
1615                        this.mPsk = pskValue;
1616                    } else {
1617                        checkStatusAndLogFailure(status, methodStr);
1618                    }
1619                });
1620                return statusOk.value;
1621            } catch (RemoteException e) {
1622                handleRemoteException(e, methodStr);
1623                return false;
1624            }
1625        }
1626    }
1627    /** See ISupplicantStaNetwork.hal for documentation */
1628    private boolean getWepKey(int keyIdx) {
1629        synchronized (mLock) {
1630            final String methodStr = "keyIdx";
1631            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1632            try {
1633                MutableBoolean statusOk = new MutableBoolean(false);
1634                mISupplicantStaNetwork.getWepKey(keyIdx, (SupplicantStatus status,
1635                        java.util.ArrayList<Byte> wepKeyValue) -> {
1636                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1637                    if (statusOk.value) {
1638                        this.mWepKey = wepKeyValue;
1639                    } else {
1640                        Log.e(TAG, methodStr + ",  failed: " + status.debugMessage);
1641                    }
1642                });
1643                return statusOk.value;
1644            } catch (RemoteException e) {
1645                handleRemoteException(e, methodStr);
1646                return false;
1647            }
1648        }
1649    }
1650    /** See ISupplicantStaNetwork.hal for documentation */
1651    private boolean getWepTxKeyIdx() {
1652        synchronized (mLock) {
1653            final String methodStr = "getWepTxKeyIdx";
1654            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1655            try {
1656                MutableBoolean statusOk = new MutableBoolean(false);
1657                mISupplicantStaNetwork.getWepTxKeyIdx((SupplicantStatus status,
1658                        int keyIdxValue) -> {
1659                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1660                    if (statusOk.value) {
1661                        this.mWepTxKeyIdx = keyIdxValue;
1662                    } else {
1663                        checkStatusAndLogFailure(status, methodStr);
1664                    }
1665                });
1666                return statusOk.value;
1667            } catch (RemoteException e) {
1668                handleRemoteException(e, methodStr);
1669                return false;
1670            }
1671        }
1672    }
1673    /** See ISupplicantStaNetwork.hal for documentation */
1674    private boolean getRequirePmf() {
1675        synchronized (mLock) {
1676            final String methodStr = "getRequirePmf";
1677            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1678            try {
1679                MutableBoolean statusOk = new MutableBoolean(false);
1680                mISupplicantStaNetwork.getRequirePmf((SupplicantStatus status,
1681                        boolean enabledValue) -> {
1682                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1683                    if (statusOk.value) {
1684                        this.mRequirePmf = enabledValue;
1685                    } else {
1686                        checkStatusAndLogFailure(status, methodStr);
1687                    }
1688                });
1689                return statusOk.value;
1690            } catch (RemoteException e) {
1691                handleRemoteException(e, methodStr);
1692                return false;
1693            }
1694        }
1695    }
1696    /** See ISupplicantStaNetwork.hal for documentation */
1697    private boolean getEapMethod() {
1698        synchronized (mLock) {
1699            final String methodStr = "getEapMethod";
1700            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1701            try {
1702                MutableBoolean statusOk = new MutableBoolean(false);
1703                mISupplicantStaNetwork.getEapMethod((SupplicantStatus status,
1704                        int methodValue) -> {
1705                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1706                    if (statusOk.value) {
1707                        this.mEapMethod = methodValue;
1708                    } else {
1709                        checkStatusAndLogFailure(status, methodStr);
1710                    }
1711                });
1712                return statusOk.value;
1713            } catch (RemoteException e) {
1714                handleRemoteException(e, methodStr);
1715                return false;
1716            }
1717        }
1718    }
1719    /** See ISupplicantStaNetwork.hal for documentation */
1720    private boolean getEapPhase2Method() {
1721        synchronized (mLock) {
1722            final String methodStr = "getEapPhase2Method";
1723            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1724            try {
1725                MutableBoolean statusOk = new MutableBoolean(false);
1726                mISupplicantStaNetwork.getEapPhase2Method((SupplicantStatus status,
1727                        int methodValue) -> {
1728                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1729                    if (statusOk.value) {
1730                        this.mEapPhase2Method = methodValue;
1731                    } else {
1732                        checkStatusAndLogFailure(status, methodStr);
1733                    }
1734                });
1735                return statusOk.value;
1736            } catch (RemoteException e) {
1737                handleRemoteException(e, methodStr);
1738                return false;
1739            }
1740        }
1741    }
1742    /** See ISupplicantStaNetwork.hal for documentation */
1743    private boolean getEapIdentity() {
1744        synchronized (mLock) {
1745            final String methodStr = "getEapIdentity";
1746            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1747            try {
1748                MutableBoolean statusOk = new MutableBoolean(false);
1749                mISupplicantStaNetwork.getEapIdentity((SupplicantStatus status,
1750                        ArrayList<Byte> identityValue) -> {
1751                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1752                    if (statusOk.value) {
1753                        this.mEapIdentity = identityValue;
1754                    } else {
1755                        checkStatusAndLogFailure(status, methodStr);
1756                    }
1757                });
1758                return statusOk.value;
1759            } catch (RemoteException e) {
1760                handleRemoteException(e, methodStr);
1761                return false;
1762            }
1763        }
1764    }
1765    /** See ISupplicantStaNetwork.hal for documentation */
1766    private boolean getEapAnonymousIdentity() {
1767        synchronized (mLock) {
1768            final String methodStr = "getEapAnonymousIdentity";
1769            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1770            try {
1771                MutableBoolean statusOk = new MutableBoolean(false);
1772                mISupplicantStaNetwork.getEapAnonymousIdentity((SupplicantStatus status,
1773                        ArrayList<Byte> identityValue) -> {
1774                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1775                    if (statusOk.value) {
1776                        this.mEapAnonymousIdentity = identityValue;
1777                    } else {
1778                        checkStatusAndLogFailure(status, methodStr);
1779                    }
1780                });
1781                return statusOk.value;
1782            } catch (RemoteException e) {
1783                handleRemoteException(e, methodStr);
1784                return false;
1785            }
1786        }
1787    }
1788
1789    /**
1790     * A wrapping method for getEapAnonymousIdentity().
1791     * This get anonymous identity from supplicant and returns it as a string.
1792     *
1793     * @return anonymous identity string if succeeds, null otherwise.
1794     */
1795    public String fetchEapAnonymousIdentity() {
1796        if (!getEapAnonymousIdentity()) {
1797            return null;
1798        }
1799        return NativeUtil.stringFromByteArrayList(mEapAnonymousIdentity);
1800    }
1801
1802    /** See ISupplicantStaNetwork.hal for documentation */
1803    private boolean getEapPassword() {
1804        synchronized (mLock) {
1805            final String methodStr = "getEapPassword";
1806            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1807            try {
1808                MutableBoolean statusOk = new MutableBoolean(false);
1809                mISupplicantStaNetwork.getEapPassword((SupplicantStatus status,
1810                        ArrayList<Byte> passwordValue) -> {
1811                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1812                    if (statusOk.value) {
1813                        this.mEapPassword = passwordValue;
1814                    } else {
1815                        checkStatusAndLogFailure(status, methodStr);
1816                    }
1817                });
1818                return statusOk.value;
1819            } catch (RemoteException e) {
1820                handleRemoteException(e, methodStr);
1821                return false;
1822            }
1823        }
1824    }
1825    /** See ISupplicantStaNetwork.hal for documentation */
1826    private boolean getEapCACert() {
1827        synchronized (mLock) {
1828            final String methodStr = "getEapCACert";
1829            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1830            try {
1831                MutableBoolean statusOk = new MutableBoolean(false);
1832                mISupplicantStaNetwork.getEapCACert((SupplicantStatus status, String pathValue) -> {
1833                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1834                    if (statusOk.value) {
1835                        this.mEapCACert = pathValue;
1836                    } else {
1837                        checkStatusAndLogFailure(status, methodStr);
1838                    }
1839                });
1840                return statusOk.value;
1841            } catch (RemoteException e) {
1842                handleRemoteException(e, methodStr);
1843                return false;
1844            }
1845        }
1846    }
1847    /** See ISupplicantStaNetwork.hal for documentation */
1848    private boolean getEapCAPath() {
1849        synchronized (mLock) {
1850            final String methodStr = "getEapCAPath";
1851            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1852            try {
1853                MutableBoolean statusOk = new MutableBoolean(false);
1854                mISupplicantStaNetwork.getEapCAPath((SupplicantStatus status, String pathValue) -> {
1855                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1856                    if (statusOk.value) {
1857                        this.mEapCAPath = pathValue;
1858                    } else {
1859                        checkStatusAndLogFailure(status, methodStr);
1860                    }
1861                });
1862                return statusOk.value;
1863            } catch (RemoteException e) {
1864                handleRemoteException(e, methodStr);
1865                return false;
1866            }
1867        }
1868    }
1869    /** See ISupplicantStaNetwork.hal for documentation */
1870    private boolean getEapClientCert() {
1871        synchronized (mLock) {
1872            final String methodStr = "getEapClientCert";
1873            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1874            try {
1875                MutableBoolean statusOk = new MutableBoolean(false);
1876                mISupplicantStaNetwork.getEapClientCert((SupplicantStatus status,
1877                        String pathValue) -> {
1878                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1879                    if (statusOk.value) {
1880                        this.mEapClientCert = pathValue;
1881                    } else {
1882                        checkStatusAndLogFailure(status, methodStr);
1883                    }
1884                });
1885                return statusOk.value;
1886            } catch (RemoteException e) {
1887                handleRemoteException(e, methodStr);
1888                return false;
1889            }
1890        }
1891    }
1892    /** See ISupplicantStaNetwork.hal for documentation */
1893    private boolean getEapPrivateKeyId() {
1894        synchronized (mLock) {
1895            final String methodStr = "getEapPrivateKeyId";
1896            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1897            try {
1898                MutableBoolean statusOk = new MutableBoolean(false);
1899                mISupplicantStaNetwork.getEapPrivateKeyId((SupplicantStatus status,
1900                        String idValue) -> {
1901                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1902                    if (statusOk.value) {
1903                        this.mEapPrivateKeyId = idValue;
1904                    } else {
1905                        checkStatusAndLogFailure(status, methodStr);
1906                    }
1907                });
1908                return statusOk.value;
1909            } catch (RemoteException e) {
1910                handleRemoteException(e, methodStr);
1911                return false;
1912            }
1913        }
1914    }
1915    /** See ISupplicantStaNetwork.hal for documentation */
1916    private boolean getEapSubjectMatch() {
1917        synchronized (mLock) {
1918            final String methodStr = "getEapSubjectMatch";
1919            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1920            try {
1921                MutableBoolean statusOk = new MutableBoolean(false);
1922                mISupplicantStaNetwork.getEapSubjectMatch((SupplicantStatus status,
1923                        String matchValue) -> {
1924                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1925                    if (statusOk.value) {
1926                        this.mEapSubjectMatch = matchValue;
1927                    } else {
1928                        checkStatusAndLogFailure(status, methodStr);
1929                    }
1930                });
1931                return statusOk.value;
1932            } catch (RemoteException e) {
1933                handleRemoteException(e, methodStr);
1934                return false;
1935            }
1936        }
1937    }
1938    /** See ISupplicantStaNetwork.hal for documentation */
1939    private boolean getEapAltSubjectMatch() {
1940        synchronized (mLock) {
1941            final String methodStr = "getEapAltSubjectMatch";
1942            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1943            try {
1944                MutableBoolean statusOk = new MutableBoolean(false);
1945                mISupplicantStaNetwork.getEapAltSubjectMatch((SupplicantStatus status,
1946                        String matchValue) -> {
1947                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1948                    if (statusOk.value) {
1949                        this.mEapAltSubjectMatch = matchValue;
1950                    } else {
1951                        checkStatusAndLogFailure(status, methodStr);
1952                    }
1953                });
1954                return statusOk.value;
1955            } catch (RemoteException e) {
1956                handleRemoteException(e, methodStr);
1957                return false;
1958            }
1959        }
1960    }
1961    /** See ISupplicantStaNetwork.hal for documentation */
1962    private boolean getEapEngine() {
1963        synchronized (mLock) {
1964            final String methodStr = "getEapEngine";
1965            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1966            try {
1967                MutableBoolean statusOk = new MutableBoolean(false);
1968                mISupplicantStaNetwork.getEapEngine((SupplicantStatus status,
1969                        boolean enabledValue) -> {
1970                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1971                    if (statusOk.value) {
1972                        this.mEapEngine = enabledValue;
1973                    } else {
1974                        checkStatusAndLogFailure(status, methodStr);
1975                    }
1976                });
1977                return statusOk.value;
1978            } catch (RemoteException e) {
1979                handleRemoteException(e, methodStr);
1980                return false;
1981            }
1982        }
1983    }
1984    /** See ISupplicantStaNetwork.hal for documentation */
1985    private boolean getEapEngineID() {
1986        synchronized (mLock) {
1987            final String methodStr = "getEapEngineID";
1988            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
1989            try {
1990                MutableBoolean statusOk = new MutableBoolean(false);
1991                mISupplicantStaNetwork.getEapEngineID((SupplicantStatus status, String idValue) -> {
1992                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
1993                    if (statusOk.value) {
1994                        this.mEapEngineID = idValue;
1995                    } else {
1996                        checkStatusAndLogFailure(status, methodStr);
1997                    }
1998                });
1999                return statusOk.value;
2000            } catch (RemoteException e) {
2001                handleRemoteException(e, methodStr);
2002                return false;
2003            }
2004        }
2005    }
2006    /** See ISupplicantStaNetwork.hal for documentation */
2007    private boolean getEapDomainSuffixMatch() {
2008        synchronized (mLock) {
2009            final String methodStr = "getEapDomainSuffixMatch";
2010            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
2011            try {
2012                MutableBoolean statusOk = new MutableBoolean(false);
2013                mISupplicantStaNetwork.getEapDomainSuffixMatch((SupplicantStatus status,
2014                        String matchValue) -> {
2015                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
2016                    if (statusOk.value) {
2017                        this.mEapDomainSuffixMatch = matchValue;
2018                    } else {
2019                        checkStatusAndLogFailure(status, methodStr);
2020                    }
2021                });
2022                return statusOk.value;
2023            } catch (RemoteException e) {
2024                handleRemoteException(e, methodStr);
2025                return false;
2026            }
2027        }
2028    }
2029    /** See ISupplicantStaNetwork.hal for documentation */
2030    private boolean getIdStr() {
2031        synchronized (mLock) {
2032            final String methodStr = "getIdStr";
2033            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
2034            try {
2035                MutableBoolean statusOk = new MutableBoolean(false);
2036                mISupplicantStaNetwork.getIdStr((SupplicantStatus status, String idString) -> {
2037                    statusOk.value = status.code == SupplicantStatusCode.SUCCESS;
2038                    if (statusOk.value) {
2039                        this.mIdStr = idString;
2040                    } else {
2041                        checkStatusAndLogFailure(status, methodStr);
2042                    }
2043                });
2044                return statusOk.value;
2045            } catch (RemoteException e) {
2046                handleRemoteException(e, methodStr);
2047                return false;
2048            }
2049        }
2050    }
2051    /** See ISupplicantStaNetwork.hal for documentation */
2052    private boolean enable(boolean noConnect) {
2053        synchronized (mLock) {
2054            final String methodStr = "enable";
2055            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
2056            try {
2057                SupplicantStatus status =  mISupplicantStaNetwork.enable(noConnect);
2058                return checkStatusAndLogFailure(status, methodStr);
2059            } catch (RemoteException e) {
2060                handleRemoteException(e, methodStr);
2061                return false;
2062            }
2063        }
2064    }
2065    /** See ISupplicantStaNetwork.hal for documentation */
2066    private boolean disable() {
2067        synchronized (mLock) {
2068            final String methodStr = "disable";
2069            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
2070            try {
2071                SupplicantStatus status =  mISupplicantStaNetwork.disable();
2072                return checkStatusAndLogFailure(status, methodStr);
2073            } catch (RemoteException e) {
2074                handleRemoteException(e, methodStr);
2075                return false;
2076            }
2077        }
2078    }
2079
2080    /**
2081     * Trigger a connection to this network.
2082     *
2083     * @return true if it succeeds, false otherwise.
2084     */
2085    public boolean select() {
2086        synchronized (mLock) {
2087            final String methodStr = "select";
2088            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
2089            try {
2090                SupplicantStatus status =  mISupplicantStaNetwork.select();
2091                return checkStatusAndLogFailure(status, methodStr);
2092            } catch (RemoteException e) {
2093                handleRemoteException(e, methodStr);
2094                return false;
2095            }
2096        }
2097    }
2098
2099    /**
2100     * Send GSM auth response.
2101     *
2102     * @param paramsStr Response params as a string.
2103     * @return true if succeeds, false otherwise.
2104     */
2105    public boolean sendNetworkEapSimGsmAuthResponse(String paramsStr) {
2106        try {
2107            Matcher match = GSM_AUTH_RESPONSE_PARAMS_PATTERN.matcher(paramsStr);
2108            ArrayList<ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams> params =
2109                    new ArrayList<>();
2110            while (match.find()) {
2111                if (match.groupCount() != 2) {
2112                    Log.e(TAG, "Malformed gsm auth response params: " + paramsStr);
2113                    return false;
2114                }
2115                ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams param =
2116                        new ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams();
2117                byte[] kc = NativeUtil.hexStringToByteArray(match.group(1));
2118                if (kc == null || kc.length != param.kc.length) {
2119                    Log.e(TAG, "Invalid kc value: " + match.group(1));
2120                    return false;
2121                }
2122                byte[] sres = NativeUtil.hexStringToByteArray(match.group(2));
2123                if (sres == null || sres.length != param.sres.length) {
2124                    Log.e(TAG, "Invalid sres value: " + match.group(2));
2125                    return false;
2126                }
2127                System.arraycopy(kc, 0, param.kc, 0, param.kc.length);
2128                System.arraycopy(sres, 0, param.sres, 0, param.sres.length);
2129                params.add(param);
2130            }
2131            // The number of kc/sres pairs can either be 2 or 3 depending on the request.
2132            if (params.size() > 3 || params.size() < 2) {
2133                Log.e(TAG, "Malformed gsm auth response params: " + paramsStr);
2134                return false;
2135            }
2136            return sendNetworkEapSimGsmAuthResponse(params);
2137        } catch (IllegalArgumentException e) {
2138            Log.e(TAG, "Illegal argument " + paramsStr, e);
2139            return false;
2140        }
2141    }
2142
2143    /** See ISupplicantStaNetwork.hal for documentation */
2144    private boolean sendNetworkEapSimGsmAuthResponse(
2145            ArrayList<ISupplicantStaNetwork.NetworkResponseEapSimGsmAuthParams> params) {
2146        synchronized (mLock) {
2147            final String methodStr = "sendNetworkEapSimGsmAuthResponse";
2148            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
2149            try {
2150                SupplicantStatus status =
2151                        mISupplicantStaNetwork.sendNetworkEapSimGsmAuthResponse(params);
2152                return checkStatusAndLogFailure(status, methodStr);
2153            } catch (RemoteException e) {
2154                handleRemoteException(e, methodStr);
2155                return false;
2156            }
2157        }
2158    }
2159    /** See ISupplicantStaNetwork.hal for documentation */
2160    public boolean sendNetworkEapSimGsmAuthFailure() {
2161        synchronized (mLock) {
2162            final String methodStr = "sendNetworkEapSimGsmAuthFailure";
2163            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
2164            try {
2165                SupplicantStatus status = mISupplicantStaNetwork.sendNetworkEapSimGsmAuthFailure();
2166                return checkStatusAndLogFailure(status, methodStr);
2167            } catch (RemoteException e) {
2168                handleRemoteException(e, methodStr);
2169                return false;
2170            }
2171        }
2172    }
2173    /**
2174     * Send UMTS auth response.
2175     *
2176     * @param paramsStr Response params as a string.
2177     * @return true if succeeds, false otherwise.
2178     */
2179    public boolean sendNetworkEapSimUmtsAuthResponse(String paramsStr) {
2180        try {
2181            Matcher match = UMTS_AUTH_RESPONSE_PARAMS_PATTERN.matcher(paramsStr);
2182            if (!match.find() || match.groupCount() != 3) {
2183                Log.e(TAG, "Malformed umts auth response params: " + paramsStr);
2184                return false;
2185            }
2186            ISupplicantStaNetwork.NetworkResponseEapSimUmtsAuthParams params =
2187                    new ISupplicantStaNetwork.NetworkResponseEapSimUmtsAuthParams();
2188            byte[] ik = NativeUtil.hexStringToByteArray(match.group(1));
2189            if (ik == null || ik.length != params.ik.length) {
2190                Log.e(TAG, "Invalid ik value: " + match.group(1));
2191                return false;
2192            }
2193            byte[] ck = NativeUtil.hexStringToByteArray(match.group(2));
2194            if (ck == null || ck.length != params.ck.length) {
2195                Log.e(TAG, "Invalid ck value: " + match.group(2));
2196                return false;
2197            }
2198            byte[] res = NativeUtil.hexStringToByteArray(match.group(3));
2199            if (res == null || res.length == 0) {
2200                Log.e(TAG, "Invalid res value: " + match.group(3));
2201                return false;
2202            }
2203            System.arraycopy(ik, 0, params.ik, 0, params.ik.length);
2204            System.arraycopy(ck, 0, params.ck, 0, params.ck.length);
2205            for (byte b : res) {
2206                params.res.add(b);
2207            }
2208            return sendNetworkEapSimUmtsAuthResponse(params);
2209        } catch (IllegalArgumentException e) {
2210            Log.e(TAG, "Illegal argument " + paramsStr, e);
2211            return false;
2212        }
2213    }
2214
2215    /** See ISupplicantStaNetwork.hal for documentation */
2216    private boolean sendNetworkEapSimUmtsAuthResponse(
2217            ISupplicantStaNetwork.NetworkResponseEapSimUmtsAuthParams params) {
2218        synchronized (mLock) {
2219            final String methodStr = "sendNetworkEapSimUmtsAuthResponse";
2220            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
2221            try {
2222                SupplicantStatus status =
2223                        mISupplicantStaNetwork.sendNetworkEapSimUmtsAuthResponse(params);
2224                return checkStatusAndLogFailure(status, methodStr);
2225            } catch (RemoteException e) {
2226                handleRemoteException(e, methodStr);
2227                return false;
2228            }
2229        }
2230    }
2231    /**
2232     * Send UMTS auts response.
2233     *
2234     * @param paramsStr Response params as a string.
2235     * @return true if succeeds, false otherwise.
2236     */
2237    public boolean sendNetworkEapSimUmtsAutsResponse(String paramsStr) {
2238        try {
2239            Matcher match = UMTS_AUTS_RESPONSE_PARAMS_PATTERN.matcher(paramsStr);
2240            if (!match.find() || match.groupCount() != 1) {
2241                Log.e(TAG, "Malformed umts auts response params: " + paramsStr);
2242                return false;
2243            }
2244            byte[] auts = NativeUtil.hexStringToByteArray(match.group(1));
2245            if (auts == null || auts.length != 14) {
2246                Log.e(TAG, "Invalid auts value: " + match.group(1));
2247                return false;
2248            }
2249            return sendNetworkEapSimUmtsAutsResponse(auts);
2250        } catch (IllegalArgumentException e) {
2251            Log.e(TAG, "Illegal argument " + paramsStr, e);
2252            return false;
2253        }
2254    }
2255    /** See ISupplicantStaNetwork.hal for documentation */
2256    private boolean sendNetworkEapSimUmtsAutsResponse(byte[/* 14 */] auts) {
2257        synchronized (mLock) {
2258            final String methodStr = "sendNetworkEapSimUmtsAutsResponse";
2259            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
2260            try {
2261                SupplicantStatus status =
2262                        mISupplicantStaNetwork.sendNetworkEapSimUmtsAutsResponse(auts);
2263                return checkStatusAndLogFailure(status, methodStr);
2264            } catch (RemoteException e) {
2265                handleRemoteException(e, methodStr);
2266                return false;
2267            }
2268        }
2269    }
2270    /** See ISupplicantStaNetwork.hal for documentation */
2271    public boolean sendNetworkEapSimUmtsAuthFailure() {
2272        synchronized (mLock) {
2273            final String methodStr = "sendNetworkEapSimUmtsAuthFailure";
2274            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
2275            try {
2276                SupplicantStatus status = mISupplicantStaNetwork.sendNetworkEapSimUmtsAuthFailure();
2277                return checkStatusAndLogFailure(status, methodStr);
2278            } catch (RemoteException e) {
2279                handleRemoteException(e, methodStr);
2280                return false;
2281            }
2282        }
2283    }
2284    /**
2285     * Send eap identity response.
2286     *
2287     * @param identityStr Identity as a string.
2288     * @return true if succeeds, false otherwise.
2289     */
2290    public boolean sendNetworkEapIdentityResponse(String identityStr) {
2291        try {
2292            ArrayList<Byte> identity = NativeUtil.stringToByteArrayList(identityStr);
2293            return sendNetworkEapIdentityResponse(identity);
2294        } catch (IllegalArgumentException e) {
2295            Log.e(TAG, "Illegal argument " + identityStr, e);
2296            return false;
2297        }
2298    }
2299    /** See ISupplicantStaNetwork.hal for documentation */
2300    private boolean sendNetworkEapIdentityResponse(ArrayList<Byte> identity) {
2301        synchronized (mLock) {
2302            final String methodStr = "sendNetworkEapIdentityResponse";
2303            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return false;
2304            try {
2305                SupplicantStatus status =
2306                        mISupplicantStaNetwork.sendNetworkEapIdentityResponse(identity);
2307                return checkStatusAndLogFailure(status, methodStr);
2308            } catch (RemoteException e) {
2309                handleRemoteException(e, methodStr);
2310                return false;
2311            }
2312        }
2313    }
2314
2315    /**
2316     * Retrieve the NFC token for this network.
2317     *
2318     * @return Hex string corresponding to the NFC token or null for failure.
2319     */
2320    public String getWpsNfcConfigurationToken() {
2321        ArrayList<Byte> token = getWpsNfcConfigurationTokenInternal();
2322        if (token == null) {
2323            return null;
2324        }
2325        return NativeUtil.hexStringFromByteArray(NativeUtil.byteArrayFromArrayList(token));
2326    }
2327
2328    /** See ISupplicantStaNetwork.hal for documentation */
2329    private ArrayList<Byte> getWpsNfcConfigurationTokenInternal() {
2330        synchronized (mLock) {
2331            final String methodStr = "getWpsNfcConfigurationToken";
2332            if (!checkISupplicantStaNetworkAndLogFailure(methodStr)) return null;
2333            final Mutable<ArrayList<Byte>> gotToken = new Mutable<>();
2334            try {
2335                mISupplicantStaNetwork.getWpsNfcConfigurationToken(
2336                        (SupplicantStatus status, ArrayList<Byte> token) -> {
2337                            if (checkStatusAndLogFailure(status, methodStr)) {
2338                                gotToken.value = token;
2339                            }
2340                        });
2341            } catch (RemoteException e) {
2342                handleRemoteException(e, methodStr);
2343            }
2344            return gotToken.value;
2345        }
2346    }
2347
2348    /**
2349     * Returns true if provided status code is SUCCESS, logs debug message and returns false
2350     * otherwise
2351     */
2352    private boolean checkStatusAndLogFailure(SupplicantStatus status, final String methodStr) {
2353        if (status.code != SupplicantStatusCode.SUCCESS) {
2354            Log.e(TAG, "ISupplicantStaNetwork." + methodStr + " failed: "
2355                    + SupplicantStaIfaceHal.supplicantStatusCodeToString(status.code) + ", "
2356                    + status.debugMessage);
2357            return false;
2358        } else {
2359            if (mVerboseLoggingEnabled) {
2360                Log.d(TAG, "ISupplicantStaNetwork." + methodStr + " succeeded");
2361            }
2362            return true;
2363        }
2364    }
2365
2366    /**
2367     * Helper function to log callbacks.
2368     */
2369    private void logCallback(final String methodStr) {
2370        if (mVerboseLoggingEnabled) {
2371            Log.d(TAG, "ISupplicantStaNetworkCallback." + methodStr + " received");
2372        }
2373    }
2374
2375    /**
2376     * Returns false if ISupplicantStaNetwork is null, and logs failure of methodStr
2377     */
2378    private boolean checkISupplicantStaNetworkAndLogFailure(final String methodStr) {
2379        if (mISupplicantStaNetwork == null) {
2380            Log.e(TAG, "Can't call " + methodStr + ", ISupplicantStaNetwork is null");
2381            return false;
2382        }
2383        return true;
2384    }
2385
2386    private void handleRemoteException(RemoteException e, String methodStr) {
2387        mISupplicantStaNetwork = null;
2388        Log.e(TAG, "ISupplicantStaNetwork." + methodStr + " failed with exception", e);
2389    }
2390
2391    /**
2392     * Adds FT flags for networks if the device supports it.
2393     */
2394    private BitSet addFastTransitionFlags(BitSet keyManagementFlags) {
2395        if (!mSystemSupportsFastBssTransition) {
2396            return keyManagementFlags;
2397        }
2398        BitSet modifiedFlags = (BitSet) keyManagementFlags.clone();
2399        if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
2400            modifiedFlags.set(WifiConfiguration.KeyMgmt.FT_PSK);
2401        }
2402        if (keyManagementFlags.get(WifiConfiguration.KeyMgmt.WPA_EAP)) {
2403            modifiedFlags.set(WifiConfiguration.KeyMgmt.FT_EAP);
2404        }
2405        return modifiedFlags;
2406    }
2407
2408    /**
2409     * Removes FT flags for networks if the device supports it.
2410     */
2411    private BitSet removeFastTransitionFlags(BitSet keyManagementFlags) {
2412        BitSet modifiedFlags = (BitSet) keyManagementFlags.clone();
2413        modifiedFlags.clear(WifiConfiguration.KeyMgmt.FT_PSK);
2414        modifiedFlags.clear(WifiConfiguration.KeyMgmt.FT_EAP);
2415        return modifiedFlags;
2416    }
2417
2418    /**
2419     * Creates the JSON encoded network extra using the map of string key, value pairs.
2420     */
2421    public static String createNetworkExtra(Map<String, String> values) {
2422        final String encoded;
2423        try {
2424            encoded = URLEncoder.encode(new JSONObject(values).toString(), "UTF-8");
2425        } catch (NullPointerException e) {
2426            Log.e(TAG, "Unable to serialize networkExtra: " + e.toString());
2427            return null;
2428        } catch (UnsupportedEncodingException e) {
2429            Log.e(TAG, "Unable to serialize networkExtra: " + e.toString());
2430            return null;
2431        }
2432        return encoded;
2433    }
2434
2435    /**
2436     * Parse the network extra JSON encoded string to a map of string key, value pairs.
2437     */
2438    public static Map<String, String> parseNetworkExtra(String encoded) {
2439        if (TextUtils.isEmpty(encoded)) {
2440            return null;
2441        }
2442        try {
2443            // This method reads a JSON dictionary that was written by setNetworkExtra(). However,
2444            // on devices that upgraded from Marshmallow, it may encounter a legacy value instead -
2445            // an FQDN stored as a plain string. If such a value is encountered, the JSONObject
2446            // constructor will thrown a JSONException and the method will return null.
2447            final JSONObject json = new JSONObject(URLDecoder.decode(encoded, "UTF-8"));
2448            final Map<String, String> values = new HashMap<>();
2449            final Iterator<?> it = json.keys();
2450            while (it.hasNext()) {
2451                final String key = (String) it.next();
2452                final Object value = json.get(key);
2453                if (value instanceof String) {
2454                    values.put(key, (String) value);
2455                }
2456            }
2457            return values;
2458        } catch (UnsupportedEncodingException e) {
2459            Log.e(TAG, "Unable to deserialize networkExtra: " + e.toString());
2460            return null;
2461        } catch (JSONException e) {
2462            // This is not necessarily an error. This exception will also occur if we encounter a
2463            // legacy FQDN stored as a plain string. We want to return null in this case as no JSON
2464            // dictionary of extras was found.
2465            return null;
2466        }
2467    }
2468
2469    private static class Mutable<E> {
2470        public E value;
2471
2472        Mutable() {
2473            value = null;
2474        }
2475
2476        Mutable(E value) {
2477            this.value = value;
2478        }
2479    }
2480
2481    private class SupplicantStaNetworkHalCallback extends ISupplicantStaNetworkCallback.Stub {
2482        /**
2483         * Current configured network's framework network id.
2484         */
2485        private final int mFramewokNetworkId;
2486        /**
2487         * Current configured network's ssid.
2488         */
2489        private final String mSsid;
2490
2491        SupplicantStaNetworkHalCallback(int framewokNetworkId, String ssid) {
2492            mFramewokNetworkId = framewokNetworkId;
2493            mSsid = ssid;
2494        }
2495
2496        @Override
2497        public void onNetworkEapSimGsmAuthRequest(
2498                ISupplicantStaNetworkCallback.NetworkRequestEapSimGsmAuthParams params) {
2499            logCallback("onNetworkEapSimGsmAuthRequest");
2500            synchronized (mLock) {
2501                String[] data = new String[params.rands.size()];
2502                int i = 0;
2503                for (byte[] rand : params.rands) {
2504                    data[i++] = NativeUtil.hexStringFromByteArray(rand);
2505                }
2506                mWifiMonitor.broadcastNetworkGsmAuthRequestEvent(
2507                        mIfaceName, mFramewokNetworkId, mSsid, data);
2508            }
2509        }
2510
2511        @Override
2512        public void onNetworkEapSimUmtsAuthRequest(
2513                ISupplicantStaNetworkCallback.NetworkRequestEapSimUmtsAuthParams params) {
2514            logCallback("onNetworkEapSimUmtsAuthRequest");
2515            synchronized (mLock) {
2516                String randHex = NativeUtil.hexStringFromByteArray(params.rand);
2517                String autnHex = NativeUtil.hexStringFromByteArray(params.autn);
2518                String[] data = {randHex, autnHex};
2519                mWifiMonitor.broadcastNetworkUmtsAuthRequestEvent(
2520                        mIfaceName, mFramewokNetworkId, mSsid, data);
2521            }
2522        }
2523
2524        @Override
2525        public void onNetworkEapIdentityRequest() {
2526            logCallback("onNetworkEapIdentityRequest");
2527            synchronized (mLock) {
2528                mWifiMonitor.broadcastNetworkIdentityRequestEvent(
2529                        mIfaceName, mFramewokNetworkId, mSsid);
2530            }
2531        }
2532    }
2533}
2534