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