WificondControl.java revision ba0868687b7a803bc5f817932fa02c0c3e934254
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        }
157045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
158045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
15955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
16055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Called by the binder subsystem upon remote object death.
16155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Invoke all the register death handlers and clear state.
16255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
16355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    @Override
16455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    public void binderDied() {
16555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        Log.e(TAG, "Wificond died!");
16655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mDeathEventHandler != null) {
16755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            mDeathEventHandler.onDeath();
16855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
16955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        clearState();
17055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        // Invalidate the global wificond handle on death. Will be refereshed
17155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        // on the next setup call.
17255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mWificond = null;
17355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
17455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
1752e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    /** Enable or disable verbose logging of WificondControl.
1762e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang     *  @param enable True to enable verbose logging. False to disable verbose logging.
1772e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang     */
1782e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    public void enableVerboseLogging(boolean enable) {
1792e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        mVerboseLoggingEnabled = enable;
1802e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    }
1812e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
18270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
183ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius     * Initializes wificond & registers a death notification for wificond.
184ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius     * This method clears any existing state in wificond daemon.
185ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius     *
18655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * @return Returns true on success.
18755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
188ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius    public boolean initialize(@NonNull WifiNative.WificondDeathEventHandler handler) {
18955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mDeathEventHandler != null) {
19055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Death handler already present");
19155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
19255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mDeathEventHandler = handler;
193ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius        tearDownInterfaces();
19455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        return true;
19555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
19655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
19755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
19855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Helper method to retrieve the global wificond handle and register for
19955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * death notifications.
20055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
20155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    private boolean retrieveWificondAndRegisterForDeath() {
20255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mWificond != null) {
203ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius            if (mVerboseLoggingEnabled) {
204ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius                Log.d(TAG, "Wificond handle already retrieved");
205ba0868687b7a803bc5f817932fa02c0c3e934254Roshan Pius            }
20655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            // We already have a wificond handle.
20755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return true;
20855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
20955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mWificond = mWifiInjector.makeWificond();
21055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mWificond == null) {
21155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Failed to get reference to wificond");
21255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
21355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
21455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        try {
21555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            mWificond.asBinder().linkToDeath(this, 0);
21655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        } catch (RemoteException e) {
21755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Failed to register death notification for wificond");
21855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            // The remote has already died.
21955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
22055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
22155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        return true;
22255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
22355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
22455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
2257065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    * Setup interface for client mode via wificond.
22670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IClientInterface as wificond client interface binder handler.
22770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
22870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
2297065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public IClientInterface setupInterfaceForClientMode(@NonNull String ifaceName) {
2307065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        Log.d(TAG, "Setting up interface for client mode");
23155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
23270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
23370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
23470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
23570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IClientInterface clientInterface = null;
23670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
237c7685b40d77b12820c5b04013592834025086cefRoshan Pius            clientInterface = mWificond.createClientInterface(ifaceName);
23870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
23970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IClientInterface due to remote exception");
24070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
24170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
24270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
24370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (clientInterface == null) {
24470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IClientInterface instance from wificond");
24570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
24670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
24770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(clientInterface.asBinder());
24870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
24970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
25091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mClientInterfaces.put(ifaceName, clientInterface);
2518631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
25291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl();
25391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            if (wificondScanner == null) {
254bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                Log.e(TAG, "Failed to get WificondScannerImpl");
255bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                return null;
256bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            }
25791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mWificondScanners.put(ifaceName, wificondScanner);
25891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            Binder.allowBlocking(wificondScanner.asBinder());
25991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            ScanEventHandler scanEventHandler = new ScanEventHandler(ifaceName);
26091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mScanEventHandlers.put(ifaceName,  scanEventHandler);
26191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            wificondScanner.subscribeScanEvents(scanEventHandler);
26291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(ifaceName);
26391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mPnoScanEventHandlers.put(ifaceName,  pnoScanEventHandler);
26491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);
2658631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e) {
2668631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to refresh wificond scanner due to remote exception");
2678631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
26870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
26970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return clientInterface;
27070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
27170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
27270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
2737065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * Teardown a specific STA interface configured in wificond.
2747065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     *
2757065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * @return Returns true on success.
2767065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     */
2777065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public boolean tearDownClientInterface(@NonNull String ifaceName) {
2787065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        boolean success;
2797065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
28091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            IWifiScannerImpl scannerImpl = mWificondScanners.get(ifaceName);
28191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            if (scannerImpl != null) {
28291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                scannerImpl.unsubscribeScanEvents();
28391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                scannerImpl.unsubscribePnoScanEvents();
2847065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            }
2857065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e) {
2867065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to unsubscribe wificond scanner due to remote exception");
2877065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
2887065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
2897065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
2907065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
2917065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            success = mWificond.tearDownClientInterface(ifaceName);
2927065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e1) {
2937065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown client interface due to remote exception");
2947065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
2957065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
2967065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        if (!success) {
2977065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown client interface");
2987065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
2997065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3007065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
30191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mClientInterfaces.remove(ifaceName);
30291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mWificondScanners.remove(ifaceName);
30391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mScanEventHandlers.remove(ifaceName);
30491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mPnoScanEventHandlers.remove(ifaceName);
3057065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        return true;
3067065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    }
3077065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
3087065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    /**
3097065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    * Setup interface for softAp mode via wificond.
31070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IApInterface as wificond Ap interface binder handler.
31170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
31270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
3137065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public IApInterface setupInterfaceForSoftApMode(@NonNull String ifaceName) {
3147065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        Log.d(TAG, "Setting up interface for soft ap mode");
31555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
31670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
31770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
31870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
31970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IApInterface apInterface = null;
32070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
321c7685b40d77b12820c5b04013592834025086cefRoshan Pius            apInterface = mWificond.createApInterface(ifaceName);
32270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
32370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IApInterface due to remote exception");
32470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
32570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
32670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
32770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (apInterface == null) {
32870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IApInterface instance from wificond");
32970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
33070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
33170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(apInterface.asBinder());
33270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
33370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
33491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.put(ifaceName, apInterface);
33570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return apInterface;
33670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
33770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
33870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
3397065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * Teardown a specific AP interface configured in wificond.
3407065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     *
3417065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * @return Returns true on success.
3427065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     */
3437065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public boolean tearDownSoftApInterface(@NonNull String ifaceName) {
3447065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        boolean success;
3457065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
3467065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            success = mWificond.tearDownApInterface(ifaceName);
3477065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e1) {
3487065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown AP interface due to remote exception");
3497065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3507065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3517065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        if (!success) {
3527065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown AP interface");
3537065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3547065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
35591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.remove(ifaceName);
35691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.remove(ifaceName);
3577065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        return true;
3587065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    }
3597065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
3607065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    /**
36170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Teardown all interfaces configured in wificond.
36270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
36370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
36470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean tearDownInterfaces() {
365512ba9008e5b9ab4019647eb036c303a6bb9e0ceNingyuan Wang        Log.d(TAG, "tearing down interfaces in wificond");
36670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Explicitly refresh the wificodn handler because |tearDownInterfaces()|
36770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // could be used to cleanup before we setup any interfaces.
36855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
36970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
37070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
37170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
37270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
37391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            for (Map.Entry<String, IWifiScannerImpl> entry : mWificondScanners.entrySet()) {
37491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                entry.getValue().unsubscribeScanEvents();
37591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                entry.getValue().unsubscribePnoScanEvents();
37670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            }
37770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            mWificond.tearDownInterfaces();
37855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            clearState();
37970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return true;
38070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
38170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to tear down interfaces due to remote exception");
38270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
38370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
38470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
38570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
38670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
38791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the interface handle using name */
38891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IClientInterface getClientInterface(@NonNull String ifaceName) {
38991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mClientInterfaces.get(ifaceName);
39091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
39191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
39270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
39370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Disable wpa_supplicant via wificond.
39470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
39570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
39670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean disableSupplicant() {
39755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
39870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
39970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
40070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
4017a9936461744922f7785a192493ccce7c4fb52f9Roshan Pius            return mWificond.disableSupplicant();
40270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
40370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to disable supplicant due to remote exception");
40470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
40570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
40670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
40770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
40870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
40970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Enable wpa_supplicant via wificond.
41070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
41170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
41270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean enableSupplicant() {
41355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
41470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
41570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
41670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
4177a9936461744922f7785a192493ccce7c4fb52f9Roshan Pius            return mWificond.enableSupplicant();
41870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
41970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to enable supplicant due to remote exception");
42070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
42170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
42270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
423d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
424d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
42591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Request signal polling to wificond.
42691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
42791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns an SignalPollResult object.
42891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns null on failure.
42991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     */
43091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public WifiNative.SignalPollResult signalPoll(@NonNull String ifaceName) {
43191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IClientInterface iface = getClientInterface(ifaceName);
43291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
433d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
434d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
435d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
436d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
437d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
438d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
43991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            resultArray = iface.signalPoll();
440d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 3) {
441d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
442d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
443d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
444d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
4452e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
446d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
447d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
448d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.SignalPollResult pollResult = new WifiNative.SignalPollResult();
449d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.currentRssi = resultArray[0];
450d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.txBitrate = resultArray[1];
451d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.associationFrequency = resultArray[2];
452d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return pollResult;
453d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
454d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
455d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
45691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Fetch TX packet counters on current connection from wificond.
45791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
45891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns an TxPacketCounters object.
45991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns null on failure.
46091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     */
46191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public WifiNative.TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) {
46291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IClientInterface iface = getClientInterface(ifaceName);
46391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
464d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
465d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
466d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
467d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
468d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
469d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
47091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            resultArray = iface.getPacketCounters();
471d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 2) {
472d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
473d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
474d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
475d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
4762e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
477d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
478d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
479d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.TxPacketCounters counters = new WifiNative.TxPacketCounters();
480d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txSucceeded = resultArray[0];
481d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txFailed = resultArray[1];
482d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return counters;
483d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
4848631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
48591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the scanner impl handle using name */
48691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IWifiScannerImpl getScannerImpl(@NonNull String ifaceName) {
48791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mWificondScanners.get(ifaceName);
48891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
48991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
4908631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    /**
4918631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Fetch the latest scan result from kernel via wificond.
49291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    * @param ifaceName Name of the interface.
4938631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * @return Returns an ArrayList of ScanDetail.
4948631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Returns an empty ArrayList on failure.
4958631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    */
49691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public ArrayList<ScanDetail> getScanResults(@NonNull String ifaceName, int scanType) {
4978631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        ArrayList<ScanDetail> results = new ArrayList<>();
49891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
49991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
5008631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
5018631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            return results;
5028631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
5038631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
50471c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            NativeScanResult[] nativeResults;
50571c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            if (scanType == SCAN_TYPE_SINGLE_SCAN) {
50691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                nativeResults = scannerImpl.getScanResults();
50771c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            } else {
50891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                nativeResults = scannerImpl.getPnoScanResults();
50971c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            }
5108631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            for (NativeScanResult result : nativeResults) {
511755bbe962c20d37491dd9264ad3497bf27e33602Ningyuan Wang                WifiSsid wifiSsid = WifiSsid.createFromByteArray(result.ssid);
5128ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                String bssid;
5138ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
5148ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    bssid = NativeUtil.macAddressFromByteArray(result.bssid);
5158ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
5168ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + result.bssid, e);
5178ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
5188ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
5198ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                if (bssid == null) {
5208ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal null bssid");
5218ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
5228ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
5238631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanResult.InformationElement[] ies =
5248631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        InformationElementUtil.parseInformationElements(result.infoElement);
5258631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                InformationElementUtil.Capabilities capabilities =
5268631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        new InformationElementUtil.Capabilities();
5278631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                capabilities.from(ies, result.capability);
5288631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                String flags = capabilities.generateCapabilitiesString();
5290a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                NetworkDetail networkDetail;
5300a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                try {
5310a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    networkDetail = new NetworkDetail(bssid, ies, null, result.frequency);
5320a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                } catch (IllegalArgumentException e) {
5330a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    Log.e(TAG, "Illegal argument for scan result with bssid: " + bssid, e);
5340a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    continue;
5350a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                }
5368631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
5378631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanDetail scanDetail = new ScanDetail(networkDetail, wifiSsid, bssid, flags,
5388631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        result.signalMbm / 100, result.frequency, result.tsf, ies, null);
5393feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                ScanResult scanResult = scanDetail.getScanResult();
5404eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // Update carrier network info if this AP's SSID is associated with a carrier Wi-Fi
5414eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // network and it uses EAP.
5424eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                if (ScanResultUtil.isScanResultForEapNetwork(scanDetail.getScanResult())
5434eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                        && mCarrierNetworkConfig.isCarrierNetwork(wifiSsid.toString())) {
5443feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.isCarrierAp = true;
5453feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.carrierApEapType =
5464eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getNetworkEapType(wifiSsid.toString());
5473feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.carrierName =
5484eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getCarrierName(wifiSsid.toString());
5494eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                }
5503feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                // Fill up the radio chain info.
5513feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                if (result.radioChainInfos != null) {
5523feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.radioChainInfos =
5533feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        new ScanResult.RadioChainInfo[result.radioChainInfos.size()];
5543feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    int idx = 0;
5553feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    for (RadioChainInfo nativeRadioChainInfo : result.radioChainInfos) {
5563feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        scanResult.radioChainInfos[idx] = new ScanResult.RadioChainInfo();
5573feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        scanResult.radioChainInfos[idx].id = nativeRadioChainInfo.chainId;
5583feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        scanResult.radioChainInfos[idx].level = nativeRadioChainInfo.level;
5593feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        idx++;
5603feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    }
5613feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                }
5628631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                results.add(scanDetail);
5638631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            }
5648631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e1) {
5658631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to create ScanDetail ArrayList");
5668631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
5672e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        if (mVerboseLoggingEnabled) {
5682e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.d(TAG, "get " + results.size() + " scan results from wificond");
5692e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        }
5702e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
5718631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        return results;
5728631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    }
573e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
574e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    /**
5753feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius     * Return scan type for the parcelable {@link SingleScanSettings}
5763feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius     */
5773feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius    private static int getScanType(int scanType) {
5783feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        switch (scanType) {
5793feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            case WifiNative.SCAN_TYPE_LOW_LATENCY:
5803feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                return IWifiScannerImpl.SCAN_TYPE_LOW_SPAN;
5813feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            case WifiNative.SCAN_TYPE_LOW_POWER:
5823feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                return IWifiScannerImpl.SCAN_TYPE_LOW_POWER;
5833feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            case WifiNative.SCAN_TYPE_HIGH_ACCURACY:
5843feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                return IWifiScannerImpl.SCAN_TYPE_HIGH_ACCURACY;
5853feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            default:
5863feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                throw new IllegalArgumentException("Invalid scan type " + scanType);
5873feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        }
5883feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius    }
5893feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius
5903feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius    /**
591e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * Start a scan using wificond for the given parameters.
59291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
5933feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius     * @param scanType Type of scan to perform.
594e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param freqs list of frequencies to scan for, if null scan all supported channels.
595e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
596e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @return Returns true on success.
597e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     */
59891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean scan(@NonNull String ifaceName,
5993feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        int scanType,
60091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                        Set<Integer> freqs,
60191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                        Set<String> hiddenNetworkSSIDs) {
60291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
60391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
604e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
605e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            return false;
606e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
607e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        SingleScanSettings settings = new SingleScanSettings();
6083feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        try {
6093feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            settings.scanType = getScanType(scanType);
6103feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        } catch (IllegalArgumentException e) {
6113feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            Log.e(TAG, "Invalid scan type ", e);
6123feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            return false;
6133feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        }
614e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.channelSettings  = new ArrayList<>();
615e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.hiddenNetworks  = new ArrayList<>();
616e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
617e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (freqs != null) {
618e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (Integer freq : freqs) {
619e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                ChannelSettings channel = new ChannelSettings();
620e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                channel.frequency = freq;
621e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.channelSettings.add(channel);
622e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
623e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
624e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (hiddenNetworkSSIDs != null) {
625e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (String ssid : hiddenNetworkSSIDs) {
626e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                HiddenNetwork network = new HiddenNetwork();
6278ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
6288ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    network.ssid = NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssid));
6298ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
6308ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + ssid, e);
6318ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
6328ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
633e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.hiddenNetworks.add(network);
634e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
635e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
636e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
637e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        try {
63891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            return scannerImpl.scan(settings);
639e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        } catch (RemoteException e1) {
640e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "Failed to request scan due to remote exception");
641e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
642e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        return false;
643e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    }
644e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
64504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
64604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Start PNO scan.
64791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
64804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @param pnoSettings Pno scan configuration.
64904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
65004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
65191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean startPnoScan(@NonNull String ifaceName, WifiNative.PnoSettings pnoSettings) {
65291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
65391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
65404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
65504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
65604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
65704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        PnoSettings settings = new PnoSettings();
65804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.pnoNetworks  = new ArrayList<>();
65904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.intervalMs = pnoSettings.periodInMs;
66004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min2gRssi = pnoSettings.min24GHzRssi;
66104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min5gRssi = pnoSettings.min5GHzRssi;
66204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (pnoSettings.networkList != null) {
66304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            for (WifiNative.PnoNetwork network : pnoSettings.networkList) {
66404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                PnoNetwork condNetwork = new PnoNetwork();
66504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                condNetwork.isHidden = (network.flags
66604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                        & WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN) != 0;
6678ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
6688ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    condNetwork.ssid =
6698ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                            NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(network.ssid));
6708ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
6718ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + network.ssid, e);
6728ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
6738ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
67404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                settings.pnoNetworks.add(condNetwork);
67504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            }
67604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
67704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
67804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
67991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            boolean success = scannerImpl.startPnoScan(settings);
680a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanStartAttempCount();
681a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            if (!success) {
682a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh                mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
683a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            }
684a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            return success;
68504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
686a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            Log.e(TAG, "Failed to start pno scan due to remote exception");
68704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
68804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
68904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
69004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
69104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
69204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Stop PNO scan.
69391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
69404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
69504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
69691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean stopPnoScan(@NonNull String ifaceName) {
69791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
69891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
69904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
70004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
70104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
70204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
70391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            return scannerImpl.stopPnoScan();
70404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
70504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "Failed to stop pno scan due to remote exception");
70604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
70704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
70804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
70904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
710c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    /**
711c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     * Abort ongoing single scan.
71291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
713c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     */
71491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public void abortScan(@NonNull String ifaceName) {
71591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
71691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
717c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
718c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            return;
719c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
720c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        try {
72191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            scannerImpl.abortScan();
722c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        } catch (RemoteException e1) {
723c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "Failed to request abortScan due to remote exception");
724c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
725c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    }
726c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang
7276baff2cb8dec599af186be521882413787595930Ningyuan Wang    /**
7286baff2cb8dec599af186be521882413787595930Ningyuan Wang     * Query the list of valid frequencies for the provided band.
7296baff2cb8dec599af186be521882413787595930Ningyuan Wang     * The result depends on the on the country code that has been set.
7306baff2cb8dec599af186be521882413787595930Ningyuan Wang     *
7316baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
7326baff2cb8dec599af186be521882413787595930Ningyuan Wang     * The following bands are supported:
7336baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_24_GHZ
7346baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_5_GHZ
7356baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY
7366baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @return frequencies vector of valid frequencies (MHz), or null for error.
7376baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @throws IllegalArgumentException if band is not recognized.
7386baff2cb8dec599af186be521882413787595930Ningyuan Wang     */
7396baff2cb8dec599af186be521882413787595930Ningyuan Wang    public int [] getChannelsForBand(int band) {
7406baff2cb8dec599af186be521882413787595930Ningyuan Wang        if (mWificond == null) {
7416baff2cb8dec599af186be521882413787595930Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
7426baff2cb8dec599af186be521882413787595930Ningyuan Wang            return null;
7436baff2cb8dec599af186be521882413787595930Ningyuan Wang        }
7446baff2cb8dec599af186be521882413787595930Ningyuan Wang        try {
7456baff2cb8dec599af186be521882413787595930Ningyuan Wang            switch (band) {
7466baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_24_GHZ:
7476baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailable2gChannels();
7486baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_5_GHZ:
7496baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailable5gNonDFSChannels();
7506baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
7516baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailableDFSChannels();
7526baff2cb8dec599af186be521882413787595930Ningyuan Wang                default:
7536baff2cb8dec599af186be521882413787595930Ningyuan Wang                    throw new IllegalArgumentException("unsupported band " + band);
7546baff2cb8dec599af186be521882413787595930Ningyuan Wang            }
7556baff2cb8dec599af186be521882413787595930Ningyuan Wang        } catch (RemoteException e1) {
7566baff2cb8dec599af186be521882413787595930Ningyuan Wang            Log.e(TAG, "Failed to request getChannelsForBand due to remote exception");
7576baff2cb8dec599af186be521882413787595930Ningyuan Wang        }
7586baff2cb8dec599af186be521882413787595930Ningyuan Wang        return null;
7596baff2cb8dec599af186be521882413787595930Ningyuan Wang    }
760045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
76191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the interface handle using name */
76291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IApInterface getApInterface(@NonNull String ifaceName) {
76391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mApInterfaces.get(ifaceName);
76491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
76591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
766045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
767295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * Start hostapd
768295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * TODO(b/71513606): Move this to a global operation.
769045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     *
77091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
771045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @param listener Callback for AP events.
772045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @return true on success, false otherwise.
773045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
774295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius    public boolean startHostapd(@NonNull String ifaceName,
77591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                               SoftApListener listener) {
77691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IApInterface iface = getApInterface(ifaceName);
77791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
778045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "No valid ap interface handler");
779045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
780045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
781045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        try {
78291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            IApInterfaceEventCallback  callback = new ApInterfaceEventCallback(listener);
78391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mApInterfaceListeners.put(ifaceName, callback);
784295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius            boolean success = iface.startHostapd(callback);
785045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
786045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to start hostapd.");
787045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
788045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
789045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        } catch (RemoteException e) {
790045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "Exception in starting soft AP: " + e);
791045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
792045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
793045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return true;
794045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
795045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
796045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
797295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * Stop hostapd
798295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * TODO(b/71513606): Move this to a global operation.
799045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     *
80091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
801045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @return true on success, false otherwise.
802045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
803295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius    public boolean stopHostapd(@NonNull String ifaceName) {
80491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IApInterface iface = getApInterface(ifaceName);
80591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
806045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "No valid ap interface handler");
807045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
808045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
809045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        try {
81091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            boolean success = iface.stopHostapd();
811045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
812045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to stop hostapd.");
813045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
814045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
815045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        } catch (RemoteException e) {
816045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "Exception in stopping soft AP: " + e);
817045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
818045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
81991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.remove(ifaceName);
820045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return true;
821045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
822045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
82355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
824f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * Set Mac address on the given interface
825f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * @param interfaceName Name of the interface.
826f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * @param mac Mac address to change into
827f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * @return true on success, false otherwise.
828f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     */
829f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim    public boolean setMacAddress(@NonNull String interfaceName, @NonNull MacAddress mac) {
830f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        IClientInterface mClientInterface = getClientInterface(interfaceName);
831f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        if (mClientInterface == null) {
832f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            Log.e(TAG, "No valid wificond client interface handler");
833f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            return false;
834f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        }
835f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        byte[] macByteArray = mac.toByteArray();
836f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim
837f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        try {
838f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            mClientInterface.setMacAddress(macByteArray);
839f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        } catch (RemoteException e) {
840f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            Log.e(TAG, "Failed to setMacAddress due to remote exception");
841f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            return false;
842f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        }
843f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        return true;
844f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim    }
845f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim
846f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim    /**
84755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Clear all internal handles.
84855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
84955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    private void clearState() {
85055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        // Refresh handlers
85191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mClientInterfaces.clear();
85291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mWificondScanners.clear();
85391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mPnoScanEventHandlers.clear();
85491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mScanEventHandlers.clear();
85591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.clear();
85691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.clear();
85755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
85870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang}
859