1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.wifi.mockwifi.nl80211;
18 
19 import android.net.wifi.nl80211.IPnoScanEvent;
20 import android.net.wifi.nl80211.IScanEvent;
21 import android.net.wifi.nl80211.IWifiScannerImpl;
22 import android.net.wifi.nl80211.NativeScanResult;
23 import android.net.wifi.nl80211.PnoSettings;
24 import android.net.wifi.nl80211.SingleScanSettings;
25 import android.os.RemoteException;
26 import android.util.ArraySet;
27 import android.util.Log;
28 
29 import java.util.Collections;
30 import java.util.Set;
31 
32 public class IWifiScannerImp extends IWifiScannerImpl.Stub {
33     private static final String TAG = "IWifiScannerImp";
34 
35     private String mIfaceName;
36     private WifiScannerInterfaceMock mWifiScannerInterfaceMock;
37     private IPnoScanEvent mIPnoScanEvent;
38     private IScanEvent mScanEventHandler;
39 
40     public interface WifiScannerInterfaceMock {
getScanResults()41         default NativeScanResult[] getScanResults() {
42             return null;
43         }
getPnoScanResults()44         default NativeScanResult[] getPnoScanResults() {
45             return null;
46         }
47         /**
48         * Configures a start Pno scan interface.
49         */
startPnoScan(PnoSettings pnoSettings)50         default boolean startPnoScan(PnoSettings pnoSettings) {
51             return false;
52         }
53     }
54 
IWifiScannerImp(String ifaceName)55     public IWifiScannerImp(String ifaceName) {
56         mIfaceName = ifaceName;
57     }
58 
isMethodOverridden(WifiScannerInterfaceMock wifiScannerInterfaceMock, String methodName)59     private boolean isMethodOverridden(WifiScannerInterfaceMock wifiScannerInterfaceMock,
60             String methodName) throws NoSuchMethodException {
61         if (methodName.equals("startPnoScan")) {
62             return !wifiScannerInterfaceMock.getClass().getMethod(
63                     methodName, PnoSettings.class).getDeclaringClass().equals(
64                     WifiScannerInterfaceMock.class);
65         }
66         if (methodName.equals("subscribePnoScanEvents")) {
67             return !wifiScannerInterfaceMock.getClass().getMethod(
68                     methodName, IPnoScanEvent.class).getDeclaringClass().equals(
69                     WifiScannerInterfaceMock.class);
70         }
71         return !wifiScannerInterfaceMock.getClass().getMethod(
72                 methodName).getDeclaringClass().equals(WifiScannerInterfaceMock.class);
73     }
74 
75     /**
76     *  Overridden method check.
77     */
setWifiScannerInterfaceMock( WifiScannerInterfaceMock wifiScannerInterfaceMock)78     public Set<String> setWifiScannerInterfaceMock(
79             WifiScannerInterfaceMock wifiScannerInterfaceMock) {
80         if (wifiScannerInterfaceMock == null) {
81             return Collections.emptySet();
82         }
83         Set<String> overriddenMethods = new ArraySet<>();
84         try {
85             if (isMethodOverridden(wifiScannerInterfaceMock, "getScanResults")) {
86                 overriddenMethods.add("getScanResults");
87             }
88             if (isMethodOverridden(wifiScannerInterfaceMock, "getPnoScanResults")) {
89                 overriddenMethods.add("getPnoScanResults");
90             }
91             if (isMethodOverridden(wifiScannerInterfaceMock, "startPnoScan")) {
92                 overriddenMethods.add("startPnoScan");
93             }
94         } catch (NoSuchMethodException e) {
95             Log.e(TAG, "Reflection error: " + e);
96             return Collections.emptySet();
97         }
98         mWifiScannerInterfaceMock = wifiScannerInterfaceMock;
99         return overriddenMethods;
100     }
101 
102     /**
103      * Trigger the scan ready event to force frameworks to get scan result again.
104      * Otherwise the mocked scan result may not work because the frameworks keep use cache data
105      * since there is no scan ready event.
106      */
mockScanResultReadyEvent(boolean isPno)107     public void mockScanResultReadyEvent(boolean isPno) {
108         try {
109             if (isPno) {
110                 if (mIPnoScanEvent != null) {
111                     mIPnoScanEvent.OnPnoNetworkFound();
112                 }
113             } else if (mScanEventHandler != null) {
114                 mScanEventHandler.OnScanResultReady();
115             }
116         } catch (RemoteException re) {
117             Log.e(TAG, "RemoteException when calling OnScanResultRead" + re);
118         }
119     }
120     // Supported methods in IWifiScannerImpl.aidl
121     @Override
getScanResults()122     public NativeScanResult[] getScanResults() {
123         Log.i(TAG, "getScanResults");
124         if (mWifiScannerInterfaceMock == null) {
125             Log.e(TAG, "mWifiScannerInterfaceMock: null!");
126             return null;
127         }
128         return mWifiScannerInterfaceMock.getScanResults();
129     }
130 
131     @Override
getPnoScanResults()132     public NativeScanResult[] getPnoScanResults() {
133         Log.i(TAG, "getPnoScanResults");
134         if (mWifiScannerInterfaceMock == null) {
135             Log.e(TAG, "mWifiScannerInterfaceMock: null!");
136             return null;
137         }
138         return mWifiScannerInterfaceMock.getPnoScanResults();
139     }
140 
141     @Override
scan(SingleScanSettings scanSettings)142     public boolean scan(SingleScanSettings scanSettings) {
143         Log.i(TAG, "scan");
144         // TODO: Mock it when we have a use (test) case.
145         return true;
146     }
147 
148     @Override
scanRequest(SingleScanSettings scanSettings)149     public int scanRequest(SingleScanSettings scanSettings) {
150         Log.i(TAG, "scanRequest");
151         // TODO: Mock it when we have a use (test) case.
152         return 0;
153     }
154 
155     @Override
subscribeScanEvents(IScanEvent handler)156     public void subscribeScanEvents(IScanEvent handler) {
157         Log.i(TAG, "subscribeScanEvents");
158         mScanEventHandler = handler;
159     }
160 
161     @Override
unsubscribeScanEvents()162     public void unsubscribeScanEvents() {
163         Log.i(TAG, "unsubscribeScanEvents");
164         // TODO: Mock it when we have a use (test) case.
165     }
166 
167     @Override
subscribePnoScanEvents(IPnoScanEvent handler)168     public void subscribePnoScanEvents(IPnoScanEvent handler) {
169         Log.i(TAG, "subscribePnoScanEvents");
170         this.mIPnoScanEvent = handler;
171     }
172 
173     @Override
unsubscribePnoScanEvents()174     public void unsubscribePnoScanEvents() {
175         Log.i(TAG, "unsubscribePnoScanEvents");
176         // TODO: Mock it when we have a use (test) case.
177     }
178 
179     @Override
startPnoScan(PnoSettings pnoSettings)180     public boolean startPnoScan(PnoSettings pnoSettings) {
181         Log.i(TAG, "startPnoScan");
182         if (mWifiScannerInterfaceMock == null || mIPnoScanEvent == null) {
183             Log.e(TAG, "startPnoScan: false mock!");
184             return false;
185         }
186         return mWifiScannerInterfaceMock.startPnoScan(pnoSettings);
187     }
188 
189     @Override
stopPnoScan()190     public boolean stopPnoScan() {
191         Log.i(TAG, "stopPnoScan");
192         // TODO: Mock it when we have a use (test) case.
193         return false;
194     }
195 
196     @Override
abortScan()197     public void abortScan() {
198         Log.i(TAG, "abortScan");
199         // TODO: Mock it when we have a use (test) case.
200     }
201 
202     @Override
getMaxSsidsPerScan()203     public int getMaxSsidsPerScan() {
204         Log.i(TAG, "getMaxSsidsPerScan");
205         // TODO: Mock it when we have a use (test) case.
206         return 0;
207     }
208 }
209