WificondControl.java revision c7685b40d77b12820c5b04013592834025086cef
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;
2170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IClientInterface;
2204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport android.net.wifi.IPnoScanEvent;
2370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wangimport android.net.wifi.IScanEvent;
248631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.IWifiScannerImpl;
2570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IWificond;
268631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.ScanResult;
2704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport android.net.wifi.WifiScanner;
288631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.WifiSsid;
2970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.os.Binder;
3070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.os.RemoteException;
3170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.util.Log;
3270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
338631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.hotspot2.NetworkDetail;
348631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.util.InformationElementUtil;
35f4b53ff21ce0aa25131222d0cd15cc4a5e8c0c4fNingyuan Wangimport com.android.server.wifi.util.NativeUtil;
364eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiuimport com.android.server.wifi.util.ScanResultUtil;
37e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.ChannelSettings;
38e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.HiddenNetwork;
398631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.wificond.NativeScanResult;
4004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport com.android.server.wifi.wificond.PnoNetwork;
4104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport com.android.server.wifi.wificond.PnoSettings;
42e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.SingleScanSettings;
438631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
448631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport java.util.ArrayList;
45e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport java.util.Set;
468631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
4770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang/**
4870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * This class provides methods for WifiNative to send control commands to wificond.
4970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * NOTE: This class should only be used from WifiNative.
5070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang */
5170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangpublic class WificondControl {
522e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    private boolean mVerboseLoggingEnabled = false;
5370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
5470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private static final String TAG = "WificondControl";
5571c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
5671c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    /* Get scan results for a single scan */
5771c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    public static final int SCAN_TYPE_SINGLE_SCAN = 0;
5871c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
5971c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    /* Get scan results for Pno Scan */
6071c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    public static final int SCAN_TYPE_PNO_SCAN = 1;
6171c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
6270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private WifiInjector mWifiInjector;
6370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private WifiMonitor mWifiMonitor;
644eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu    private final CarrierNetworkConfig mCarrierNetworkConfig;
6570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
6670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    // Cached wificond binder handlers.
6770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private IWificond mWificond;
6870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private IClientInterface mClientInterface;
6970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private IApInterface mApInterface;
708631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    private IWifiScannerImpl mWificondScanner;
7170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private IScanEvent mScanEventHandler;
7204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    private IPnoScanEvent mPnoScanEventHandler;
7370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
7470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private String mClientInterfaceName;
7570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
7670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
7770a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private class ScanEventHandler extends IScanEvent.Stub {
7870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        @Override
7970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        public void OnScanResultReady() {
8070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            Log.d(TAG, "Scan result ready event");
8170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mWifiMonitor.broadcastScanResultEvent(mClientInterfaceName);
8270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        }
8370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
8470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        @Override
8570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        public void OnScanFailed() {
8670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            Log.d(TAG, "Scan failed event");
8770a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mWifiMonitor.broadcastScanFailedEvent(mClientInterfaceName);
8870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        }
8970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    }
9070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
914eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu    WificondControl(WifiInjector wifiInjector, WifiMonitor wifiMonitor,
924eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu            CarrierNetworkConfig carrierNetworkConfig) {
9370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mWifiInjector = wifiInjector;
9470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        mWifiMonitor = wifiMonitor;
954eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu        mCarrierNetworkConfig = carrierNetworkConfig;
9670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
9770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
9804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    private class PnoScanEventHandler extends IPnoScanEvent.Stub {
9904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        @Override
10004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        public void OnPnoNetworkFound() {
10104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.d(TAG, "Pno scan result event");
10251493e199ebf1e1191ccf652f0081d229018a11fNingyuan Wang            mWifiMonitor.broadcastPnoScanResultEvent(mClientInterfaceName);
103a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoFoundNetworkEventCount();
10404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
10504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
10604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        @Override
10704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        public void OnPnoScanFailed() {
10804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.d(TAG, "Pno Scan failed event");
109a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
11004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
11185c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao
11285c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        @Override
11385c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        public void OnPnoScanOverOffloadStarted() {
11485c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao            Log.d(TAG, "Pno scan over offload started");
115a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanStartedOverOffloadCount();
11685c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        }
11785c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao
11885c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        @Override
11985c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        public void OnPnoScanOverOffloadFailed(int reason) {
12085c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao            Log.d(TAG, "Pno scan over offload failed");
121a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanFailedOverOffloadCount();
12285c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        }
12304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
12404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
1252e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    /** Enable or disable verbose logging of WificondControl.
1262e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang     *  @param enable True to enable verbose logging. False to disable verbose logging.
1272e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang     */
1282e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    public void enableVerboseLogging(boolean enable) {
1292e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        mVerboseLoggingEnabled = enable;
1302e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    }
1312e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
13270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
13370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Setup driver for client mode via wificond.
13470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IClientInterface as wificond client interface binder handler.
13570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
13670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
137c7685b40d77b12820c5b04013592834025086cefRoshan Pius    public IClientInterface setupDriverForClientMode(@NonNull String ifaceName) {
138512ba9008e5b9ab4019647eb036c303a6bb9e0ceNingyuan Wang        Log.d(TAG, "Setting up driver for client mode");
13970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mWificond = mWifiInjector.makeWificond();
14070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (mWificond == null) {
14170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get reference to wificond");
14270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
14370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
14470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
14570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IClientInterface clientInterface = null;
14670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
147c7685b40d77b12820c5b04013592834025086cefRoshan Pius            clientInterface = mWificond.createClientInterface(ifaceName);
14870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
14970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IClientInterface due to remote exception");
15070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
15170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
15270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
15370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (clientInterface == null) {
15470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IClientInterface instance from wificond");
15570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
15670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
15770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(clientInterface.asBinder());
15870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
15970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
16070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mClientInterface = clientInterface;
1618631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
16270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mClientInterfaceName = clientInterface.getInterfaceName();
1638631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            mWificondScanner = mClientInterface.getWifiScannerImpl();
164bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            if (mWificondScanner == null) {
165bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                Log.e(TAG, "Failed to get WificondScannerImpl");
166bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                return null;
167bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            }
168bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            Binder.allowBlocking(mWificondScanner.asBinder());
16970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mScanEventHandler = new ScanEventHandler();
17070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mWificondScanner.subscribeScanEvents(mScanEventHandler);
17104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            mPnoScanEventHandler = new PnoScanEventHandler();
17204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            mWificondScanner.subscribePnoScanEvents(mPnoScanEventHandler);
1738631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e) {
1748631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to refresh wificond scanner due to remote exception");
1758631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
17670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
17770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return clientInterface;
17870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
17970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
18070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
18170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Setup driver for softAp mode via wificond.
18270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IApInterface as wificond Ap interface binder handler.
18370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
18470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
185c7685b40d77b12820c5b04013592834025086cefRoshan Pius    public IApInterface setupDriverForSoftApMode(@NonNull String ifaceName) {
186512ba9008e5b9ab4019647eb036c303a6bb9e0ceNingyuan Wang        Log.d(TAG, "Setting up driver for soft ap mode");
18770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mWificond = mWifiInjector.makeWificond();
18870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (mWificond == null) {
18970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get reference to wificond");
19070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
19170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
19270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
19370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IApInterface apInterface = null;
19470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
195c7685b40d77b12820c5b04013592834025086cefRoshan Pius            apInterface = mWificond.createApInterface(ifaceName);
19670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
19770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IApInterface due to remote exception");
19870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
19970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
20070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
20170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (apInterface == null) {
20270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IApInterface instance from wificond");
20370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
20470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
20570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(apInterface.asBinder());
20670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
20770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
20870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mApInterface = apInterface;
20970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
21070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return apInterface;
21170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
21270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
21370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
21470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Teardown all interfaces configured in wificond.
21570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
21670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
21770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean tearDownInterfaces() {
218512ba9008e5b9ab4019647eb036c303a6bb9e0ceNingyuan Wang        Log.d(TAG, "tearing down interfaces in wificond");
21970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Explicitly refresh the wificodn handler because |tearDownInterfaces()|
22070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // could be used to cleanup before we setup any interfaces.
22170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mWificond = mWifiInjector.makeWificond();
22270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (mWificond == null) {
22370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get reference to wificond");
22470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
22570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
22670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
22770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
22870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            if (mWificondScanner != null) {
22970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang                mWificondScanner.unsubscribeScanEvents();
23004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                mWificondScanner.unsubscribePnoScanEvents();
23170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            }
23270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            mWificond.tearDownInterfaces();
23370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
23470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            // Refresh handlers
23570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mClientInterface = null;
23670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mWificondScanner = null;
23704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            mPnoScanEventHandler = null;
23870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mScanEventHandler = null;
23970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mApInterface = null;
24070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
24170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return true;
24270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
24370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to tear down interfaces due to remote exception");
24470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
24570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
24670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
24770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
24870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
24970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
25070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Disable wpa_supplicant via wificond.
25170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
25270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
25370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean disableSupplicant() {
25470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (mClientInterface == null) {
25570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
25670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
25770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
25870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
25970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return mClientInterface.disableSupplicant();
26070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
26170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to disable supplicant due to remote exception");
26270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
26370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
26470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
26570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
26670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
26770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Enable wpa_supplicant via wificond.
26870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
26970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
27070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean enableSupplicant() {
27170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (mClientInterface == null) {
27270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
27370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
27470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
27570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
27670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
27770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return mClientInterface.enableSupplicant();
27870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
27970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to enable supplicant due to remote exception");
28070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
28170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
28270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
283d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
284d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
285d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Request signal polling to wificond.
286d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns an SignalPollResult object.
287d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns null on failure.
288d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    */
289d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    public WifiNative.SignalPollResult signalPoll() {
290d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        if (mClientInterface == null) {
291d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
292d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
293d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
294d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
295d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
296d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
297d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            resultArray = mClientInterface.signalPoll();
298d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 3) {
299d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
300d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
301d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
302d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
3032e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
304d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
305d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
306d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.SignalPollResult pollResult = new WifiNative.SignalPollResult();
307d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.currentRssi = resultArray[0];
308d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.txBitrate = resultArray[1];
309d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.associationFrequency = resultArray[2];
310d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return pollResult;
311d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
312d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
313d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
314d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Fetch TX packet counters on current connection from wificond.
315d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns an TxPacketCounters object.
316d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns null on failure.
317d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    */
318d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    public WifiNative.TxPacketCounters getTxPacketCounters() {
319d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        if (mClientInterface == null) {
320d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
321d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
322d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
323d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
324d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
325d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
326d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            resultArray = mClientInterface.getPacketCounters();
327d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 2) {
328d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
329d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
330d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
331d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
3322e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
333d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
334d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
335d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.TxPacketCounters counters = new WifiNative.TxPacketCounters();
336d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txSucceeded = resultArray[0];
337d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txFailed = resultArray[1];
338d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return counters;
339d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
3408631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
3418631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    /**
3428631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Fetch the latest scan result from kernel via wificond.
3438631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * @return Returns an ArrayList of ScanDetail.
3448631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Returns an empty ArrayList on failure.
3458631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    */
34671c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    public ArrayList<ScanDetail> getScanResults(int scanType) {
3478631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        ArrayList<ScanDetail> results = new ArrayList<>();
3488631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        if (mWificondScanner == null) {
3498631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
3508631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            return results;
3518631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
3528631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
35371c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            NativeScanResult[] nativeResults;
35471c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            if (scanType == SCAN_TYPE_SINGLE_SCAN) {
35571c4c2a898a827a867564159ce78e41aedd2295bSohani Rao                nativeResults = mWificondScanner.getScanResults();
35671c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            } else {
35771c4c2a898a827a867564159ce78e41aedd2295bSohani Rao                nativeResults = mWificondScanner.getPnoScanResults();
35871c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            }
3598631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            for (NativeScanResult result : nativeResults) {
360755bbe962c20d37491dd9264ad3497bf27e33602Ningyuan Wang                WifiSsid wifiSsid = WifiSsid.createFromByteArray(result.ssid);
3618ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                String bssid;
3628ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
3638ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    bssid = NativeUtil.macAddressFromByteArray(result.bssid);
3648ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
3658ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + result.bssid, e);
3668ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
3678ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
3688ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                if (bssid == null) {
3698ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal null bssid");
3708ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
3718ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
3728631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanResult.InformationElement[] ies =
3738631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        InformationElementUtil.parseInformationElements(result.infoElement);
3748631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                InformationElementUtil.Capabilities capabilities =
3758631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        new InformationElementUtil.Capabilities();
3768631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                capabilities.from(ies, result.capability);
3778631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                String flags = capabilities.generateCapabilitiesString();
3788631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                NetworkDetail networkDetail =
3798631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        new NetworkDetail(bssid, ies, null, result.frequency);
3808631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
3818631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanDetail scanDetail = new ScanDetail(networkDetail, wifiSsid, bssid, flags,
3828631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        result.signalMbm / 100, result.frequency, result.tsf, ies, null);
3834eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // Update carrier network info if this AP's SSID is associated with a carrier Wi-Fi
3844eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // network and it uses EAP.
3854eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                if (ScanResultUtil.isScanResultForEapNetwork(scanDetail.getScanResult())
3864eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                        && mCarrierNetworkConfig.isCarrierNetwork(wifiSsid.toString())) {
3874eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().isCarrierAp = true;
3884eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().carrierApEapType =
3894eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getNetworkEapType(wifiSsid.toString());
3904eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().carrierName =
3914eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getCarrierName(wifiSsid.toString());
3924eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                }
3938631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                results.add(scanDetail);
3948631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            }
3958631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e1) {
3968631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to create ScanDetail ArrayList");
3978631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
3982e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        if (mVerboseLoggingEnabled) {
3992e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.d(TAG, "get " + results.size() + " scan results from wificond");
4002e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        }
4012e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
4028631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        return results;
4038631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    }
404e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
405e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    /**
406e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * Start a scan using wificond for the given parameters.
407e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param freqs list of frequencies to scan for, if null scan all supported channels.
408e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
409e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @return Returns true on success.
410e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     */
411e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    public boolean scan(Set<Integer> freqs, Set<String> hiddenNetworkSSIDs) {
412e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (mWificondScanner == null) {
413e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
414e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            return false;
415e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
416e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        SingleScanSettings settings = new SingleScanSettings();
417e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.channelSettings  = new ArrayList<>();
418e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.hiddenNetworks  = new ArrayList<>();
419e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
420e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (freqs != null) {
421e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (Integer freq : freqs) {
422e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                ChannelSettings channel = new ChannelSettings();
423e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                channel.frequency = freq;
424e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.channelSettings.add(channel);
425e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
426e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
427e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (hiddenNetworkSSIDs != null) {
428e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (String ssid : hiddenNetworkSSIDs) {
429e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                HiddenNetwork network = new HiddenNetwork();
4308ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
4318ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    network.ssid = NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssid));
4328ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
4338ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + ssid, e);
4348ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
4358ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
436e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.hiddenNetworks.add(network);
437e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
438e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
439e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
440e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        try {
441e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            return mWificondScanner.scan(settings);
442e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        } catch (RemoteException e1) {
443e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "Failed to request scan due to remote exception");
444e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
445e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        return false;
446e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    }
447e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
44804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
44904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Start PNO scan.
45004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @param pnoSettings Pno scan configuration.
45104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
45204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
45304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    public boolean startPnoScan(WifiNative.PnoSettings pnoSettings) {
45404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (mWificondScanner == null) {
45504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
45604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
45704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
45804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        PnoSettings settings = new PnoSettings();
45904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.pnoNetworks  = new ArrayList<>();
46004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.intervalMs = pnoSettings.periodInMs;
46104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min2gRssi = pnoSettings.min24GHzRssi;
46204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min5gRssi = pnoSettings.min5GHzRssi;
46304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (pnoSettings.networkList != null) {
46404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            for (WifiNative.PnoNetwork network : pnoSettings.networkList) {
46504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                PnoNetwork condNetwork = new PnoNetwork();
46604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                condNetwork.isHidden = (network.flags
46704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                        & WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN) != 0;
4688ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
4698ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    condNetwork.ssid =
4708ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                            NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(network.ssid));
4718ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
4728ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + network.ssid, e);
4738ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
4748ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
47504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                settings.pnoNetworks.add(condNetwork);
47604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            }
47704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
47804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
47904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
480a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            boolean success = mWificondScanner.startPnoScan(settings);
481a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanStartAttempCount();
482a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            if (!success) {
483a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh                mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
484a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            }
485a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            return success;
48604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
487a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            Log.e(TAG, "Failed to start pno scan due to remote exception");
48804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
48904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
49004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
49104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
49204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
49304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Stop PNO scan.
49404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
49504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
49604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    public boolean stopPnoScan() {
49704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (mWificondScanner == null) {
49804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
49904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
50004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
50104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
50204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return mWificondScanner.stopPnoScan();
50304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
50404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "Failed to stop pno scan due to remote exception");
50504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
50604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
50704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
50804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
509c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    /**
510c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     * Abort ongoing single scan.
511c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     */
512c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    public void abortScan() {
513c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        if (mWificondScanner == null) {
514c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
515c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            return;
516c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
517c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        try {
518c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            mWificondScanner.abortScan();
519c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        } catch (RemoteException e1) {
520c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "Failed to request abortScan due to remote exception");
521c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
522c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    }
523c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang
52470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang}
525