1 /* 2 * Copyright (C) 2021 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.internal.telephony; 18 19 import static android.telephony.TelephonyManager.HAL_SERVICE_DATA; 20 import static android.telephony.TelephonyManager.HAL_SERVICE_IMS; 21 import static android.telephony.TelephonyManager.HAL_SERVICE_MESSAGING; 22 import static android.telephony.TelephonyManager.HAL_SERVICE_MODEM; 23 import static android.telephony.TelephonyManager.HAL_SERVICE_NETWORK; 24 import static android.telephony.TelephonyManager.HAL_SERVICE_SIM; 25 import static android.telephony.TelephonyManager.HAL_SERVICE_VOICE; 26 27 import android.app.ActivityManager; 28 import android.content.ComponentName; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.ServiceConnection; 32 import android.os.IBinder; 33 import android.os.UserHandle; 34 35 import com.android.telephony.Rlog; 36 37 /** This class provides wrapper APIs for binding interfaces to mock service. */ 38 public class MockModem { 39 private static final String TAG = "MockModem"; 40 private static final String BIND_IRADIOMODEM = "android.telephony.mockmodem.iradiomodem"; 41 private static final String BIND_IRADIOSIM = "android.telephony.mockmodem.iradiosim"; 42 private static final String BIND_IRADIOMESSAGING = 43 "android.telephony.mockmodem.iradiomessaging"; 44 private static final String BIND_IRADIODATA = "android.telephony.mockmodem.iradiodata"; 45 private static final String BIND_IRADIONETWORK = "android.telephony.mockmodem.iradionetwork"; 46 private static final String BIND_IRADIOVOICE = "android.telephony.mockmodem.iradiovoice"; 47 private static final String BIND_IRADIOIMS = "android.telephony.mockmodem.iradioims"; 48 private static final String BIND_IRADIOCONFIG = "android.telephony.mockmodem.iradioconfig"; 49 private static final String PHONE_ID = "phone_id"; 50 51 private static final byte DEFAULT_PHONE_ID = 0x00; 52 53 static final int RADIOCONFIG_SERVICE = RIL.MAX_SERVICE_IDX + 1; 54 55 static final int BINDER_RETRY_MILLIS = 3 * 100; 56 static final int BINDER_MAX_RETRY = 10; 57 58 private Context mContext; 59 private String mServiceName; 60 private String mPackageName; 61 62 private IBinder mModemBinder; 63 private IBinder mSimBinder; 64 private IBinder mMessagingBinder; 65 private IBinder mDataBinder; 66 private IBinder mNetworkBinder; 67 private IBinder mVoiceBinder; 68 private IBinder mImsBinder; 69 private IBinder mConfigBinder; 70 private ServiceConnection mModemServiceConnection; 71 private ServiceConnection mSimServiceConnection; 72 private ServiceConnection mMessagingServiceConnection; 73 private ServiceConnection mDataServiceConnection; 74 private ServiceConnection mNetworkServiceConnection; 75 private ServiceConnection mVoiceServiceConnection; 76 private ServiceConnection mImsServiceConnection; 77 private ServiceConnection mConfigServiceConnection; 78 79 private byte mPhoneId; 80 private String mTag; 81 MockModem(Context context, String serviceName)82 MockModem(Context context, String serviceName) { 83 this(context, serviceName, 0); 84 } 85 MockModem(Context context, String serviceName, int phoneId)86 MockModem(Context context, String serviceName, int phoneId) { 87 mPhoneId = (byte) phoneId; 88 mTag = TAG + "-" + mPhoneId; 89 mContext = context; 90 String[] componentInfo = serviceName.split("/", 2); 91 mPackageName = componentInfo[0]; 92 mServiceName = componentInfo[1]; 93 } 94 95 private class MockModemConnection implements ServiceConnection { 96 private int mService; 97 MockModemConnection(int module)98 MockModemConnection(int module) { 99 mService = module; 100 } 101 102 @Override onServiceConnected(ComponentName name, IBinder binder)103 public void onServiceConnected(ComponentName name, IBinder binder) { 104 Rlog.d(mTag, "IRadio " + getModuleName(mService) + " - onServiceConnected"); 105 106 if (mService == HAL_SERVICE_MODEM) { 107 mModemBinder = binder; 108 } else if (mService == HAL_SERVICE_SIM) { 109 mSimBinder = binder; 110 } else if (mService == HAL_SERVICE_MESSAGING) { 111 mMessagingBinder = binder; 112 } else if (mService == HAL_SERVICE_DATA) { 113 mDataBinder = binder; 114 } else if (mService == HAL_SERVICE_NETWORK) { 115 mNetworkBinder = binder; 116 } else if (mService == HAL_SERVICE_VOICE) { 117 mVoiceBinder = binder; 118 } else if (mService == HAL_SERVICE_IMS) { 119 mImsBinder = binder; 120 } else if (mService == RADIOCONFIG_SERVICE) { 121 mConfigBinder = binder; 122 } 123 } 124 125 @Override onServiceDisconnected(ComponentName name)126 public void onServiceDisconnected(ComponentName name) { 127 Rlog.d(mTag, "IRadio " + getModuleName(mService) + " - onServiceDisconnected"); 128 129 if (mService == HAL_SERVICE_MODEM) { 130 mModemBinder = null; 131 } else if (mService == HAL_SERVICE_SIM) { 132 mSimBinder = null; 133 } else if (mService == HAL_SERVICE_MESSAGING) { 134 mMessagingBinder = null; 135 } else if (mService == HAL_SERVICE_DATA) { 136 mDataBinder = null; 137 } else if (mService == HAL_SERVICE_NETWORK) { 138 mNetworkBinder = null; 139 } else if (mService == HAL_SERVICE_VOICE) { 140 mVoiceBinder = null; 141 } else if (mService == HAL_SERVICE_IMS) { 142 mImsBinder = null; 143 } else if (mService == RADIOCONFIG_SERVICE) { 144 mConfigBinder = null; 145 } 146 } 147 } 148 bindModuleToMockModemService( String actionName, ServiceConnection serviceConnection)149 private boolean bindModuleToMockModemService( 150 String actionName, ServiceConnection serviceConnection) { 151 return bindModuleToMockModemService(DEFAULT_PHONE_ID, actionName, serviceConnection); 152 } 153 bindModuleToMockModemService( byte phoneId, String actionName, ServiceConnection serviceConnection)154 private boolean bindModuleToMockModemService( 155 byte phoneId, String actionName, ServiceConnection serviceConnection) { 156 boolean status = false; 157 158 Intent intent = new Intent(); 159 intent.setComponent(new ComponentName(mPackageName, mServiceName)); 160 intent.setAction(actionName + phoneId); 161 intent.putExtra(PHONE_ID, phoneId); 162 163 status = mContext.bindServiceAsUser(intent, serviceConnection, Context.BIND_AUTO_CREATE, 164 UserHandle.of(ActivityManager.getCurrentUser())); 165 return status; 166 } 167 168 /** waitForBinder */ getServiceBinder(int service)169 public IBinder getServiceBinder(int service) { 170 switch (service) { 171 case HAL_SERVICE_MODEM: 172 return mModemBinder; 173 case HAL_SERVICE_SIM: 174 return mSimBinder; 175 case HAL_SERVICE_MESSAGING: 176 return mMessagingBinder; 177 case HAL_SERVICE_DATA: 178 return mDataBinder; 179 case HAL_SERVICE_NETWORK: 180 return mNetworkBinder; 181 case HAL_SERVICE_VOICE: 182 return mVoiceBinder; 183 case HAL_SERVICE_IMS: 184 return mImsBinder; 185 case RADIOCONFIG_SERVICE: 186 return mConfigBinder; 187 default: 188 return null; 189 } 190 } 191 192 /** Binding interfaces with mock modem service */ bindAllMockModemService()193 public void bindAllMockModemService() { 194 for (int service = RIL.MIN_SERVICE_IDX; service <= RIL.MAX_SERVICE_IDX; service++) { 195 bindToMockModemService(service); 196 } 197 } 198 199 /** bindToMockModemService */ bindToMockModemService(int service)200 public void bindToMockModemService(int service) { 201 if (service == RADIOCONFIG_SERVICE) { 202 if (mConfigBinder == null) { 203 mConfigServiceConnection = new MockModemConnection(RADIOCONFIG_SERVICE); 204 205 boolean status = 206 bindModuleToMockModemService(BIND_IRADIOCONFIG, mConfigServiceConnection); 207 if (!status) { 208 Rlog.d(mTag, "IRadio Config bind fail"); 209 mConfigServiceConnection = null; 210 } 211 } else { 212 Rlog.d(mTag, "IRadio Config is bound"); 213 } 214 } else if (service == HAL_SERVICE_MODEM) { 215 if (mModemBinder == null) { 216 mModemServiceConnection = new MockModemConnection(HAL_SERVICE_MODEM); 217 218 boolean status = 219 bindModuleToMockModemService( 220 mPhoneId, BIND_IRADIOMODEM, mModemServiceConnection); 221 if (!status) { 222 Rlog.d(mTag, "IRadio Modem bind fail"); 223 mModemServiceConnection = null; 224 } 225 } else { 226 Rlog.d(mTag, "IRadio Modem is bound"); 227 } 228 } else if (service == HAL_SERVICE_SIM) { 229 if (mSimBinder == null) { 230 mSimServiceConnection = new MockModemConnection(HAL_SERVICE_SIM); 231 232 boolean status = 233 bindModuleToMockModemService( 234 mPhoneId, BIND_IRADIOSIM, mSimServiceConnection); 235 if (!status) { 236 Rlog.d(mTag, "IRadio Sim bind fail"); 237 mSimServiceConnection = null; 238 } 239 } else { 240 Rlog.d(mTag, "IRadio Sim is bound"); 241 } 242 } else if (service == HAL_SERVICE_MESSAGING) { 243 if (mMessagingBinder == null) { 244 mMessagingServiceConnection = new MockModemConnection(HAL_SERVICE_MESSAGING); 245 246 boolean status = 247 bindModuleToMockModemService( 248 mPhoneId, BIND_IRADIOMESSAGING, mMessagingServiceConnection); 249 if (!status) { 250 Rlog.d(mTag, "IRadio Messaging bind fail"); 251 mMessagingServiceConnection = null; 252 } 253 } else { 254 Rlog.d(mTag, "IRadio Messaging is bound"); 255 } 256 } else if (service == HAL_SERVICE_DATA) { 257 if (mDataBinder == null) { 258 mDataServiceConnection = new MockModemConnection(HAL_SERVICE_DATA); 259 260 boolean status = 261 bindModuleToMockModemService( 262 mPhoneId, BIND_IRADIODATA, mDataServiceConnection); 263 if (!status) { 264 Rlog.d(mTag, "IRadio Data bind fail"); 265 mDataServiceConnection = null; 266 } 267 } else { 268 Rlog.d(mTag, "IRadio Data is bound"); 269 } 270 } else if (service == HAL_SERVICE_NETWORK) { 271 if (mNetworkBinder == null) { 272 mNetworkServiceConnection = new MockModemConnection(HAL_SERVICE_NETWORK); 273 274 boolean status = 275 bindModuleToMockModemService( 276 mPhoneId, BIND_IRADIONETWORK, mNetworkServiceConnection); 277 if (!status) { 278 Rlog.d(mTag, "IRadio Network bind fail"); 279 mNetworkServiceConnection = null; 280 } 281 } else { 282 Rlog.d(mTag, "IRadio Network is bound"); 283 } 284 } else if (service == HAL_SERVICE_VOICE) { 285 if (mVoiceBinder == null) { 286 mVoiceServiceConnection = new MockModemConnection(HAL_SERVICE_VOICE); 287 288 boolean status = 289 bindModuleToMockModemService( 290 mPhoneId, BIND_IRADIOVOICE, mVoiceServiceConnection); 291 if (!status) { 292 Rlog.d(mTag, "IRadio Voice bind fail"); 293 mVoiceServiceConnection = null; 294 } 295 } else { 296 Rlog.d(mTag, "IRadio Voice is bound"); 297 } 298 } else if (service == HAL_SERVICE_IMS) { 299 if (mImsBinder == null) { 300 mImsServiceConnection = new MockModemConnection(HAL_SERVICE_IMS); 301 302 boolean status = 303 bindModuleToMockModemService( 304 mPhoneId, BIND_IRADIOIMS, mImsServiceConnection); 305 if (!status) { 306 Rlog.d(TAG, "IRadio Ims bind fail"); 307 mImsServiceConnection = null; 308 } 309 } else { 310 Rlog.d(TAG, "IRadio Ims is bound"); 311 } 312 } 313 } 314 315 /** unbindMockModemService */ unbindMockModemService(int service)316 public void unbindMockModemService(int service) { 317 318 if (service == RADIOCONFIG_SERVICE) { 319 if (mConfigServiceConnection != null) { 320 mContext.unbindService(mConfigServiceConnection); 321 mConfigServiceConnection = null; 322 mConfigBinder = null; 323 Rlog.d(mTag, "unbind IRadio Config"); 324 } 325 } else if (service == HAL_SERVICE_MODEM) { 326 if (mModemServiceConnection != null) { 327 mContext.unbindService(mModemServiceConnection); 328 mModemServiceConnection = null; 329 mModemBinder = null; 330 Rlog.d(mTag, "unbind IRadio Modem"); 331 } 332 } else if (service == HAL_SERVICE_SIM) { 333 if (mSimServiceConnection != null) { 334 mContext.unbindService(mSimServiceConnection); 335 mSimServiceConnection = null; 336 mSimBinder = null; 337 Rlog.d(mTag, "unbind IRadio Sim"); 338 } 339 } else if (service == HAL_SERVICE_MESSAGING) { 340 if (mMessagingServiceConnection != null) { 341 mContext.unbindService(mMessagingServiceConnection); 342 mMessagingServiceConnection = null; 343 mMessagingBinder = null; 344 Rlog.d(mTag, "unbind IRadio Messaging"); 345 } 346 } else if (service == HAL_SERVICE_DATA) { 347 if (mDataServiceConnection != null) { 348 mContext.unbindService(mDataServiceConnection); 349 mDataServiceConnection = null; 350 mDataBinder = null; 351 Rlog.d(mTag, "unbind IRadio Data"); 352 } 353 } else if (service == HAL_SERVICE_NETWORK) { 354 if (mNetworkServiceConnection != null) { 355 mContext.unbindService(mNetworkServiceConnection); 356 mNetworkServiceConnection = null; 357 mNetworkBinder = null; 358 Rlog.d(mTag, "unbind IRadio Network"); 359 } 360 } else if (service == HAL_SERVICE_VOICE) { 361 if (mVoiceServiceConnection != null) { 362 mContext.unbindService(mVoiceServiceConnection); 363 mVoiceServiceConnection = null; 364 mVoiceBinder = null; 365 Rlog.d(mTag, "unbind IRadio Voice"); 366 } 367 } else if (service == HAL_SERVICE_IMS) { 368 if (mImsServiceConnection != null) { 369 mContext.unbindService(mImsServiceConnection); 370 mImsServiceConnection = null; 371 mImsBinder = null; 372 Rlog.d(TAG, "unbind IRadio Ims"); 373 } 374 } 375 } 376 getServiceName()377 public String getServiceName() { 378 return mServiceName; 379 } 380 getModuleName(int service)381 private String getModuleName(int service) { 382 switch (service) { 383 case HAL_SERVICE_MODEM: 384 return "modem"; 385 case HAL_SERVICE_SIM: 386 return "sim"; 387 case HAL_SERVICE_MESSAGING: 388 return "messaging"; 389 case HAL_SERVICE_DATA: 390 return "data"; 391 case HAL_SERVICE_NETWORK: 392 return "network"; 393 case HAL_SERVICE_VOICE: 394 return "voice"; 395 case HAL_SERVICE_IMS: 396 return "ims"; 397 case RADIOCONFIG_SERVICE: 398 return "config"; 399 default: 400 return "none"; 401 } 402 } 403 } 404