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 android.hardware.radio.RadioError; 20 import android.hardware.radio.RadioIndicationType; 21 import android.hardware.radio.RadioResponseInfo; 22 import android.hardware.radio.messaging.IRadioMessaging; 23 import android.hardware.radio.messaging.IRadioMessagingIndication; 24 import android.hardware.radio.messaging.IRadioMessagingResponse; 25 import android.os.RemoteException; 26 import android.support.annotation.GuardedBy; 27 import android.util.ArraySet; 28 import android.util.Log; 29 30 import java.util.Set; 31 import java.util.concurrent.CopyOnWriteArrayList; 32 import java.util.concurrent.Executor; 33 34 public class IRadioMessagingImpl extends IRadioMessaging.Stub { 35 private static final String TAG = "MRMSG"; 36 37 private final MockModemService mService; 38 private IRadioMessagingResponse mRadioMessagingResponse; 39 private IRadioMessagingIndication mRadioMessagingIndication; 40 41 @GuardedBy("mGsmBroadcastConfigSet") 42 private final Set<Integer> mGsmBroadcastConfigSet = new ArraySet<Integer>(); 43 44 @GuardedBy("mCdmaBroadcastConfigSet") 45 private final Set<Integer> mCdmaBroadcastConfigSet = new ArraySet<Integer>(); 46 47 private CopyOnWriteArrayList<CallBackWithExecutor> mBroadcastCallbacks = 48 new CopyOnWriteArrayList<>(); 49 50 private MockModemConfigInterface mMockModemConfigInterface; 51 private int mSubId; 52 private String mTag; 53 54 public interface BroadcastCallback { onGsmBroadcastActivated()55 void onGsmBroadcastActivated(); onCdmaBroadcastActivated()56 void onCdmaBroadcastActivated(); 57 } 58 59 public static class CallBackWithExecutor { 60 public Executor mExecutor; 61 public BroadcastCallback mCallback; 62 CallBackWithExecutor(Executor executor, BroadcastCallback callback)63 public CallBackWithExecutor(Executor executor, BroadcastCallback callback) { 64 mExecutor = executor; 65 mCallback = callback; 66 } 67 } 68 IRadioMessagingImpl( MockModemService service, MockModemConfigInterface configInterface, int instanceId)69 public IRadioMessagingImpl( 70 MockModemService service, MockModemConfigInterface configInterface, int instanceId) { 71 mTag = TAG + "-" + instanceId; 72 Log.d(mTag, "Instantiated"); 73 74 this.mService = service; 75 mMockModemConfigInterface = configInterface; 76 mSubId = instanceId; 77 } 78 79 // Implementation of IRadioMessaging functions 80 @Override setResponseFunctions( IRadioMessagingResponse radioMessagingResponse, IRadioMessagingIndication radioMessagingIndication)81 public void setResponseFunctions( 82 IRadioMessagingResponse radioMessagingResponse, 83 IRadioMessagingIndication radioMessagingIndication) { 84 Log.d(mTag, "setResponseFunctions"); 85 mRadioMessagingResponse = radioMessagingResponse; 86 mRadioMessagingIndication = radioMessagingIndication; 87 mService.countDownLatch(MockModemService.LATCH_RADIO_INTERFACES_READY); 88 } 89 90 @Override acknowledgeIncomingGsmSmsWithPdu(int serial, boolean success, String ackPdu)91 public void acknowledgeIncomingGsmSmsWithPdu(int serial, boolean success, String ackPdu) { 92 Log.d(mTag, "acknowledgeIncomingGsmSmsWithPdu"); 93 94 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 95 try { 96 mRadioMessagingResponse.acknowledgeIncomingGsmSmsWithPduResponse(rsp); 97 } catch (RemoteException ex) { 98 Log.e(mTag, "Failed to acknowledgeIncomingGsmSmsWithPdu from AIDL. Exception" + ex); 99 } 100 } 101 102 @Override acknowledgeLastIncomingCdmaSms( int serial, android.hardware.radio.messaging.CdmaSmsAck smsAck)103 public void acknowledgeLastIncomingCdmaSms( 104 int serial, android.hardware.radio.messaging.CdmaSmsAck smsAck) { 105 Log.d(mTag, "acknowledgeLastIncomingCdmaSms"); 106 107 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 108 try { 109 mRadioMessagingResponse.acknowledgeLastIncomingCdmaSmsResponse(rsp); 110 } catch (RemoteException ex) { 111 Log.e(mTag, "Failed to acknowledgeLastIncomingCdmaSms from AIDL. Exception" + ex); 112 } 113 } 114 115 @Override acknowledgeLastIncomingGsmSms(int serial, boolean success, int cause)116 public void acknowledgeLastIncomingGsmSms(int serial, boolean success, int cause) { 117 Log.d(mTag, "acknowledgeLastIncomingGsmSms"); 118 119 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 120 try { 121 mRadioMessagingResponse.acknowledgeLastIncomingGsmSmsResponse(rsp); 122 } catch (RemoteException ex) { 123 Log.e(mTag, "Failed to acknowledgeLastIncomingGsmSms from AIDL. Exception" + ex); 124 } 125 } 126 127 @Override deleteSmsOnRuim(int serial, int index)128 public void deleteSmsOnRuim(int serial, int index) { 129 Log.d(mTag, "deleteSmsOnRuim"); 130 131 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 132 try { 133 mRadioMessagingResponse.deleteSmsOnRuimResponse(rsp); 134 } catch (RemoteException ex) { 135 Log.e(mTag, "Failed to deleteSmsOnRuim from AIDL. Exception" + ex); 136 } 137 } 138 139 @Override deleteSmsOnSim(int serial, int index)140 public void deleteSmsOnSim(int serial, int index) { 141 Log.d(mTag, "deleteSmsOnSim"); 142 143 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 144 try { 145 mRadioMessagingResponse.deleteSmsOnSimResponse(rsp); 146 } catch (RemoteException ex) { 147 Log.e(mTag, "Failed to deleteSmsOnSim from AIDL. Exception" + ex); 148 } 149 } 150 151 @Override getCdmaBroadcastConfig(int serial)152 public void getCdmaBroadcastConfig(int serial) { 153 Log.d(mTag, "getCdmaBroadcastConfig"); 154 155 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 156 try { 157 mRadioMessagingResponse.getCdmaBroadcastConfigResponse(rsp, null); 158 } catch (RemoteException ex) { 159 Log.e(mTag, "Failed to getCdmaBroadcastConfig from AIDL. Exception" + ex); 160 } 161 } 162 163 @Override getGsmBroadcastConfig(int serial)164 public void getGsmBroadcastConfig(int serial) { 165 Log.d(mTag, "getGsmBroadcastConfig"); 166 167 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 168 try { 169 mRadioMessagingResponse.getGsmBroadcastConfigResponse(rsp, null); 170 } catch (RemoteException ex) { 171 Log.e(mTag, "Failed to getGsmBroadcastConfig from AIDL. Exception" + ex); 172 } 173 } 174 175 @Override getSmscAddress(int serial)176 public void getSmscAddress(int serial) { 177 Log.d(mTag, "getSmscAddress"); 178 179 String smsc = ""; 180 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 181 try { 182 mRadioMessagingResponse.getSmscAddressResponse(rsp, smsc); 183 } catch (RemoteException ex) { 184 Log.e(mTag, "Failed to getSmscAddress from AIDL. Exception" + ex); 185 } 186 } 187 188 @Override reportSmsMemoryStatus(int serial, boolean available)189 public void reportSmsMemoryStatus(int serial, boolean available) { 190 Log.d(mTag, "reportSmsMemoryStatus"); 191 192 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 193 try { 194 mRadioMessagingResponse.reportSmsMemoryStatusResponse(rsp); 195 } catch (RemoteException ex) { 196 Log.e(mTag, "Failed to reportSmsMemoryStatus from AIDL. Exception" + ex); 197 } 198 } 199 200 @Override responseAcknowledgement()201 public void responseAcknowledgement() { 202 Log.d(mTag, "responseAcknowledgement"); 203 // TODO 204 } 205 206 @Override sendCdmaSms(int serial, android.hardware.radio.messaging.CdmaSmsMessage sms)207 public void sendCdmaSms(int serial, android.hardware.radio.messaging.CdmaSmsMessage sms) { 208 Log.d(mTag, "sendCdmaSms"); 209 210 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 211 try { 212 mRadioMessagingResponse.sendCdmaSmsResponse(rsp, null); 213 } catch (RemoteException ex) { 214 Log.e(mTag, "Failed to sendCdmaSms from AIDL. Exception" + ex); 215 } 216 } 217 218 @Override sendCdmaSmsExpectMore( int serial, android.hardware.radio.messaging.CdmaSmsMessage sms)219 public void sendCdmaSmsExpectMore( 220 int serial, android.hardware.radio.messaging.CdmaSmsMessage sms) { 221 Log.d(mTag, "sendCdmaSmsExpectMore"); 222 223 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 224 try { 225 mRadioMessagingResponse.sendCdmaSmsExpectMoreResponse(rsp, null); 226 } catch (RemoteException ex) { 227 Log.e(mTag, "Failed to sendCdmaSmsExpectMore from AIDL. Exception" + ex); 228 } 229 } 230 231 @Override sendImsSms(int serial, android.hardware.radio.messaging.ImsSmsMessage message)232 public void sendImsSms(int serial, android.hardware.radio.messaging.ImsSmsMessage message) { 233 Log.d(mTag, "sendImsSms"); 234 235 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 236 try { 237 mRadioMessagingResponse.sendImsSmsResponse(rsp, null); 238 } catch (RemoteException ex) { 239 Log.e(mTag, "Failed to sendImsSms from AIDL. Exception" + ex); 240 } 241 } 242 243 @Override sendSms(int serial, android.hardware.radio.messaging.GsmSmsMessage message)244 public void sendSms(int serial, android.hardware.radio.messaging.GsmSmsMessage message) { 245 Log.d(mTag, "sendSms"); 246 247 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 248 try { 249 mRadioMessagingResponse.sendSmsResponse(rsp, null); 250 } catch (RemoteException ex) { 251 Log.e(mTag, "Failed to sendSms from AIDL. Exception" + ex); 252 } 253 } 254 255 @Override sendSmsExpectMore( int serial, android.hardware.radio.messaging.GsmSmsMessage message)256 public void sendSmsExpectMore( 257 int serial, android.hardware.radio.messaging.GsmSmsMessage message) { 258 Log.d(mTag, "sendSmsExpectMore"); 259 260 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 261 try { 262 mRadioMessagingResponse.sendSmsExpectMoreResponse(rsp, null); 263 } catch (RemoteException ex) { 264 Log.e(mTag, "Failed to sendSmsExpectMore from AIDL. Exception" + ex); 265 } 266 } 267 268 @Override setCdmaBroadcastActivation(int serial, boolean activate)269 public void setCdmaBroadcastActivation(int serial, boolean activate) { 270 Log.d(mTag, "setCdmaBroadcastActivation, activate = " + activate); 271 272 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.NONE); 273 try { 274 mRadioMessagingResponse.setCdmaBroadcastActivationResponse(rsp); 275 } catch (RemoteException ex) { 276 Log.e(mTag, "Failed to setCdmaBroadcastActivation from AIDL. Exception" + ex); 277 } 278 if (activate) { 279 for (CallBackWithExecutor callbackWithExecutor : mBroadcastCallbacks) { 280 callbackWithExecutor.mExecutor.execute( 281 () -> callbackWithExecutor.mCallback.onCdmaBroadcastActivated()); 282 } 283 } 284 } 285 286 @Override setCdmaBroadcastConfig( int serial, android.hardware.radio.messaging.CdmaBroadcastSmsConfigInfo[] configInfo)287 public void setCdmaBroadcastConfig( 288 int serial, android.hardware.radio.messaging.CdmaBroadcastSmsConfigInfo[] configInfo) { 289 Log.d(mTag, "setCdmaBroadcastConfig"); 290 291 int error = RadioError.NONE; 292 if (configInfo == null) { 293 error = RadioError.INVALID_ARGUMENTS; 294 } else { 295 synchronized (mCdmaBroadcastConfigSet) { 296 mCdmaBroadcastConfigSet.clear(); 297 for (int i = 0; i < configInfo.length; i++) { 298 Log.d(mTag, "configInfo serviceCategory" + configInfo[i].serviceCategory); 299 mCdmaBroadcastConfigSet.add(configInfo[i].serviceCategory); 300 } 301 } 302 } 303 RadioResponseInfo rsp = mService.makeSolRsp(serial, error); 304 try { 305 mRadioMessagingResponse.setCdmaBroadcastConfigResponse(rsp); 306 } catch (RemoteException ex) { 307 Log.e(mTag, "Failed to setCdmaBroadcastConfig from AIDL. Exception" + ex); 308 } 309 } 310 311 @Override setGsmBroadcastActivation(int serial, boolean activate)312 public void setGsmBroadcastActivation(int serial, boolean activate) { 313 Log.d(mTag, "setGsmBroadcastActivation, activate = " + activate); 314 315 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.NONE); 316 try { 317 mRadioMessagingResponse.setGsmBroadcastActivationResponse(rsp); 318 } catch (RemoteException ex) { 319 Log.e(mTag, "Failed to setGsmBroadcastActivation from AIDL. Exception" + ex); 320 } 321 if (activate) { 322 for (CallBackWithExecutor callbackWithExecutor : mBroadcastCallbacks) { 323 callbackWithExecutor.mExecutor.execute( 324 () -> callbackWithExecutor.mCallback.onGsmBroadcastActivated()); 325 } 326 } 327 } 328 329 @Override setGsmBroadcastConfig( int serial, android.hardware.radio.messaging.GsmBroadcastSmsConfigInfo[] configInfo)330 public void setGsmBroadcastConfig( 331 int serial, android.hardware.radio.messaging.GsmBroadcastSmsConfigInfo[] configInfo) { 332 Log.d(mTag, "setGsmBroadcastConfig"); 333 334 int error = RadioError.NONE; 335 if (configInfo == null) { 336 error = RadioError.INVALID_ARGUMENTS; 337 } else { 338 synchronized (mGsmBroadcastConfigSet) { 339 mGsmBroadcastConfigSet.clear(); 340 for (int i = 0; i < configInfo.length; i++) { 341 int startId = configInfo[i].fromServiceId; 342 int endId = configInfo[i].toServiceId; 343 boolean selected = configInfo[i].selected; 344 Log.d( 345 mTag, 346 "configInfo from: " 347 + startId 348 + ", to: " 349 + endId 350 + ", selected: " 351 + selected); 352 if (selected) { 353 for (int j = startId; j <= endId; j++) { 354 mGsmBroadcastConfigSet.add(j); 355 } 356 } 357 } 358 } 359 } 360 RadioResponseInfo rsp = mService.makeSolRsp(serial, error); 361 try { 362 mRadioMessagingResponse.setGsmBroadcastConfigResponse(rsp); 363 } catch (RemoteException ex) { 364 Log.e(mTag, "Failed to setGsmBroadcastConfig from AIDL. Exception" + ex); 365 } 366 } 367 368 @Override setSmscAddress(int serial, String smsc)369 public void setSmscAddress(int serial, String smsc) { 370 Log.d(mTag, "setSmscAddress"); 371 372 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 373 try { 374 mRadioMessagingResponse.setSmscAddressResponse(rsp); 375 } catch (RemoteException ex) { 376 Log.e(mTag, "Failed to setSmscAddress from AIDL. Exception" + ex); 377 } 378 } 379 380 @Override writeSmsToRuim( int serial, android.hardware.radio.messaging.CdmaSmsWriteArgs cdmaSms)381 public void writeSmsToRuim( 382 int serial, android.hardware.radio.messaging.CdmaSmsWriteArgs cdmaSms) { 383 Log.d(mTag, "writeSmsToRuim"); 384 385 int index = 0; 386 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 387 try { 388 mRadioMessagingResponse.writeSmsToRuimResponse(rsp, index); 389 } catch (RemoteException ex) { 390 Log.e(mTag, "Failed to writeSmsToRuim from AIDL. Exception" + ex); 391 } 392 } 393 394 @Override writeSmsToSim( int serial, android.hardware.radio.messaging.SmsWriteArgs smsWriteArgs)395 public void writeSmsToSim( 396 int serial, android.hardware.radio.messaging.SmsWriteArgs smsWriteArgs) { 397 Log.d(mTag, "writeSmsToSim"); 398 399 int index = 0; 400 RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED); 401 try { 402 mRadioMessagingResponse.writeSmsToSimResponse(rsp, index); 403 } catch (RemoteException ex) { 404 Log.e(mTag, "Failed to writeSmsToSim from AIDL. Exception" + ex); 405 } 406 } 407 cdmaNewSms(android.hardware.radio.messaging.CdmaSmsMessage msg)408 public void cdmaNewSms(android.hardware.radio.messaging.CdmaSmsMessage msg) { 409 Log.d(mTag, "cdmaNewSms"); 410 411 if (mRadioMessagingIndication != null) { 412 try { 413 mRadioMessagingIndication.cdmaNewSms(RadioIndicationType.UNSOLICITED, msg); 414 } catch (RemoteException ex) { 415 Log.e(mTag, "Failed to cdmaNewSms indication from AIDL. Exception" + ex); 416 } 417 } else { 418 Log.e(mTag, "null mRadioMessagingIndication"); 419 } 420 } 421 cdmaRuimSmsStorageFull()422 public void cdmaRuimSmsStorageFull() { 423 Log.d(mTag, "cdmaRuimSmsStorageFull"); 424 425 if (mRadioMessagingIndication != null) { 426 try { 427 mRadioMessagingIndication.cdmaRuimSmsStorageFull(RadioIndicationType.UNSOLICITED); 428 } catch (RemoteException ex) { 429 Log.e( 430 mTag, 431 "Failed to cdmaRuimSmsStorageFull indication from AIDL. Exception" + ex); 432 } 433 } else { 434 Log.e(mTag, "null mRadioMessagingIndication"); 435 } 436 } 437 newBroadcastSms(byte[] data)438 public void newBroadcastSms(byte[] data) { 439 Log.d(mTag, "newBroadcastSms"); 440 441 if (mRadioMessagingIndication != null) { 442 try { 443 mRadioMessagingIndication.newBroadcastSms(RadioIndicationType.UNSOLICITED, data); 444 } catch (RemoteException ex) { 445 Log.e(mTag, "Failed to newBroadcastSms indication from AIDL. Exception" + ex); 446 } 447 } else { 448 Log.e(mTag, "null mRadioMessagingIndication"); 449 } 450 } 451 newSms(byte[] pdu)452 public void newSms(byte[] pdu) { 453 Log.d(mTag, "newSms"); 454 455 if (mRadioMessagingIndication != null) { 456 try { 457 mRadioMessagingIndication.newSms(RadioIndicationType.UNSOLICITED, pdu); 458 } catch (RemoteException ex) { 459 Log.e(mTag, "Failed to newSms indication from AIDL. Exception" + ex); 460 } 461 } else { 462 Log.e(mTag, "null mRadioMessagingIndication"); 463 } 464 } 465 newSmsOnSim(int recordNumber)466 public void newSmsOnSim(int recordNumber) { 467 Log.d(mTag, "newSmsOnSim"); 468 469 if (mRadioMessagingIndication != null) { 470 try { 471 mRadioMessagingIndication.newSmsOnSim( 472 RadioIndicationType.UNSOLICITED, recordNumber); 473 } catch (RemoteException ex) { 474 Log.e(mTag, "Failed to newSmsOnSim indication from AIDL. Exception" + ex); 475 } 476 } else { 477 Log.e(mTag, "null mRadioMessagingIndication"); 478 } 479 } 480 newSmsStatusReport(byte[] pdu)481 public void newSmsStatusReport(byte[] pdu) { 482 Log.d(mTag, "newSmsStatusReport"); 483 484 if (mRadioMessagingIndication != null) { 485 try { 486 mRadioMessagingIndication.newSmsStatusReport(RadioIndicationType.UNSOLICITED, pdu); 487 } catch (RemoteException ex) { 488 Log.e(mTag, "Failed to newSmsStatusReport indication from AIDL. Exception" + ex); 489 } 490 } else { 491 Log.e(mTag, "null mRadioMessagingIndication"); 492 } 493 } 494 simSmsStorageFull()495 public void simSmsStorageFull() { 496 Log.d(mTag, "simSmsStorageFull"); 497 498 if (mRadioMessagingIndication != null) { 499 try { 500 mRadioMessagingIndication.simSmsStorageFull(RadioIndicationType.UNSOLICITED); 501 } catch (RemoteException ex) { 502 Log.e(mTag, "Failed to simSmsStorageFull indication from AIDL. Exception" + ex); 503 } 504 } else { 505 Log.e(mTag, "null mRadioMessagingIndication"); 506 } 507 } 508 509 @Override getInterfaceHash()510 public String getInterfaceHash() { 511 return IRadioMessaging.HASH; 512 } 513 514 @Override getInterfaceVersion()515 public int getInterfaceVersion() { 516 return IRadioMessaging.VERSION; 517 } 518 getGsmBroadcastConfigSet()519 public Set<Integer> getGsmBroadcastConfigSet() { 520 synchronized (mGsmBroadcastConfigSet) { 521 Log.d(mTag, "getBroadcastConfigSet. " + mGsmBroadcastConfigSet); 522 return mGsmBroadcastConfigSet; 523 } 524 } 525 getCdmaBroadcastConfigSet()526 public Set<Integer> getCdmaBroadcastConfigSet() { 527 synchronized (mCdmaBroadcastConfigSet) { 528 Log.d(mTag, "getBroadcastConfigSet. " + mCdmaBroadcastConfigSet); 529 return mCdmaBroadcastConfigSet; 530 } 531 } 532 registerBroadcastCallback(CallBackWithExecutor callback)533 public void registerBroadcastCallback(CallBackWithExecutor callback) { 534 mBroadcastCallbacks.add(callback); 535 } unregisterBroadcastCallback(CallBackWithExecutor callback)536 public void unregisterBroadcastCallback(CallBackWithExecutor callback) { 537 mBroadcastCallbacks.remove(callback); 538 } 539 } 540