WificondControl.java revision 7065d8fb5b3b814d9f15d053b3a30f4543164bae
170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang/*
270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * Copyright (C) 2017 The Android Open Source Project
370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang *
470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * Licensed under the Apache License, Version 2.0 (the "License");
570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * you may not use this file except in compliance with the License.
670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * You may obtain a copy of the License at
770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang *
870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang *      http://www.apache.org/licenses/LICENSE-2.0
970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang *
1070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * Unless required by applicable law or agreed to in writing, software
1170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * distributed under the License is distributed on an "AS IS" BASIS,
1270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * See the License for the specific language governing permissions and
1470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * limitations under the License.
1570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang */
1670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
1770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangpackage com.android.server.wifi;
1870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
19c7685b40d77b12820c5b04013592834025086cefRoshan Piusimport android.annotation.NonNull;
2070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IApInterface;
21045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Piusimport android.net.wifi.IApInterfaceEventCallback;
2270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IClientInterface;
2304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport android.net.wifi.IPnoScanEvent;
2470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wangimport android.net.wifi.IScanEvent;
258631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.IWifiScannerImpl;
2670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.net.wifi.IWificond;
278631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.ScanResult;
28045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Piusimport android.net.wifi.WifiConfiguration;
2904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport android.net.wifi.WifiScanner;
308631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport android.net.wifi.WifiSsid;
3170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.os.Binder;
3255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Piusimport android.os.IBinder;
3370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.os.RemoteException;
3470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wangimport android.util.Log;
3570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
36045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Piusimport com.android.server.wifi.WifiNative.SoftApListener;
378631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.hotspot2.NetworkDetail;
388631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.util.InformationElementUtil;
39f4b53ff21ce0aa25131222d0cd15cc4a5e8c0c4fNingyuan Wangimport com.android.server.wifi.util.NativeUtil;
404eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiuimport com.android.server.wifi.util.ScanResultUtil;
41e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.ChannelSettings;
42e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.HiddenNetwork;
438631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport com.android.server.wifi.wificond.NativeScanResult;
4404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport com.android.server.wifi.wificond.PnoNetwork;
4504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wangimport com.android.server.wifi.wificond.PnoSettings;
46e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport com.android.server.wifi.wificond.SingleScanSettings;
478631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
48045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Piusimport java.nio.charset.StandardCharsets;
498631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wangimport java.util.ArrayList;
50e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wangimport java.util.Set;
518631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
5270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang/**
5370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * This class provides methods for WifiNative to send control commands to wificond.
5470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang * NOTE: This class should only be used from WifiNative.
5570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang */
5655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Piuspublic class WificondControl implements IBinder.DeathRecipient {
572e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    private boolean mVerboseLoggingEnabled = false;
5870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
5970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private static final String TAG = "WificondControl";
6071c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
6171c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    /* Get scan results for a single scan */
6271c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    public static final int SCAN_TYPE_SINGLE_SCAN = 0;
6371c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
6471c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    /* Get scan results for Pno Scan */
6571c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    public static final int SCAN_TYPE_PNO_SCAN = 1;
6671c4c2a898a827a867564159ce78e41aedd2295bSohani Rao
6770a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private WifiInjector mWifiInjector;
6870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private WifiMonitor mWifiMonitor;
694eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu    private final CarrierNetworkConfig mCarrierNetworkConfig;
7070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
7170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    // Cached wificond binder handlers.
7270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private IWificond mWificond;
7370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private IClientInterface mClientInterface;
7470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    private IApInterface mApInterface;
758631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    private IWifiScannerImpl mWificondScanner;
7670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private IScanEvent mScanEventHandler;
7704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    private IPnoScanEvent mPnoScanEventHandler;
78045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    private IApInterfaceEventCallback mApInterfaceListener;
7955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    private WifiNative.WificondDeathEventHandler mDeathEventHandler;
8070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
8170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private String mClientInterfaceName;
8270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
8370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
8470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    private class ScanEventHandler extends IScanEvent.Stub {
8570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        @Override
8670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        public void OnScanResultReady() {
8770a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            Log.d(TAG, "Scan result ready event");
8870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mWifiMonitor.broadcastScanResultEvent(mClientInterfaceName);
8970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        }
9070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
9170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        @Override
9270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        public void OnScanFailed() {
9370a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            Log.d(TAG, "Scan failed event");
9470a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mWifiMonitor.broadcastScanFailedEvent(mClientInterfaceName);
9570a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        }
9670a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang    }
9770a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
984eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu    WificondControl(WifiInjector wifiInjector, WifiMonitor wifiMonitor,
994eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu            CarrierNetworkConfig carrierNetworkConfig) {
10070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mWifiInjector = wifiInjector;
10170a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang        mWifiMonitor = wifiMonitor;
1024eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu        mCarrierNetworkConfig = carrierNetworkConfig;
10370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
10470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
10504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    private class PnoScanEventHandler extends IPnoScanEvent.Stub {
10604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        @Override
10704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        public void OnPnoNetworkFound() {
10804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.d(TAG, "Pno scan result event");
10951493e199ebf1e1191ccf652f0081d229018a11fNingyuan Wang            mWifiMonitor.broadcastPnoScanResultEvent(mClientInterfaceName);
110a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoFoundNetworkEventCount();
11104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
11204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
11304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        @Override
11404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        public void OnPnoScanFailed() {
11504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.d(TAG, "Pno Scan failed event");
116a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
11704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
11885c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao
11985c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        @Override
12085c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        public void OnPnoScanOverOffloadStarted() {
12185c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao            Log.d(TAG, "Pno scan over offload started");
122a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanStartedOverOffloadCount();
12385c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        }
12485c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao
12585c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        @Override
12685c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        public void OnPnoScanOverOffloadFailed(int reason) {
12785c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao            Log.d(TAG, "Pno scan over offload failed");
128a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanFailedOverOffloadCount();
12985c806c0d32bb30f421ebc372a59b2f3ea2dce41Sohani Rao        }
13004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
13104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
132045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
133045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * Listener for AP Interface events.
134045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
135045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    private class ApInterfaceEventCallback extends IApInterfaceEventCallback.Stub {
136045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        private SoftApListener mSoftApListener;
137045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
138045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        ApInterfaceEventCallback(SoftApListener listener) {
139045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            mSoftApListener = listener;
140045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
141045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
142045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        @Override
143045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        public void onNumAssociatedStationsChanged(int numStations) {
144045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            mSoftApListener.onNumAssociatedStationsChanged(numStations);
145045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
146045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
147045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
14855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
14955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Called by the binder subsystem upon remote object death.
15055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Invoke all the register death handlers and clear state.
15155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
15255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    @Override
15355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    public void binderDied() {
15455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        Log.e(TAG, "Wificond died!");
15555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mDeathEventHandler != null) {
15655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            mDeathEventHandler.onDeath();
15755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
15855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        clearState();
15955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        // Invalidate the global wificond handle on death. Will be refereshed
16055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        // on the next setup call.
16155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mWificond = null;
16255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
16355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
1642e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    /** Enable or disable verbose logging of WificondControl.
1652e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang     *  @param enable True to enable verbose logging. False to disable verbose logging.
1662e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang     */
1672e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    public void enableVerboseLogging(boolean enable) {
1682e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        mVerboseLoggingEnabled = enable;
1692e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang    }
1702e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
17170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
17255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Registers a death notification for wificond.
17355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * @return Returns true on success.
17455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
17555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    public boolean registerDeathHandler(@NonNull WifiNative.WificondDeathEventHandler handler) {
17655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mDeathEventHandler != null) {
17755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Death handler already present");
17855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
17955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
18055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mDeathEventHandler = handler;
18155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        return true;
18255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
18355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
18455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
18555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Deregisters a death notification for wificond.
18655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * @return Returns true on success.
18755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
18855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    public boolean deregisterDeathHandler() {
18955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mDeathEventHandler == null) {
19055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "No Death handler present");
19155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
19255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
19355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mDeathEventHandler = null;
19455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        return true;
19555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
19655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
19755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
19855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Helper method to retrieve the global wificond handle and register for
19955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * death notifications.
20055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
20155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    private boolean retrieveWificondAndRegisterForDeath() {
20255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mWificond != null) {
20355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.d(TAG, "Wificond handle already retrieved");
20455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            // We already have a wificond handle.
20555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return true;
20655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
20755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mWificond = mWifiInjector.makeWificond();
20855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (mWificond == null) {
20955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Failed to get reference to wificond");
21055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
21155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
21255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        try {
21355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            mWificond.asBinder().linkToDeath(this, 0);
21455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        } catch (RemoteException e) {
21555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            Log.e(TAG, "Failed to register death notification for wificond");
21655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            // The remote has already died.
21755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            return false;
21855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        }
21955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        return true;
22055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
22155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
22255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
2237065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    * Setup interface for client mode via wificond.
22470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IClientInterface as wificond client interface binder handler.
22570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
22670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
2277065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public IClientInterface setupInterfaceForClientMode(@NonNull String ifaceName) {
2287065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        Log.d(TAG, "Setting up interface for client mode");
22955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
23070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
23170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
23270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
23370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IClientInterface clientInterface = null;
23470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
235c7685b40d77b12820c5b04013592834025086cefRoshan Pius            clientInterface = mWificond.createClientInterface(ifaceName);
23670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
23770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IClientInterface due to remote exception");
23870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
23970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
24070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
24170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (clientInterface == null) {
24270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IClientInterface instance from wificond");
24370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
24470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
24570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(clientInterface.asBinder());
24670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
24770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
24870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mClientInterface = clientInterface;
2498631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
25070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mClientInterfaceName = clientInterface.getInterfaceName();
2518631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            mWificondScanner = mClientInterface.getWifiScannerImpl();
252bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            if (mWificondScanner == null) {
253bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                Log.e(TAG, "Failed to get WificondScannerImpl");
254bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang                return null;
255bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            }
256bb1a2db286601be78d36c9fe747e779d40cd7d6cNingyuan Wang            Binder.allowBlocking(mWificondScanner.asBinder());
25770a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mScanEventHandler = new ScanEventHandler();
25870a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            mWificondScanner.subscribeScanEvents(mScanEventHandler);
25904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            mPnoScanEventHandler = new PnoScanEventHandler();
26004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            mWificondScanner.subscribePnoScanEvents(mPnoScanEventHandler);
2618631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e) {
2628631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to refresh wificond scanner due to remote exception");
2638631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
26470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
26570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return clientInterface;
26670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
26770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
26870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
2697065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * Teardown a specific STA interface configured in wificond.
2707065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     *
2717065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * @return Returns true on success.
2727065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     */
2737065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public boolean tearDownClientInterface(@NonNull String ifaceName) {
2747065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        boolean success;
2757065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
2767065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            if (mWificondScanner != null) {
2777065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius                mWificondScanner.unsubscribeScanEvents();
2787065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius                mWificondScanner.unsubscribePnoScanEvents();
2797065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            }
2807065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e) {
2817065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to unsubscribe wificond scanner due to remote exception");
2827065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
2837065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
2847065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
2857065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
2867065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            success = mWificond.tearDownClientInterface(ifaceName);
2877065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e1) {
2887065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown client interface due to remote exception");
2897065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
2907065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
2917065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        if (!success) {
2927065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown client interface");
2937065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
2947065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
2957065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
2967065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        mClientInterface = null;
2977065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        mWificondScanner = null;
2987065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        mPnoScanEventHandler = null;
2997065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        mScanEventHandler = null;
3007065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        return true;
3017065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    }
3027065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
3037065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    /**
3047065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    * Setup interface for softAp mode via wificond.
30570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return An IApInterface as wificond Ap interface binder handler.
30670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Returns null on failure.
30770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
3087065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public IApInterface setupInterfaceForSoftApMode(@NonNull String ifaceName) {
3097065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        Log.d(TAG, "Setting up interface for soft ap mode");
31055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
31170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
31270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
31370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
31470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        IApInterface apInterface = null;
31570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
316c7685b40d77b12820c5b04013592834025086cefRoshan Pius            apInterface = mWificond.createApInterface(ifaceName);
31770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e1) {
31870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to get IApInterface due to remote exception");
31970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
32070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
32170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
32270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        if (apInterface == null) {
32370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Could not get IApInterface instance from wificond");
32470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return null;
32570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
32670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        Binder.allowBlocking(apInterface.asBinder());
32770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
32870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Refresh Handlers
32970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        mApInterface = apInterface;
33070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
33170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return apInterface;
33270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
33370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
33470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
3357065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * Teardown a specific AP interface configured in wificond.
3367065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     *
3377065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     * @return Returns true on success.
3387065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius     */
3397065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    public boolean tearDownSoftApInterface(@NonNull String ifaceName) {
3407065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        boolean success;
3417065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        try {
3427065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            success = mWificond.tearDownApInterface(ifaceName);
3437065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        } catch (RemoteException e1) {
3447065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown AP interface due to remote exception");
3457065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3467065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3477065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        if (!success) {
3487065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            Log.e(TAG, "Failed to teardown AP interface");
3497065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius            return false;
3507065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        }
3517065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        mApInterface = null;
3527065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        mApInterfaceListener = null;
3537065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        return true;
3547065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    }
3557065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius
3567065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius    /**
35770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Teardown all interfaces configured in wificond.
35870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
35970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
36070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean tearDownInterfaces() {
361512ba9008e5b9ab4019647eb036c303a6bb9e0ceNingyuan Wang        Log.d(TAG, "tearing down interfaces in wificond");
36270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // Explicitly refresh the wificodn handler because |tearDownInterfaces()|
36370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        // could be used to cleanup before we setup any interfaces.
36455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
36570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
36670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
36770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
36870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
36970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            if (mWificondScanner != null) {
37070a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang                mWificondScanner.unsubscribeScanEvents();
37104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                mWificondScanner.unsubscribePnoScanEvents();
37270a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang            }
37370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            mWificond.tearDownInterfaces();
37455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius            clearState();
37570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return true;
37670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
37770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to tear down interfaces due to remote exception");
37870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
37970a9b25ee5d051660b8aeb15ffa97d36a181741dNingyuan Wang
38070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
38170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
38270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
38370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
38470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Disable wpa_supplicant via wificond.
38570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
38670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
38770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean disableSupplicant() {
38855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
38970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
39070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
39170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
3927a9936461744922f7785a192493ccce7c4fb52f9Roshan Pius            return mWificond.disableSupplicant();
39370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
39470603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to disable supplicant due to remote exception");
39570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
39670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
39770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
39870603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang
39970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    /**
40070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * Enable wpa_supplicant via wificond.
40170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    * @return Returns true on success.
40270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    */
40370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    public boolean enableSupplicant() {
40455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        if (!retrieveWificondAndRegisterForDeath()) {
40570603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            return false;
40670603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
40770603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        try {
4087a9936461744922f7785a192493ccce7c4fb52f9Roshan Pius            return mWificond.enableSupplicant();
40970603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        } catch (RemoteException e) {
41070603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang            Log.e(TAG, "Failed to enable supplicant due to remote exception");
41170603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        }
41270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang        return false;
41370603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang    }
414d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
415d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
416d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Request signal polling to wificond.
417d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns an SignalPollResult object.
418d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns null on failure.
419d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    */
420d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    public WifiNative.SignalPollResult signalPoll() {
421d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        if (mClientInterface == null) {
422d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
423d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
424d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
425d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
426d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
427d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
428d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            resultArray = mClientInterface.signalPoll();
429d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 3) {
430d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
431d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
432d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
433d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
4342e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
435d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
436d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
437d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.SignalPollResult pollResult = new WifiNative.SignalPollResult();
438d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.currentRssi = resultArray[0];
439d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.txBitrate = resultArray[1];
440d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        pollResult.associationFrequency = resultArray[2];
441d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return pollResult;
442d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
443d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
444d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    /**
445d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Fetch TX packet counters on current connection from wificond.
446d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns an TxPacketCounters object.
447d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    * Returns null on failure.
448d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    */
449d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    public WifiNative.TxPacketCounters getTxPacketCounters() {
450d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        if (mClientInterface == null) {
451d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            Log.e(TAG, "No valid wificond client interface handler");
452d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
453d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
454d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang
455d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        int[] resultArray;
456d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        try {
457d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            resultArray = mClientInterface.getPacketCounters();
458d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            if (resultArray == null || resultArray.length != 2) {
459d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                Log.e(TAG, "Invalid signal poll result from wificond");
460d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang                return null;
461d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            }
462d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        } catch (RemoteException e) {
4632e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.e(TAG, "Failed to do signal polling due to remote exception");
464d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang            return null;
465d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        }
466d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        WifiNative.TxPacketCounters counters = new WifiNative.TxPacketCounters();
467d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txSucceeded = resultArray[0];
468d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        counters.txFailed = resultArray[1];
469d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang        return counters;
470d45b46b01f8562219468291bdc19363f0540ced0Ningyuan Wang    }
4718631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
4728631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    /**
4738631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Fetch the latest scan result from kernel via wificond.
4748631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * @return Returns an ArrayList of ScanDetail.
4758631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    * Returns an empty ArrayList on failure.
4768631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    */
47771c4c2a898a827a867564159ce78e41aedd2295bSohani Rao    public ArrayList<ScanDetail> getScanResults(int scanType) {
4788631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        ArrayList<ScanDetail> results = new ArrayList<>();
4798631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        if (mWificondScanner == null) {
4808631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
4818631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            return results;
4828631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
4838631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        try {
48471c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            NativeScanResult[] nativeResults;
48571c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            if (scanType == SCAN_TYPE_SINGLE_SCAN) {
48671c4c2a898a827a867564159ce78e41aedd2295bSohani Rao                nativeResults = mWificondScanner.getScanResults();
48771c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            } else {
48871c4c2a898a827a867564159ce78e41aedd2295bSohani Rao                nativeResults = mWificondScanner.getPnoScanResults();
48971c4c2a898a827a867564159ce78e41aedd2295bSohani Rao            }
4908631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            for (NativeScanResult result : nativeResults) {
491755bbe962c20d37491dd9264ad3497bf27e33602Ningyuan Wang                WifiSsid wifiSsid = WifiSsid.createFromByteArray(result.ssid);
4928ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                String bssid;
4938ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
4948ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    bssid = NativeUtil.macAddressFromByteArray(result.bssid);
4958ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
4968ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + result.bssid, e);
4978ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
4988ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
4998ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                if (bssid == null) {
5008ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal null bssid");
5018ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
5028ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
5038631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanResult.InformationElement[] ies =
5048631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        InformationElementUtil.parseInformationElements(result.infoElement);
5058631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                InformationElementUtil.Capabilities capabilities =
5068631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        new InformationElementUtil.Capabilities();
5078631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                capabilities.from(ies, result.capability);
5088631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                String flags = capabilities.generateCapabilitiesString();
5090a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                NetworkDetail networkDetail;
5100a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                try {
5110a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    networkDetail = new NetworkDetail(bssid, ies, null, result.frequency);
5120a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                } catch (IllegalArgumentException e) {
5130a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    Log.e(TAG, "Illegal argument for scan result with bssid: " + bssid, e);
5140a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                    continue;
5150a6b9c1199f91790606acc70c771548f079fa8f0Ningyuan Wang                }
5168631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang
5178631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                ScanDetail scanDetail = new ScanDetail(networkDetail, wifiSsid, bssid, flags,
5188631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                        result.signalMbm / 100, result.frequency, result.tsf, ies, null);
5194eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // Update carrier network info if this AP's SSID is associated with a carrier Wi-Fi
5204eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                // network and it uses EAP.
5214eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                if (ScanResultUtil.isScanResultForEapNetwork(scanDetail.getScanResult())
5224eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                        && mCarrierNetworkConfig.isCarrierNetwork(wifiSsid.toString())) {
5234eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().isCarrierAp = true;
5244eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().carrierApEapType =
5254eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getNetworkEapType(wifiSsid.toString());
5264eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                    scanDetail.getScanResult().carrierName =
5274eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                            mCarrierNetworkConfig.getCarrierName(wifiSsid.toString());
5284eef41ced6143fe7228cf1f06f8a1f45aa8a2b1fPeter Qiu                }
5298631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang                results.add(scanDetail);
5308631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            }
5318631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        } catch (RemoteException e1) {
5328631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang            Log.e(TAG, "Failed to create ScanDetail ArrayList");
5338631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        }
5342e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        if (mVerboseLoggingEnabled) {
5352e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang            Log.d(TAG, "get " + results.size() + " scan results from wificond");
5362e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang        }
5372e5959fc746d48ab49f731cdbbb2b9fea6704e2aNingyuan Wang
5388631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang        return results;
5398631700c2c81784d8fb02d38a304cf6609f67c14Ningyuan Wang    }
540e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
541e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    /**
542e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * Start a scan using wificond for the given parameters.
543e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param freqs list of frequencies to scan for, if null scan all supported channels.
544e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
545e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     * @return Returns true on success.
546e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang     */
547e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    public boolean scan(Set<Integer> freqs, Set<String> hiddenNetworkSSIDs) {
548e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (mWificondScanner == null) {
549e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
550e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            return false;
551e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
552e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        SingleScanSettings settings = new SingleScanSettings();
553e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.channelSettings  = new ArrayList<>();
554e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        settings.hiddenNetworks  = new ArrayList<>();
555e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
556e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (freqs != null) {
557e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (Integer freq : freqs) {
558e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                ChannelSettings channel = new ChannelSettings();
559e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                channel.frequency = freq;
560e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.channelSettings.add(channel);
561e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
562e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
563e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        if (hiddenNetworkSSIDs != null) {
564e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            for (String ssid : hiddenNetworkSSIDs) {
565e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                HiddenNetwork network = new HiddenNetwork();
5668ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
5678ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    network.ssid = NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssid));
5688ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
5698ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + ssid, e);
5708ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
5718ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
572e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang                settings.hiddenNetworks.add(network);
573e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            }
574e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
575e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
576e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        try {
577e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            return mWificondScanner.scan(settings);
578e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        } catch (RemoteException e1) {
579e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang            Log.e(TAG, "Failed to request scan due to remote exception");
580e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        }
581e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang        return false;
582e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang    }
583e6d7f23569585f8f0fb02adbef992d3f1430db44Ningyuan Wang
58404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
58504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Start PNO scan.
58604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @param pnoSettings Pno scan configuration.
58704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
58804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
58904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    public boolean startPnoScan(WifiNative.PnoSettings pnoSettings) {
59004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (mWificondScanner == null) {
59104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
59204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
59304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
59404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        PnoSettings settings = new PnoSettings();
59504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.pnoNetworks  = new ArrayList<>();
59604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.intervalMs = pnoSettings.periodInMs;
59704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min2gRssi = pnoSettings.min24GHzRssi;
59804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        settings.min5gRssi = pnoSettings.min5GHzRssi;
59904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (pnoSettings.networkList != null) {
60004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            for (WifiNative.PnoNetwork network : pnoSettings.networkList) {
60104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                PnoNetwork condNetwork = new PnoNetwork();
60204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                condNetwork.isHidden = (network.flags
60304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                        & WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN) != 0;
6048ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                try {
6058ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    condNetwork.ssid =
6068ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                            NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(network.ssid));
6078ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                } catch (IllegalArgumentException e) {
6088ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    Log.e(TAG, "Illegal argument " + network.ssid, e);
6098ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                    continue;
6108ce63761f263cc5190e87d6f5f8d0501e531168fNingyuan Wang                }
61104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang                settings.pnoNetworks.add(condNetwork);
61204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            }
61304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
61404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
61504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
616a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            boolean success = mWificondScanner.startPnoScan(settings);
617a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            mWifiInjector.getWifiMetrics().incrementPnoScanStartAttempCount();
618a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            if (!success) {
619a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh                mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
620a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            }
621a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            return success;
62204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
623a2dae3436431f3fe2ac79ad087fe62f6fcda8ad7Mehdi Alizadeh            Log.e(TAG, "Failed to start pno scan due to remote exception");
62404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
62504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
62604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
62704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
62804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    /**
62904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * Stop PNO scan.
63004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     * @return true on success.
63104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang     */
63204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    public boolean stopPnoScan() {
63304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        if (mWificondScanner == null) {
63404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
63504c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return false;
63604c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
63704c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        try {
63804c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            return mWificondScanner.stopPnoScan();
63904c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        } catch (RemoteException e1) {
64004c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang            Log.e(TAG, "Failed to stop pno scan due to remote exception");
64104c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        }
64204c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang        return false;
64304c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang    }
64404c453c2e07efc30b99528926f205740226f1c7bNingyuan Wang
645c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    /**
646c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     * Abort ongoing single scan.
647c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang     */
648c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    public void abortScan() {
649c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        if (mWificondScanner == null) {
650c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
651c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            return;
652c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
653c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        try {
654c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            mWificondScanner.abortScan();
655c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        } catch (RemoteException e1) {
656c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang            Log.e(TAG, "Failed to request abortScan due to remote exception");
657c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang        }
658c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang    }
659c4ad341e844e88a34be7ed4c3c9509fb72608b37Ningyuan Wang
6606baff2cb8dec599af186be521882413787595930Ningyuan Wang    /**
6616baff2cb8dec599af186be521882413787595930Ningyuan Wang     * Query the list of valid frequencies for the provided band.
6626baff2cb8dec599af186be521882413787595930Ningyuan Wang     * The result depends on the on the country code that has been set.
6636baff2cb8dec599af186be521882413787595930Ningyuan Wang     *
6646baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
6656baff2cb8dec599af186be521882413787595930Ningyuan Wang     * The following bands are supported:
6666baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_24_GHZ
6676baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_5_GHZ
6686baff2cb8dec599af186be521882413787595930Ningyuan Wang     * WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY
6696baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @return frequencies vector of valid frequencies (MHz), or null for error.
6706baff2cb8dec599af186be521882413787595930Ningyuan Wang     * @throws IllegalArgumentException if band is not recognized.
6716baff2cb8dec599af186be521882413787595930Ningyuan Wang     */
6726baff2cb8dec599af186be521882413787595930Ningyuan Wang    public int [] getChannelsForBand(int band) {
6736baff2cb8dec599af186be521882413787595930Ningyuan Wang        if (mWificond == null) {
6746baff2cb8dec599af186be521882413787595930Ningyuan Wang            Log.e(TAG, "No valid wificond scanner interface handler");
6756baff2cb8dec599af186be521882413787595930Ningyuan Wang            return null;
6766baff2cb8dec599af186be521882413787595930Ningyuan Wang        }
6776baff2cb8dec599af186be521882413787595930Ningyuan Wang        try {
6786baff2cb8dec599af186be521882413787595930Ningyuan Wang            switch (band) {
6796baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_24_GHZ:
6806baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailable2gChannels();
6816baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_5_GHZ:
6826baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailable5gNonDFSChannels();
6836baff2cb8dec599af186be521882413787595930Ningyuan Wang                case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY:
6846baff2cb8dec599af186be521882413787595930Ningyuan Wang                    return mWificond.getAvailableDFSChannels();
6856baff2cb8dec599af186be521882413787595930Ningyuan Wang                default:
6866baff2cb8dec599af186be521882413787595930Ningyuan Wang                    throw new IllegalArgumentException("unsupported band " + band);
6876baff2cb8dec599af186be521882413787595930Ningyuan Wang            }
6886baff2cb8dec599af186be521882413787595930Ningyuan Wang        } catch (RemoteException e1) {
6896baff2cb8dec599af186be521882413787595930Ningyuan Wang            Log.e(TAG, "Failed to request getChannelsForBand due to remote exception");
6906baff2cb8dec599af186be521882413787595930Ningyuan Wang        }
6916baff2cb8dec599af186be521882413787595930Ningyuan Wang        return null;
6926baff2cb8dec599af186be521882413787595930Ningyuan Wang    }
693045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
694045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
695045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * Start Soft AP operation using the provided configuration.
696045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     *
697045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @param config Configuration to use for the soft ap created.
698045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @param listener Callback for AP events.
699045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @return true on success, false otherwise.
700045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
701045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    public boolean startSoftAp(WifiConfiguration config, SoftApListener listener) {
702045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        if (mApInterface == null) {
703045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "No valid ap interface handler");
704045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
705045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
706045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        int encryptionType = getIApInterfaceEncryptionType(config);
707045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        try {
708045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            // TODO(b/67745880) Note that config.SSID is intended to be either a
709045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            // hex string or "double quoted".
710045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            // However, it seems that whatever is handing us these configurations does not obey
711045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            // this convention.
712045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            boolean success = mApInterface.writeHostapdConfig(
713045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                    config.SSID.getBytes(StandardCharsets.UTF_8), config.hiddenSSID,
714045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                    config.apChannel, encryptionType,
715045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                    (config.preSharedKey != null)
716045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                            ? config.preSharedKey.getBytes(StandardCharsets.UTF_8)
717045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                            : new byte[0]);
718045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
719045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to write hostapd configuration");
720045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
721045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
722045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            mApInterfaceListener = new ApInterfaceEventCallback(listener);
723045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            success = mApInterface.startHostapd(mApInterfaceListener);
724045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
725045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to start hostapd.");
726045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
727045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
728045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        } catch (RemoteException e) {
729045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "Exception in starting soft AP: " + e);
730045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
731045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
732045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return true;
733045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
734045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
735045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    /**
736045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * Stop the ongoing Soft AP operation.
737045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     *
738045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     * @return true on success, false otherwise.
739045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius     */
740045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    public boolean stopSoftAp() {
741045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        if (mApInterface == null) {
742045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "No valid ap interface handler");
743045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
744045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
745045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        try {
746045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            boolean success = mApInterface.stopHostapd();
747045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            if (!success) {
748045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                Log.e(TAG, "Failed to stop hostapd.");
749045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                return false;
750045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            }
751045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        } catch (RemoteException e) {
752045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            Log.e(TAG, "Exception in stopping soft AP: " + e);
753045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            return false;
754045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
755045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        mApInterfaceListener = null;
756045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return true;
757045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
758045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius
759045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    private static int getIApInterfaceEncryptionType(WifiConfiguration localConfig) {
760045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        int encryptionType;
761045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        switch (localConfig.getAuthType()) {
762045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            case WifiConfiguration.KeyMgmt.NONE:
763045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                encryptionType = IApInterface.ENCRYPTION_TYPE_NONE;
764045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                break;
765045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            case WifiConfiguration.KeyMgmt.WPA_PSK:
766045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                encryptionType = IApInterface.ENCRYPTION_TYPE_WPA;
767045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                break;
768045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            case WifiConfiguration.KeyMgmt.WPA2_PSK:
769045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                encryptionType = IApInterface.ENCRYPTION_TYPE_WPA2;
770045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                break;
771045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius            default:
772045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                // We really shouldn't default to None, but this was how NetworkManagementService
773045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                // used to do this.
774045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                encryptionType = IApInterface.ENCRYPTION_TYPE_NONE;
775045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius                break;
776045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        }
777045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius        return encryptionType;
778045079df57626fd6a8b94ac19fcdb0540b508c19Roshan Pius    }
77955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius
78055dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    /**
78155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     * Clear all internal handles.
78255dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius     */
78355dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    private void clearState() {
78455dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        // Refresh handlers
78555dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mClientInterface = null;
78655dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mWificondScanner = null;
78755dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mPnoScanEventHandler = null;
78855dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mScanEventHandler = null;
78955dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius        mApInterface = null;
7907065d8fb5b3b814d9f15d053b3a30f4543164baeRoshan Pius        mApInterfaceListener = null;
79155dd51a9f9df48a7b92a57f9c969d256c98d33a7Roshan Pius    }
79270603901b67c48202ecbb1818e59d487bbcceedaNingyuan Wang}
793