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 android.telephony.mockmodem; 18 19 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_RADIO_POWER; 20 21 import android.hardware.radio.RadioError; 22 import android.hardware.radio.RadioIndicationType; 23 import android.hardware.radio.RadioResponseInfo; 24 import android.hardware.radio.modem.IRadioModem; 25 import android.hardware.radio.modem.IRadioModemIndication; 26 import android.hardware.radio.modem.IRadioModemResponse; 27 import android.hardware.radio.modem.ImeiInfo; 28 import android.hardware.radio.modem.RadioState; 29 import android.os.AsyncResult; 30 import android.os.Handler; 31 import android.os.Message; 32 import android.os.RemoteException; 33 import android.util.Log; 34 35 public class IRadioModemImpl extends IRadioModem.Stub { 36 private static final String TAG = "MRMDM"; 37 38 private final MockModemService mService; 39 private IRadioModemResponse mRadioModemResponse; 40 private IRadioModemIndication mRadioModemIndication; 41 42 private int mForceRadioPowerError = -1; 43 44 private MockModemConfigInterface mMockModemConfigInterface; 45 private Object mCacheUpdateMutex; 46 private final Handler mHandler; 47 private int mSubId; 48 private String mTag; 49 50 // ***** Events 51 static final int EVENT_BASEBAND_VERSION_CHANGED = 1; 52 static final int EVENT_DEVICE_IDENTITY_CHANGED = 2; 53 static final int EVENT_RADIO_STATE_CHANGED = 3; 54 static final int EVENT_DEVICE_IMEI_INFO_CHANGED = 4; 55 56 // ***** Cache of modem attributes/status 57 private String mBasebandVer; 58 private String mImei; 59 private String mImeiSv; 60 private String mEsn; 61 private String mMeid; 62 private int mImeiType; 63 private int mRadioState; 64 IRadioModemImpl( MockModemService service, MockModemConfigInterface configInterface, int instanceId)65 public IRadioModemImpl( 66 MockModemService service, MockModemConfigInterface configInterface, int instanceId) { 67 mTag = TAG + "-" + instanceId; 68 Log.d(mTag, "Instantiated"); 69 70 this.mService = service; 71 mMockModemConfigInterface = configInterface; 72 mCacheUpdateMutex = new Object(); 73 mHandler = new IRadioModemHandler(); 74 mSubId = instanceId; 75 76 // Register events 77 mMockModemConfigInterface.registerForBasebandVersionChanged( 78 mSubId, mHandler, EVENT_BASEBAND_VERSION_CHANGED, null); 79 mMockModemConfigInterface.registerForDeviceIdentityChanged( 80 mSubId, mHandler, EVENT_DEVICE_IDENTITY_CHANGED, null); 81 mMockModemConfigInterface.registerForRadioStateChanged( 82 mSubId, mHandler, EVENT_RADIO_STATE_CHANGED, null); 83 mMockModemConfigInterface.registerForDeviceImeiInfoChanged( 84 mSubId, mHandler, EVENT_DEVICE_IMEI_INFO_CHANGED, null); 85 } 86 87 /** Handler class to handle callbacks */ 88 private final class IRadioModemHandler extends Handler { 89 @Override handleMessage(Message msg)90 public void handleMessage(Message msg) { 91 AsyncResult ar; 92 synchronized (mCacheUpdateMutex) { 93 switch (msg.what) { 94 case EVENT_BASEBAND_VERSION_CHANGED: 95 Log.d(mTag, "Received EVENT_BASEBAND_VERSION_CHANGED"); 96 ar = (AsyncResult) msg.obj; 97 if (ar != null && ar.exception == null) { 98 mBasebandVer = (String) ar.result; 99 Log.i(mTag, "Basedband version = " + mBasebandVer); 100 } else { 101 Log.e( 102 mTag, 103 msg.what 104 + " failure. Not update baseband version." 105 + ar.exception); 106 } 107 break; 108 case EVENT_DEVICE_IDENTITY_CHANGED: 109 Log.d(mTag, "Received EVENT_DEVICE_IDENTITY_CHANGED"); 110 ar = (AsyncResult) msg.obj; 111 if (ar != null && ar.exception == null) { 112 String[] deviceIdentity = (String[]) ar.result; 113 mImei = deviceIdentity[0]; 114 mImeiSv = deviceIdentity[1]; 115 mEsn = deviceIdentity[2]; 116 mMeid = deviceIdentity[3]; 117 Log.i( 118 mTag, 119 "Device identity: IMEI = " 120 + mImei 121 + " IMEISV = " 122 + mImeiSv 123 + " ESN = " 124 + mEsn 125 + " MEID =" 126 + mMeid); 127 } else { 128 Log.e( 129 mTag, 130 msg.what 131 + " failure. Not update device identity." 132 + ar.exception); 133 } 134 break; 135 case EVENT_RADIO_STATE_CHANGED: 136 Log.d(mTag, "Received EVENT_RADIO_STATE_CHANGED"); 137 ar = (AsyncResult) msg.obj; 138 if (ar != null && ar.exception == null) { 139 mRadioState = (int) ar.result; 140 Log.i(mTag, "Radio state: " + mRadioState); 141 } else { 142 Log.e(mTag, msg.what + " failure. Exception: " + ar.exception); 143 } 144 break; 145 case EVENT_DEVICE_IMEI_INFO_CHANGED: 146 Log.d(mTag, "Received EVENT_DEVICE_IMEIINFO_CHANGED"); 147 ar = (AsyncResult) msg.obj; 148 if (ar != null && ar.exception == null) { 149 ImeiInfo imeiInfo = (ImeiInfo) ar.result; 150 mImei = imeiInfo.imei; 151 mImeiSv = imeiInfo.svn; 152 mImeiType = imeiInfo.type; 153 Log.i(mTag, "IMEIInfo : ImeiType = " + mImeiType); 154 } else { 155 Log.e(mTag, msg.what + " failure. Not update device ImeiInfo." 156 + ar.exception); 157 } 158 break; 159 } 160 } 161 } 162 } 163 164 // Implementation of IRadioModem functions 165 @Override setResponseFunctions( IRadioModemResponse radioModemResponse, IRadioModemIndication radioModemIndication)166 public void setResponseFunctions( 167 IRadioModemResponse radioModemResponse, IRadioModemIndication radioModemIndication) { 168 Log.d(mTag, "setResponseFunctions"); 169 mRadioModemResponse = radioModemResponse; 170 mRadioModemIndication = radioModemIndication; 171 mService.countDownLatch(MockModemService.LATCH_RADIO_INTERFACES_READY); 172 } 173 174 @Override enableModem(int serial, boolean on)175 public void enableModem(int serial, boolean on) { 176 Log.d(mTag, "getNumOfLiveModems " + on); 177 178 // TODO: cache value 179 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 180 try { 181 mRadioModemResponse.enableModemResponse(rsp); 182 } catch (RemoteException ex) { 183 Log.e(mTag, "Failed to enableModem from AIDL. Exception" + ex); 184 } 185 } 186 187 @Override getBasebandVersion(int serial)188 public void getBasebandVersion(int serial) { 189 Log.d(mTag, "getBasebandVersion"); 190 191 String baseband; 192 193 synchronized (mCacheUpdateMutex) { 194 baseband = mBasebandVer; 195 } 196 197 RadioResponseInfo rsp = mService.makeSolRsp(serial); 198 try { 199 mRadioModemResponse.getBasebandVersionResponse(rsp, baseband); 200 } catch (RemoteException ex) { 201 Log.e(mTag, "Failed to getBasebandVersion from AIDL. Exception" + ex); 202 } 203 } 204 205 @Override getDeviceIdentity(int serial)206 public void getDeviceIdentity(int serial) { 207 Log.d(mTag, "getDeviceIdentity"); 208 209 String imei, imeisv, esn, meid; 210 211 synchronized (mCacheUpdateMutex) { 212 imei = mImei; 213 imeisv = mImeiSv; 214 esn = mEsn; 215 meid = mMeid; 216 } 217 218 RadioResponseInfo rsp = mService.makeSolRsp(serial); 219 try { 220 mRadioModemResponse.getDeviceIdentityResponse(rsp, imei, imeisv, esn, meid); 221 } catch (RemoteException ex) { 222 Log.e(mTag, "Failed to getDeviceIdentity from AIDL. Exception" + ex); 223 } 224 } 225 226 @Override getImei(int serial)227 public void getImei(int serial) { 228 Log.d(mTag, "getImei"); 229 android.hardware.radio.modem.ImeiInfo imeiInfo = 230 new android.hardware.radio.modem.ImeiInfo(); 231 synchronized (mCacheUpdateMutex) { 232 imeiInfo.type = mImeiType; 233 imeiInfo.imei = mImei; 234 imeiInfo.svn = mImeiSv; 235 } 236 RadioResponseInfo rsp = mService.makeSolRsp(serial); 237 try { 238 mRadioModemResponse.getImeiResponse(rsp, imeiInfo); 239 } catch (RemoteException ex) { 240 Log.e(mTag, "Failed to getImeiResponse from AIDL. Exception" + ex); 241 } 242 } 243 244 @Override getHardwareConfig(int serial)245 public void getHardwareConfig(int serial) { 246 Log.d(mTag, "getHardwareConfig"); 247 248 android.hardware.radio.modem.HardwareConfig[] config = 249 new android.hardware.radio.modem.HardwareConfig[0]; 250 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 251 try { 252 mRadioModemResponse.getHardwareConfigResponse(rsp, config); 253 } catch (RemoteException ex) { 254 Log.e(mTag, "Failed to getHardwareConfig from AIDL. Exception" + ex); 255 } 256 } 257 258 @Override getModemActivityInfo(int serial)259 public void getModemActivityInfo(int serial) { 260 Log.d(mTag, "getModemActivityInfo"); 261 262 android.hardware.radio.modem.ActivityStatsInfo activityInfo = 263 new android.hardware.radio.modem.ActivityStatsInfo(); 264 265 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 266 try { 267 mRadioModemResponse.getModemActivityInfoResponse(rsp, activityInfo); 268 } catch (RemoteException ex) { 269 Log.e(mTag, "Failed to getModemActivityInfo from AIDL. Exception" + ex); 270 } 271 } 272 273 @Override getModemStackStatus(int serial)274 public void getModemStackStatus(int serial) { 275 Log.d(mTag, "getModemStackStatus"); 276 277 boolean isEnabled = false; 278 279 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 280 try { 281 mRadioModemResponse.getModemStackStatusResponse(rsp, isEnabled); 282 } catch (RemoteException ex) { 283 Log.e(mTag, "Failed to getModemStackStatus from AIDL. Exception" + ex); 284 } 285 } 286 287 @Override getRadioCapability(int serial)288 public void getRadioCapability(int serial) { 289 Log.d(mTag, "getRadioCapability"); 290 291 android.hardware.radio.modem.RadioCapability rc = 292 new android.hardware.radio.modem.RadioCapability(); 293 294 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 295 try { 296 mRadioModemResponse.getRadioCapabilityResponse(rsp, rc); 297 } catch (RemoteException ex) { 298 Log.e(mTag, "Failed to getRadioCapability from AIDL. Exception" + ex); 299 } 300 } 301 302 @Override nvReadItem(int serial, int itemId)303 public void nvReadItem(int serial, int itemId) { 304 Log.d(mTag, "nvReadItem"); 305 306 // TODO: cache value 307 String result = ""; 308 309 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 310 try { 311 mRadioModemResponse.nvReadItemResponse(rsp, result); 312 } catch (RemoteException ex) { 313 Log.e(mTag, "Failed to nvReadItem from AIDL. Exception" + ex); 314 } 315 } 316 317 @Override nvResetConfig(int serial, int resetType)318 public void nvResetConfig(int serial, int resetType) { 319 Log.d(mTag, "nvResetConfig"); 320 321 // TODO: cache value 322 323 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 324 try { 325 mRadioModemResponse.nvResetConfigResponse(rsp); 326 } catch (RemoteException ex) { 327 Log.e(mTag, "Failed to nvResetConfig from AIDL. Exception" + ex); 328 } 329 } 330 331 @Override nvWriteCdmaPrl(int serial, byte[] prl)332 public void nvWriteCdmaPrl(int serial, byte[] prl) { 333 Log.d(mTag, "nvWriteCdmaPrl"); 334 335 // TODO: cache value 336 337 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 338 try { 339 mRadioModemResponse.nvWriteCdmaPrlResponse(rsp); 340 } catch (RemoteException ex) { 341 Log.e(mTag, "Failed to nvWriteCdmaPrl from AIDL. Exception" + ex); 342 } 343 } 344 345 @Override nvWriteItem(int serial, android.hardware.radio.modem.NvWriteItem item)346 public void nvWriteItem(int serial, android.hardware.radio.modem.NvWriteItem item) { 347 Log.d(mTag, "nvWriteItem"); 348 349 // TODO: cache value 350 351 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 352 try { 353 mRadioModemResponse.nvWriteItemResponse(rsp); 354 } catch (RemoteException ex) { 355 Log.e(mTag, "Failed to nvWriteItem from AIDL. Exception" + ex); 356 } 357 } 358 359 @Override requestShutdown(int serial)360 public void requestShutdown(int serial) { 361 Log.d(mTag, "requestShutdown"); 362 363 RadioResponseInfo rsp = mService.makeSolRsp(serial); 364 try { 365 mRadioModemResponse.requestShutdownResponse(rsp); 366 } catch (RemoteException ex) { 367 Log.e(mTag, "Failed to requestShutdown from AIDL. Exception" + ex); 368 } 369 } 370 371 @Override sendDeviceState(int serial, int deviceStateType, boolean state)372 public void sendDeviceState(int serial, int deviceStateType, boolean state) { 373 Log.d(mTag, "sendDeviceState"); 374 375 // TODO: cache value 376 377 RadioResponseInfo rsp = mService.makeSolRsp(serial); 378 try { 379 mRadioModemResponse.sendDeviceStateResponse(rsp); 380 } catch (RemoteException ex) { 381 Log.e(mTag, "Failed to sendDeviceState from AIDL. Exception" + ex); 382 } 383 } 384 385 @Override responseAcknowledgement()386 public void responseAcknowledgement() { 387 Log.d(mTag, "responseAcknowledgement"); 388 } 389 390 @Override setRadioCapability(int serial, android.hardware.radio.modem.RadioCapability rc)391 public void setRadioCapability(int serial, android.hardware.radio.modem.RadioCapability rc) { 392 Log.d(mTag, "setRadioCapability"); 393 394 // TODO: cache value 395 android.hardware.radio.modem.RadioCapability respRc = 396 new android.hardware.radio.modem.RadioCapability(); 397 398 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 399 try { 400 mRadioModemResponse.setRadioCapabilityResponse(rsp, respRc); 401 } catch (RemoteException ex) { 402 Log.e(mTag, "Failed to setRadioCapability from AIDL. Exception" + ex); 403 } 404 } 405 406 @Override setRadioPower( int serial, boolean powerOn, boolean forEmergencyCall, boolean preferredForEmergencyCall)407 public void setRadioPower( 408 int serial, 409 boolean powerOn, 410 boolean forEmergencyCall, 411 boolean preferredForEmergencyCall) { 412 Log.d(mTag, "setRadioPower"); 413 RadioResponseInfo rsp = null; 414 415 // Check if the error response needs to be modified 416 if (mForceRadioPowerError != -1) { 417 rsp = mService.makeSolRsp(serial, mForceRadioPowerError); 418 } else { 419 synchronized (mCacheUpdateMutex) { 420 if (powerOn) { 421 mRadioState = MockModemConfigInterface.RADIO_STATE_ON; 422 } else { 423 mRadioState = MockModemConfigInterface.RADIO_STATE_OFF; 424 } 425 mMockModemConfigInterface.setRadioState(mSubId, mRadioState, mTag); 426 } 427 rsp = mService.makeSolRsp(serial); 428 } 429 430 try { 431 mRadioModemResponse.setRadioPowerResponse(rsp); 432 } catch (RemoteException ex) { 433 Log.e(mTag, "Failed to setRadioPower from AIDL. Exception" + ex); 434 } 435 436 if (rsp.error == RadioError.NONE) { 437 if (powerOn) { 438 radioStateChanged(RadioState.ON); 439 } else { 440 radioStateChanged(RadioState.OFF); 441 } 442 } 443 } 444 445 /** 446 * Sent when setRadioCapability() completes. Returns the same RadioCapability as 447 * getRadioCapability() and is the same as the one sent by setRadioCapability(). 448 * 449 * @param radioCapability Current radio capability 450 */ radioCapabilityIndication( android.hardware.radio.modem.RadioCapability radioCapability)451 public void radioCapabilityIndication( 452 android.hardware.radio.modem.RadioCapability radioCapability) { 453 Log.d(mTag, "radioCapabilityIndication"); 454 455 if (mRadioModemIndication != null) { 456 try { 457 mRadioModemIndication.radioCapabilityIndication( 458 RadioIndicationType.UNSOLICITED, radioCapability); 459 } catch (RemoteException ex) { 460 Log.e(mTag, "Failed to radioCapabilityIndication from AIDL. Exception" + ex); 461 } 462 } else { 463 464 Log.e(mTag, "null mRadioModemIndication"); 465 } 466 } 467 468 /** 469 * Indicates when radio state changes. 470 * 471 * @param radioState Current radio state 472 */ radioStateChanged(int radioState)473 public void radioStateChanged(int radioState) { 474 Log.d(mTag, "radioStateChanged"); 475 476 if (mRadioModemIndication != null) { 477 try { 478 mRadioModemIndication.radioStateChanged( 479 RadioIndicationType.UNSOLICITED, radioState); 480 } catch (RemoteException ex) { 481 Log.e(mTag, "Failed to radioStateChanged from AIDL. Exception" + ex); 482 } 483 } else { 484 485 Log.e(mTag, "null mRadioModemIndication"); 486 } 487 } 488 489 /** Indicates the ril connects and returns the version. */ rilConnected()490 public void rilConnected() { 491 Log.d(mTag, "rilConnected"); 492 493 if (mRadioModemIndication != null) { 494 try { 495 mRadioModemIndication.rilConnected(RadioIndicationType.UNSOLICITED); 496 } catch (RemoteException ex) { 497 Log.e(mTag, "Failed to rilConnected from AIDL. Exception" + ex); 498 } 499 } else { 500 501 Log.e(mTag, "null mRadioModemIndication"); 502 } 503 } 504 forceErrorResponse(int requestId, int error)505 public void forceErrorResponse(int requestId, int error) { 506 switch (requestId) { 507 case RIL_REQUEST_RADIO_POWER: 508 mForceRadioPowerError = error; 509 break; 510 default: 511 break; 512 } 513 } 514 515 @Override getInterfaceHash()516 public String getInterfaceHash() { 517 return IRadioModem.HASH; 518 } 519 520 @Override getInterfaceVersion()521 public int getInterfaceVersion() { 522 return IRadioModem.VERSION; 523 } 524 } 525