WificondControl.java revision f4e144565d1dba55e25ab7b454a7eb7d4a6f8290
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        clearState();
167f4e144565d1dba55e25ab7b454a7eb7d4a6f8290Roshan Pius        // Invalidate the global wificond handle on death. Will be refreshed
16855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        // on the next setup call.
16955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mWificond = null;
170f4e144565d1dba55e25ab7b454a7eb7d4a6f8290Roshan Pius        if (mDeathEventHandler != null) {
171f4e144565d1dba55e25ab7b454a7eb7d4a6f8290Roshan Pius            mDeathEventHandler.onDeath();
172f4e144565d1dba55e25ab7b454a7eb7d4a6f8290Roshan Pius        }
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) {
2784d2109e282e5ff427c64788dae814baccb542faeRoshan Pius        if (getClientInterface(ifaceName) == null) {
2794d2109e282e5ff427c64788dae814baccb542faeRoshan Pius            Log.e(TAG, "No valid wificond client interface handler");
2804d2109e282e5ff427c64788dae814baccb542faeRoshan Pius            return false;
2814d2109e282e5ff427c64788dae814baccb542faeRoshan Pius        }
2827065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
28391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            IWifiScannerImpl scannerImpl = mWificondScanners.get(ifaceName);
28491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            if (scannerImpl != null) {
28591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                scannerImpl.unsubscribeScanEvents();
28691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                scannerImpl.unsubscribePnoScanEvents();
2877065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            }
2887065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e) {
2897065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to unsubscribe wificond scanner due to remote exception");
2907065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
2917065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
2927065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
2934d2109e282e5ff427c64788dae814baccb542faeRoshan Pius        boolean success;
2947065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
2957065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            success = mWificond.tearDownClientInterface(ifaceName);
2967065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e1) {
2977065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown client interface due to remote exception");
2987065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
2997065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3007065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        if (!success) {
3017065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown client interface");
3027065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3037065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3047065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
30591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mClientInterfaces.remove(ifaceName);
30691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mWificondScanners.remove(ifaceName);
30791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mScanEventHandlers.remove(ifaceName);
30891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mPnoScanEventHandlers.remove(ifaceName);
3097065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        return true;
3107065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    }
3117065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
3127065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    /**
3137065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    * Setup interface for softAp mode via wificond.
31470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IApInterface as wificond Ap interface binder handler.
31570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
31670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
3177065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public IApInterface setupInterfaceForSoftApMode(@NonNull String ifaceName) {
3187065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        Log.d(TAG, "Setting up interface for soft ap mode");
31955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
32070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
32170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
32270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
32370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IApInterface apInterface = null;
32470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
325c7685b40d77b12820c5b04013592834025086cefRoshan Pius            apInterface = mWificond.createApInterface(ifaceName);
32670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
32770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IApInterface due to remote exception");
32870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
32970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
33070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
33170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (apInterface == null) {
33270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IApInterface instance from wificond");
33370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
33470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
33570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(apInterface.asBinder());
33670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
33770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
33891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.put(ifaceName, apInterface);
33970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return apInterface;
34070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
34170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
34270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
3437065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * Teardown a specific AP interface configured in wificond.
3447065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     *
3457065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * @return Returns true on success.
3467065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     */
3477065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public boolean tearDownSoftApInterface(@NonNull String ifaceName) {
3484d2109e282e5ff427c64788dae814baccb542faeRoshan Pius        if (getApInterface(ifaceName) == null) {
3494d2109e282e5ff427c64788dae814baccb542faeRoshan Pius            Log.e(TAG, "No valid wificond ap interface handler");
3504d2109e282e5ff427c64788dae814baccb542faeRoshan Pius            return false;
3514d2109e282e5ff427c64788dae814baccb542faeRoshan Pius        }
3527065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        boolean success;
3537065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
3547065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            success = mWificond.tearDownApInterface(ifaceName);
3557065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e1) {
3567065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown AP interface due to remote exception");
3577065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3587065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3597065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        if (!success) {
3607065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown AP interface");
3617065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3627065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
36391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.remove(ifaceName);
36491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.remove(ifaceName);
3657065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        return true;
3667065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    }
3677065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
3687065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    /**
36970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Teardown all interfaces configured in wificond.
37070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
37170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
37270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean tearDownInterfaces() {
373512ba9008e5b9ab4019647eb036c303a6bb9e0ceNingyuan Wang        Log.d(TAG, "tearing down interfaces in wificond");
37470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Explicitly refresh the wificodn handler because |tearDownInterfaces()|
37570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // could be used to cleanup before we setup any interfaces.
37655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
37770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
37870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
37970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
38070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
38191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            for (Map.Entry<String, IWifiScannerImpl> entry : mWificondScanners.entrySet()) {
38291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                entry.getValue().unsubscribeScanEvents();
38391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                entry.getValue().unsubscribePnoScanEvents();
38470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            }
38570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            mWificond.tearDownInterfaces();
38655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            clearState();
38770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return true;
38870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
38970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to tear down interfaces due to remote exception");
39070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
39170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
39270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
39370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
39470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
39591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the interface handle using name */
39691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IClientInterface getClientInterface(@NonNull String ifaceName) {
39791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mClientInterfaces.get(ifaceName);
39891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
39991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
40070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
40170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Disable wpa_supplicant via wificond.
40270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
40370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
40470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean disableSupplicant() {
40555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
40670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
40770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
40870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
4097a9936461744922f7785a192493ccce7c4fb52f9Roshan Pius            return mWificond.disableSupplicant();
41070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
41170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to disable supplicant due to remote exception");
41270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
41370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
41470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
41570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
41670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
41770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Enable wpa_supplicant via wificond.
41870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
41970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
42070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean enableSupplicant() {
42155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
42270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
42370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
42470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
4257a9936461744922f7785a192493ccce7c4fb52f9Roshan Pius            return mWificond.enableSupplicant();
42670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
42770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to enable supplicant due to remote exception");
42870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
42970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
43070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
431d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
432d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
43391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Request signal polling to wificond.
43491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
43591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns an SignalPollResult object.
43691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns null on failure.
43791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     */
43891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public WifiNative.SignalPollResult signalPoll(@NonNull String ifaceName) {
43991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IClientInterface iface = getClientInterface(ifaceName);
44091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
441d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
442d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
443d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
444d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
445d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
446d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
44791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            resultArray = iface.signalPoll();
448d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 3) {
449d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
450d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
451d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
452d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
4532e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
454d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
455d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
456d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.SignalPollResult pollResult = new WifiNative.SignalPollResult();
457d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.currentRssi = resultArray[0];
458d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.txBitrate = resultArray[1];
459d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.associationFrequency = resultArray[2];
460d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return pollResult;
461d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
462d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
463d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
46491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Fetch TX packet counters on current connection from wificond.
46591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
46691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns an TxPacketCounters object.
46791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns null on failure.
46891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     */
46991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public WifiNative.TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) {
47091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IClientInterface iface = getClientInterface(ifaceName);
47191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
472d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
473d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
474d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
475d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
476d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
477d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
47891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            resultArray = iface.getPacketCounters();
479d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 2) {
480d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
481d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
482d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
483d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
4842e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
485d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
486d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
487d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.TxPacketCounters counters = new WifiNative.TxPacketCounters();
488d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txSucceeded = resultArray[0];
489d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txFailed = resultArray[1];
490d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return counters;
491d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
4928631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
49391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the scanner impl handle using name */
49491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IWifiScannerImpl getScannerImpl(@NonNull String ifaceName) {
49591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mWificondScanners.get(ifaceName);
49691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
49791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
4988631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    /**
4998631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Fetch the latest scan result from kernel via wificond.
50091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    * @param ifaceName Name of the interface.
5018631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * @return Returns an ArrayList of ScanDetail.
5028631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Returns an empty ArrayList on failure.
5038631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    */
50491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public ArrayList<ScanDetail> getScanResults(@NonNull String ifaceName, int scanType) {
5058631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        ArrayList<ScanDetail> results = new ArrayList<>();
50691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
50791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
5088631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
5098631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            return results;
5108631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
5118631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
51271c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            NativeScanResult[] nativeResults;
51371c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            if (scanType == SCAN_TYPE_SINGLE_SCAN) {
51491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                nativeResults = scannerImpl.getScanResults();
51571c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            } else {
51691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                nativeResults = scannerImpl.getPnoScanResults();
51771c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            }
5188631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            for (NativeScanResult result : nativeResults) {
519755bbe962c20d37491dd9264ad3497bf27e33602Ningyuan Wang                WifiSsid wifiSsid = WifiSsid.createFromByteArray(result.ssid);
5208ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                String bssid;
5218ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
5228ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    bssid = NativeUtil.macAddressFromByteArray(result.bssid);
5238ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
5248ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + result.bssid, e);
5258ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
5268ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
5278ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                if (bssid == null) {
5288ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal null bssid");
5298ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
5308ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
5318631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanResult.InformationElement[] ies =
5328631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        InformationElementUtil.parseInformationElements(result.infoElement);
5338631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                InformationElementUtil.Capabilities capabilities =
5348631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        new InformationElementUtil.Capabilities();
5358631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                capabilities.from(ies, result.capability);
5368631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                String flags = capabilities.generateCapabilitiesString();
5370a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                NetworkDetail networkDetail;
5380a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                try {
5390a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    networkDetail = new NetworkDetail(bssid, ies, null, result.frequency);
5400a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                } catch (IllegalArgumentException e) {
5410a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    Log.e(TAG, "Illegal argument for scan result with bssid: " + bssid, e);
5420a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    continue;
5430a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                }
5448631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
5458631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanDetail scanDetail = new ScanDetail(networkDetail, wifiSsid, bssid, flags,
5468631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        result.signalMbm / 100, result.frequency, result.tsf, ies, null);
5473feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                ScanResult scanResult = scanDetail.getScanResult();
5484eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // Update carrier network info if this AP's SSID is associated with a carrier Wi-Fi
5494eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // network and it uses EAP.
5504eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                if (ScanResultUtil.isScanResultForEapNetwork(scanDetail.getScanResult())
5514eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                        && mCarrierNetworkConfig.isCarrierNetwork(wifiSsid.toString())) {
5523feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.isCarrierAp = true;
5533feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.carrierApEapType =
5544eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getNetworkEapType(wifiSsid.toString());
5553feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.carrierName =
5564eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getCarrierName(wifiSsid.toString());
5574eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                }
5583feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                // Fill up the radio chain info.
5593feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                if (result.radioChainInfos != null) {
5603feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    scanResult.radioChainInfos =
5613feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        new ScanResult.RadioChainInfo[result.radioChainInfos.size()];
5623feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    int idx = 0;
5633feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    for (RadioChainInfo nativeRadioChainInfo : result.radioChainInfos) {
5643feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        scanResult.radioChainInfos[idx] = new ScanResult.RadioChainInfo();
5653feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        scanResult.radioChainInfos[idx].id = nativeRadioChainInfo.chainId;
5663feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        scanResult.radioChainInfos[idx].level = nativeRadioChainInfo.level;
5673feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        idx++;
5683feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                    }
5693feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                }
5708631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                results.add(scanDetail);
5718631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            }
5728631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e1) {
5738631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to create ScanDetail ArrayList");
5748631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
5752e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        if (mVerboseLoggingEnabled) {
5762e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.d(TAG, "get " + results.size() + " scan results from wificond");
5772e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        }
5782e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
5798631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        return results;
5808631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    }
581e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
582e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    /**
5833feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius     * Return scan type for the parcelable {@link SingleScanSettings}
5843feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius     */
5853feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius    private static int getScanType(int scanType) {
5863feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        switch (scanType) {
5873feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            case WifiNative.SCAN_TYPE_LOW_LATENCY:
5883feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                return IWifiScannerImpl.SCAN_TYPE_LOW_SPAN;
5893feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            case WifiNative.SCAN_TYPE_LOW_POWER:
5903feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                return IWifiScannerImpl.SCAN_TYPE_LOW_POWER;
5913feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            case WifiNative.SCAN_TYPE_HIGH_ACCURACY:
5923feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                return IWifiScannerImpl.SCAN_TYPE_HIGH_ACCURACY;
5933feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            default:
5943feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                throw new IllegalArgumentException("Invalid scan type " + scanType);
5953feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        }
5963feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius    }
5973feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius
5983feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius    /**
599e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * Start a scan using wificond for the given parameters.
60091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
6013feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius     * @param scanType Type of scan to perform.
602e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param freqs list of frequencies to scan for, if null scan all supported channels.
603e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
604e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @return Returns true on success.
605e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     */
60691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean scan(@NonNull String ifaceName,
6073feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius                        int scanType,
60891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                        Set<Integer> freqs,
60991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                        Set<String> hiddenNetworkSSIDs) {
61091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
61191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
612e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
613e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            return false;
614e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
615e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        SingleScanSettings settings = new SingleScanSettings();
6163feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        try {
6173feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            settings.scanType = getScanType(scanType);
6183feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        } catch (IllegalArgumentException e) {
6193feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            Log.e(TAG, "Invalid scan type ", e);
6203feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius            return false;
6213feac6fe9249c1b7bf284c7a9bfa65a86b973154Roshan Pius        }
622e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.channelSettings  = new ArrayList<>();
623e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.hiddenNetworks  = new ArrayList<>();
624e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
625e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (freqs != null) {
626e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (Integer freq : freqs) {
627e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                ChannelSettings channel = new ChannelSettings();
628e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                channel.frequency = freq;
629e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.channelSettings.add(channel);
630e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
631e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
632e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (hiddenNetworkSSIDs != null) {
633e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (String ssid : hiddenNetworkSSIDs) {
634e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                HiddenNetwork network = new HiddenNetwork();
6358ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
6368ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    network.ssid = NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssid));
6378ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
6388ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + ssid, e);
6398ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
6408ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
641e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.hiddenNetworks.add(network);
642e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
643e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
644e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
645e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        try {
64691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            return scannerImpl.scan(settings);
647e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        } catch (RemoteException e1) {
648e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "Failed to request scan due to remote exception");
649e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
650e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        return false;
651e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    }
652e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
65304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
65404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Start PNO scan.
65591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
65604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @param pnoSettings Pno scan configuration.
65704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
65804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
65991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean startPnoScan(@NonNull String ifaceName, WifiNative.PnoSettings pnoSettings) {
66091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
66191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
66204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
66304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
66404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
66504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        PnoSettings settings = new PnoSettings();
66604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.pnoNetworks  = new ArrayList<>();
66704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.intervalMs = pnoSettings.periodInMs;
66804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min2gRssi = pnoSettings.min24GHzRssi;
66904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min5gRssi = pnoSettings.min5GHzRssi;
67004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (pnoSettings.networkList != null) {
67104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            for (WifiNative.PnoNetwork network : pnoSettings.networkList) {
67204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                PnoNetwork condNetwork = new PnoNetwork();
67304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                condNetwork.isHidden = (network.flags
67404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                        & WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN) != 0;
6758ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
6768ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    condNetwork.ssid =
6778ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                            NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(network.ssid));
6788ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
6798ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + network.ssid, e);
6808ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
6818ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
68204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                settings.pnoNetworks.add(condNetwork);
68304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            }
68404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
68504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
68604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
68791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            boolean success = scannerImpl.startPnoScan(settings);
688a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanStartAttempCount();
689a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            if (!success) {
690a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh                mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
691a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            }
692a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            return success;
69304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
694a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            Log.e(TAG, "Failed to start pno scan due to remote exception");
69504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
69604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
69704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
69804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
69904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
70004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Stop PNO scan.
70191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
70204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
70304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
70491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean stopPnoScan(@NonNull String ifaceName) {
70591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
70691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
70704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
70804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
70904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
71004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
71191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            return scannerImpl.stopPnoScan();
71204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
71304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "Failed to stop pno scan due to remote exception");
71404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
71504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
71604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
71704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
718c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    /**
719c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     * Abort ongoing single scan.
72091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
721c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     */
72291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public void abortScan(@NonNull String ifaceName) {
72391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
72491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
725c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
726c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            return;
727c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
728c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        try {
72991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            scannerImpl.abortScan();
730c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        } catch (RemoteException e1) {
731c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "Failed to request abortScan due to remote exception");
732c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
733c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    }
734c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang
7356baff2cb8dec599af186be521882413787595930Ningyuan Wang    /**
7366baff2cb8dec599af186be521882413787595930Ningyuan Wang     * Query the list of valid frequencies for the provided band.
7376baff2cb8dec599af186be521882413787595930Ningyuan Wang     * The result depends on the on the country code that has been set.
7386baff2cb8dec599af186be521882413787595930Ningyuan Wang     *
7396baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
7406baff2cb8dec599af186be521882413787595930Ningyuan Wang     * The following bands are supported:
7416baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_24_GHZ
7426baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_5_GHZ
7436baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY
7446baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @return frequencies vector of valid frequencies (MHz), or null for error.
7456baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @throws IllegalArgumentException if band is not recognized.
7466baff2cb8dec599af186be521882413787595930Ningyuan Wang     */
7476baff2cb8dec599af186be521882413787595930Ningyuan Wang    public int [] getChannelsForBand(int band) {
7486baff2cb8dec599af186be521882413787595930Ningyuan Wang        if (mWificond == null) {
7496baff2cb8dec599af186be521882413787595930Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
7506baff2cb8dec599af186be521882413787595930Ningyuan Wang            return null;
7516baff2cb8dec599af186be521882413787595930Ningyuan Wang        }
7526baff2cb8dec599af186be521882413787595930Ningyuan Wang        try {
7536baff2cb8dec599af186be521882413787595930Ningyuan Wang            switch (band) {
7546baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_24_GHZ:
7556baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailable2gChannels();
7566baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_5_GHZ:
7576baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailable5gNonDFSChannels();
7586baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
7596baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailableDFSChannels();
7606baff2cb8dec599af186be521882413787595930Ningyuan Wang                default:
7616baff2cb8dec599af186be521882413787595930Ningyuan Wang                    throw new IllegalArgumentException("unsupported band " + band);
7626baff2cb8dec599af186be521882413787595930Ningyuan Wang            }
7636baff2cb8dec599af186be521882413787595930Ningyuan Wang        } catch (RemoteException e1) {
7646baff2cb8dec599af186be521882413787595930Ningyuan Wang            Log.e(TAG, "Failed to request getChannelsForBand due to remote exception");
7656baff2cb8dec599af186be521882413787595930Ningyuan Wang        }
7666baff2cb8dec599af186be521882413787595930Ningyuan Wang        return null;
7676baff2cb8dec599af186be521882413787595930Ningyuan Wang    }
768045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
76991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the interface handle using name */
77091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IApInterface getApInterface(@NonNull String ifaceName) {
77191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mApInterfaces.get(ifaceName);
77291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
77391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
774045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
775295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * Start hostapd
776295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * TODO(b/71513606): Move this to a global operation.
777045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     *
77891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
779045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @param listener Callback for AP events.
780045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @return true on success, false otherwise.
781045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
782295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius    public boolean startHostapd(@NonNull String ifaceName,
78391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                               SoftApListener listener) {
78491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IApInterface iface = getApInterface(ifaceName);
78591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
786045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "No valid ap interface handler");
787045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
788045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
789045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        try {
79091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            IApInterfaceEventCallback  callback = new ApInterfaceEventCallback(listener);
79191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mApInterfaceListeners.put(ifaceName, callback);
792295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius            boolean success = iface.startHostapd(callback);
793045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
794045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to start hostapd.");
795045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
796045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
797045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        } catch (RemoteException e) {
798045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "Exception in starting soft AP: " + e);
799045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
800045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
801045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return true;
802045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
803045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
804045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
805295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * Stop hostapd
806295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius     * TODO(b/71513606): Move this to a global operation.
807045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     *
80891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
809045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @return true on success, false otherwise.
810045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
811295a0f1632f2c46ffb050ad538eddeb9a2aa7a76Roshan Pius    public boolean stopHostapd(@NonNull String ifaceName) {
81291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IApInterface iface = getApInterface(ifaceName);
81391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
814045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "No valid ap interface handler");
815045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
816045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
817045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        try {
81891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            boolean success = iface.stopHostapd();
819045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
820045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to stop hostapd.");
821045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
822045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
823045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        } catch (RemoteException e) {
824045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "Exception in stopping soft AP: " + e);
825045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
826045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
82791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.remove(ifaceName);
828045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return true;
829045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
830045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
83155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
832f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * Set Mac address on the given interface
833f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * @param interfaceName Name of the interface.
834f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * @param mac Mac address to change into
835f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     * @return true on success, false otherwise.
836f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim     */
837f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim    public boolean setMacAddress(@NonNull String interfaceName, @NonNull MacAddress mac) {
838f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        IClientInterface mClientInterface = getClientInterface(interfaceName);
839f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        if (mClientInterface == null) {
840f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            Log.e(TAG, "No valid wificond client interface handler");
841f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            return false;
842f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        }
843f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        byte[] macByteArray = mac.toByteArray();
844f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim
845f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        try {
846f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            mClientInterface.setMacAddress(macByteArray);
847f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        } catch (RemoteException e) {
848f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            Log.e(TAG, "Failed to setMacAddress due to remote exception");
849f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim            return false;
850f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        }
851f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim        return true;
852f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim    }
853f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim
854f8418067cfc279fc451f3347dab20908a1837bfcJong Wook Kim    /**
85555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Clear all internal handles.
85655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
85755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    private void clearState() {
85855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        // Refresh handlers
85991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mClientInterfaces.clear();
86091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mWificondScanners.clear();
86191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mPnoScanEventHandlers.clear();
86291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mScanEventHandlers.clear();
86391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.clear();
86491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.clear();
86555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
86670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang}
867