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