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