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