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