• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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