WificondControl.java revision 91375b39b0fdd6b9c692a5d48120673ee472e3ff
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;
2070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IApInterface;
21045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Piusimport android.net.wifi.IApInterfaceEventCallback;
2270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IClientInterface;
2304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport android.net.wifi.IPnoScanEvent;
2470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wangimport android.net.wifi.IScanEvent;
258631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.IWifiScannerImpl;
2670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IWificond;
278631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.ScanResult;
28045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Piusimport android.net.wifi.WifiConfiguration;
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;
46e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.SingleScanSettings;
478631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
48045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Piusimport java.nio.charset.StandardCharsets;
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    /**
18355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Registers a death notification for wificond.
18455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * @return Returns true on success.
18555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
18655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    public boolean registerDeathHandler(@NonNull WifiNative.WificondDeathEventHandler handler) {
18755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mDeathEventHandler != null) {
18855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Death handler already present");
18955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
19055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
19155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mDeathEventHandler = handler;
19255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        return true;
19355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
19455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
19555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
19655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Deregisters a death notification for wificond.
19755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * @return Returns true on success.
19855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
19955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    public boolean deregisterDeathHandler() {
20055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mDeathEventHandler == null) {
20155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "No Death handler present");
20255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
20355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
20455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mDeathEventHandler = null;
20555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        return true;
20655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
20755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
20855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
20955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Helper method to retrieve the global wificond handle and register for
21055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * death notifications.
21155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
21255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    private boolean retrieveWificondAndRegisterForDeath() {
21355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mWificond != null) {
21455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.d(TAG, "Wificond handle already retrieved");
21555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            // We already have a wificond handle.
21655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return true;
21755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
21855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mWificond = mWifiInjector.makeWificond();
21955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mWificond == null) {
22055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Failed to get reference to wificond");
22155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
22255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
22355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        try {
22455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            mWificond.asBinder().linkToDeath(this, 0);
22555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        } catch (RemoteException e) {
22655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Failed to register death notification for wificond");
22755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            // The remote has already died.
22855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
22955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
23055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        return true;
23155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
23255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
23355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
2347065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    * Setup interface for client mode via wificond.
23570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IClientInterface as wificond client interface binder handler.
23670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
23770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
2387065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public IClientInterface setupInterfaceForClientMode(@NonNull String ifaceName) {
2397065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        Log.d(TAG, "Setting up interface for client mode");
24055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
24170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
24270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
24370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
24470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IClientInterface clientInterface = null;
24570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
246c7685b40d77b12820c5b04013592834025086cefRoshan Pius            clientInterface = mWificond.createClientInterface(ifaceName);
24770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
24870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IClientInterface due to remote exception");
24970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
25070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
25170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
25270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (clientInterface == null) {
25370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IClientInterface instance from wificond");
25470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
25570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
25670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(clientInterface.asBinder());
25770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
25870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
25991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mClientInterfaces.put(ifaceName, clientInterface);
2608631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
26191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl();
26291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            if (wificondScanner == null) {
263bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                Log.e(TAG, "Failed to get WificondScannerImpl");
264bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                return null;
265bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            }
26691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mWificondScanners.put(ifaceName, wificondScanner);
26791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            Binder.allowBlocking(wificondScanner.asBinder());
26891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            ScanEventHandler scanEventHandler = new ScanEventHandler(ifaceName);
26991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mScanEventHandlers.put(ifaceName,  scanEventHandler);
27091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            wificondScanner.subscribeScanEvents(scanEventHandler);
27191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(ifaceName);
27291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mPnoScanEventHandlers.put(ifaceName,  pnoScanEventHandler);
27391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);
2748631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e) {
2758631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to refresh wificond scanner due to remote exception");
2768631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
27770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
27870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return clientInterface;
27970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
28070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
28170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
2827065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * Teardown a specific STA interface configured in wificond.
2837065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     *
2847065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * @return Returns true on success.
2857065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     */
2867065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public boolean tearDownClientInterface(@NonNull String ifaceName) {
2877065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        boolean success;
2887065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
28991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            IWifiScannerImpl scannerImpl = mWificondScanners.get(ifaceName);
29091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            if (scannerImpl != null) {
29191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                scannerImpl.unsubscribeScanEvents();
29291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                scannerImpl.unsubscribePnoScanEvents();
2937065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            }
2947065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e) {
2957065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to unsubscribe wificond scanner due to remote exception");
2967065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
2977065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
2987065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
2997065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
3007065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            success = mWificond.tearDownClientInterface(ifaceName);
3017065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e1) {
3027065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown client interface due to remote exception");
3037065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3047065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3057065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        if (!success) {
3067065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown client interface");
3077065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3087065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3097065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
31091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mClientInterfaces.remove(ifaceName);
31191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mWificondScanners.remove(ifaceName);
31291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mScanEventHandlers.remove(ifaceName);
31391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mPnoScanEventHandlers.remove(ifaceName);
3147065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        return true;
3157065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    }
3167065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
3177065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    /**
3187065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    * Setup interface for softAp mode via wificond.
31970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IApInterface as wificond Ap interface binder handler.
32070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
32170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
3227065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public IApInterface setupInterfaceForSoftApMode(@NonNull String ifaceName) {
3237065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        Log.d(TAG, "Setting up interface for soft ap mode");
32455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
32570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
32670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
32770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
32870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IApInterface apInterface = null;
32970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
330c7685b40d77b12820c5b04013592834025086cefRoshan Pius            apInterface = mWificond.createApInterface(ifaceName);
33170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
33270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IApInterface due to remote exception");
33370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
33470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
33570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
33670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (apInterface == null) {
33770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IApInterface instance from wificond");
33870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
33970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
34070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(apInterface.asBinder());
34170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
34270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
34391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.put(ifaceName, apInterface);
34470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return apInterface;
34570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
34670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
34770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
3487065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * Teardown a specific AP interface configured in wificond.
3497065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     *
3507065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * @return Returns true on success.
3517065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     */
3527065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public boolean tearDownSoftApInterface(@NonNull String ifaceName) {
3537065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        boolean success;
3547065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
3557065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            success = mWificond.tearDownApInterface(ifaceName);
3567065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e1) {
3577065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown AP interface due to remote exception");
3587065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3597065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3607065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        if (!success) {
3617065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown AP interface");
3627065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3637065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
36491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.remove(ifaceName);
36591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.remove(ifaceName);
3667065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        return true;
3677065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    }
3687065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
3697065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    /**
37070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Teardown all interfaces configured in wificond.
37170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
37270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
37370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean tearDownInterfaces() {
374512ba9008e5b9ab4019647eb036c303a6bb9e0ceNingyuan Wang        Log.d(TAG, "tearing down interfaces in wificond");
37570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Explicitly refresh the wificodn handler because |tearDownInterfaces()|
37670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // could be used to cleanup before we setup any interfaces.
37755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
37870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
37970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
38070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
38170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
38291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            for (Map.Entry<String, IWifiScannerImpl> entry : mWificondScanners.entrySet()) {
38391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                entry.getValue().unsubscribeScanEvents();
38491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                entry.getValue().unsubscribePnoScanEvents();
38570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            }
38670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            mWificond.tearDownInterfaces();
38755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            clearState();
38870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return true;
38970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
39070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to tear down interfaces due to remote exception");
39170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
39270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
39370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
39470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
39570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
39691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the interface handle using name */
39791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IClientInterface getClientInterface(@NonNull String ifaceName) {
39891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mClientInterfaces.get(ifaceName);
39991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
40091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
40170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
40270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Disable wpa_supplicant via wificond.
40370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
40470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
40570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean disableSupplicant() {
40655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
40770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
40870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
40970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
4107a9936461744922f7785a192493ccce7c4fb52f9Roshan Pius            return mWificond.disableSupplicant();
41170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
41270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to disable supplicant due to remote exception");
41370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
41470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
41570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
41670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
41770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
41870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Enable wpa_supplicant via wificond.
41970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
42070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
42170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean enableSupplicant() {
42255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
42370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
42470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
42570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
4267a9936461744922f7785a192493ccce7c4fb52f9Roshan Pius            return mWificond.enableSupplicant();
42770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
42870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to enable supplicant due to remote exception");
42970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
43070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
43170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
432d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
433d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
43491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Request signal polling to wificond.
43591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
43691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns an SignalPollResult object.
43791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns null on failure.
43891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     */
43991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public WifiNative.SignalPollResult signalPoll(@NonNull String ifaceName) {
44091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IClientInterface iface = getClientInterface(ifaceName);
44191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
442d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
443d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
444d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
445d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
446d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
447d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
44891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            resultArray = iface.signalPoll();
449d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 3) {
450d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
451d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
452d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
453d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
4542e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
455d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
456d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
457d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.SignalPollResult pollResult = new WifiNative.SignalPollResult();
458d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.currentRssi = resultArray[0];
459d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.txBitrate = resultArray[1];
460d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.associationFrequency = resultArray[2];
461d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return pollResult;
462d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
463d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
464d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
46591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Fetch TX packet counters on current connection from wificond.
46691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
46791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns an TxPacketCounters object.
46891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * Returns null on failure.
46991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     */
47091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public WifiNative.TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) {
47191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IClientInterface iface = getClientInterface(ifaceName);
47291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
473d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
474d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
475d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
476d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
477d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
478d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
47991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            resultArray = iface.getPacketCounters();
480d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 2) {
481d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
482d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
483d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
484d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
4852e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
486d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
487d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
488d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.TxPacketCounters counters = new WifiNative.TxPacketCounters();
489d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txSucceeded = resultArray[0];
490d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txFailed = resultArray[1];
491d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return counters;
492d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
4938631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
49491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the scanner impl handle using name */
49591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IWifiScannerImpl getScannerImpl(@NonNull String ifaceName) {
49691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mWificondScanners.get(ifaceName);
49791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
49891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
4998631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    /**
5008631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Fetch the latest scan result from kernel via wificond.
50191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    * @param ifaceName Name of the interface.
5028631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * @return Returns an ArrayList of ScanDetail.
5038631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Returns an empty ArrayList on failure.
5048631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    */
50591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public ArrayList<ScanDetail> getScanResults(@NonNull String ifaceName, int scanType) {
5068631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        ArrayList<ScanDetail> results = new ArrayList<>();
50791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
50891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
5098631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
5108631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            return results;
5118631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
5128631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
51371c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            NativeScanResult[] nativeResults;
51471c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            if (scanType == SCAN_TYPE_SINGLE_SCAN) {
51591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                nativeResults = scannerImpl.getScanResults();
51671c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            } else {
51791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                nativeResults = scannerImpl.getPnoScanResults();
51871c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            }
5198631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            for (NativeScanResult result : nativeResults) {
520755bbe962c20d37491dd9264ad3497bf27e33602Ningyuan Wang                WifiSsid wifiSsid = WifiSsid.createFromByteArray(result.ssid);
5218ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                String bssid;
5228ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
5238ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    bssid = NativeUtil.macAddressFromByteArray(result.bssid);
5248ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
5258ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + result.bssid, e);
5268ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
5278ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
5288ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                if (bssid == null) {
5298ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal null bssid");
5308ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
5318ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
5328631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanResult.InformationElement[] ies =
5338631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        InformationElementUtil.parseInformationElements(result.infoElement);
5348631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                InformationElementUtil.Capabilities capabilities =
5358631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        new InformationElementUtil.Capabilities();
5368631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                capabilities.from(ies, result.capability);
5378631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                String flags = capabilities.generateCapabilitiesString();
5380a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                NetworkDetail networkDetail;
5390a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                try {
5400a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    networkDetail = new NetworkDetail(bssid, ies, null, result.frequency);
5410a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                } catch (IllegalArgumentException e) {
5420a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    Log.e(TAG, "Illegal argument for scan result with bssid: " + bssid, e);
5430a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    continue;
5440a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                }
5458631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
5468631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanDetail scanDetail = new ScanDetail(networkDetail, wifiSsid, bssid, flags,
5478631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        result.signalMbm / 100, result.frequency, result.tsf, ies, null);
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())) {
5524eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().isCarrierAp = true;
5534eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().carrierApEapType =
5544eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getNetworkEapType(wifiSsid.toString());
5554eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().carrierName =
5564eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getCarrierName(wifiSsid.toString());
5574eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                }
5588631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                results.add(scanDetail);
5598631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            }
5608631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e1) {
5618631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to create ScanDetail ArrayList");
5628631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
5632e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        if (mVerboseLoggingEnabled) {
5642e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.d(TAG, "get " + results.size() + " scan results from wificond");
5652e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        }
5662e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
5678631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        return results;
5688631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    }
569e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
570e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    /**
571e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * Start a scan using wificond for the given parameters.
57291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
573e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param freqs list of frequencies to scan for, if null scan all supported channels.
574e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
575e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @return Returns true on success.
576e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     */
57791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean scan(@NonNull String ifaceName,
57891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                        Set<Integer> freqs,
57991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                        Set<String> hiddenNetworkSSIDs) {
58091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
58191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
582e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
583e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            return false;
584e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
585e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        SingleScanSettings settings = new SingleScanSettings();
586e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.channelSettings  = new ArrayList<>();
587e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.hiddenNetworks  = new ArrayList<>();
588e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
589e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (freqs != null) {
590e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (Integer freq : freqs) {
591e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                ChannelSettings channel = new ChannelSettings();
592e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                channel.frequency = freq;
593e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.channelSettings.add(channel);
594e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
595e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
596e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (hiddenNetworkSSIDs != null) {
597e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (String ssid : hiddenNetworkSSIDs) {
598e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                HiddenNetwork network = new HiddenNetwork();
5998ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
6008ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    network.ssid = NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssid));
6018ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
6028ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + ssid, e);
6038ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
6048ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
605e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.hiddenNetworks.add(network);
606e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
607e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
608e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
609e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        try {
61091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            return scannerImpl.scan(settings);
611e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        } catch (RemoteException e1) {
612e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "Failed to request scan due to remote exception");
613e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
614e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        return false;
615e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    }
616e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
61704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
61804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Start PNO scan.
61991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
62004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @param pnoSettings Pno scan configuration.
62104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
62204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
62391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean startPnoScan(@NonNull String ifaceName, WifiNative.PnoSettings pnoSettings) {
62491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
62591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
62604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
62704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
62804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
62904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        PnoSettings settings = new PnoSettings();
63004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.pnoNetworks  = new ArrayList<>();
63104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.intervalMs = pnoSettings.periodInMs;
63204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min2gRssi = pnoSettings.min24GHzRssi;
63304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min5gRssi = pnoSettings.min5GHzRssi;
63404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (pnoSettings.networkList != null) {
63504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            for (WifiNative.PnoNetwork network : pnoSettings.networkList) {
63604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                PnoNetwork condNetwork = new PnoNetwork();
63704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                condNetwork.isHidden = (network.flags
63804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                        & WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN) != 0;
6398ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
6408ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    condNetwork.ssid =
6418ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                            NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(network.ssid));
6428ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
6438ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + network.ssid, e);
6448ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
6458ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
64604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                settings.pnoNetworks.add(condNetwork);
64704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            }
64804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
64904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
65004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
65191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            boolean success = scannerImpl.startPnoScan(settings);
652a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanStartAttempCount();
653a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            if (!success) {
654a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh                mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
655a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            }
656a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            return success;
65704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
658a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            Log.e(TAG, "Failed to start pno scan due to remote exception");
65904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
66004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
66104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
66204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
66304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
66404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Stop PNO scan.
66591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
66604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
66704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
66891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean stopPnoScan(@NonNull String ifaceName) {
66991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
67091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
67104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
67204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
67304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
67404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
67591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            return scannerImpl.stopPnoScan();
67604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
67704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "Failed to stop pno scan due to remote exception");
67804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
67904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
68004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
68104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
682c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    /**
683c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     * Abort ongoing single scan.
68491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
685c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     */
68691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public void abortScan(@NonNull String ifaceName) {
68791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
68891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (scannerImpl == null) {
689c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
690c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            return;
691c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
692c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        try {
69391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            scannerImpl.abortScan();
694c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        } catch (RemoteException e1) {
695c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "Failed to request abortScan due to remote exception");
696c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
697c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    }
698c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang
6996baff2cb8dec599af186be521882413787595930Ningyuan Wang    /**
7006baff2cb8dec599af186be521882413787595930Ningyuan Wang     * Query the list of valid frequencies for the provided band.
7016baff2cb8dec599af186be521882413787595930Ningyuan Wang     * The result depends on the on the country code that has been set.
7026baff2cb8dec599af186be521882413787595930Ningyuan Wang     *
7036baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
7046baff2cb8dec599af186be521882413787595930Ningyuan Wang     * The following bands are supported:
7056baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_24_GHZ
7066baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_5_GHZ
7076baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY
7086baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @return frequencies vector of valid frequencies (MHz), or null for error.
7096baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @throws IllegalArgumentException if band is not recognized.
7106baff2cb8dec599af186be521882413787595930Ningyuan Wang     */
7116baff2cb8dec599af186be521882413787595930Ningyuan Wang    public int [] getChannelsForBand(int band) {
7126baff2cb8dec599af186be521882413787595930Ningyuan Wang        if (mWificond == null) {
7136baff2cb8dec599af186be521882413787595930Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
7146baff2cb8dec599af186be521882413787595930Ningyuan Wang            return null;
7156baff2cb8dec599af186be521882413787595930Ningyuan Wang        }
7166baff2cb8dec599af186be521882413787595930Ningyuan Wang        try {
7176baff2cb8dec599af186be521882413787595930Ningyuan Wang            switch (band) {
7186baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_24_GHZ:
7196baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailable2gChannels();
7206baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_5_GHZ:
7216baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailable5gNonDFSChannels();
7226baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
7236baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailableDFSChannels();
7246baff2cb8dec599af186be521882413787595930Ningyuan Wang                default:
7256baff2cb8dec599af186be521882413787595930Ningyuan Wang                    throw new IllegalArgumentException("unsupported band " + band);
7266baff2cb8dec599af186be521882413787595930Ningyuan Wang            }
7276baff2cb8dec599af186be521882413787595930Ningyuan Wang        } catch (RemoteException e1) {
7286baff2cb8dec599af186be521882413787595930Ningyuan Wang            Log.e(TAG, "Failed to request getChannelsForBand due to remote exception");
7296baff2cb8dec599af186be521882413787595930Ningyuan Wang        }
7306baff2cb8dec599af186be521882413787595930Ningyuan Wang        return null;
7316baff2cb8dec599af186be521882413787595930Ningyuan Wang    }
732045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
73391375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    /** Helper function to look up the interface handle using name */
73491375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    private IApInterface getApInterface(@NonNull String ifaceName) {
73591375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        return mApInterfaces.get(ifaceName);
73691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    }
73791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius
738045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
739045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * Start Soft AP operation using the provided configuration.
740045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     *
74191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
742045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @param config Configuration to use for the soft ap created.
743045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @param listener Callback for AP events.
744045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @return true on success, false otherwise.
745045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
74691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean startSoftAp(@NonNull String ifaceName,
74791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                               WifiConfiguration config,
74891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius                               SoftApListener listener) {
74991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IApInterface iface = getApInterface(ifaceName);
75091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
751045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "No valid ap interface handler");
752045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
753045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
754045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        int encryptionType = getIApInterfaceEncryptionType(config);
755045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        try {
756045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            // TODO(b/67745880) Note that config.SSID is intended to be either a
757045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            // hex string or "double quoted".
758045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            // However, it seems that whatever is handing us these configurations does not obey
759045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            // this convention.
76091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            boolean success = iface.writeHostapdConfig(
761045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                    config.SSID.getBytes(StandardCharsets.UTF_8), config.hiddenSSID,
762045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                    config.apChannel, encryptionType,
763045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                    (config.preSharedKey != null)
764045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                            ? config.preSharedKey.getBytes(StandardCharsets.UTF_8)
765045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                            : new byte[0]);
766045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
767045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to write hostapd configuration");
768045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
769045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
77091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            IApInterfaceEventCallback  callback = new ApInterfaceEventCallback(listener);
77191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            mApInterfaceListeners.put(ifaceName, callback);
77291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            success = iface.startHostapd(callback);
773045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
774045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to start hostapd.");
775045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
776045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
777045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        } catch (RemoteException e) {
778045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "Exception in starting soft AP: " + e);
779045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
780045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
781045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return true;
782045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
783045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
784045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
785045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * Stop the ongoing Soft AP operation.
786045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     *
78791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius     * @param ifaceName Name of the interface.
788045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @return true on success, false otherwise.
789045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
79091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius    public boolean stopSoftAp(@NonNull String ifaceName) {
79191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        IApInterface iface = getApInterface(ifaceName);
79291375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        if (iface == null) {
793045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "No valid ap interface handler");
794045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
795045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
796045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        try {
79791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius            boolean success = iface.stopHostapd();
798045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
799045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to stop hostapd.");
800045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
801045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
802045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        } catch (RemoteException e) {
803045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "Exception in stopping soft AP: " + e);
804045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
805045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
80691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.remove(ifaceName);
807045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return true;
808045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
809045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
810045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    private static int getIApInterfaceEncryptionType(WifiConfiguration localConfig) {
811045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        int encryptionType;
812045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        switch (localConfig.getAuthType()) {
813045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            case WifiConfiguration.KeyMgmt.NONE:
814045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                encryptionType = IApInterface.ENCRYPTION_TYPE_NONE;
815045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                break;
816045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            case WifiConfiguration.KeyMgmt.WPA_PSK:
817045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                encryptionType = IApInterface.ENCRYPTION_TYPE_WPA;
818045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                break;
819045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            case WifiConfiguration.KeyMgmt.WPA2_PSK:
820045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                encryptionType = IApInterface.ENCRYPTION_TYPE_WPA2;
821045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                break;
822045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            default:
823045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                // We really shouldn't default to None, but this was how NetworkManagementService
824045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                // used to do this.
825045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                encryptionType = IApInterface.ENCRYPTION_TYPE_NONE;
826045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                break;
827045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
828045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return encryptionType;
829045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
83055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
83155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
83255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Clear all internal handles.
83355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
83455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    private void clearState() {
83555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        // Refresh handlers
83691375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mClientInterfaces.clear();
83791375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mWificondScanners.clear();
83891375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mPnoScanEventHandlers.clear();
83991375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mScanEventHandlers.clear();
84091375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaces.clear();
84191375b39b0fdd6b9c692a5d48120673ee472e3ffRoshan Pius        mApInterfaceListeners.clear();
84255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
84370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang}
844