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