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.voice.EmergencyNumber;
23 import android.hardware.radio.voice.IRadioVoice;
24 import android.hardware.radio.voice.IRadioVoiceIndication;
25 import android.hardware.radio.voice.IRadioVoiceResponse;
26 import android.hardware.radio.voice.LastCallFailCauseInfo;
27 import android.os.AsyncResult;
28 import android.os.Handler;
29 import android.os.HandlerThread;
30 import android.os.Looper;
31 import android.os.Message;
32 import android.os.RemoteException;
33 import android.telephony.mockmodem.MockVoiceService.MockCallInfo;
34 import android.util.Log;
35 
36 import java.util.ArrayList;
37 import java.util.concurrent.CountDownLatch;
38 import java.util.concurrent.TimeUnit;
39 
40 public class IRadioVoiceImpl extends IRadioVoice.Stub {
41     private static final String TAG = "MRVOICE";
42 
43     public static final int LATCH_EMERGENCY_DIAL = 0;
44     public static final int LATCH_GET_LAST_CALL_FAIL_CAUSE = 1;
45     private static final int LATCH_MAX = 2;
46 
47     private final CountDownLatch[] mLatches = new CountDownLatch[LATCH_MAX];
48 
49     private final MockModemService mService;
50     private IRadioVoiceResponse mRadioVoiceResponse;
51     private IRadioVoiceIndication mRadioVoiceIndication;
52     private MockModemConfigInterface mMockModemConfigInterface;
53     private final Object mCacheUpdateMutex;
54     private final HandlerThread mHandlerThread;
55     private final Handler mHandler;
56     private int mSubId;
57     private String mTag;
58 
59     // ***** Events
60     static final int EVENT_CALL_STATE_CHANGED = 1;
61     static final int EVENT_CURRENT_CALLS_RESPONSE = 2;
62     static final int EVENT_CALL_INCOMING = 3;
63     static final int EVENT_RINGBACK_TONE = 4;
64 
65     // ***** Cache of modem attributes/status
66     private ArrayList<MockCallInfo> mCallList;
67     private ArrayList<Integer> mGetCurrentCallReqList;
68 
IRadioVoiceImpl( MockModemService service, MockModemConfigInterface configInterface, int instanceId)69     public IRadioVoiceImpl(
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         mCacheUpdateMutex = new Object();
78         mHandlerThread = new HandlerThread(mTag);
79         mHandlerThread.start();
80         mHandler = new IRadioVoiceHandler(mHandlerThread.getLooper());
81         mGetCurrentCallReqList = new ArrayList<Integer>();
82 
83         // Register events
84         mMockModemConfigInterface.registerForCallStateChanged(
85                 mSubId, mHandler, EVENT_CALL_STATE_CHANGED, null);
86         mMockModemConfigInterface.registerForCurrentCallsResponse(
87                 mSubId, mHandler, EVENT_CURRENT_CALLS_RESPONSE, null);
88         mMockModemConfigInterface.registerForCallIncoming(
89                 mSubId, mHandler, EVENT_CALL_INCOMING, null);
90         mMockModemConfigInterface.registerRingbackTone(mSubId, mHandler, EVENT_RINGBACK_TONE, null);
91 
92         for (int i = 0; i < LATCH_MAX; i++) {
93             mLatches[i] = new CountDownLatch(1);
94         }
95     }
96 
97     /** Handler class to handle callbacks */
98     private final class IRadioVoiceHandler extends Handler {
IRadioVoiceHandler(Looper looper)99         IRadioVoiceHandler(Looper looper) {
100             super(looper);
101         }
102 
103         @Override
handleMessage(Message msg)104         public void handleMessage(Message msg) {
105             AsyncResult ar;
106             synchronized (mCacheUpdateMutex) {
107                 switch (msg.what) {
108                     case EVENT_CALL_STATE_CHANGED:
109                         Log.d(mTag, "Received EVENT_CALL_STATE_CHANGED");
110                         ar = (AsyncResult) msg.obj;
111                         if (ar != null && ar.exception == null) {
112                             mCallList = (ArrayList<MockCallInfo>) ar.result;
113                             Log.i(mTag, "num of calls: " + mCallList.size());
114                             callStateChanged();
115                         } else {
116                             Log.e(mTag, msg.what + " failure. Exception: " + ar.exception);
117                         }
118                         break;
119                     case EVENT_CURRENT_CALLS_RESPONSE:
120                         Log.d(mTag, "Received EVENT_CURRENT_CALLS_RESPONSE");
121                         ar = (AsyncResult) msg.obj;
122                         if (ar != null && ar.exception == null) {
123                             final ArrayList<MockCallInfo> callList =
124                                     (ArrayList<MockCallInfo>) ar.result;
125                             synchronized (callList) {
126                                 mCallList = callList;
127                                 Log.i(
128                                         mTag,
129                                         "num of calls: "
130                                                 + mCallList.size()
131                                                 + ", num of getCurrentCalls requests: "
132                                                 + mGetCurrentCallReqList.size());
133                                 for (int i = 0; i < mGetCurrentCallReqList.size(); i++) {
134                                     getCurrentCallsRespnose(
135                                             mGetCurrentCallReqList.get(i).intValue());
136                                 }
137                                 mGetCurrentCallReqList.clear();
138                             }
139                         } else {
140                             Log.e(mTag, msg.what + " failure. Exception: " + ar.exception);
141                         }
142                         break;
143                     case EVENT_CALL_INCOMING:
144                         Log.d(mTag, "Received EVENT_CALL_INCOMING");
145                         ar = (AsyncResult) msg.obj;
146                         if (ar != null && ar.exception == null) {
147                             MockCallInfo callInfo = (MockCallInfo) ar.result;
148                             Log.i(mTag, "Incoming call id = " + callInfo.getCallId());
149                             boolean hasCdmaSignalInfoRecord =
150                                     (callInfo.getCdmaSignalInfoRecord() != null) ? true : false;
151                             callRing(!hasCdmaSignalInfoRecord, callInfo.getCdmaSignalInfoRecord());
152                         } else {
153                             Log.e(mTag, msg.what + " failure. Exception: " + ar.exception);
154                         }
155                         break;
156                     case EVENT_RINGBACK_TONE:
157                         Log.d(mTag, "Received EVENT_RINGBACK_TONE");
158                         ar = (AsyncResult) msg.obj;
159                         if (ar != null && ar.exception == null) {
160                             boolean ringbackToneState = (boolean) ar.result;
161                             Log.i(mTag, "ringbackToneState = " + ringbackToneState);
162                             indicateRingbackTone(ringbackToneState);
163                         } else {
164                             Log.e(mTag, msg.what + " failure. Exception: " + ar.exception);
165                         }
166                         break;
167                 }
168             }
169         }
170     }
171 
convertCallState(int callstate)172     private int convertCallState(int callstate) {
173         int state = -1;
174 
175         switch (callstate) {
176             case MockCallInfo.CALL_STATE_ACTIVE:
177                 state = android.hardware.radio.voice.Call.STATE_ACTIVE;
178                 break;
179 
180             case MockCallInfo.CALL_STATE_HOLDING:
181                 state = android.hardware.radio.voice.Call.STATE_HOLDING;
182                 break;
183 
184             case MockCallInfo.CALL_STATE_DIALING:
185                 state = android.hardware.radio.voice.Call.STATE_DIALING;
186                 break;
187 
188             case MockCallInfo.CALL_STATE_ALERTING:
189                 state = android.hardware.radio.voice.Call.STATE_ALERTING;
190                 break;
191 
192             case MockCallInfo.CALL_STATE_INCOMING:
193                 state = android.hardware.radio.voice.Call.STATE_INCOMING;
194                 break;
195 
196             case MockCallInfo.CALL_STATE_WAITING:
197                 state = android.hardware.radio.voice.Call.STATE_WAITING;
198                 break;
199 
200             default:
201                 Log.e(mTag, "Unknown call state = " + callstate);
202                 break;
203         }
204 
205         return state;
206     }
207 
fillUpCurrentCallsRespnose()208     private android.hardware.radio.voice.Call[] fillUpCurrentCallsRespnose() {
209         int numOfCalls = 0;
210         android.hardware.radio.voice.Call[] calls = null;
211 
212         if (mCallList != null) {
213             numOfCalls = mCallList.size();
214         }
215 
216         if (mMockModemConfigInterface != null
217                 && mMockModemConfigInterface.getNumberOfCalls(mSubId, mTag) == numOfCalls) {
218             calls = new android.hardware.radio.voice.Call[numOfCalls];
219 
220             if (calls != null) {
221                 for (int i = 0; i < numOfCalls; i++) {
222                     calls[i] = new android.hardware.radio.voice.Call();
223                     if (calls[i] != null) {
224                         calls[i].state = convertCallState(mCallList.get(i).getCallState());
225                         calls[i].index = mCallList.get(i).getCallId();
226                         calls[i].toa = mCallList.get(i).getCallToa();
227                         calls[i].isMpty = mCallList.get(i).isMpty();
228                         calls[i].isMT = mCallList.get(i).isMT();
229                         calls[i].als = mCallList.get(i).getCallAls();
230                         calls[i].isVoice = mCallList.get(i).isVoice();
231                         calls[i].isVoicePrivacy = mCallList.get(i).isVoicePrivacy();
232                         calls[i].number = mCallList.get(i).getNumber();
233                         calls[i].numberPresentation = mCallList.get(i).getNumberPresentation();
234                         calls[i].uusInfo = mCallList.get(i).getUusInfo();
235                         calls[i].audioQuality = mCallList.get(i).getAudioQuality();
236                         calls[i].forwardedNumber = mCallList.get(i).getForwardedNumber();
237                     } else {
238                         Log.e(
239                                 mTag,
240                                 "Failed to allocate memory for call " + i + "/" + numOfCalls + ".");
241                         break;
242                     }
243                 }
244             } else {
245                 Log.e(mTag, "Failed to allocate memory for calls.");
246             }
247         } else {
248             Log.e(mTag, "mMockModemConfigInterface != null or num of calls isn't matched.");
249         }
250 
251         return calls;
252     }
253 
getCurrentCallsRespnose(int serial)254     private void getCurrentCallsRespnose(int serial) {
255         int responseError = RadioError.NONE;
256         android.hardware.radio.voice.Call[] calls = fillUpCurrentCallsRespnose();
257 
258         if (calls == null) {
259             responseError = RadioError.INTERNAL_ERR;
260             Log.e(mTag, "calls == null!!");
261         }
262 
263         RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
264         try {
265             mRadioVoiceResponse.getCurrentCallsResponse(rsp, calls);
266         } catch (RemoteException ex) {
267             Log.e(mTag, "Failed to getCurrentCalls from AIDL. Exception" + ex);
268         }
269     }
270 
271     // Implementation of IRadioVoice functions
272     @Override
setResponseFunctions( IRadioVoiceResponse radioVoiceResponse, IRadioVoiceIndication radioVoiceIndication)273     public void setResponseFunctions(
274             IRadioVoiceResponse radioVoiceResponse, IRadioVoiceIndication radioVoiceIndication) {
275         Log.d(mTag, "setResponseFunctions");
276         mRadioVoiceResponse = radioVoiceResponse;
277         mRadioVoiceIndication = radioVoiceIndication;
278         mService.countDownLatch(MockModemService.LATCH_RADIO_INTERFACES_READY);
279     }
280 
281     @Override
acceptCall(int serial)282     public void acceptCall(int serial) {
283         Log.d(mTag, "acceptCall");
284         int responseError = RadioError.NONE;
285 
286         if (mMockModemConfigInterface != null) {
287             boolean ret = mMockModemConfigInterface.acceptVoiceCall(mSubId, mTag);
288 
289             if (!ret) {
290                 Log.e(mTag, "Failed: accept request failed");
291                 responseError = RadioError.INTERNAL_ERR;
292             }
293         } else {
294             Log.e(mTag, "Failed: mMockModemConfigInterface == null");
295             responseError = RadioError.INTERNAL_ERR;
296         }
297 
298         RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
299         try {
300             mRadioVoiceResponse.acceptCallResponse(rsp);
301         } catch (RemoteException ex) {
302             Log.e(mTag, "Failed to acceptCall from AIDL. Exception" + ex);
303         }
304     }
305 
306     @Override
cancelPendingUssd(int serial)307     public void cancelPendingUssd(int serial) {
308         Log.d(mTag, "cancelPendingUssd");
309 
310         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
311         try {
312             mRadioVoiceResponse.cancelPendingUssdResponse(rsp);
313         } catch (RemoteException ex) {
314             Log.e(mTag, "Failed to cancelPendingUssd from AIDL. Exception" + ex);
315         }
316     }
317 
318     @Override
conference(int serial)319     public void conference(int serial) {
320         Log.d(mTag, "conference");
321 
322         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
323         try {
324             mRadioVoiceResponse.conferenceResponse(rsp);
325         } catch (RemoteException ex) {
326             Log.e(mTag, "Failed to conference from AIDL. Exception" + ex);
327         }
328     }
329 
330     @Override
dial(int serial, android.hardware.radio.voice.Dial dialInfo)331     public void dial(int serial, android.hardware.radio.voice.Dial dialInfo) {
332         Log.d(mTag, "dial");
333         int responseError = RadioError.NONE;
334 
335         if (mMockModemConfigInterface != null) {
336             boolean ret =
337                     mMockModemConfigInterface.dialVoiceCall(
338                             mSubId, dialInfo.address, dialInfo.clir, dialInfo.uusInfo, mTag);
339 
340             if (!ret) {
341                 Log.e(mTag, "Failed: dial request failed");
342                 responseError = RadioError.INTERNAL_ERR;
343             }
344         } else {
345             Log.e(mTag, "Failed: mMockModemConfigInterface == null");
346             responseError = RadioError.INTERNAL_ERR;
347         }
348 
349         RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
350         try {
351             mRadioVoiceResponse.dialResponse(rsp);
352         } catch (RemoteException ex) {
353             Log.e(mTag, "Failed to dial from AIDL. Exception" + ex);
354         }
355     }
356 
357     @Override
emergencyDial( int serial, android.hardware.radio.voice.Dial dialInfo, int categories, String[] urns, int routing, boolean hasKnownUserIntentEmergency, boolean isTesting)358     public void emergencyDial(
359             int serial,
360             android.hardware.radio.voice.Dial dialInfo,
361             int categories,
362             String[] urns,
363             int routing,
364             boolean hasKnownUserIntentEmergency,
365             boolean isTesting) {
366         Log.d(mTag, "emergencyDial");
367         int responseError = RadioError.NONE;
368 
369         if (mMockModemConfigInterface != null) {
370             boolean ret =
371                     mMockModemConfigInterface.dialEccVoiceCall(
372                             mSubId, dialInfo.address, categories, urns, routing, mTag);
373 
374             if (!ret) {
375                 Log.e(mTag, "Failed: dial request failed");
376                 responseError = RadioError.INTERNAL_ERR;
377             }
378         } else {
379             Log.e(mTag, "Failed: mMockModemConfigInterface == null");
380             responseError = RadioError.INTERNAL_ERR;
381         }
382 
383         RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
384         try {
385             mRadioVoiceResponse.emergencyDialResponse(rsp);
386         } catch (RemoteException ex) {
387             Log.e(mTag, "Failed to emergencyDial from AIDL. Exception" + ex);
388         }
389 
390         countDownLatch(LATCH_EMERGENCY_DIAL);
391         resetLatch(LATCH_GET_LAST_CALL_FAIL_CAUSE);
392     }
393 
394     @Override
exitEmergencyCallbackMode(int serial)395     public void exitEmergencyCallbackMode(int serial) {
396         Log.d(mTag, "exitEmergencyCallbackMode");
397 
398         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
399         try {
400             mRadioVoiceResponse.exitEmergencyCallbackModeResponse(rsp);
401         } catch (RemoteException ex) {
402             Log.e(mTag, "Failed to exitEmergencyCallbackMode from AIDL. Exception" + ex);
403         }
404     }
405 
406     @Override
explicitCallTransfer(int serial)407     public void explicitCallTransfer(int serial) {
408         Log.d(mTag, "explicitCallTransfer");
409 
410         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
411         try {
412             mRadioVoiceResponse.explicitCallTransferResponse(rsp);
413         } catch (RemoteException ex) {
414             Log.e(mTag, "Failed to explicitCallTransfer from AIDL. Exception" + ex);
415         }
416     }
417 
418     @Override
getCallForwardStatus( int serial, android.hardware.radio.voice.CallForwardInfo callInfo)419     public void getCallForwardStatus(
420             int serial, android.hardware.radio.voice.CallForwardInfo callInfo) {
421         Log.d(mTag, "getCallForwardStatus");
422 
423         android.hardware.radio.voice.CallForwardInfo[] callForwardInfos =
424                 new android.hardware.radio.voice.CallForwardInfo[0];
425         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
426         try {
427             mRadioVoiceResponse.getCallForwardStatusResponse(rsp, callForwardInfos);
428         } catch (RemoteException ex) {
429             Log.e(mTag, "Failed to getCallForwardStatus from AIDL. Exception" + ex);
430         }
431     }
432 
433     @Override
getCallWaiting(int serial, int serviceClass)434     public void getCallWaiting(int serial, int serviceClass) {
435         Log.d(mTag, "getCallWaiting");
436 
437         boolean enable = false;
438         int rspServiceClass = 0;
439         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
440         try {
441             mRadioVoiceResponse.getCallWaitingResponse(rsp, enable, rspServiceClass);
442         } catch (RemoteException ex) {
443             Log.e(mTag, "Failed to getCallWaiting from AIDL. Exception" + ex);
444         }
445     }
446 
447     @Override
getClip(int serial)448     public void getClip(int serial) {
449         Log.d(mTag, "getClip");
450 
451         int status = 0;
452         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
453         try {
454             mRadioVoiceResponse.getClipResponse(rsp, status);
455         } catch (RemoteException ex) {
456             Log.e(mTag, "Failed to getClip from AIDL. Exception" + ex);
457         }
458     }
459 
460     @Override
getClir(int serial)461     public void getClir(int serial) {
462         Log.d(mTag, "getClir");
463 
464         int n = 0;
465         int m = 0;
466         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
467         try {
468             mRadioVoiceResponse.getClirResponse(rsp, n, m);
469         } catch (RemoteException ex) {
470             Log.e(mTag, "Failed to getClir from AIDL. Exception" + ex);
471         }
472     }
473 
474     @Override
getCurrentCalls(int serial)475     public void getCurrentCalls(int serial) {
476         Log.d(mTag, "getCurrentCalls");
477 
478         int responseError = RadioError.NONE;
479 
480         if (mMockModemConfigInterface != null) {
481             Integer request = Integer.valueOf(serial);
482 
483             synchronized (mCacheUpdateMutex) {
484                 if (mGetCurrentCallReqList != null && request != null) {
485                     mGetCurrentCallReqList.add(request);
486                     Log.d(mTag, "Add GetCurrentCallReq");
487                 } else {
488                     Log.e(mTag, "Failed: mGetCurrentCallReqList == null or request == null");
489                     responseError = RadioError.INTERNAL_ERR;
490                 }
491             }
492 
493             if (responseError == RadioError.NONE) {
494                 boolean ret = mMockModemConfigInterface.getCurrentCalls(mSubId, mTag);
495 
496                 if (!ret) {
497                     Log.e(mTag, "Failed: getCurrentCalls request failed");
498                     responseError = RadioError.INTERNAL_ERR;
499                 }
500             }
501         } else {
502             Log.e(mTag, "Failed: mMockModemConfigInterface == null");
503             responseError = RadioError.INTERNAL_ERR;
504         }
505 
506         if (responseError != RadioError.NONE) {
507             android.hardware.radio.voice.Call[] calls = new android.hardware.radio.voice.Call[0];
508             RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
509             try {
510                 mRadioVoiceResponse.getCurrentCallsResponse(rsp, calls);
511             } catch (RemoteException ex) {
512                 Log.e(mTag, "Failed to getCurrentCalls from AIDL. Exception" + ex);
513             }
514         }
515     }
516 
517     @Override
getLastCallFailCause(int serial)518     public void getLastCallFailCause(int serial) {
519         Log.d(mTag, "getLastCallFailCause");
520         LastCallFailCauseInfo failCauseInfo = null;
521         int responseError = RadioError.NONE;
522 
523         if (mMockModemConfigInterface != null) {
524             failCauseInfo = mMockModemConfigInterface.getLastCallFailCause(mSubId, mTag);
525 
526             if (failCauseInfo == null) {
527                 Log.e(mTag, "Failed: get last call fail cause request failed");
528                 responseError = RadioError.INTERNAL_ERR;
529             }
530         } else {
531             Log.e(mTag, "Failed: mMockModemConfigInterface == null");
532             responseError = RadioError.INTERNAL_ERR;
533         }
534 
535         RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
536         try {
537             mRadioVoiceResponse.getLastCallFailCauseResponse(rsp, failCauseInfo);
538         } catch (RemoteException ex) {
539             Log.e(mTag, "Failed to getLastCallFailCause from AIDL. Exception" + ex);
540         }
541         countDownLatch(LATCH_GET_LAST_CALL_FAIL_CAUSE);
542     }
543 
544     @Override
getMute(int serial)545     public void getMute(int serial) {
546         Log.d(mTag, "getMute");
547         int responseError = RadioError.NONE;
548         boolean muteMode = false;
549 
550         if (mMockModemConfigInterface != null) {
551             muteMode = mMockModemConfigInterface.getVoiceMuteMode(mSubId, mTag);
552         } else {
553             Log.e(mTag, "Failed: mMockModemConfigInterface == null");
554             responseError = RadioError.INTERNAL_ERR;
555         }
556 
557         RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
558         try {
559             mRadioVoiceResponse.getMuteResponse(rsp, muteMode);
560         } catch (RemoteException ex) {
561             Log.e(mTag, "Failed to getMute from AIDL. Exception" + ex);
562         }
563     }
564 
565     @Override
getPreferredVoicePrivacy(int serial)566     public void getPreferredVoicePrivacy(int serial) {
567         Log.d(mTag, "getPreferredVoicePrivacy");
568 
569         boolean enable = false;
570         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
571         try {
572             mRadioVoiceResponse.getPreferredVoicePrivacyResponse(rsp, enable);
573         } catch (RemoteException ex) {
574             Log.e(mTag, "Failed to getPreferredVoicePrivacy from AIDL. Exception" + ex);
575         }
576     }
577 
578     @Override
getTtyMode(int serial)579     public void getTtyMode(int serial) {
580         Log.d(mTag, "getTtyMode");
581 
582         int mode = 0;
583         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
584         try {
585             mRadioVoiceResponse.getTtyModeResponse(rsp, mode);
586         } catch (RemoteException ex) {
587             Log.e(mTag, "Failed to getTtyMode from AIDL. Exception" + ex);
588         }
589     }
590 
591     @Override
handleStkCallSetupRequestFromSim(int serial, boolean accept)592     public void handleStkCallSetupRequestFromSim(int serial, boolean accept) {
593         Log.d(mTag, "handleStkCallSetupRequestFromSim");
594 
595         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
596         try {
597             mRadioVoiceResponse.handleStkCallSetupRequestFromSimResponse(rsp);
598         } catch (RemoteException ex) {
599             Log.e(mTag, "Failed to handleStkCallSetupRequestFromSim from AIDL. Exception" + ex);
600         }
601     }
602 
603     @Override
hangup(int serial, int gsmIndex)604     public void hangup(int serial, int gsmIndex) {
605         Log.d(mTag, "hangup");
606         int responseError = RadioError.NONE;
607 
608         if (mMockModemConfigInterface != null) {
609             boolean ret = mMockModemConfigInterface.hangupVoiceCall(mSubId, gsmIndex, mTag);
610 
611             if (!ret) {
612                 Log.e(mTag, "Failed: hangup request failed");
613                 responseError = RadioError.INTERNAL_ERR;
614             }
615         } else {
616             Log.e(mTag, "Failed: mMockModemConfigInterface == null");
617             responseError = RadioError.INTERNAL_ERR;
618         }
619 
620         RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
621         try {
622             mRadioVoiceResponse.hangupConnectionResponse(rsp);
623         } catch (RemoteException ex) {
624             Log.e(mTag, "Failed to hangup from AIDL. Exception" + ex);
625         }
626     }
627 
628     @Override
hangupForegroundResumeBackground(int serial)629     public void hangupForegroundResumeBackground(int serial) {
630         Log.d(mTag, "hangupForegroundResumeBackground");
631 
632         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
633         try {
634             mRadioVoiceResponse.hangupForegroundResumeBackgroundResponse(rsp);
635         } catch (RemoteException ex) {
636             Log.e(mTag, "Failed to hangupForegroundResumeBackground from AIDL. Exception" + ex);
637         }
638     }
639 
640     @Override
hangupWaitingOrBackground(int serial)641     public void hangupWaitingOrBackground(int serial) {
642         Log.d(mTag, "hangupWaitingOrBackground");
643 
644         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
645         try {
646             mRadioVoiceResponse.hangupWaitingOrBackgroundResponse(rsp);
647         } catch (RemoteException ex) {
648             Log.e(mTag, "Failed to hangupWaitingOrBackground from AIDL. Exception" + ex);
649         }
650     }
651 
652     @Override
isVoNrEnabled(int serial)653     public void isVoNrEnabled(int serial) {
654         Log.d(mTag, "isVoNrEnabled");
655 
656         boolean enable = false;
657         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
658         try {
659             mRadioVoiceResponse.isVoNrEnabledResponse(rsp, enable);
660         } catch (RemoteException ex) {
661             Log.e(mTag, "Failed to isVoNrEnabled from AIDL. Exception" + ex);
662         }
663     }
664 
665     @Override
rejectCall(int serial)666     public void rejectCall(int serial) {
667         Log.d(mTag, "rejectCall");
668         int responseError = RadioError.NONE;
669 
670         if (mMockModemConfigInterface != null) {
671             boolean ret = mMockModemConfigInterface.rejectVoiceCall(mSubId, mTag);
672 
673             if (!ret) {
674                 Log.e(mTag, "Failed: reject request failed");
675                 responseError = RadioError.INTERNAL_ERR;
676             }
677         } else {
678             Log.e(mTag, "Failed: mMockModemConfigInterface == null");
679             responseError = RadioError.INTERNAL_ERR;
680         }
681 
682         RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
683         try {
684             mRadioVoiceResponse.rejectCallResponse(rsp);
685         } catch (RemoteException ex) {
686             Log.e(mTag, "Failed to rejectCall from AIDL. Exception" + ex);
687         }
688     }
689 
690     @Override
responseAcknowledgement()691     public void responseAcknowledgement() {
692         Log.d(mTag, "responseAcknowledgement");
693         // TODO
694     }
695 
696     @Override
sendBurstDtmf(int serial, String dtmf, int on, int off)697     public void sendBurstDtmf(int serial, String dtmf, int on, int off) {
698         Log.d(mTag, "sendBurstDtmf");
699 
700         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
701         try {
702             mRadioVoiceResponse.sendBurstDtmfResponse(rsp);
703         } catch (RemoteException ex) {
704             Log.e(mTag, "Failed to sendBurstDtmf from AIDL. Exception" + ex);
705         }
706     }
707 
708     @Override
sendCdmaFeatureCode(int serial, String featureCode)709     public void sendCdmaFeatureCode(int serial, String featureCode) {
710         Log.d(mTag, "sendCdmaFeatureCode");
711 
712         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
713         try {
714             mRadioVoiceResponse.sendCdmaFeatureCodeResponse(rsp);
715         } catch (RemoteException ex) {
716             Log.e(mTag, "Failed to sendCdmaFeatureCode from AIDL. Exception" + ex);
717         }
718     }
719 
720     @Override
sendDtmf(int serial, String s)721     public void sendDtmf(int serial, String s) {
722         Log.d(mTag, "sendDtmf");
723 
724         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
725         try {
726             mRadioVoiceResponse.sendDtmfResponse(rsp);
727         } catch (RemoteException ex) {
728             Log.e(mTag, "Failed to sendDtmf from AIDL. Exception" + ex);
729         }
730     }
731 
732     @Override
sendUssd(int serial, String ussd)733     public void sendUssd(int serial, String ussd) {
734         Log.d(mTag, "sendUssd");
735 
736         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
737         try {
738             mRadioVoiceResponse.sendUssdResponse(rsp);
739         } catch (RemoteException ex) {
740             Log.e(mTag, "Failed to sendUssd from AIDL. Exception" + ex);
741         }
742     }
743 
744     @Override
separateConnection(int serial, int gsmIndex)745     public void separateConnection(int serial, int gsmIndex) {
746         Log.d(mTag, "separateConnection");
747 
748         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
749         try {
750             mRadioVoiceResponse.separateConnectionResponse(rsp);
751         } catch (RemoteException ex) {
752             Log.e(mTag, "Failed to separateConnection from AIDL. Exception" + ex);
753         }
754     }
755 
756     @Override
setCallForward(int serial, android.hardware.radio.voice.CallForwardInfo callInfo)757     public void setCallForward(int serial, android.hardware.radio.voice.CallForwardInfo callInfo) {
758         Log.d(mTag, "setCallForward");
759 
760         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
761         try {
762             mRadioVoiceResponse.setCallForwardResponse(rsp);
763         } catch (RemoteException ex) {
764             Log.e(mTag, "Failed to setCallForward from AIDL. Exception" + ex);
765         }
766     }
767 
768     @Override
setCallWaiting(int serial, boolean enable, int serviceClass)769     public void setCallWaiting(int serial, boolean enable, int serviceClass) {
770         Log.d(mTag, "setCallWaiting");
771 
772         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
773         try {
774             mRadioVoiceResponse.setCallWaitingResponse(rsp);
775         } catch (RemoteException ex) {
776             Log.e(mTag, "Failed to setCallWaiting from AIDL. Exception" + ex);
777         }
778     }
779 
780     @Override
setClir(int serial, int status)781     public void setClir(int serial, int status) {
782         Log.d(mTag, "setClir");
783 
784         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
785         try {
786             mRadioVoiceResponse.setClirResponse(rsp);
787         } catch (RemoteException ex) {
788             Log.e(mTag, "Failed to setClir from AIDL. Exception" + ex);
789         }
790     }
791 
792     @Override
setMute(int serial, boolean enable)793     public void setMute(int serial, boolean enable) {
794         Log.d(mTag, "setMute");
795         int responseError = RadioError.NONE;
796 
797         if (mMockModemConfigInterface != null) {
798             boolean ret = mMockModemConfigInterface.setVoiceMuteMode(mSubId, enable, mTag);
799 
800             if (!ret) {
801                 Log.e(mTag, "Failed: setMute request failed");
802                 responseError = RadioError.INTERNAL_ERR;
803             }
804         } else {
805             Log.e(mTag, "Failed: mMockModemConfigInterface == null");
806             responseError = RadioError.INTERNAL_ERR;
807         }
808 
809         RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
810         try {
811             mRadioVoiceResponse.setMuteResponse(rsp);
812         } catch (RemoteException ex) {
813             Log.e(mTag, "Failed to setMute from AIDL. Exception" + ex);
814         }
815     }
816 
817     @Override
setPreferredVoicePrivacy(int serial, boolean enable)818     public void setPreferredVoicePrivacy(int serial, boolean enable) {
819         Log.d(mTag, "setPreferredVoicePrivacy");
820 
821         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
822         try {
823             mRadioVoiceResponse.setPreferredVoicePrivacyResponse(rsp);
824         } catch (RemoteException ex) {
825             Log.e(mTag, "Failed to setPreferredVoicePrivacy from AIDL. Exception" + ex);
826         }
827     }
828 
829     @Override
setTtyMode(int serial, int mode)830     public void setTtyMode(int serial, int mode) {
831         Log.d(mTag, "setTtyMode");
832 
833         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
834         try {
835             mRadioVoiceResponse.setTtyModeResponse(rsp);
836         } catch (RemoteException ex) {
837             Log.e(mTag, "Failed to setTtyMode from AIDL. Exception" + ex);
838         }
839     }
840 
841     @Override
setVoNrEnabled(int serial, boolean enable)842     public void setVoNrEnabled(int serial, boolean enable) {
843         Log.d(mTag, "setVoNrEnabled");
844 
845         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
846         try {
847             mRadioVoiceResponse.setVoNrEnabledResponse(rsp);
848         } catch (RemoteException ex) {
849             Log.e(mTag, "Failed to setVoNrEnabled from AIDL. Exception" + ex);
850         }
851     }
852 
853     @Override
startDtmf(int serial, String s)854     public void startDtmf(int serial, String s) {
855         Log.d(mTag, "startDtmf");
856 
857         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
858         try {
859             mRadioVoiceResponse.startDtmfResponse(rsp);
860         } catch (RemoteException ex) {
861             Log.e(mTag, "Failed to startDtmf from AIDL. Exception" + ex);
862         }
863     }
864 
865     @Override
stopDtmf(int serial)866     public void stopDtmf(int serial) {
867         Log.d(mTag, "stopDtmf");
868 
869         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
870         try {
871             mRadioVoiceResponse.stopDtmfResponse(rsp);
872         } catch (RemoteException ex) {
873             Log.e(mTag, "Failed to stopDtmf from AIDL. Exception" + ex);
874         }
875     }
876 
877     @Override
switchWaitingOrHoldingAndActive(int serial)878     public void switchWaitingOrHoldingAndActive(int serial) {
879         Log.d(mTag, "switchWaitingOrHoldingAndActive");
880 
881         RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
882         try {
883             mRadioVoiceResponse.switchWaitingOrHoldingAndActiveResponse(rsp);
884         } catch (RemoteException ex) {
885             Log.e(mTag, "Failed to switchWaitingOrHoldingAndActive from AIDL. Exception" + ex);
886         }
887     }
888 
callRing(boolean isGsm, android.hardware.radio.voice.CdmaSignalInfoRecord record)889     public void callRing(boolean isGsm, android.hardware.radio.voice.CdmaSignalInfoRecord record) {
890         Log.d(mTag, "callRing");
891 
892         if (mRadioVoiceIndication != null) {
893             try {
894                 mRadioVoiceIndication.callRing(RadioIndicationType.UNSOLICITED, isGsm, record);
895             } catch (RemoteException ex) {
896                 Log.e(mTag, "Failed to callRing indication from AIDL. Exception" + ex);
897             }
898         } else {
899             Log.e(mTag, "null mRadioVoiceIndication");
900         }
901     }
902 
callStateChanged()903     public void callStateChanged() {
904         Log.d(mTag, "callStateChanged");
905 
906         if (mRadioVoiceIndication != null) {
907             try {
908                 mRadioVoiceIndication.callStateChanged(RadioIndicationType.UNSOLICITED);
909             } catch (RemoteException ex) {
910                 Log.e(mTag, "Failed to callStateChanged indication from AIDL. Exception" + ex);
911             }
912         } else {
913             Log.e(mTag, "null mRadioVoiceIndication");
914         }
915     }
916 
cdmaCallWaiting(android.hardware.radio.voice.CdmaCallWaiting callWaitingRecord)917     public void cdmaCallWaiting(android.hardware.radio.voice.CdmaCallWaiting callWaitingRecord) {
918         Log.d(mTag, "cdmaCallWaiting");
919 
920         if (mRadioVoiceIndication != null) {
921             try {
922                 mRadioVoiceIndication.cdmaCallWaiting(
923                         RadioIndicationType.UNSOLICITED, callWaitingRecord);
924             } catch (RemoteException ex) {
925                 Log.e(mTag, "Failed to cdmaCallWaiting indication from AIDL. Exception" + ex);
926             }
927         } else {
928             Log.e(mTag, "null mRadioVoiceIndication");
929         }
930     }
931 
cdmaInfoRec(android.hardware.radio.voice.CdmaInformationRecord[] records)932     public void cdmaInfoRec(android.hardware.radio.voice.CdmaInformationRecord[] records) {
933         Log.d(mTag, "cdmaInfoRec");
934 
935         if (mRadioVoiceIndication != null) {
936             try {
937                 mRadioVoiceIndication.cdmaInfoRec(RadioIndicationType.UNSOLICITED, records);
938             } catch (RemoteException ex) {
939                 Log.e(mTag, "Failed to cdmaInfoRec indication from AIDL. Exception" + ex);
940             }
941         } else {
942             Log.e(mTag, "null mRadioVoiceIndication");
943         }
944     }
945 
cdmaOtaProvisionStatus(int status)946     public void cdmaOtaProvisionStatus(int status) {
947         Log.d(mTag, "cdmaOtaProvisionStatus");
948 
949         if (mRadioVoiceIndication != null) {
950             try {
951                 mRadioVoiceIndication.cdmaOtaProvisionStatus(
952                         RadioIndicationType.UNSOLICITED, status);
953             } catch (RemoteException ex) {
954                 Log.e(
955                         mTag,
956                         "Failed to cdmaOtaProvisionStatus indication from AIDL. Exception" + ex);
957             }
958         } else {
959             Log.e(mTag, "null mRadioVoiceIndication");
960         }
961     }
962 
currentEmergencyNumberList( android.hardware.radio.voice.EmergencyNumber[] emergencyNumberList)963     public void currentEmergencyNumberList(
964             android.hardware.radio.voice.EmergencyNumber[] emergencyNumberList) {
965         Log.d(mTag, "currentEmergencyNumberList");
966 
967         if (mRadioVoiceIndication != null) {
968             try {
969                 mRadioVoiceIndication.currentEmergencyNumberList(
970                         RadioIndicationType.UNSOLICITED, emergencyNumberList);
971             } catch (RemoteException ex) {
972                 Log.e(
973                         mTag,
974                         "Failed to currentEmergencyNumberList indication from AIDL. Exception"
975                                 + ex);
976             }
977         } else {
978             Log.e(mTag, "null mRadioVoiceIndication");
979         }
980     }
981 
enterEmergencyCallbackMode()982     public void enterEmergencyCallbackMode() {
983         Log.d(mTag, "enterEmergencyCallbackMode");
984 
985         if (mRadioVoiceIndication != null) {
986             try {
987                 mRadioVoiceIndication.enterEmergencyCallbackMode(RadioIndicationType.UNSOLICITED);
988             } catch (RemoteException ex) {
989                 Log.e(
990                         mTag,
991                         "Failed to enterEmergencyCallbackMode indication from AIDL. Exception"
992                                 + ex);
993             }
994         } else {
995             Log.e(mTag, "null mRadioVoiceIndication");
996         }
997     }
998 
exitEmergencyCallbackMode()999     public void exitEmergencyCallbackMode() {
1000         Log.d(mTag, "exitEmergencyCallbackMode");
1001 
1002         if (mRadioVoiceIndication != null) {
1003             try {
1004                 mRadioVoiceIndication.exitEmergencyCallbackMode(RadioIndicationType.UNSOLICITED);
1005             } catch (RemoteException ex) {
1006                 Log.e(
1007                         mTag,
1008                         "Failed to exitEmergencyCallbackMode indication from AIDL. Exception" + ex);
1009             }
1010         } else {
1011             Log.e(mTag, "null mRadioVoiceIndication");
1012         }
1013     }
1014 
indicateRingbackTone(boolean start)1015     public void indicateRingbackTone(boolean start) {
1016         Log.d(mTag, "indicateRingbackTone");
1017 
1018         if (mRadioVoiceIndication != null) {
1019             try {
1020                 mRadioVoiceIndication.indicateRingbackTone(RadioIndicationType.UNSOLICITED, start);
1021             } catch (RemoteException ex) {
1022                 Log.e(mTag, "Failed to indicateRingbackTone indication from AIDL. Exception" + ex);
1023             }
1024         } else {
1025             Log.e(mTag, "null mRadioVoiceIndication");
1026         }
1027     }
1028 
onSupplementaryServiceIndication( android.hardware.radio.voice.StkCcUnsolSsResult ss)1029     public void onSupplementaryServiceIndication(
1030             android.hardware.radio.voice.StkCcUnsolSsResult ss) {
1031         Log.d(mTag, "onSupplementaryServiceIndication");
1032 
1033         if (mRadioVoiceIndication != null) {
1034             try {
1035                 mRadioVoiceIndication.onSupplementaryServiceIndication(
1036                         RadioIndicationType.UNSOLICITED, ss);
1037             } catch (RemoteException ex) {
1038                 Log.e(
1039                         mTag,
1040                         "Failed to onSupplementaryServiceIndication indication from AIDL. Exception"
1041                                 + ex);
1042             }
1043         } else {
1044             Log.e(mTag, "null mRadioVoiceIndication");
1045         }
1046     }
1047 
onUssd(int modeType, String msg)1048     public void onUssd(int modeType, String msg) {
1049         Log.d(mTag, "onUssd");
1050 
1051         if (mRadioVoiceIndication != null) {
1052             try {
1053                 mRadioVoiceIndication.onUssd(RadioIndicationType.UNSOLICITED, modeType, msg);
1054             } catch (RemoteException ex) {
1055                 Log.e(mTag, "Failed to onUssd indication from AIDL. Exception" + ex);
1056             }
1057         } else {
1058             Log.e(mTag, "null mRadioVoiceIndication");
1059         }
1060     }
1061 
resendIncallMute()1062     public void resendIncallMute() {
1063         Log.d(mTag, "resendIncallMute");
1064 
1065         if (mRadioVoiceIndication != null) {
1066             try {
1067                 mRadioVoiceIndication.resendIncallMute(RadioIndicationType.UNSOLICITED);
1068             } catch (RemoteException ex) {
1069                 Log.e(mTag, "Failed to resendIncallMute indication from AIDL. Exception" + ex);
1070             }
1071         } else {
1072             Log.e(mTag, "null mRadioVoiceIndication");
1073         }
1074     }
1075 
srvccStateNotify(int state)1076     public void srvccStateNotify(int state) {
1077         Log.d(mTag, "srvccStateNotify");
1078 
1079         if (mRadioVoiceIndication != null) {
1080             try {
1081                 mRadioVoiceIndication.srvccStateNotify(RadioIndicationType.UNSOLICITED, state);
1082             } catch (RemoteException ex) {
1083                 Log.e(mTag, "Failed to srvccStateNotify indication from AIDL. Exception" + ex);
1084             }
1085         } else {
1086             Log.e(mTag, "null mRadioVoiceIndication");
1087         }
1088     }
1089 
stkCallControlAlphaNotify(String alpha)1090     public void stkCallControlAlphaNotify(String alpha) {
1091         Log.d(mTag, "stkCallControlAlphaNotify");
1092 
1093         if (mRadioVoiceIndication != null) {
1094             try {
1095                 mRadioVoiceIndication.stkCallControlAlphaNotify(
1096                         RadioIndicationType.UNSOLICITED, alpha);
1097             } catch (RemoteException ex) {
1098                 Log.e(
1099                         mTag,
1100                         "Failed to stkCallControlAlphaNotify indication from AIDL. Exception" + ex);
1101             }
1102         } else {
1103             Log.e(mTag, "null mRadioVoiceIndication");
1104         }
1105     }
1106 
stkCallSetup(long timeout)1107     public void stkCallSetup(long timeout) {
1108         Log.d(mTag, "stkCallSetup");
1109 
1110         if (mRadioVoiceIndication != null) {
1111             try {
1112                 mRadioVoiceIndication.stkCallSetup(RadioIndicationType.UNSOLICITED, timeout);
1113             } catch (RemoteException ex) {
1114                 Log.e(mTag, "Failed to stkCallSetup indication from AIDL. Exception" + ex);
1115             }
1116         } else {
1117             Log.e(mTag, "null mRadioVoiceIndication");
1118         }
1119     }
1120 
notifyEmergencyNumberList(String[] numbers)1121     public void notifyEmergencyNumberList(String[] numbers) {
1122         if (numbers == null || numbers.length == 0) return;
1123 
1124         EmergencyNumber[] emergencyNumberList = new EmergencyNumber[numbers.length];
1125 
1126         for (int i = 0; i < numbers.length; i++) {
1127             EmergencyNumber number = new EmergencyNumber();
1128             number.number = numbers[i];
1129             number.mcc = "310";
1130             number.mnc = "";
1131             String urn = "sip:" + numbers[i] + "@test.3gpp.com";
1132             number.urns = new String[] { urn };
1133             number.sources = EmergencyNumber.SOURCE_MODEM_CONFIG;
1134             emergencyNumberList[i] = number;
1135         }
1136 
1137         currentEmergencyNumberList(emergencyNumberList);
1138     }
1139 
1140 
countDownLatch(int latchIndex)1141     private void countDownLatch(int latchIndex) {
1142         synchronized (mLatches) {
1143             mLatches[latchIndex].countDown();
1144         }
1145     }
1146 
resetLatch(int latchIndex)1147     private void resetLatch(int latchIndex) {
1148         synchronized (mLatches) {
1149             mLatches[latchIndex] = new CountDownLatch(1);
1150         }
1151     }
1152 
1153     /**
1154      * Waits for the event of voice service.
1155      *
1156      * @param latchIndex The index of the event.
1157      * @param waitMs The timeout in milliseconds.
1158      * @return {@code true} if the event happens.
1159      */
waitForLatchCountdown(int latchIndex, long waitMs)1160     public boolean waitForLatchCountdown(int latchIndex, long waitMs) {
1161         boolean complete = false;
1162         try {
1163             CountDownLatch latch;
1164             synchronized (mLatches) {
1165                 latch = mLatches[latchIndex];
1166             }
1167             long startTime = System.currentTimeMillis();
1168             complete = latch.await(waitMs, TimeUnit.MILLISECONDS);
1169             Log.i(TAG, "Latch " + latchIndex + " took "
1170                     + (System.currentTimeMillis() - startTime) + " ms to count down.");
1171         } catch (InterruptedException e) {
1172             Log.e(TAG, "Waiting latch " + latchIndex + " interrupted, e=" + e);
1173         }
1174         synchronized (mLatches) {
1175             mLatches[latchIndex] = new CountDownLatch(1);
1176         }
1177         return complete;
1178     }
1179 
1180     /**
1181      * Resets the CountDownLatches.
1182      */
resetAllLatchCountdown()1183     public void resetAllLatchCountdown() {
1184         synchronized (mLatches) {
1185             for (int i = 0; i < LATCH_MAX; i++) {
1186                 mLatches[i] = new CountDownLatch(1);
1187             }
1188         }
1189     }
1190 
1191     @Override
getInterfaceHash()1192     public String getInterfaceHash() {
1193         return IRadioVoice.HASH;
1194     }
1195 
1196     @Override
getInterfaceVersion()1197     public int getInterfaceVersion() {
1198         return IRadioVoice.VERSION;
1199     }
1200 }
1201