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 com.android.server.wifi.mockwifi; 18 19 import static android.os.UserHandle.CURRENT; 20 21 import android.annotation.IntDef; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.ServiceConnection; 26 import android.net.wifi.nl80211.WifiNl80211Manager; 27 import android.os.IBinder; 28 import android.util.Log; 29 30 import com.android.server.wifi.WifiMonitor; 31 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 35 /** This class provides wrapper APIs for binding interfaces to mock service. */ 36 public class MockWifiServiceUtil { 37 private static final String TAG = "MockWifiModemUtil"; 38 private static final String BIND_NL80211 = "android.wifi.mockwifimodem.nl80211"; 39 private static final String BIND_SUPPLICANT = "android.wifi.mockwifimodem.supplicant"; 40 41 @IntDef({MOCK_NL80211_SERVICE, MOCK_SUPPLICANT_SERVICE}) 42 @Retention(RetentionPolicy.SOURCE) 43 public @interface MockServiceType {} 44 45 public static final int MOCK_NL80211_SERVICE = 0; 46 public static final int MOCK_SUPPLICANT_SERVICE = 1; 47 public static final int MIN_SERVICE_IDX = MOCK_NL80211_SERVICE; 48 public static final int NUM_SERVICES = 2; 49 public static final int BINDER_RETRY_MILLIS = 3 * 100; 50 public static final int BINDER_MAX_RETRY = 3; 51 52 public static final String METHOD_SEPARATOR = ","; 53 public static final String CLASS_IDENTIFIER = "-"; 54 public static final String AIDL_METHOD_IDENTIFIER = "#"; 55 56 private static final String TAG_MOCK_NL80211 = "WifiNL80211ManagerImp"; 57 private static final String TAG_MOCK_SUPPLICANT = "ISupplicantImp"; 58 59 private Context mContext; 60 private WifiMonitor mWifiMonitor; 61 private String mServiceName; 62 private String mPackageName; 63 private MockWifiNl80211Manager mMockWifiNl80211Manager; 64 private MockSupplicantManager mMockSupplicantManager; 65 private IBinder mMockNl80211Binder; 66 private ServiceConnection mMockNl80211ServiceConnection; 67 private IBinder mMockSupplicantBinder; 68 private ServiceConnection mMockSupplicantServiceConnection; 69 MockWifiServiceUtil(Context context, String serviceName, WifiMonitor wifiMonitor)70 public MockWifiServiceUtil(Context context, String serviceName, WifiMonitor wifiMonitor) { 71 mContext = context.createContextAsUser(CURRENT, 0); 72 mWifiMonitor = wifiMonitor; 73 String[] componentInfo = serviceName.split("/", 2); 74 mPackageName = componentInfo[0]; 75 mServiceName = componentInfo[1]; 76 } 77 78 private class MockModemConnection implements ServiceConnection { 79 private int mService; 80 MockModemConnection(int module)81 MockModemConnection(int module) { 82 mService = module; 83 } 84 85 @Override onServiceConnected(ComponentName name, IBinder binder)86 public void onServiceConnected(ComponentName name, IBinder binder) { 87 Log.d(TAG, "Wifi mock Service " + getModuleName(mService) + " - onServiceConnected"); 88 if (mService == MOCK_NL80211_SERVICE) { 89 mMockNl80211Binder = binder; 90 mMockWifiNl80211Manager = new MockWifiNl80211Manager(mMockNl80211Binder, mContext, 91 mWifiMonitor); 92 } 93 if (mService == MOCK_SUPPLICANT_SERVICE) { 94 mMockSupplicantBinder = binder; 95 mMockSupplicantManager = new MockSupplicantManager(mMockSupplicantBinder, 96 mWifiMonitor); 97 } 98 99 } 100 101 @Override onServiceDisconnected(ComponentName name)102 public void onServiceDisconnected(ComponentName name) { 103 Log.d(TAG, "Wifi mock Service " + getModuleName(mService) 104 + " - onServiceDisconnected"); 105 if (mService == MOCK_NL80211_SERVICE) { 106 mMockNl80211Binder = null; 107 mMockWifiNl80211Manager = null; 108 } 109 if (mService == MOCK_SUPPLICANT_SERVICE) { 110 mMockSupplicantBinder = null; 111 mMockSupplicantManager = null; 112 } 113 } 114 } 115 bindModuleToMockModemService( String actionName, ServiceConnection serviceConnection)116 private boolean bindModuleToMockModemService( 117 String actionName, ServiceConnection serviceConnection) { 118 boolean status = false; 119 120 Intent intent = new Intent(); 121 intent.setComponent(new ComponentName(mPackageName, mServiceName)); 122 intent.setAction(actionName); 123 124 status = mContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); 125 return status; 126 } 127 128 /** 129 * Unbind of the provided service. 130 */ unbindMockModemService()131 public void unbindMockModemService() { 132 mContext.unbindService(mMockNl80211ServiceConnection); 133 mContext.unbindService(mMockSupplicantServiceConnection); 134 } 135 136 /** waitForBinder */ getServiceBinder(@ockServiceType int service)137 public IBinder getServiceBinder(@MockServiceType int service) { 138 switch (service) { 139 case MOCK_NL80211_SERVICE: 140 return mMockNl80211Binder; 141 case MOCK_SUPPLICANT_SERVICE: 142 return mMockSupplicantBinder; 143 default: 144 return null; 145 } 146 } 147 148 /** Binding interfaces with mock modem service */ bindAllMockModemService()149 public void bindAllMockModemService() { 150 for (int service = MIN_SERVICE_IDX; service < NUM_SERVICES; service++) { 151 bindToMockModemService(service); 152 } 153 } 154 155 /** bindToMockModemService */ bindToMockModemService(@ockServiceType int service)156 public void bindToMockModemService(@MockServiceType int service) { 157 // Based on {@code service} to get each mocked HAL binder 158 if (service == MOCK_NL80211_SERVICE) { 159 mMockNl80211ServiceConnection = new MockModemConnection(MOCK_NL80211_SERVICE); 160 161 boolean status = 162 bindModuleToMockModemService(BIND_NL80211, mMockNl80211ServiceConnection); 163 if (!status) { 164 Log.d(TAG, getModuleName(service) + " bind fail"); 165 mMockNl80211ServiceConnection = null; 166 } 167 } 168 if (service == MOCK_SUPPLICANT_SERVICE) { 169 mMockSupplicantServiceConnection = new MockModemConnection(MOCK_SUPPLICANT_SERVICE); 170 boolean status = 171 bindModuleToMockModemService(BIND_SUPPLICANT, mMockSupplicantServiceConnection); 172 if (!status) { 173 Log.d(TAG, getModuleName(service) + " bind fail"); 174 mMockSupplicantServiceConnection = null; 175 } 176 } 177 } 178 getServiceName()179 public String getServiceName() { 180 return mServiceName; 181 } 182 getServiceConnection(@ockServiceType int service)183 private ServiceConnection getServiceConnection(@MockServiceType int service) { 184 switch (service) { 185 case MOCK_NL80211_SERVICE: 186 return mMockNl80211ServiceConnection; 187 case MOCK_SUPPLICANT_SERVICE: 188 return mMockSupplicantServiceConnection; 189 default: 190 return null; 191 } 192 } 193 194 /** 195 * Returns name of the provided service. 196 */ getModuleName(@ockServiceType int service)197 public String getModuleName(@MockServiceType int service) { 198 switch (service) { 199 case MOCK_NL80211_SERVICE: 200 return "nl80211"; 201 case MOCK_SUPPLICANT_SERVICE: 202 return "supplicant"; 203 default: 204 return "none"; 205 } 206 } 207 208 /** 209 * set mocked methods. 210 * 211 * @param methods mocked methods with format HAL-method, ... 212 */ setMockedMethods(String methods)213 public boolean setMockedMethods(String methods) { 214 Log.i(TAG, "setMockedMethods - " + methods); 215 if (methods == null) { 216 return false; 217 } 218 if (mMockWifiNl80211Manager != null) { 219 mMockWifiNl80211Manager.resetMockedMethods(); 220 } 221 if (mMockSupplicantManager != null) { 222 mMockSupplicantManager.resetMockedMethods(); 223 } 224 String[] mockedMethods = methods.split(METHOD_SEPARATOR); 225 for (String mockedMethod : mockedMethods) { 226 String[] mockedMethodInfo = mockedMethod.split(CLASS_IDENTIFIER); 227 if (mockedMethodInfo.length != 2) { 228 return false; 229 } 230 String mockedClassName = mockedMethodInfo[0]; 231 String mockedMethodName = mockedMethodInfo[1]; 232 if (TAG_MOCK_NL80211.equals(mockedClassName) && mMockWifiNl80211Manager != null) { 233 mMockWifiNl80211Manager.addMockedMethod(mockedMethodName); 234 } 235 if (TAG_MOCK_SUPPLICANT.equals(mockedClassName) && mMockSupplicantManager != null) { 236 mMockSupplicantManager.addMockedMethod(mockedMethodName); 237 } 238 } 239 return true; 240 } 241 getMockSupplicantManager()242 public MockSupplicantManager getMockSupplicantManager() { 243 return mMockSupplicantManager; 244 } 245 getMockWifiNl80211Manager()246 public MockWifiNl80211Manager getMockWifiNl80211Manager() { 247 return mMockWifiNl80211Manager; 248 } 249 getWifiNl80211Manager()250 public WifiNl80211Manager getWifiNl80211Manager() { 251 return mMockWifiNl80211Manager == null 252 ? null : mMockWifiNl80211Manager.getWifiNl80211Manager(); 253 } 254 255 /** 256 * Get method configured status based on service. 257 */ isMethodConfigured(@ockServiceType int service, String methodName)258 public boolean isMethodConfigured(@MockServiceType int service, String methodName) { 259 switch (service) { 260 case MOCK_NL80211_SERVICE: 261 return getWifiNl80211Manager() != null 262 && getMockWifiNl80211Manager().isMethodConfigured(methodName); 263 case MOCK_SUPPLICANT_SERVICE: 264 return mMockSupplicantManager != null 265 && getMockSupplicantManager().isMethodConfigured(methodName); 266 default: 267 return false; 268 } 269 } 270 } 271