WificondControl.java revision 0a6b9c1199f91790606acc70c771548f079fa8f0
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
1970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IApInterface;
2070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IClientInterface;
2104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport android.net.wifi.IPnoScanEvent;
2270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wangimport android.net.wifi.IScanEvent;
238631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.IWifiScannerImpl;
2470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IWificond;
258631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.ScanResult;
2604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport android.net.wifi.WifiScanner;
278631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.WifiSsid;
2870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.os.Binder;
2970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.os.RemoteException;
3070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.util.Log;
3170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
328631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.hotspot2.NetworkDetail;
338631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.util.InformationElementUtil;
34f4b53ff21ce0aa25131222d0cd15cc4a5e8c0c4fNingyuan Wangimport com.android.server.wifi.util.NativeUtil;
354eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiuimport com.android.server.wifi.util.ScanResultUtil;
36e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.ChannelSettings;
37e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.HiddenNetwork;
388631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.wificond.NativeScanResult;
3904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport com.android.server.wifi.wificond.PnoNetwork;
4004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport com.android.server.wifi.wificond.PnoSettings;
41e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.SingleScanSettings;
428631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
438631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport java.util.ArrayList;
44e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport java.util.Set;
458631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
4670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang/**
4770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * This class provides methods for WifiNative to send control commands to wificond.
4870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * NOTE: This class should only be used from WifiNative.
4970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang */
5070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangpublic class WificondControl {
512e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    private boolean mVerboseLoggingEnabled = false;
5270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
5370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private static final String TAG = "WificondControl";
5471c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
5571c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    /* Get scan results for a single scan */
5671c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    public static final int SCAN_TYPE_SINGLE_SCAN = 0;
5771c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
5871c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    /* Get scan results for Pno Scan */
5971c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    public static final int SCAN_TYPE_PNO_SCAN = 1;
6071c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
6170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private WifiInjector mWifiInjector;
6270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private WifiMonitor mWifiMonitor;
634eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu    private final CarrierNetworkConfig mCarrierNetworkConfig;
6470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
6570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    // Cached wificond binder handlers.
6670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private IWificond mWificond;
6770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private IClientInterface mClientInterface;
6870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private IApInterface mApInterface;
698631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    private IWifiScannerImpl mWificondScanner;
7070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private IScanEvent mScanEventHandler;
7104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    private IPnoScanEvent mPnoScanEventHandler;
7270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
7370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private String mClientInterfaceName;
7470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
7570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
7670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private class ScanEventHandler extends IScanEvent.Stub {
7770a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        @Override
7870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        public void OnScanResultReady() {
7970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            Log.d(TAG, "Scan result ready event");
8070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mWifiMonitor.broadcastScanResultEvent(mClientInterfaceName);
8170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        }
8270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
8370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        @Override
8470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        public void OnScanFailed() {
8570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            Log.d(TAG, "Scan failed event");
8670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mWifiMonitor.broadcastScanFailedEvent(mClientInterfaceName);
8770a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        }
8870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    }
8970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
904eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu    WificondControl(WifiInjector wifiInjector, WifiMonitor wifiMonitor,
914eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu            CarrierNetworkConfig carrierNetworkConfig) {
9270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mWifiInjector = wifiInjector;
9370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        mWifiMonitor = wifiMonitor;
944eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu        mCarrierNetworkConfig = carrierNetworkConfig;
9570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
9670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
9704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    private class PnoScanEventHandler extends IPnoScanEvent.Stub {
9804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        @Override
9904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        public void OnPnoNetworkFound() {
10004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.d(TAG, "Pno scan result event");
10151493e199ebf1e1191ccf652f0081d229018a11fNingyuan Wang            mWifiMonitor.broadcastPnoScanResultEvent(mClientInterfaceName);
102a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoFoundNetworkEventCount();
10304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
10404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
10504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        @Override
10604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        public void OnPnoScanFailed() {
10704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.d(TAG, "Pno Scan failed event");
108a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
10904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
11085c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao
11185c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        @Override
11285c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        public void OnPnoScanOverOffloadStarted() {
11385c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao            Log.d(TAG, "Pno scan over offload started");
114a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanStartedOverOffloadCount();
11585c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        }
11685c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao
11785c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        @Override
11885c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        public void OnPnoScanOverOffloadFailed(int reason) {
11985c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao            Log.d(TAG, "Pno scan over offload failed");
120a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanFailedOverOffloadCount();
12185c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        }
12204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
12304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
1242e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    /** Enable or disable verbose logging of WificondControl.
1252e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang     *  @param enable True to enable verbose logging. False to disable verbose logging.
1262e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang     */
1272e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    public void enableVerboseLogging(boolean enable) {
1282e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        mVerboseLoggingEnabled = enable;
1292e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    }
1302e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
13170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
13270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Setup driver for client mode via wificond.
13370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IClientInterface as wificond client interface binder handler.
13470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
13570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
13670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public IClientInterface setupDriverForClientMode() {
137512ba9008e5b9ab4019647eb036c303a6bb9e0ceNingyuan Wang        Log.d(TAG, "Setting up driver for client mode");
13870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mWificond = mWifiInjector.makeWificond();
13970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (mWificond == null) {
14070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get reference to wificond");
14170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
14270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
14370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
14470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IClientInterface clientInterface = null;
14570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
14670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            clientInterface = mWificond.createClientInterface();
14770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
14870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IClientInterface due to remote exception");
14970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
15070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
15170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
15270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (clientInterface == null) {
15370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IClientInterface instance from wificond");
15470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
15570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
15670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(clientInterface.asBinder());
15770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
15870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
15970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mClientInterface = clientInterface;
1608631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
16170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mClientInterfaceName = clientInterface.getInterfaceName();
1628631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            mWificondScanner = mClientInterface.getWifiScannerImpl();
163bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            if (mWificondScanner == null) {
164bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                Log.e(TAG, "Failed to get WificondScannerImpl");
165bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                return null;
166bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            }
167bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            Binder.allowBlocking(mWificondScanner.asBinder());
16870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mScanEventHandler = new ScanEventHandler();
16970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mWificondScanner.subscribeScanEvents(mScanEventHandler);
17004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            mPnoScanEventHandler = new PnoScanEventHandler();
17104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            mWificondScanner.subscribePnoScanEvents(mPnoScanEventHandler);
1728631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e) {
1738631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to refresh wificond scanner due to remote exception");
1748631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
17570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
17670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return clientInterface;
17770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
17870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
17970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
18070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Setup driver for softAp mode via wificond.
18170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IApInterface as wificond Ap interface binder handler.
18270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
18370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
18470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public IApInterface setupDriverForSoftApMode() {
185512ba9008e5b9ab4019647eb036c303a6bb9e0ceNingyuan Wang        Log.d(TAG, "Setting up driver for soft ap mode");
18670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mWificond = mWifiInjector.makeWificond();
18770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (mWificond == null) {
18870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get reference to wificond");
18970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
19070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
19170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
19270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IApInterface apInterface = null;
19370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
19470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            apInterface = mWificond.createApInterface();
19570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
19670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IApInterface due to remote exception");
19770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
19870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
19970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
20070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (apInterface == null) {
20170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IApInterface instance from wificond");
20270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
20370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
20470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(apInterface.asBinder());
20570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
20670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
20770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mApInterface = apInterface;
20870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
20970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return apInterface;
21070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
21170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
21270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
21370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Teardown all interfaces configured in wificond.
21470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
21570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
21670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean tearDownInterfaces() {
217512ba9008e5b9ab4019647eb036c303a6bb9e0ceNingyuan Wang        Log.d(TAG, "tearing down interfaces in wificond");
21870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Explicitly refresh the wificodn handler because |tearDownInterfaces()|
21970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // could be used to cleanup before we setup any interfaces.
22070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mWificond = mWifiInjector.makeWificond();
22170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (mWificond == null) {
22270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get reference to wificond");
22370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
22470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
22570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
22670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
22770a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            if (mWificondScanner != null) {
22870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang                mWificondScanner.unsubscribeScanEvents();
22904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                mWificondScanner.unsubscribePnoScanEvents();
23070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            }
23170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            mWificond.tearDownInterfaces();
23270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
23370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            // Refresh handlers
23470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mClientInterface = null;
23570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mWificondScanner = null;
23604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            mPnoScanEventHandler = null;
23770a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mScanEventHandler = null;
23870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mApInterface = null;
23970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
24070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return true;
24170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
24270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to tear down interfaces due to remote exception");
24370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
24470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
24570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
24670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
24770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
24870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
24970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Disable wpa_supplicant via wificond.
25070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
25170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
25270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean disableSupplicant() {
25370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (mClientInterface == null) {
25470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
25570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
25670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
25770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
25870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return mClientInterface.disableSupplicant();
25970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
26070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to disable supplicant due to remote exception");
26170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
26270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
26370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
26470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
26570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
26670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Enable wpa_supplicant via wificond.
26770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
26870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
26970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean enableSupplicant() {
27070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (mClientInterface == null) {
27170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
27270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
27370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
27470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
27570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
27670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return mClientInterface.enableSupplicant();
27770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
27870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to enable supplicant due to remote exception");
27970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
28070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
28170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
282d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
283d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
284d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Request signal polling to wificond.
285d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns an SignalPollResult object.
286d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns null on failure.
287d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    */
288d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    public WifiNative.SignalPollResult signalPoll() {
289d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        if (mClientInterface == null) {
290d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
291d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
292d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
293d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
294d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
295d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
296d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            resultArray = mClientInterface.signalPoll();
297d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 3) {
298d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
299d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
300d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
301d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
3022e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
303d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
304d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
305d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.SignalPollResult pollResult = new WifiNative.SignalPollResult();
306d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.currentRssi = resultArray[0];
307d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.txBitrate = resultArray[1];
308d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.associationFrequency = resultArray[2];
309d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return pollResult;
310d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
311d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
312d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
313d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Fetch TX packet counters on current connection from wificond.
314d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns an TxPacketCounters object.
315d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns null on failure.
316d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    */
317d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    public WifiNative.TxPacketCounters getTxPacketCounters() {
318d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        if (mClientInterface == null) {
319d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
320d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
321d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
322d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
323d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
324d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
325d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            resultArray = mClientInterface.getPacketCounters();
326d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 2) {
327d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
328d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
329d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
330d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
3312e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
332d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
333d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
334d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.TxPacketCounters counters = new WifiNative.TxPacketCounters();
335d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txSucceeded = resultArray[0];
336d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txFailed = resultArray[1];
337d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return counters;
338d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
3398631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
3408631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    /**
3418631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Fetch the latest scan result from kernel via wificond.
3428631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * @return Returns an ArrayList of ScanDetail.
3438631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Returns an empty ArrayList on failure.
3448631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    */
34571c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    public ArrayList<ScanDetail> getScanResults(int scanType) {
3468631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        ArrayList<ScanDetail> results = new ArrayList<>();
3478631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        if (mWificondScanner == null) {
3488631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
3498631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            return results;
3508631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
3518631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
35271c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            NativeScanResult[] nativeResults;
35371c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            if (scanType == SCAN_TYPE_SINGLE_SCAN) {
35471c4c2a898a827a867564159ce78e41aedd2295bSohani Rao                nativeResults = mWificondScanner.getScanResults();
35571c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            } else {
35671c4c2a898a827a867564159ce78e41aedd2295bSohani Rao                nativeResults = mWificondScanner.getPnoScanResults();
35771c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            }
3588631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            for (NativeScanResult result : nativeResults) {
359755bbe962c20d37491dd9264ad3497bf27e33602Ningyuan Wang                WifiSsid wifiSsid = WifiSsid.createFromByteArray(result.ssid);
3608ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                String bssid;
3618ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
3628ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    bssid = NativeUtil.macAddressFromByteArray(result.bssid);
3638ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
3648ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + result.bssid, e);
3658ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
3668ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
3678ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                if (bssid == null) {
3688ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal null bssid");
3698ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
3708ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
3718631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanResult.InformationElement[] ies =
3728631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        InformationElementUtil.parseInformationElements(result.infoElement);
3738631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                InformationElementUtil.Capabilities capabilities =
3748631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        new InformationElementUtil.Capabilities();
3758631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                capabilities.from(ies, result.capability);
3768631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                String flags = capabilities.generateCapabilitiesString();
3770a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                NetworkDetail networkDetail;
3780a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                try {
3790a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    networkDetail = new NetworkDetail(bssid, ies, null, result.frequency);
3800a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                } catch (IllegalArgumentException e) {
3810a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    Log.e(TAG, "Illegal argument for scan result with bssid: " + bssid, e);
3820a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    continue;
3830a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                }
3848631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
3858631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanDetail scanDetail = new ScanDetail(networkDetail, wifiSsid, bssid, flags,
3868631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        result.signalMbm / 100, result.frequency, result.tsf, ies, null);
3874eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // Update carrier network info if this AP's SSID is associated with a carrier Wi-Fi
3884eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // network and it uses EAP.
3894eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                if (ScanResultUtil.isScanResultForEapNetwork(scanDetail.getScanResult())
3904eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                        && mCarrierNetworkConfig.isCarrierNetwork(wifiSsid.toString())) {
3914eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().isCarrierAp = true;
3924eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().carrierApEapType =
3934eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getNetworkEapType(wifiSsid.toString());
3944eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().carrierName =
3954eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getCarrierName(wifiSsid.toString());
3964eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                }
3978631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                results.add(scanDetail);
3988631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            }
3998631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e1) {
4008631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to create ScanDetail ArrayList");
4018631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
4022e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        if (mVerboseLoggingEnabled) {
4032e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.d(TAG, "get " + results.size() + " scan results from wificond");
4042e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        }
4052e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
4068631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        return results;
4078631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    }
408e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
409e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    /**
410e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * Start a scan using wificond for the given parameters.
411e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param freqs list of frequencies to scan for, if null scan all supported channels.
412e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
413e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @return Returns true on success.
414e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     */
415e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    public boolean scan(Set<Integer> freqs, Set<String> hiddenNetworkSSIDs) {
416e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (mWificondScanner == null) {
417e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
418e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            return false;
419e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
420e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        SingleScanSettings settings = new SingleScanSettings();
421e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.channelSettings  = new ArrayList<>();
422e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.hiddenNetworks  = new ArrayList<>();
423e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
424e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (freqs != null) {
425e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (Integer freq : freqs) {
426e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                ChannelSettings channel = new ChannelSettings();
427e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                channel.frequency = freq;
428e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.channelSettings.add(channel);
429e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
430e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
431e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (hiddenNetworkSSIDs != null) {
432e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (String ssid : hiddenNetworkSSIDs) {
433e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                HiddenNetwork network = new HiddenNetwork();
4348ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
4358ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    network.ssid = NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssid));
4368ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
4378ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + ssid, e);
4388ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
4398ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
440e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.hiddenNetworks.add(network);
441e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
442e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
443e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
444e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        try {
445e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            return mWificondScanner.scan(settings);
446e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        } catch (RemoteException e1) {
447e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "Failed to request scan due to remote exception");
448e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
449e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        return false;
450e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    }
451e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
45204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
45304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Start PNO scan.
45404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @param pnoSettings Pno scan configuration.
45504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
45604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
45704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    public boolean startPnoScan(WifiNative.PnoSettings pnoSettings) {
45804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (mWificondScanner == null) {
45904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
46004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
46104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
46204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        PnoSettings settings = new PnoSettings();
46304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.pnoNetworks  = new ArrayList<>();
46404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.intervalMs = pnoSettings.periodInMs;
46504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min2gRssi = pnoSettings.min24GHzRssi;
46604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min5gRssi = pnoSettings.min5GHzRssi;
46704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (pnoSettings.networkList != null) {
46804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            for (WifiNative.PnoNetwork network : pnoSettings.networkList) {
46904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                PnoNetwork condNetwork = new PnoNetwork();
47004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                condNetwork.isHidden = (network.flags
47104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                        & WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN) != 0;
4728ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
4738ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    condNetwork.ssid =
4748ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                            NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(network.ssid));
4758ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
4768ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + network.ssid, e);
4778ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
4788ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
47904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                settings.pnoNetworks.add(condNetwork);
48004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            }
48104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
48204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
48304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
484a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            boolean success = mWificondScanner.startPnoScan(settings);
485a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanStartAttempCount();
486a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            if (!success) {
487a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh                mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
488a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            }
489a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            return success;
49004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
491a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            Log.e(TAG, "Failed to start pno scan due to remote exception");
49204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
49304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
49404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
49504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
49604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
49704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Stop PNO scan.
49804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
49904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
50004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    public boolean stopPnoScan() {
50104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (mWificondScanner == null) {
50204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
50304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
50404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
50504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
50604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return mWificondScanner.stopPnoScan();
50704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
50804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "Failed to stop pno scan due to remote exception");
50904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
51004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
51104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
51204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
513c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    /**
514c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     * Abort ongoing single scan.
515c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     */
516c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    public void abortScan() {
517c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        if (mWificondScanner == null) {
518c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
519c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            return;
520c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
521c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        try {
522c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            mWificondScanner.abortScan();
523c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        } catch (RemoteException e1) {
524c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "Failed to request abortScan due to remote exception");
525c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
526c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    }
527c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang
52870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang}
529