170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang/*
270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * Copyright (C) 2017 The Android Open Source Project
370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang *
470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * Licensed under the Apache License, Version 2.0 (the "License");
570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * you may not use this file except in compliance with the License.
670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * You may obtain a copy of the License at
770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang *
870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang *      http://www.apache.org/licenses/LICENSE-2.0
970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang *
1070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * Unless required by applicable law or agreed to in writing, software
1170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * distributed under the License is distributed on an "AS IS" BASIS,
1270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * See the License for the specific language governing permissions and
1470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * limitations under the License.
1570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang */
1670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
1770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangpackage com.android.server.wifi;
1870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
19c7685b40d77b12820c5b04013592834025086cefRoshan Piusimport android.annotation.NonNull;
20f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kimimport android.net.MacAddress;
2170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IApInterface;
22045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Piusimport android.net.wifi.IApInterfaceEventCallback;
2370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IClientInterface;
2404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport android.net.wifi.IPnoScanEvent;
2570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wangimport android.net.wifi.IScanEvent;
268631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.IWifiScannerImpl;
2770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IWificond;
288631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.ScanResult;
2904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport android.net.wifi.WifiScanner;
308631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.WifiSsid;
3170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.os.Binder;
3255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Piusimport android.os.IBinder;
3370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.os.RemoteException;
3470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.util.Log;
3570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
36045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Piusimport com.android.server.wifi.WifiNative.SoftApListener;
378631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.hotspot2.NetworkDetail;
388631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.util.InformationElementUtil;
39f4b53ff21ce0aa25131222d0cd15cc4a5e8c0c4fNingyuan Wangimport com.android.server.wifi.util.NativeUtil;
404eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiuimport com.android.server.wifi.util.ScanResultUtil;
41e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.ChannelSettings;
42e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.HiddenNetwork;
438631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.wificond.NativeScanResult;
4404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport com.android.server.wifi.wificond.PnoNetwork;
4504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport com.android.server.wifi.wificond.PnoSettings;
463feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Piusimport com.android.server.wifi.wificond.RadioChainInfo;
47e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.SingleScanSettings;
488631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
498631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport java.util.ArrayList;
5091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Piusimport java.util.HashMap;
5191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Piusimport java.util.Map;
52e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport java.util.Set;
538631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
5470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang/**
5570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * This class provides methods for WifiNative to send control commands to wificond.
5670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * NOTE: This class should only be used from WifiNative.
5770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang */
5855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Piuspublic class WificondControl implements IBinder.DeathRecipient {
592e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    private boolean mVerboseLoggingEnabled = false;
6070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
6170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private static final String TAG = "WificondControl";
6271c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
6371c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    /* Get scan results for a single scan */
6471c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    public static final int SCAN_TYPE_SINGLE_SCAN = 0;
6571c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
6671c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    /* Get scan results for Pno Scan */
6771c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    public static final int SCAN_TYPE_PNO_SCAN = 1;
6871c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
6970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private WifiInjector mWifiInjector;
7070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private WifiMonitor mWifiMonitor;
714eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu    private final CarrierNetworkConfig mCarrierNetworkConfig;
7270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
7370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    // Cached wificond binder handlers.
7470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private IWificond mWificond;
7591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private HashMap<String, IClientInterface> mClientInterfaces = new HashMap<>();
7691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private HashMap<String, IApInterface> mApInterfaces = new HashMap<>();
7791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private HashMap<String, IWifiScannerImpl> mWificondScanners = new HashMap<>();
7891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private HashMap<String, IScanEvent> mScanEventHandlers = new HashMap<>();
7991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private HashMap<String, IPnoScanEvent> mPnoScanEventHandlers = new HashMap<>();
8091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private HashMap<String, IApInterfaceEventCallback> mApInterfaceListeners = new HashMap<>();
8155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    private WifiNative.WificondDeathEventHandler mDeathEventHandler;
8270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
8391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private class ScanEventHandler extends IScanEvent.Stub {
8491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        private String mIfaceName;
8570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
8691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        ScanEventHandler(@NonNull String ifaceName) {
8791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mIfaceName = ifaceName;
8891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        }
8970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
9070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        @Override
9170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        public void OnScanResultReady() {
9270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            Log.d(TAG, "Scan result ready event");
9391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mWifiMonitor.broadcastScanResultEvent(mIfaceName);
9470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        }
9570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
9670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        @Override
9770a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        public void OnScanFailed() {
9870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            Log.d(TAG, "Scan failed event");
9991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mWifiMonitor.broadcastScanFailedEvent(mIfaceName);
10070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        }
10170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    }
10270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
1034eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu    WificondControl(WifiInjector wifiInjector, WifiMonitor wifiMonitor,
1044eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu            CarrierNetworkConfig carrierNetworkConfig) {
10570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mWifiInjector = wifiInjector;
10670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        mWifiMonitor = wifiMonitor;
1074eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu        mCarrierNetworkConfig = carrierNetworkConfig;
10870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
10970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
11004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    private class PnoScanEventHandler extends IPnoScanEvent.Stub {
11191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        private String mIfaceName;
11291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
11391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        PnoScanEventHandler(@NonNull String ifaceName) {
11491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mIfaceName = ifaceName;
11591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        }
11691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
11704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        @Override
11804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        public void OnPnoNetworkFound() {
11904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.d(TAG, "Pno scan result event");
12091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mWifiMonitor.broadcastPnoScanResultEvent(mIfaceName);
121a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoFoundNetworkEventCount();
12204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
12304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
12404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        @Override
12504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        public void OnPnoScanFailed() {
12604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.d(TAG, "Pno Scan failed event");
127a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
12804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
12985c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao
13085c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        @Override
13185c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        public void OnPnoScanOverOffloadStarted() {
13285c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao            Log.d(TAG, "Pno scan over offload started");
133a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanStartedOverOffloadCount();
13485c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        }
13585c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao
13685c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        @Override
13785c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        public void OnPnoScanOverOffloadFailed(int reason) {
13885c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao            Log.d(TAG, "Pno scan over offload failed");
139a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanFailedOverOffloadCount();
14085c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        }
14104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
14204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
143045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
144045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * Listener for AP Interface events.
145045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
146045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    private class ApInterfaceEventCallback extends IApInterfaceEventCallback.Stub {
147045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        private SoftApListener mSoftApListener;
148045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
149045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        ApInterfaceEventCallback(SoftApListener listener) {
150045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            mSoftApListener = listener;
151045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
152045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
153045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        @Override
154045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        public void onNumAssociatedStationsChanged(int numStations) {
155045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            mSoftApListener.onNumAssociatedStationsChanged(numStations);
156045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
1574de36821d74eb8980c49a0f79c20343591b12e27Mehdi Alizadeh
1584de36821d74eb8980c49a0f79c20343591b12e27Mehdi Alizadeh        @Override
1594de36821d74eb8980c49a0f79c20343591b12e27Mehdi Alizadeh        public void onSoftApChannelSwitched(int frequency, int bandwidth) {
1604de36821d74eb8980c49a0f79c20343591b12e27Mehdi Alizadeh            mSoftApListener.onSoftApChannelSwitched(frequency, bandwidth);
1614de36821d74eb8980c49a0f79c20343591b12e27Mehdi Alizadeh        }
162045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
163045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
16455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
16555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Called by the binder subsystem upon remote object death.
16655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Invoke all the register death handlers and clear state.
16755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
16855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    @Override
16955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    public void binderDied() {
17055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        Log.e(TAG, "Wificond died!");
17155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        clearState();
172f4e144565d1dba55e25ab7b454a7eb7d4a6f8290Roshan Pius        // Invalidate the global wificond handle on death. Will be refreshed
17355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        // on the next setup call.
17455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mWificond = null;
175f4e144565d1dba55e25ab7b454a7eb7d4a6f8290Roshan Pius        if (mDeathEventHandler != null) {
176f4e144565d1dba55e25ab7b454a7eb7d4a6f8290Roshan Pius            mDeathEventHandler.onDeath();
177f4e144565d1dba55e25ab7b454a7eb7d4a6f8290Roshan Pius        }
17855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
17955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
1802e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    /** Enable or disable verbose logging of WificondControl.
1812e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang     *  @param enable True to enable verbose logging. False to disable verbose logging.
1822e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang     */
1832e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    public void enableVerboseLogging(boolean enable) {
1842e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        mVerboseLoggingEnabled = enable;
1852e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    }
1862e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
18770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
188ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius     * Initializes wificond & registers a death notification for wificond.
189ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius     * This method clears any existing state in wificond daemon.
190ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius     *
19155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * @return Returns true on success.
19255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
193ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius    public boolean initialize(@NonNull WifiNative.WificondDeathEventHandler handler) {
19455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mDeathEventHandler != null) {
19555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Death handler already present");
19655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
19755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mDeathEventHandler = handler;
198ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius        tearDownInterfaces();
19955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        return true;
20055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
20155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
20255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
20355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Helper method to retrieve the global wificond handle and register for
20455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * death notifications.
20555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
20655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    private boolean retrieveWificondAndRegisterForDeath() {
20755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mWificond != null) {
208ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius            if (mVerboseLoggingEnabled) {
209ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius                Log.d(TAG, "Wificond handle already retrieved");
210ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius            }
21155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            // We already have a wificond handle.
21255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return true;
21355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
21455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mWificond = mWifiInjector.makeWificond();
21555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mWificond == null) {
21655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Failed to get reference to wificond");
21755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
21855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
21955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        try {
22055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            mWificond.asBinder().linkToDeath(this, 0);
22155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        } catch (RemoteException e) {
22255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Failed to register death notification for wificond");
22355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            // The remote has already died.
22455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
22555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
22655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        return true;
22755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
22855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
22955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
2307065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    * Setup interface for client mode via wificond.
23170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IClientInterface as wificond client interface binder handler.
23270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
23370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
2347065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public IClientInterface setupInterfaceForClientMode(@NonNull String ifaceName) {
2357065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        Log.d(TAG, "Setting up interface for client mode");
23655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
23770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
23870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
23970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
24070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IClientInterface clientInterface = null;
24170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
242c7685b40d77b12820c5b04013592834025086cefRoshan Pius            clientInterface = mWificond.createClientInterface(ifaceName);
24370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
24470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IClientInterface due to remote exception");
24570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
24670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
24770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
24870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (clientInterface == null) {
24970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IClientInterface instance from wificond");
25070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
25170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
25270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(clientInterface.asBinder());
25370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
25470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
25591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mClientInterfaces.put(ifaceName, clientInterface);
2568631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
25791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl();
25891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            if (wificondScanner == null) {
259bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                Log.e(TAG, "Failed to get WificondScannerImpl");
260bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                return null;
261bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            }
26291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mWificondScanners.put(ifaceName, wificondScanner);
26391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            Binder.allowBlocking(wificondScanner.asBinder());
26491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            ScanEventHandler scanEventHandler = new ScanEventHandler(ifaceName);
26591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mScanEventHandlers.put(ifaceName,  scanEventHandler);
26691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            wificondScanner.subscribeScanEvents(scanEventHandler);
26791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(ifaceName);
26891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mPnoScanEventHandlers.put(ifaceName,  pnoScanEventHandler);
26991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);
2708631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e) {
2718631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to refresh wificond scanner due to remote exception");
2728631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
27370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
27470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return clientInterface;
27570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
27670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
27770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
2787065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * Teardown a specific STA interface configured in wificond.
2797065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     *
2807065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * @return Returns true on success.
2817065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     */
2827065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public boolean tearDownClientInterface(@NonNull String ifaceName) {
2834d2109e282e5ff427c64788dae814baccb542faeRoshan Pius        if (getClientInterface(ifaceName) == null) {
2844d2109e282e5ff427c64788dae814baccb542faeRoshan Pius            Log.e(TAG, "No valid wificond client interface handler");
2854d2109e282e5ff427c64788dae814baccb542faeRoshan Pius            return false;
2864d2109e282e5ff427c64788dae814baccb542faeRoshan Pius        }
2877065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
28891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            IWifiScannerImpl scannerImpl = mWificondScanners.get(ifaceName);
28991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            if (scannerImpl != null) {
29091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                scannerImpl.unsubscribeScanEvents();
29191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                scannerImpl.unsubscribePnoScanEvents();
2927065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            }
2937065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e) {
2947065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to unsubscribe wificond scanner due to remote exception");
2957065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
2967065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
2977065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
2984d2109e282e5ff427c64788dae814baccb542faeRoshan Pius        boolean success;
2997065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
3007065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            success = mWificond.tearDownClientInterface(ifaceName);
3017065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e1) {
3027065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown client interface due to remote exception");
3037065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3047065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3057065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        if (!success) {
3067065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown client interface");
3077065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3087065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3097065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
31091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mClientInterfaces.remove(ifaceName);
31191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mWificondScanners.remove(ifaceName);
31291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mScanEventHandlers.remove(ifaceName);
31391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mPnoScanEventHandlers.remove(ifaceName);
3147065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        return true;
3157065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    }
3167065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
3177065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    /**
3187065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    * Setup interface for softAp mode via wificond.
31970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IApInterface as wificond Ap interface binder handler.
32070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
32170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
3227065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public IApInterface setupInterfaceForSoftApMode(@NonNull String ifaceName) {
3237065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        Log.d(TAG, "Setting up interface for soft ap mode");
32455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
32570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
32670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
32770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
32870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IApInterface apInterface = null;
32970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
330c7685b40d77b12820c5b04013592834025086cefRoshan Pius            apInterface = mWificond.createApInterface(ifaceName);
33170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
33270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IApInterface due to remote exception");
33370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
33470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
33570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
33670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (apInterface == null) {
33770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IApInterface instance from wificond");
33870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
33970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
34070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(apInterface.asBinder());
34170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
34270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
34391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.put(ifaceName, apInterface);
34470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return apInterface;
34570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
34670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
34770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
3487065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * Teardown a specific AP interface configured in wificond.
3497065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     *
3507065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * @return Returns true on success.
3517065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     */
3527065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public boolean tearDownSoftApInterface(@NonNull String ifaceName) {
3534d2109e282e5ff427c64788dae814baccb542faeRoshan Pius        if (getApInterface(ifaceName) == null) {
3544d2109e282e5ff427c64788dae814baccb542faeRoshan Pius            Log.e(TAG, "No valid wificond ap interface handler");
3554d2109e282e5ff427c64788dae814baccb542faeRoshan Pius            return false;
3564d2109e282e5ff427c64788dae814baccb542faeRoshan Pius        }
3577065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        boolean success;
3587065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
3597065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            success = mWificond.tearDownApInterface(ifaceName);
3607065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e1) {
3617065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown AP interface due to remote exception");
3627065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3637065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3647065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        if (!success) {
3657065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown AP interface");
3667065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3677065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
36891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.remove(ifaceName);
36991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.remove(ifaceName);
3707065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        return true;
3717065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    }
3727065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
3737065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    /**
37470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Teardown all interfaces configured in wificond.
37570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
37670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
37770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean tearDownInterfaces() {
378512ba9008e5b9ab4019647eb036c303a6bb9e0ceNingyuan Wang        Log.d(TAG, "tearing down interfaces in wificond");
37970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Explicitly refresh the wificodn handler because |tearDownInterfaces()|
38070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // could be used to cleanup before we setup any interfaces.
38155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
38270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
38370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
38470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
38570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
38691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            for (Map.Entry<String, IWifiScannerImpl> entry : mWificondScanners.entrySet()) {
38791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                entry.getValue().unsubscribeScanEvents();
38891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                entry.getValue().unsubscribePnoScanEvents();
38970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            }
39070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            mWificond.tearDownInterfaces();
39155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            clearState();
39270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return true;
39370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
39470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to tear down interfaces due to remote exception");
39570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
39670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
39770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
39870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
39970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
40091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the interface handle using name */
40191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IClientInterface getClientInterface(@NonNull String ifaceName) {
40291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mClientInterfaces.get(ifaceName);
40391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
40491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
40570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
40670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Disable wpa_supplicant via wificond.
40770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
40870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
40970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean disableSupplicant() {
41055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
41170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
41270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
41370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
4147a9936461744922f7785a192493ccce7c4fb52f9Roshan Pius            return mWificond.disableSupplicant();
41570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
41670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to disable supplicant due to remote exception");
41770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
41870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
41970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
42070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
42170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
42270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Enable wpa_supplicant via wificond.
42370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
42470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
42570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean enableSupplicant() {
42655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
42770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
42870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
42970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
4307a9936461744922f7785a192493ccce7c4fb52f9Roshan Pius            return mWificond.enableSupplicant();
43170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
43270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to enable supplicant due to remote exception");
43370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
43470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
43570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
436d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
437d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
43891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Request signal polling to wificond.
43991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
44091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns an SignalPollResult object.
44191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns null on failure.
44291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     */
44391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public WifiNative.SignalPollResult signalPoll(@NonNull String ifaceName) {
44491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IClientInterface iface = getClientInterface(ifaceName);
44591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
446d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
447d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
448d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
449d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
450d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
451d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
45291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            resultArray = iface.signalPoll();
453d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 3) {
454d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
455d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
456d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
457d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
4582e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
459d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
460d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
461d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.SignalPollResult pollResult = new WifiNative.SignalPollResult();
462d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.currentRssi = resultArray[0];
463d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.txBitrate = resultArray[1];
464d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.associationFrequency = resultArray[2];
465d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return pollResult;
466d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
467d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
468d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
46991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Fetch TX packet counters on current connection from wificond.
47091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
47191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns an TxPacketCounters object.
47291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns null on failure.
47391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     */
47491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public WifiNative.TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) {
47591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IClientInterface iface = getClientInterface(ifaceName);
47691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
477d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
478d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
479d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
480d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
481d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
482d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
48391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            resultArray = iface.getPacketCounters();
484d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 2) {
485d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
486d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
487d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
488d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
4892e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
490d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
491d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
492d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.TxPacketCounters counters = new WifiNative.TxPacketCounters();
493d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txSucceeded = resultArray[0];
494d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txFailed = resultArray[1];
495d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return counters;
496d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
4978631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
49891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the scanner impl handle using name */
49991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IWifiScannerImpl getScannerImpl(@NonNull String ifaceName) {
50091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mWificondScanners.get(ifaceName);
50191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
50291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
5038631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    /**
5048631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Fetch the latest scan result from kernel via wificond.
50591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    * @param ifaceName Name of the interface.
5068631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * @return Returns an ArrayList of ScanDetail.
5078631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Returns an empty ArrayList on failure.
5088631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    */
50991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public ArrayList<ScanDetail> getScanResults(@NonNull String ifaceName, int scanType) {
5108631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        ArrayList<ScanDetail> results = new ArrayList<>();
51191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
51291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
5138631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
5148631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            return results;
5158631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
5168631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
51771c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            NativeScanResult[] nativeResults;
51871c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            if (scanType == SCAN_TYPE_SINGLE_SCAN) {
51991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                nativeResults = scannerImpl.getScanResults();
52071c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            } else {
52191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                nativeResults = scannerImpl.getPnoScanResults();
52271c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            }
5238631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            for (NativeScanResult result : nativeResults) {
524755bbe962c20d37491dd9264ad3497bf27e33602Ningyuan Wang                WifiSsid wifiSsid = WifiSsid.createFromByteArray(result.ssid);
5258ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                String bssid;
5268ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
5278ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    bssid = NativeUtil.macAddressFromByteArray(result.bssid);
5288ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
5298ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + result.bssid, e);
5308ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
5318ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
5328ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                if (bssid == null) {
5338ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal null bssid");
5348ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
5358ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
5368631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanResult.InformationElement[] ies =
5378631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        InformationElementUtil.parseInformationElements(result.infoElement);
5388631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                InformationElementUtil.Capabilities capabilities =
5398631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        new InformationElementUtil.Capabilities();
5408631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                capabilities.from(ies, result.capability);
5418631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                String flags = capabilities.generateCapabilitiesString();
5420a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                NetworkDetail networkDetail;
5430a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                try {
5440a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    networkDetail = new NetworkDetail(bssid, ies, null, result.frequency);
5450a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                } catch (IllegalArgumentException e) {
5460a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    Log.e(TAG, "Illegal argument for scan result with bssid: " + bssid, e);
5470a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    continue;
5480a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                }
5498631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
5508631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanDetail scanDetail = new ScanDetail(networkDetail, wifiSsid, bssid, flags,
5518631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        result.signalMbm / 100, result.frequency, result.tsf, ies, null);
5523feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                ScanResult scanResult = scanDetail.getScanResult();
5534eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // Update carrier network info if this AP's SSID is associated with a carrier Wi-Fi
5544eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // network and it uses EAP.
5554eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                if (ScanResultUtil.isScanResultForEapNetwork(scanDetail.getScanResult())
5564eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                        && mCarrierNetworkConfig.isCarrierNetwork(wifiSsid.toString())) {
5573feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.isCarrierAp = true;
5583feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.carrierApEapType =
5594eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getNetworkEapType(wifiSsid.toString());
5603feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.carrierName =
5614eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getCarrierName(wifiSsid.toString());
5624eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                }
5633feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                // Fill up the radio chain info.
5643feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                if (result.radioChainInfos != null) {
5653feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.radioChainInfos =
5663feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        new ScanResult.RadioChainInfo[result.radioChainInfos.size()];
5673feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    int idx = 0;
5683feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    for (RadioChainInfo nativeRadioChainInfo : result.radioChainInfos) {
5693feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        scanResult.radioChainInfos[idx] = new ScanResult.RadioChainInfo();
5703feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        scanResult.radioChainInfos[idx].id = nativeRadioChainInfo.chainId;
5713feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        scanResult.radioChainInfos[idx].level = nativeRadioChainInfo.level;
5723feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        idx++;
5733feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    }
5743feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                }
5758631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                results.add(scanDetail);
5768631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            }
5778631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e1) {
5788631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to create ScanDetail ArrayList");
5798631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
5802e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        if (mVerboseLoggingEnabled) {
5812e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.d(TAG, "get " + results.size() + " scan results from wificond");
5822e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        }
5832e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
5848631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        return results;
5858631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    }
586e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
587e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    /**
5883feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius     * Return scan type for the parcelable {@link SingleScanSettings}
5893feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius     */
5903feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius    private static int getScanType(int scanType) {
5913feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        switch (scanType) {
5923feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            case WifiNative.SCAN_TYPE_LOW_LATENCY:
5933feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                return IWifiScannerImpl.SCAN_TYPE_LOW_SPAN;
5943feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            case WifiNative.SCAN_TYPE_LOW_POWER:
5953feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                return IWifiScannerImpl.SCAN_TYPE_LOW_POWER;
5963feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            case WifiNative.SCAN_TYPE_HIGH_ACCURACY:
5973feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                return IWifiScannerImpl.SCAN_TYPE_HIGH_ACCURACY;
5983feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            default:
5993feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                throw new IllegalArgumentException("Invalid scan type " + scanType);
6003feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        }
6013feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius    }
6023feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius
6033feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius    /**
604e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * Start a scan using wificond for the given parameters.
60591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
6063feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius     * @param scanType Type of scan to perform.
607e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param freqs list of frequencies to scan for, if null scan all supported channels.
608e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
609e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @return Returns true on success.
610e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     */
61191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean scan(@NonNull String ifaceName,
6123feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        int scanType,
61391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                        Set<Integer> freqs,
61491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                        Set<String> hiddenNetworkSSIDs) {
61591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
61691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
617e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
618e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            return false;
619e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
620e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        SingleScanSettings settings = new SingleScanSettings();
6213feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        try {
6223feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            settings.scanType = getScanType(scanType);
6233feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        } catch (IllegalArgumentException e) {
6243feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            Log.e(TAG, "Invalid scan type ", e);
6253feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            return false;
6263feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        }
627e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.channelSettings  = new ArrayList<>();
628e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.hiddenNetworks  = new ArrayList<>();
629e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
630e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (freqs != null) {
631e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (Integer freq : freqs) {
632e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                ChannelSettings channel = new ChannelSettings();
633e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                channel.frequency = freq;
634e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.channelSettings.add(channel);
635e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
636e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
637e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (hiddenNetworkSSIDs != null) {
638e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (String ssid : hiddenNetworkSSIDs) {
639e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                HiddenNetwork network = new HiddenNetwork();
6408ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
6418ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    network.ssid = NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssid));
6428ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
6438ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + ssid, e);
6448ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
6458ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
646e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.hiddenNetworks.add(network);
647e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
648e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
649e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
650e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        try {
65191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            return scannerImpl.scan(settings);
652e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        } catch (RemoteException e1) {
653e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "Failed to request scan due to remote exception");
654e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
655e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        return false;
656e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    }
657e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
65804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
65904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Start PNO scan.
66091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
66104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @param pnoSettings Pno scan configuration.
66204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
66304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
66491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean startPnoScan(@NonNull String ifaceName, WifiNative.PnoSettings pnoSettings) {
66591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
66691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
66704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
66804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
66904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
67004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        PnoSettings settings = new PnoSettings();
67104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.pnoNetworks  = new ArrayList<>();
67204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.intervalMs = pnoSettings.periodInMs;
67304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min2gRssi = pnoSettings.min24GHzRssi;
67404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min5gRssi = pnoSettings.min5GHzRssi;
67504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (pnoSettings.networkList != null) {
67604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            for (WifiNative.PnoNetwork network : pnoSettings.networkList) {
67704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                PnoNetwork condNetwork = new PnoNetwork();
67804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                condNetwork.isHidden = (network.flags
67904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                        & WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN) != 0;
6808ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
6818ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    condNetwork.ssid =
6828ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                            NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(network.ssid));
6838ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
6848ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + network.ssid, e);
6858ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
6868ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
68704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                settings.pnoNetworks.add(condNetwork);
68804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            }
68904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
69004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
69104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
69291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            boolean success = scannerImpl.startPnoScan(settings);
693a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanStartAttempCount();
694a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            if (!success) {
695a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh                mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
696a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            }
697a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            return success;
69804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
699a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            Log.e(TAG, "Failed to start pno scan due to remote exception");
70004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
70104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
70204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
70304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
70404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
70504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Stop PNO scan.
70691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
70704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
70804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
70991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean stopPnoScan(@NonNull String ifaceName) {
71091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
71191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
71204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
71304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
71404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
71504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
71691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            return scannerImpl.stopPnoScan();
71704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
71804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "Failed to stop pno scan due to remote exception");
71904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
72004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
72104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
72204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
723c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    /**
724c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     * Abort ongoing single scan.
72591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
726c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     */
72791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public void abortScan(@NonNull String ifaceName) {
72891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
72991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
730c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
731c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            return;
732c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
733c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        try {
73491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            scannerImpl.abortScan();
735c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        } catch (RemoteException e1) {
736c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "Failed to request abortScan due to remote exception");
737c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
738c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    }
739c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang
7406baff2cb8dec599af186be521882413787595930Ningyuan Wang    /**
7416baff2cb8dec599af186be521882413787595930Ningyuan Wang     * Query the list of valid frequencies for the provided band.
7426baff2cb8dec599af186be521882413787595930Ningyuan Wang     * The result depends on the on the country code that has been set.
7436baff2cb8dec599af186be521882413787595930Ningyuan Wang     *
7446baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
7456baff2cb8dec599af186be521882413787595930Ningyuan Wang     * The following bands are supported:
7466baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_24_GHZ
7476baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_5_GHZ
7486baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY
7496baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @return frequencies vector of valid frequencies (MHz), or null for error.
7506baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @throws IllegalArgumentException if band is not recognized.
7516baff2cb8dec599af186be521882413787595930Ningyuan Wang     */
7526baff2cb8dec599af186be521882413787595930Ningyuan Wang    public int [] getChannelsForBand(int band) {
7536baff2cb8dec599af186be521882413787595930Ningyuan Wang        if (mWificond == null) {
7546baff2cb8dec599af186be521882413787595930Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
7556baff2cb8dec599af186be521882413787595930Ningyuan Wang            return null;
7566baff2cb8dec599af186be521882413787595930Ningyuan Wang        }
7576baff2cb8dec599af186be521882413787595930Ningyuan Wang        try {
7586baff2cb8dec599af186be521882413787595930Ningyuan Wang            switch (band) {
7596baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_24_GHZ:
7606baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailable2gChannels();
7616baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_5_GHZ:
7626baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailable5gNonDFSChannels();
7636baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
7646baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailableDFSChannels();
7656baff2cb8dec599af186be521882413787595930Ningyuan Wang                default:
7666baff2cb8dec599af186be521882413787595930Ningyuan Wang                    throw new IllegalArgumentException("unsupported band " + band);
7676baff2cb8dec599af186be521882413787595930Ningyuan Wang            }
7686baff2cb8dec599af186be521882413787595930Ningyuan Wang        } catch (RemoteException e1) {
7696baff2cb8dec599af186be521882413787595930Ningyuan Wang            Log.e(TAG, "Failed to request getChannelsForBand due to remote exception");
7706baff2cb8dec599af186be521882413787595930Ningyuan Wang        }
7716baff2cb8dec599af186be521882413787595930Ningyuan Wang        return null;
7726baff2cb8dec599af186be521882413787595930Ningyuan Wang    }
773045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
77491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the interface handle using name */
77591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IApInterface getApInterface(@NonNull String ifaceName) {
77691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mApInterfaces.get(ifaceName);
77791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
77891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
779045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
780295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * Start hostapd
781295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * TODO(b/71513606): Move this to a global operation.
782045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     *
78391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
784045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @param listener Callback for AP events.
785045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @return true on success, false otherwise.
786045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
787295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius    public boolean startHostapd(@NonNull String ifaceName,
78891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                               SoftApListener listener) {
78991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IApInterface iface = getApInterface(ifaceName);
79091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
791045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "No valid ap interface handler");
792045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
793045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
794045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        try {
79591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            IApInterfaceEventCallback  callback = new ApInterfaceEventCallback(listener);
79691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mApInterfaceListeners.put(ifaceName, callback);
797295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius            boolean success = iface.startHostapd(callback);
798045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
799045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to start hostapd.");
800045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
801045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
802045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        } catch (RemoteException e) {
803045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "Exception in starting soft AP: " + e);
804045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
805045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
806045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return true;
807045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
808045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
809045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
810295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * Stop hostapd
811295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * TODO(b/71513606): Move this to a global operation.
812045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     *
81391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
814045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @return true on success, false otherwise.
815045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
816295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius    public boolean stopHostapd(@NonNull String ifaceName) {
81791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IApInterface iface = getApInterface(ifaceName);
81891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
819045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "No valid ap interface handler");
820045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
821045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
822045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        try {
82391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            boolean success = iface.stopHostapd();
824045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
825045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to stop hostapd.");
826045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
827045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
828045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        } catch (RemoteException e) {
829045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "Exception in stopping soft AP: " + e);
830045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
831045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
83291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.remove(ifaceName);
833045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return true;
834045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
835045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
83655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
837f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * Set Mac address on the given interface
838f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * @param interfaceName Name of the interface.
839f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * @param mac Mac address to change into
840f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * @return true on success, false otherwise.
841f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     */
842f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim    public boolean setMacAddress(@NonNull String interfaceName, @NonNull MacAddress mac) {
843f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        IClientInterface mClientInterface = getClientInterface(interfaceName);
844f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        if (mClientInterface == null) {
845f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            Log.e(TAG, "No valid wificond client interface handler");
846f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            return false;
847f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        }
848f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        byte[] macByteArray = mac.toByteArray();
849f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim
850f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        try {
851f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            mClientInterface.setMacAddress(macByteArray);
852f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        } catch (RemoteException e) {
853f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            Log.e(TAG, "Failed to setMacAddress due to remote exception");
854f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            return false;
855f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        }
856f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        return true;
857f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim    }
858f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim
859f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim    /**
86055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Clear all internal handles.
86155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
86255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    private void clearState() {
86355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        // Refresh handlers
86491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mClientInterfaces.clear();
86591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mWificondScanners.clear();
86691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mPnoScanEventHandlers.clear();
86791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mScanEventHandlers.clear();
86891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.clear();
86991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.clear();
87055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
87170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang}
872