1 /*
2  * Copyright (C) 2010 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 com.android.internal.telephony;
18 
19 import android.annotation.UnsupportedAppUsage;
20 import android.content.Context;
21 import android.os.AsyncResult;
22 import android.os.Handler;
23 import android.os.Message;
24 import android.os.Registrant;
25 import android.os.RegistrantList;
26 import android.telephony.PhoneNumberUtils;
27 import android.telephony.PhoneStateListener;
28 import android.telephony.Rlog;
29 import android.telephony.ServiceState;
30 import android.telephony.TelephonyManager;
31 
32 import com.android.internal.telephony.sip.SipPhone;
33 
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.List;
38 
39 
40 
41 /**
42  * @hide
43  *
44  * CallManager class provides an abstract layer for PhoneApp to access
45  * and control calls. It implements Phone interface.
46  *
47  * CallManager provides call and connection control as well as
48  * channel capability.
49  *
50  * There are three categories of APIs CallManager provided
51  *
52  *  1. Call control and operation, such as dial() and hangup()
53  *  2. Channel capabilities, such as CanConference()
54  *  3. Register notification
55  *
56  *
57  */
58 public class CallManager {
59 
60     private static final String LOG_TAG ="CallManager";
61     private static final boolean DBG = true;
62     private static final boolean VDBG = false;
63 
64     private static final int EVENT_DISCONNECT = 100;
65     private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101;
66     private static final int EVENT_NEW_RINGING_CONNECTION = 102;
67     private static final int EVENT_UNKNOWN_CONNECTION = 103;
68     private static final int EVENT_INCOMING_RING = 104;
69     private static final int EVENT_RINGBACK_TONE = 105;
70     private static final int EVENT_IN_CALL_VOICE_PRIVACY_ON = 106;
71     private static final int EVENT_IN_CALL_VOICE_PRIVACY_OFF = 107;
72     private static final int EVENT_CALL_WAITING = 108;
73     private static final int EVENT_DISPLAY_INFO = 109;
74     private static final int EVENT_SIGNAL_INFO = 110;
75     private static final int EVENT_CDMA_OTA_STATUS_CHANGE = 111;
76     private static final int EVENT_RESEND_INCALL_MUTE = 112;
77     private static final int EVENT_MMI_INITIATE = 113;
78     private static final int EVENT_MMI_COMPLETE = 114;
79     private static final int EVENT_ECM_TIMER_RESET = 115;
80     private static final int EVENT_SUBSCRIPTION_INFO_READY = 116;
81     private static final int EVENT_SUPP_SERVICE_FAILED = 117;
82     private static final int EVENT_SERVICE_STATE_CHANGED = 118;
83     private static final int EVENT_POST_DIAL_CHARACTER = 119;
84     private static final int EVENT_ONHOLD_TONE = 120;
85     // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
86     //private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 121;
87     private static final int EVENT_TTY_MODE_RECEIVED = 122;
88 
89     // Singleton instance
90     private static final CallManager INSTANCE = new CallManager();
91 
92     // list of registered phones, which are Phone objs
93     @UnsupportedAppUsage
94     private final ArrayList<Phone> mPhones;
95 
96     // list of supported ringing calls
97     @UnsupportedAppUsage
98     private final ArrayList<Call> mRingingCalls;
99 
100     // list of supported background calls
101     @UnsupportedAppUsage
102     private final ArrayList<Call> mBackgroundCalls;
103 
104     // list of supported foreground calls
105     @UnsupportedAppUsage
106     private final ArrayList<Call> mForegroundCalls;
107 
108     // empty connection list
109     @UnsupportedAppUsage
110     private final ArrayList<Connection> mEmptyConnections = new ArrayList<Connection>();
111 
112     // mapping of phones to registered handler instances used for callbacks from RIL
113     private final HashMap<Phone, CallManagerHandler> mHandlerMap = new HashMap<>();
114 
115     // default phone as the first phone registered, which is Phone obj
116     private Phone mDefaultPhone;
117 
118     private boolean mSpeedUpAudioForMtCall = false;
119     // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
120     //private boolean mIsEccDialing = false;
121 
122     private Object mRegistrantidentifier = new Object();
123 
124     // state registrants
125     protected final RegistrantList mPreciseCallStateRegistrants
126     = new RegistrantList();
127 
128     protected final RegistrantList mNewRingingConnectionRegistrants
129     = new RegistrantList();
130 
131     protected final RegistrantList mIncomingRingRegistrants
132     = new RegistrantList();
133 
134     protected final RegistrantList mDisconnectRegistrants
135     = new RegistrantList();
136 
137     protected final RegistrantList mMmiRegistrants
138     = new RegistrantList();
139 
140     protected final RegistrantList mUnknownConnectionRegistrants
141     = new RegistrantList();
142 
143     protected final RegistrantList mRingbackToneRegistrants
144     = new RegistrantList();
145 
146     protected final RegistrantList mOnHoldToneRegistrants
147     = new RegistrantList();
148 
149     protected final RegistrantList mInCallVoicePrivacyOnRegistrants
150     = new RegistrantList();
151 
152     protected final RegistrantList mInCallVoicePrivacyOffRegistrants
153     = new RegistrantList();
154 
155     protected final RegistrantList mCallWaitingRegistrants
156     = new RegistrantList();
157 
158     protected final RegistrantList mDisplayInfoRegistrants
159     = new RegistrantList();
160 
161     protected final RegistrantList mSignalInfoRegistrants
162     = new RegistrantList();
163 
164     protected final RegistrantList mCdmaOtaStatusChangeRegistrants
165     = new RegistrantList();
166 
167     protected final RegistrantList mResendIncallMuteRegistrants
168     = new RegistrantList();
169 
170     protected final RegistrantList mMmiInitiateRegistrants
171     = new RegistrantList();
172 
173     protected final RegistrantList mMmiCompleteRegistrants
174     = new RegistrantList();
175 
176     protected final RegistrantList mEcmTimerResetRegistrants
177     = new RegistrantList();
178 
179     protected final RegistrantList mSubscriptionInfoReadyRegistrants
180     = new RegistrantList();
181 
182     protected final RegistrantList mSuppServiceFailedRegistrants
183     = new RegistrantList();
184 
185     protected final RegistrantList mServiceStateChangedRegistrants
186     = new RegistrantList();
187 
188     protected final RegistrantList mPostDialCharacterRegistrants
189     = new RegistrantList();
190 
191     protected final RegistrantList mTtyModeReceivedRegistrants
192     = new RegistrantList();
193 
CallManager()194     private CallManager() {
195         mPhones = new ArrayList<Phone>();
196         mRingingCalls = new ArrayList<Call>();
197         mBackgroundCalls = new ArrayList<Call>();
198         mForegroundCalls = new ArrayList<Call>();
199         mDefaultPhone = null;
200     }
201 
202     /**
203      * get singleton instance of CallManager
204      * @return CallManager
205      */
206     @UnsupportedAppUsage
getInstance()207     public static CallManager getInstance() {
208         return INSTANCE;
209     }
210 
211     /**
212      * get Phone object corresponds to subId
213      * @return Phone
214      */
getPhone(int subId)215     private Phone getPhone(int subId) {
216         Phone p = null;
217         for (Phone phone : mPhones) {
218             if (phone.getSubId() == subId &&
219                     phone.getPhoneType() != PhoneConstants.PHONE_TYPE_IMS) {
220                 p = phone;
221                 break;
222             }
223         }
224         return p;
225     }
226 
227     /**
228      * Get current coarse-grained voice call state.
229      * If the Call Manager has an active call and call waiting occurs,
230      * then the phone state is RINGING not OFFHOOK
231      *
232      */
233     @UnsupportedAppUsage
getState()234     public PhoneConstants.State getState() {
235         PhoneConstants.State s = PhoneConstants.State.IDLE;
236 
237         for (Phone phone : mPhones) {
238             if (phone.getState() == PhoneConstants.State.RINGING) {
239                 s = PhoneConstants.State.RINGING;
240             } else if (phone.getState() == PhoneConstants.State.OFFHOOK) {
241                 if (s == PhoneConstants.State.IDLE) s = PhoneConstants.State.OFFHOOK;
242             }
243         }
244         return s;
245     }
246 
247     /**
248      * Get current coarse-grained voice call state on a subId.
249      * If the Call Manager has an active call and call waiting occurs,
250      * then the phone state is RINGING not OFFHOOK
251      *
252      */
253     @UnsupportedAppUsage
getState(int subId)254     public PhoneConstants.State getState(int subId) {
255         PhoneConstants.State s = PhoneConstants.State.IDLE;
256 
257         for (Phone phone : mPhones) {
258             if (phone.getSubId() == subId) {
259                 if (phone.getState() == PhoneConstants.State.RINGING) {
260                     s = PhoneConstants.State.RINGING;
261                 } else if (phone.getState() == PhoneConstants.State.OFFHOOK) {
262                     if (s == PhoneConstants.State.IDLE) s = PhoneConstants.State.OFFHOOK;
263                 }
264             }
265         }
266         return s;
267     }
268 
269     /**
270      * @return the service state of CallManager, which represents the
271      * highest priority state of all the service states of phones
272      *
273      * The priority is defined as
274      *
275      * STATE_IN_SERIVCE > STATE_OUT_OF_SERIVCE > STATE_EMERGENCY > STATE_POWER_OFF
276      *
277      */
278 
getServiceState()279     public int getServiceState() {
280         int resultState = ServiceState.STATE_OUT_OF_SERVICE;
281 
282         for (Phone phone : mPhones) {
283             int serviceState = phone.getServiceState().getState();
284             if (serviceState == ServiceState.STATE_IN_SERVICE) {
285                 // IN_SERVICE has the highest priority
286                 resultState = serviceState;
287                 break;
288             } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) {
289                 // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF
290                 // Note: EMERGENCY_ONLY is not in use at this moment
291                 if ( resultState == ServiceState.STATE_EMERGENCY_ONLY ||
292                         resultState == ServiceState.STATE_POWER_OFF) {
293                     resultState = serviceState;
294                 }
295             } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
296                 if (resultState == ServiceState.STATE_POWER_OFF) {
297                     resultState = serviceState;
298                 }
299             }
300         }
301         return resultState;
302     }
303 
304     /**
305      * @return the Phone service state corresponds to subId
306      */
getServiceState(int subId)307     public int getServiceState(int subId) {
308         int resultState = ServiceState.STATE_OUT_OF_SERVICE;
309 
310         for (Phone phone : mPhones) {
311             if (phone.getSubId() == subId) {
312                 int serviceState = phone.getServiceState().getState();
313                 if (serviceState == ServiceState.STATE_IN_SERVICE) {
314                     // IN_SERVICE has the highest priority
315                     resultState = serviceState;
316                     break;
317                 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) {
318                     // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF
319                     // Note: EMERGENCY_ONLY is not in use at this moment
320                     if ( resultState == ServiceState.STATE_EMERGENCY_ONLY ||
321                             resultState == ServiceState.STATE_POWER_OFF) {
322                         resultState = serviceState;
323                     }
324                 } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
325                     if (resultState == ServiceState.STATE_POWER_OFF) {
326                         resultState = serviceState;
327                     }
328                 }
329             }
330         }
331         return resultState;
332     }
333 
334     /**
335      * @return the phone associated with any call
336      */
337     @UnsupportedAppUsage
getPhoneInCall()338     public Phone getPhoneInCall() {
339         Phone phone = null;
340         if (!getFirstActiveRingingCall().isIdle()) {
341             phone = getFirstActiveRingingCall().getPhone();
342         } else if (!getActiveFgCall().isIdle()) {
343             phone = getActiveFgCall().getPhone();
344         } else {
345             // If BG call is idle, we return default phone
346             phone = getFirstActiveBgCall().getPhone();
347         }
348         return phone;
349     }
350 
351     /**
352      * Register phone to CallManager
353      * @param phone to be registered
354      * @return true if register successfully
355      */
356     @UnsupportedAppUsage
registerPhone(Phone phone)357     public boolean registerPhone(Phone phone) {
358         if (phone != null && !mPhones.contains(phone)) {
359 
360             if (DBG) {
361                 Rlog.d(LOG_TAG, "registerPhone(" +
362                         phone.getPhoneName() + " " + phone + ")");
363             }
364 
365             if (mPhones.isEmpty()) {
366                 mDefaultPhone = phone;
367             }
368             mPhones.add(phone);
369             mRingingCalls.add(phone.getRingingCall());
370             mBackgroundCalls.add(phone.getBackgroundCall());
371             mForegroundCalls.add(phone.getForegroundCall());
372             registerForPhoneStates(phone);
373             return true;
374         }
375         return false;
376     }
377 
378     /**
379      * unregister phone from CallManager
380      * @param phone to be unregistered
381      */
382     @UnsupportedAppUsage
unregisterPhone(Phone phone)383     public void unregisterPhone(Phone phone) {
384         if (phone != null && mPhones.contains(phone)) {
385 
386             if (DBG) {
387                 Rlog.d(LOG_TAG, "unregisterPhone(" +
388                         phone.getPhoneName() + " " + phone + ")");
389             }
390 
391             Phone imsPhone = phone.getImsPhone();
392             if (imsPhone != null) {
393                 unregisterPhone(imsPhone);
394             }
395 
396             mPhones.remove(phone);
397             mRingingCalls.remove(phone.getRingingCall());
398             mBackgroundCalls.remove(phone.getBackgroundCall());
399             mForegroundCalls.remove(phone.getForegroundCall());
400             unregisterForPhoneStates(phone);
401             if (phone == mDefaultPhone) {
402                 if (mPhones.isEmpty()) {
403                     mDefaultPhone = null;
404                 } else {
405                     mDefaultPhone = mPhones.get(0);
406                 }
407             }
408         }
409     }
410 
411     /**
412      * return the default phone or null if no phone available
413      */
414     @UnsupportedAppUsage
getDefaultPhone()415     public Phone getDefaultPhone() {
416         return mDefaultPhone;
417     }
418 
419     /**
420      * @return the phone associated with the foreground call
421      */
422     @UnsupportedAppUsage
getFgPhone()423     public Phone getFgPhone() {
424         return getActiveFgCall().getPhone();
425     }
426 
427     /**
428      * @return the phone associated with the foreground call
429      * of a particular subId
430      */
431     @UnsupportedAppUsage
getFgPhone(int subId)432     public Phone getFgPhone(int subId) {
433         return getActiveFgCall(subId).getPhone();
434     }
435 
436     /**
437      * @return the phone associated with the background call
438      */
439     @UnsupportedAppUsage
getBgPhone()440     public Phone getBgPhone() {
441         return getFirstActiveBgCall().getPhone();
442     }
443 
444     /**
445      * @return the phone associated with the ringing call
446      */
447     @UnsupportedAppUsage
getRingingPhone()448     public Phone getRingingPhone() {
449         return getFirstActiveRingingCall().getPhone();
450     }
451 
452     /**
453      * @return the phone associated with the ringing call
454      * of a particular subId
455      */
getRingingPhone(int subId)456     public Phone getRingingPhone(int subId) {
457         return getFirstActiveRingingCall(subId).getPhone();
458     }
459 
460     /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
461     public void setAudioMode() {
462         Context context = getContext();
463         if (context == null) return;
464         AudioManager audioManager = (AudioManager)
465                 context.getSystemService(Context.AUDIO_SERVICE);
466 
467         if (!isServiceStateInService() && !mIsEccDialing) {
468             if (audioManager.getMode() != AudioManager.MODE_NORMAL) {
469                 if (VDBG) Rlog.d(LOG_TAG, "abandonAudioFocus");
470                 // abandon audio focus after the mode has been set back to normal
471                 audioManager.abandonAudioFocusForCall();
472                 audioManager.setMode(AudioManager.MODE_NORMAL);
473             }
474             return;
475         }
476 
477         // change the audio mode and request/abandon audio focus according to phone state,
478         // but only on audio mode transitions
479         switch (getState()) {
480             case RINGING:
481                 int curAudioMode = audioManager.getMode();
482                 if (curAudioMode != AudioManager.MODE_RINGTONE) {
483                     if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_RING");
484                     audioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
485                             AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
486                     if(!mSpeedUpAudioForMtCall) {
487                         audioManager.setMode(AudioManager.MODE_RINGTONE);
488                     }
489                 }
490 
491                 if (mSpeedUpAudioForMtCall && (curAudioMode != AudioManager.MODE_IN_CALL)) {
492                     audioManager.setMode(AudioManager.MODE_IN_CALL);
493                 }
494                 break;
495             case OFFHOOK:
496                 Phone offhookPhone = getFgPhone();
497                 if (getActiveFgCallState() == Call.State.IDLE) {
498                     // There is no active Fg calls, the OFFHOOK state
499                     // is set by the Bg call. So set the phone to bgPhone.
500                     offhookPhone = getBgPhone();
501                 }
502 
503                 int newAudioMode = AudioManager.MODE_IN_CALL;
504                 if (offhookPhone instanceof SipPhone) {
505                     Rlog.d(LOG_TAG, "setAudioMode Set audio mode for SIP call!");
506                     // enable IN_COMMUNICATION audio mode instead for sipPhone
507                     newAudioMode = AudioManager.MODE_IN_COMMUNICATION;
508                 }
509                 int currMode = audioManager.getMode();
510                 if (currMode != newAudioMode || mSpeedUpAudioForMtCall) {
511                     // request audio focus before setting the new mode
512                     if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_VOICE_CALL");
513                     audioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
514                             AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
515                     Rlog.d(LOG_TAG, "setAudioMode Setting audio mode from "
516                             + currMode + " to " + newAudioMode);
517                     audioManager.setMode(newAudioMode);
518                 }
519                 mSpeedUpAudioForMtCall = false;
520                 break;
521             case IDLE:
522                 if (audioManager.getMode() != AudioManager.MODE_NORMAL) {
523                     audioManager.setMode(AudioManager.MODE_NORMAL);
524                     if (VDBG) Rlog.d(LOG_TAG, "abandonAudioFocus");
525                     // abandon audio focus after the mode has been set back to normal
526                     audioManager.abandonAudioFocusForCall();
527                 }
528                 mSpeedUpAudioForMtCall = false;
529                 break;
530         }
531         Rlog.d(LOG_TAG, "setAudioMode state = " + getState());
532     }
533     */
534 
535     @UnsupportedAppUsage
getContext()536     private Context getContext() {
537         Phone defaultPhone = getDefaultPhone();
538         return ((defaultPhone == null) ? null : defaultPhone.getContext());
539     }
540 
getRegistrantIdentifier()541     public Object getRegistrantIdentifier() {
542         return mRegistrantidentifier;
543     }
544 
registerForPhoneStates(Phone phone)545     private void registerForPhoneStates(Phone phone) {
546         // We need to keep a mapping of handler to Phone for proper unregistration.
547         // TODO: Clean up this solution as it is just a work around for each Phone instance
548         // using the same Handler to register with the RIL. When time permits, we should consider
549         // moving the handler (or the reference ot the handler) into the Phone object.
550         // See b/17414427.
551         CallManagerHandler handler = mHandlerMap.get(phone);
552         if (handler != null) {
553             Rlog.d(LOG_TAG, "This phone has already been registered.");
554             return;
555         }
556 
557         // New registration, create a new handler instance and register the phone.
558         handler = new CallManagerHandler();
559         mHandlerMap.put(phone, handler);
560 
561         // for common events supported by all phones
562         // The mRegistrantIdentifier passed here, is to identify in the Phone
563         // that the registrants are coming from the CallManager.
564         phone.registerForPreciseCallStateChanged(handler, EVENT_PRECISE_CALL_STATE_CHANGED,
565                 mRegistrantidentifier);
566         phone.registerForDisconnect(handler, EVENT_DISCONNECT,
567                 mRegistrantidentifier);
568         phone.registerForNewRingingConnection(handler, EVENT_NEW_RINGING_CONNECTION,
569                 mRegistrantidentifier);
570         phone.registerForUnknownConnection(handler, EVENT_UNKNOWN_CONNECTION,
571                 mRegistrantidentifier);
572         phone.registerForIncomingRing(handler, EVENT_INCOMING_RING,
573                 mRegistrantidentifier);
574         phone.registerForRingbackTone(handler, EVENT_RINGBACK_TONE,
575                 mRegistrantidentifier);
576         phone.registerForInCallVoicePrivacyOn(handler, EVENT_IN_CALL_VOICE_PRIVACY_ON,
577                 mRegistrantidentifier);
578         phone.registerForInCallVoicePrivacyOff(handler, EVENT_IN_CALL_VOICE_PRIVACY_OFF,
579                 mRegistrantidentifier);
580         phone.registerForDisplayInfo(handler, EVENT_DISPLAY_INFO,
581                 mRegistrantidentifier);
582         phone.registerForSignalInfo(handler, EVENT_SIGNAL_INFO,
583                 mRegistrantidentifier);
584         phone.registerForResendIncallMute(handler, EVENT_RESEND_INCALL_MUTE,
585                 mRegistrantidentifier);
586         phone.registerForMmiInitiate(handler, EVENT_MMI_INITIATE,
587                 mRegistrantidentifier);
588         phone.registerForMmiComplete(handler, EVENT_MMI_COMPLETE,
589                 mRegistrantidentifier);
590         phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED,
591                 mRegistrantidentifier);
592         phone.registerForServiceStateChanged(handler, EVENT_SERVICE_STATE_CHANGED,
593                 mRegistrantidentifier);
594 
595         // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
596         //phone.registerForRadioOffOrNotAvailable(handler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
597 
598         // for events supported only by GSM, CDMA and IMS phone
599         phone.setOnPostDialCharacter(handler, EVENT_POST_DIAL_CHARACTER, null);
600 
601         // for events supported only by CDMA phone
602         phone.registerForCdmaOtaStatusChange(handler, EVENT_CDMA_OTA_STATUS_CHANGE, null);
603         phone.registerForSubscriptionInfoReady(handler, EVENT_SUBSCRIPTION_INFO_READY, null);
604         phone.registerForCallWaiting(handler, EVENT_CALL_WAITING, null);
605         phone.registerForEcmTimerReset(handler, EVENT_ECM_TIMER_RESET, null);
606 
607         // for events supported only by IMS phone
608         phone.registerForOnHoldTone(handler, EVENT_ONHOLD_TONE, null);
609         phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED, null);
610         phone.registerForTtyModeReceived(handler, EVENT_TTY_MODE_RECEIVED, null);
611     }
612 
unregisterForPhoneStates(Phone phone)613     private void unregisterForPhoneStates(Phone phone) {
614         // Make sure that we clean up our map of handlers to Phones.
615         CallManagerHandler handler = mHandlerMap.get(phone);
616         if (handler == null) {
617             Rlog.e(LOG_TAG, "Could not find Phone handler for unregistration");
618             return;
619         }
620         mHandlerMap.remove(phone);
621 
622         //  for common events supported by all phones
623         phone.unregisterForPreciseCallStateChanged(handler);
624         phone.unregisterForDisconnect(handler);
625         phone.unregisterForNewRingingConnection(handler);
626         phone.unregisterForUnknownConnection(handler);
627         phone.unregisterForIncomingRing(handler);
628         phone.unregisterForRingbackTone(handler);
629         phone.unregisterForInCallVoicePrivacyOn(handler);
630         phone.unregisterForInCallVoicePrivacyOff(handler);
631         phone.unregisterForDisplayInfo(handler);
632         phone.unregisterForSignalInfo(handler);
633         phone.unregisterForResendIncallMute(handler);
634         phone.unregisterForMmiInitiate(handler);
635         phone.unregisterForMmiComplete(handler);
636         phone.unregisterForSuppServiceFailed(handler);
637         phone.unregisterForServiceStateChanged(handler);
638         phone.unregisterForTtyModeReceived(handler);
639         // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
640         //phone.unregisterForRadioOffOrNotAvailable(handler);
641 
642         // for events supported only by GSM, CDMA and IMS phone
643         phone.setOnPostDialCharacter(null, EVENT_POST_DIAL_CHARACTER, null);
644 
645         // for events supported only by CDMA phone
646         phone.unregisterForCdmaOtaStatusChange(handler);
647         phone.unregisterForSubscriptionInfoReady(handler);
648         phone.unregisterForCallWaiting(handler);
649         phone.unregisterForEcmTimerReset(handler);
650 
651         // for events supported only by IMS phone
652         phone.unregisterForOnHoldTone(handler);
653         phone.unregisterForSuppServiceFailed(handler);
654     }
655 
656     /**
657      * Reject (ignore) a ringing call. In GSM, this means UDUB
658      * (User Determined User Busy). Reject occurs asynchronously,
659      * and final notification occurs via
660      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
661      * java.lang.Object) registerForPreciseCallStateChanged()}.
662      *
663      * @exception CallStateException when no call is ringing or waiting
664      */
rejectCall(Call ringingCall)665     public void rejectCall(Call ringingCall) throws CallStateException {
666         if (VDBG) {
667             Rlog.d(LOG_TAG, toString());
668         }
669 
670         Phone ringingPhone = ringingCall.getPhone();
671 
672         ringingPhone.rejectCall();
673 
674         if (VDBG) {
675             Rlog.d(LOG_TAG, "End rejectCall(" +ringingCall + ")");
676             Rlog.d(LOG_TAG, toString());
677         }
678     }
679 
680     /**
681      * Whether or not the phone can conference in the current phone
682      * state--that is, one call holding and one call active.
683      * @return true if the phone can conference; false otherwise.
684      */
canConference(Call heldCall)685     public boolean canConference(Call heldCall) {
686         Phone activePhone = null;
687         Phone heldPhone = null;
688 
689         if (hasActiveFgCall()) {
690             activePhone = getActiveFgCall().getPhone();
691         }
692 
693         if (heldCall != null) {
694             heldPhone = heldCall.getPhone();
695         }
696 
697         return heldPhone.getClass().equals(activePhone.getClass());
698     }
699 
700     /**
701      * Whether or not the phone can conference in the current phone
702      * state--that is, one call holding and one call active.
703      * This method consider the phone object which is specific
704      * to the provided subId.
705      * @return true if the phone can conference; false otherwise.
706      */
707     @UnsupportedAppUsage
canConference(Call heldCall, int subId)708     public boolean canConference(Call heldCall, int subId) {
709         Phone activePhone = null;
710         Phone heldPhone = null;
711 
712         if (hasActiveFgCall(subId)) {
713             activePhone = getActiveFgCall(subId).getPhone();
714         }
715 
716         if (heldCall != null) {
717             heldPhone = heldCall.getPhone();
718         }
719 
720         return heldPhone.getClass().equals(activePhone.getClass());
721     }
722 
723     /**
724      * Conferences holding and active. Conference occurs asynchronously
725      * and may fail. Final notification occurs via
726      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
727      * java.lang.Object) registerForPreciseCallStateChanged()}.
728      *
729      * @exception CallStateException if canConference() would return false.
730      * In these cases, this operation may not be performed.
731      */
732     @UnsupportedAppUsage
conference(Call heldCall)733     public void conference(Call heldCall) throws CallStateException {
734         int subId  = heldCall.getPhone().getSubId();
735 
736         if (VDBG) {
737             Rlog.d(LOG_TAG, "conference(" +heldCall + ")");
738             Rlog.d(LOG_TAG, toString());
739         }
740 
741         Phone fgPhone = getFgPhone(subId);
742         if (fgPhone != null) {
743             if (fgPhone instanceof SipPhone) {
744                 ((SipPhone) fgPhone).conference(heldCall);
745             } else if (canConference(heldCall)) {
746                 fgPhone.conference();
747             } else {
748                 throw(new CallStateException("Can't conference foreground and selected background call"));
749             }
750         } else {
751             Rlog.d(LOG_TAG, "conference: fgPhone=null");
752         }
753 
754         if (VDBG) {
755             Rlog.d(LOG_TAG, "End conference(" +heldCall + ")");
756             Rlog.d(LOG_TAG, toString());
757         }
758 
759     }
760 
761     /**
762      * Initiate a new voice connection. This happens asynchronously, so you
763      * cannot assume the audio path is connected (or a call index has been
764      * assigned) until PhoneStateChanged notification has occurred.
765      *
766      * @exception CallStateException if a new outgoing call is not currently
767      * possible because no more call slots exist or a call exists that is
768      * dialing, alerting, ringing, or waiting.  Other errors are
769      * handled asynchronously.
770      */
dial(Phone phone, String dialString, int videoState)771     public Connection dial(Phone phone, String dialString, int videoState)
772             throws CallStateException {
773         int subId = phone.getSubId();
774         Connection result;
775 
776         if (VDBG) {
777             Rlog.d(LOG_TAG, " dial(" + phone + ", "+ dialString + ")" +
778                     " subId = " + subId);
779             Rlog.d(LOG_TAG, toString());
780         }
781 
782         if (!canDial(phone)) {
783             /*
784              * canDial function only checks whether the phone can make a new call.
785              * InCall MMI commmands are basically supplementary services
786              * within a call eg: call hold, call deflection, explicit call transfer etc.
787              */
788             String newDialString = PhoneNumberUtils.stripSeparators(dialString);
789             if (phone.handleInCallMmiCommands(newDialString)) {
790                 return null;
791             } else {
792                 throw new CallStateException("cannot dial in current state");
793             }
794         }
795 
796         if ( hasActiveFgCall(subId) ) {
797             Phone activePhone = getActiveFgCall(subId).getPhone();
798             boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle());
799 
800             if (DBG) {
801                 Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == phone));
802             }
803 
804             // Manipulation between IMS phone and its owner
805             // will be treated in GSM/CDMA phone.
806             Phone imsPhone = phone.getImsPhone();
807             if (activePhone != phone
808                     && (imsPhone == null || imsPhone != activePhone)) {
809                 if (hasBgCall) {
810                     Rlog.d(LOG_TAG, "Hangup");
811                     getActiveFgCall(subId).hangup();
812                 } else {
813                     Rlog.d(LOG_TAG, "Switch");
814                     activePhone.switchHoldingAndActive();
815                 }
816             }
817         }
818 
819         // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
820         //mIsEccDialing = PhoneNumberUtils.isEmergencyNumber(dialString);
821 
822         result = phone.dial(dialString, new PhoneInternalInterface.DialArgs.Builder<>()
823                 .setVideoState(videoState).build());
824 
825         if (VDBG) {
826             Rlog.d(LOG_TAG, "End dial(" + phone + ", "+ dialString + ")");
827             Rlog.d(LOG_TAG, toString());
828         }
829 
830         return result;
831     }
832 
833     /**
834      * Initiate a new voice connection. This happens asynchronously, so you
835      * cannot assume the audio path is connected (or a call index has been
836      * assigned) until PhoneStateChanged notification has occurred.
837      *
838      * @exception CallStateException if a new outgoing call is not currently
839      * possible because no more call slots exist or a call exists that is
840      * dialing, alerting, ringing, or waiting.  Other errors are
841      * handled asynchronously.
842      */
dial(Phone phone, String dialString, UUSInfo uusInfo, int videoState)843     public Connection dial(Phone phone, String dialString, UUSInfo uusInfo, int videoState)
844             throws CallStateException {
845         return phone.dial(dialString,
846                 new PhoneInternalInterface.DialArgs.Builder<>()
847                         .setUusInfo(uusInfo)
848                         .setVideoState(videoState).build());
849     }
850 
851     /**
852      * clear disconnect connection for each phone
853      */
clearDisconnected()854     public void clearDisconnected() {
855         for(Phone phone : mPhones) {
856             phone.clearDisconnected();
857         }
858     }
859 
860     /**
861      * clear disconnect connection for a phone specific
862      * to the provided subId
863      */
clearDisconnected(int subId)864     public void clearDisconnected(int subId) {
865         for(Phone phone : mPhones) {
866             if (phone.getSubId() == subId) {
867                 phone.clearDisconnected();
868             }
869         }
870     }
871 
872     /**
873      * Phone can make a call only if ALL of the following are true:
874      *        - Phone is not powered off
875      *        - There's no incoming or waiting call
876      *        - The foreground call is ACTIVE or IDLE or DISCONNECTED.
877      *          (We mainly need to make sure it *isn't* DIALING or ALERTING.)
878      * @param phone
879      * @return true if the phone can make a new call
880      */
881     @UnsupportedAppUsage
canDial(Phone phone)882     private boolean canDial(Phone phone) {
883         int serviceState = phone.getServiceState().getState();
884         int subId = phone.getSubId();
885         boolean hasRingingCall = hasActiveRingingCall();
886         Call.State fgCallState = getActiveFgCallState(subId);
887 
888         boolean result = (serviceState != ServiceState.STATE_POWER_OFF
889                 && !hasRingingCall
890                 && ((fgCallState == Call.State.ACTIVE)
891                     || (fgCallState == Call.State.IDLE)
892                     || (fgCallState == Call.State.DISCONNECTED)
893                     /*As per 3GPP TS 51.010-1 section 31.13.1.4
894                     call should be alowed when the foreground
895                     call is in ALERTING state*/
896                     || (fgCallState == Call.State.ALERTING)));
897 
898         if (result == false) {
899             Rlog.d(LOG_TAG, "canDial serviceState=" + serviceState
900                             + " hasRingingCall=" + hasRingingCall
901                             + " fgCallState=" + fgCallState);
902         }
903         return result;
904     }
905 
906     /**
907      * Whether or not the phone can do explicit call transfer in the current
908      * phone state--that is, one call holding and one call active.
909      * @return true if the phone can do explicit call transfer; false otherwise.
910      */
canTransfer(Call heldCall)911     public boolean canTransfer(Call heldCall) {
912         Phone activePhone = null;
913         Phone heldPhone = null;
914 
915         if (hasActiveFgCall()) {
916             activePhone = getActiveFgCall().getPhone();
917         }
918 
919         if (heldCall != null) {
920             heldPhone = heldCall.getPhone();
921         }
922 
923         return (heldPhone == activePhone && activePhone.canTransfer());
924     }
925 
926     /**
927      * Whether or not the phone specific to subId can do explicit call transfer
928      * in the current phone state--that is, one call holding and one call active.
929      * @return true if the phone can do explicit call transfer; false otherwise.
930      */
canTransfer(Call heldCall, int subId)931     public boolean canTransfer(Call heldCall, int subId) {
932         Phone activePhone = null;
933         Phone heldPhone = null;
934 
935         if (hasActiveFgCall(subId)) {
936             activePhone = getActiveFgCall(subId).getPhone();
937         }
938 
939         if (heldCall != null) {
940             heldPhone = heldCall.getPhone();
941         }
942 
943         return (heldPhone == activePhone && activePhone.canTransfer());
944     }
945 
946     /**
947      * Connects the held call and active call
948      * Disconnects the subscriber from both calls
949      *
950      * Explicit Call Transfer occurs asynchronously
951      * and may fail. Final notification occurs via
952      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
953      * java.lang.Object) registerForPreciseCallStateChanged()}.
954      *
955      * @exception CallStateException if canTransfer() would return false.
956      * In these cases, this operation may not be performed.
957      */
explicitCallTransfer(Call heldCall)958     public void explicitCallTransfer(Call heldCall) throws CallStateException {
959         if (VDBG) {
960             Rlog.d(LOG_TAG, " explicitCallTransfer(" + heldCall + ")");
961             Rlog.d(LOG_TAG, toString());
962         }
963 
964         if (canTransfer(heldCall)) {
965             heldCall.getPhone().explicitCallTransfer();
966         }
967 
968         if (VDBG) {
969             Rlog.d(LOG_TAG, "End explicitCallTransfer(" + heldCall + ")");
970             Rlog.d(LOG_TAG, toString());
971         }
972 
973     }
974 
975     /**
976      * Returns a list of MMI codes that are pending for a phone. (They have initiated
977      * but have not yet completed).
978      * Presently there is only ever one.
979      *
980      * Use <code>registerForMmiInitiate</code>
981      * and <code>registerForMmiComplete</code> for change notification.
982      * @return null if phone doesn't have or support mmi code
983      */
getPendingMmiCodes(Phone phone)984     public List<? extends MmiCode> getPendingMmiCodes(Phone phone) {
985         Rlog.e(LOG_TAG, "getPendingMmiCodes not implemented");
986         return null;
987     }
988 
989     /**
990      * Sends user response to a USSD REQUEST message.  An MmiCode instance
991      * representing this response is sent to handlers registered with
992      * registerForMmiInitiate.
993      *
994      * @param ussdMessge    Message to send in the response.
995      * @return false if phone doesn't support ussd service
996      */
sendUssdResponse(Phone phone, String ussdMessge)997     public boolean sendUssdResponse(Phone phone, String ussdMessge) {
998         Rlog.e(LOG_TAG, "sendUssdResponse not implemented");
999         return false;
1000     }
1001 
1002     /**
1003      * Mutes or unmutes the microphone for the active call. The microphone
1004      * is automatically unmuted if a call is answered, dialed, or resumed
1005      * from a holding state.
1006      *
1007      * @param muted true to mute the microphone,
1008      * false to activate the microphone.
1009      */
1010 
setMute(boolean muted)1011     public void setMute(boolean muted) {
1012         if (VDBG) {
1013             Rlog.d(LOG_TAG, " setMute(" + muted + ")");
1014             Rlog.d(LOG_TAG, toString());
1015         }
1016 
1017         if (hasActiveFgCall()) {
1018             getActiveFgCall().getPhone().setMute(muted);
1019         }
1020 
1021         if (VDBG) {
1022             Rlog.d(LOG_TAG, "End setMute(" + muted + ")");
1023             Rlog.d(LOG_TAG, toString());
1024         }
1025     }
1026 
1027     /**
1028      * Gets current mute status. Use
1029      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
1030      * java.lang.Object) registerForPreciseCallStateChanged()}
1031      * as a change notifcation, although presently phone state changed is not
1032      * fired when setMute() is called.
1033      *
1034      * @return true is muting, false is unmuting
1035      */
getMute()1036     public boolean getMute() {
1037         if (hasActiveFgCall()) {
1038             return getActiveFgCall().getPhone().getMute();
1039         } else if (hasActiveBgCall()) {
1040             return getFirstActiveBgCall().getPhone().getMute();
1041         }
1042         return false;
1043     }
1044 
1045     /**
1046      * Enables or disables echo suppression.
1047      */
setEchoSuppressionEnabled()1048     public void setEchoSuppressionEnabled() {
1049         if (VDBG) {
1050             Rlog.d(LOG_TAG, " setEchoSuppression()");
1051             Rlog.d(LOG_TAG, toString());
1052         }
1053 
1054         if (hasActiveFgCall()) {
1055             getActiveFgCall().getPhone().setEchoSuppressionEnabled();
1056         }
1057 
1058         if (VDBG) {
1059             Rlog.d(LOG_TAG, "End setEchoSuppression()");
1060             Rlog.d(LOG_TAG, toString());
1061         }
1062     }
1063 
1064     /**
1065      * Play a DTMF tone on the active call.
1066      *
1067      * @param c should be one of 0-9, '*' or '#'. Other values will be
1068      * silently ignored.
1069      * @return false if no active call or the active call doesn't support
1070      *         dtmf tone
1071      */
sendDtmf(char c)1072     public boolean sendDtmf(char c) {
1073         boolean result = false;
1074 
1075         if (VDBG) {
1076             Rlog.d(LOG_TAG, " sendDtmf(" + c + ")");
1077             Rlog.d(LOG_TAG, toString());
1078         }
1079 
1080         if (hasActiveFgCall()) {
1081             getActiveFgCall().getPhone().sendDtmf(c);
1082             result = true;
1083         }
1084 
1085         if (VDBG) {
1086             Rlog.d(LOG_TAG, "End sendDtmf(" + c + ")");
1087             Rlog.d(LOG_TAG, toString());
1088         }
1089         return result;
1090     }
1091 
1092     /**
1093      * Start to paly a DTMF tone on the active call.
1094      * or there is a playing DTMF tone.
1095      * @param c should be one of 0-9, '*' or '#'. Other values will be
1096      * silently ignored.
1097      *
1098      * @return false if no active call or the active call doesn't support
1099      *         dtmf tone
1100      */
startDtmf(char c)1101     public boolean startDtmf(char c) {
1102         boolean result = false;
1103 
1104         if (VDBG) {
1105             Rlog.d(LOG_TAG, " startDtmf(" + c + ")");
1106             Rlog.d(LOG_TAG, toString());
1107         }
1108 
1109         if (hasActiveFgCall()) {
1110             getActiveFgCall().getPhone().startDtmf(c);
1111             result = true;
1112         }
1113 
1114         if (VDBG) {
1115             Rlog.d(LOG_TAG, "End startDtmf(" + c + ")");
1116             Rlog.d(LOG_TAG, toString());
1117         }
1118 
1119         return result;
1120     }
1121 
1122     /**
1123      * Stop the playing DTMF tone. Ignored if there is no playing DTMF
1124      * tone or no active call.
1125      */
stopDtmf()1126     public void stopDtmf() {
1127         if (VDBG) {
1128             Rlog.d(LOG_TAG, " stopDtmf()" );
1129             Rlog.d(LOG_TAG, toString());
1130         }
1131 
1132         if (hasActiveFgCall()) getFgPhone().stopDtmf();
1133 
1134         if (VDBG) {
1135             Rlog.d(LOG_TAG, "End stopDtmf()");
1136             Rlog.d(LOG_TAG, toString());
1137         }
1138     }
1139 
1140     /**
1141      * send burst DTMF tone, it can send the string as single character or multiple character
1142      * ignore if there is no active call or not valid digits string.
1143      * Valid digit means only includes characters ISO-LATIN characters 0-9, *, #
1144      * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character,
1145      * this api can send single character and multiple character, also, this api has response
1146      * back to caller.
1147      *
1148      * @param dtmfString is string representing the dialing digit(s) in the active call
1149      * @param on the DTMF ON length in milliseconds, or 0 for default
1150      * @param off the DTMF OFF length in milliseconds, or 0 for default
1151      * @param onComplete is the callback message when the action is processed by BP
1152      *
1153      */
sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)1154     public boolean sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
1155         if (hasActiveFgCall()) {
1156             getActiveFgCall().getPhone().sendBurstDtmf(dtmfString, on, off, onComplete);
1157             return true;
1158         }
1159         return false;
1160     }
1161 
1162     /**
1163      * Notifies when a voice connection has disconnected, either due to local
1164      * or remote hangup or error.
1165      *
1166      *  Messages received from this will have the following members:<p>
1167      *  <ul><li>Message.obj will be an AsyncResult</li>
1168      *  <li>AsyncResult.userObj = obj</li>
1169      *  <li>AsyncResult.result = a Connection object that is
1170      *  no longer connected.</li></ul>
1171      */
1172     @UnsupportedAppUsage
registerForDisconnect(Handler h, int what, Object obj)1173     public void registerForDisconnect(Handler h, int what, Object obj) {
1174         mDisconnectRegistrants.addUnique(h, what, obj);
1175     }
1176 
1177     /**
1178      * Unregisters for voice disconnection notification.
1179      * Extraneous calls are tolerated silently
1180      */
1181     @UnsupportedAppUsage
unregisterForDisconnect(Handler h)1182     public void unregisterForDisconnect(Handler h){
1183         mDisconnectRegistrants.remove(h);
1184     }
1185 
1186     /**
1187      * Register for getting notifications for change in the Call State {@link Call.State}
1188      * This is called PreciseCallState because the call state is more precise than what
1189      * can be obtained using the {@link PhoneStateListener}
1190      *
1191      * Resulting events will have an AsyncResult in <code>Message.obj</code>.
1192      * AsyncResult.userData will be set to the obj argument here.
1193      * The <em>h</em> parameter is held only by a weak reference.
1194      */
1195     @UnsupportedAppUsage
registerForPreciseCallStateChanged(Handler h, int what, Object obj)1196     public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){
1197         mPreciseCallStateRegistrants.addUnique(h, what, obj);
1198     }
1199 
1200     /**
1201      * Unregisters for voice call state change notifications.
1202      * Extraneous calls are tolerated silently.
1203      */
1204     @UnsupportedAppUsage
unregisterForPreciseCallStateChanged(Handler h)1205     public void unregisterForPreciseCallStateChanged(Handler h){
1206         mPreciseCallStateRegistrants.remove(h);
1207     }
1208 
1209     /**
1210      * Notifies when a previously untracked non-ringing/waiting connection has appeared.
1211      * This is likely due to some other entity (eg, SIM card application) initiating a call.
1212      */
registerForUnknownConnection(Handler h, int what, Object obj)1213     public void registerForUnknownConnection(Handler h, int what, Object obj){
1214         mUnknownConnectionRegistrants.addUnique(h, what, obj);
1215     }
1216 
1217     /**
1218      * Unregisters for unknown connection notifications.
1219      */
unregisterForUnknownConnection(Handler h)1220     public void unregisterForUnknownConnection(Handler h){
1221         mUnknownConnectionRegistrants.remove(h);
1222     }
1223 
1224 
1225     /**
1226      * Notifies when a new ringing or waiting connection has appeared.<p>
1227      *
1228      *  Messages received from this:
1229      *  Message.obj will be an AsyncResult
1230      *  AsyncResult.userObj = obj
1231      *  AsyncResult.result = a Connection. <p>
1232      *  Please check Connection.isRinging() to make sure the Connection
1233      *  has not dropped since this message was posted.
1234      *  If Connection.isRinging() is true, then
1235      *   Connection.getCall() == Phone.getRingingCall()
1236      */
1237     @UnsupportedAppUsage
registerForNewRingingConnection(Handler h, int what, Object obj)1238     public void registerForNewRingingConnection(Handler h, int what, Object obj){
1239         mNewRingingConnectionRegistrants.addUnique(h, what, obj);
1240     }
1241 
1242     /**
1243      * Unregisters for new ringing connection notification.
1244      * Extraneous calls are tolerated silently
1245      */
1246 
1247     @UnsupportedAppUsage
unregisterForNewRingingConnection(Handler h)1248     public void unregisterForNewRingingConnection(Handler h){
1249         mNewRingingConnectionRegistrants.remove(h);
1250     }
1251 
1252     /**
1253      * Notifies when an incoming call rings.<p>
1254      *
1255      *  Messages received from this:
1256      *  Message.obj will be an AsyncResult
1257      *  AsyncResult.userObj = obj
1258      *  AsyncResult.result = a Connection. <p>
1259      */
registerForIncomingRing(Handler h, int what, Object obj)1260     public void registerForIncomingRing(Handler h, int what, Object obj){
1261         mIncomingRingRegistrants.addUnique(h, what, obj);
1262     }
1263 
1264     /**
1265      * Unregisters for ring notification.
1266      * Extraneous calls are tolerated silently
1267      */
1268 
unregisterForIncomingRing(Handler h)1269     public void unregisterForIncomingRing(Handler h){
1270         mIncomingRingRegistrants.remove(h);
1271     }
1272 
1273     /**
1274      * Notifies when out-band ringback tone is needed.<p>
1275      *
1276      *  Messages received from this:
1277      *  Message.obj will be an AsyncResult
1278      *  AsyncResult.userObj = obj
1279      *  AsyncResult.result = boolean, true to start play ringback tone
1280      *                       and false to stop. <p>
1281      */
registerForRingbackTone(Handler h, int what, Object obj)1282     public void registerForRingbackTone(Handler h, int what, Object obj){
1283         mRingbackToneRegistrants.addUnique(h, what, obj);
1284     }
1285 
1286     /**
1287      * Unregisters for ringback tone notification.
1288      */
1289 
unregisterForRingbackTone(Handler h)1290     public void unregisterForRingbackTone(Handler h){
1291         mRingbackToneRegistrants.remove(h);
1292     }
1293 
1294     /**
1295      * Notifies when out-band on-hold tone is needed.<p>
1296      *
1297      *  Messages received from this:
1298      *  Message.obj will be an AsyncResult
1299      *  AsyncResult.userObj = obj
1300      *  AsyncResult.result = boolean, true to start play on-hold tone
1301      *                       and false to stop. <p>
1302      */
registerForOnHoldTone(Handler h, int what, Object obj)1303     public void registerForOnHoldTone(Handler h, int what, Object obj){
1304         mOnHoldToneRegistrants.addUnique(h, what, obj);
1305     }
1306 
1307     /**
1308      * Unregisters for on-hold tone notification.
1309      */
1310 
unregisterForOnHoldTone(Handler h)1311     public void unregisterForOnHoldTone(Handler h){
1312         mOnHoldToneRegistrants.remove(h);
1313     }
1314 
1315     /**
1316      * Registers the handler to reset the uplink mute state to get
1317      * uplink audio.
1318      */
registerForResendIncallMute(Handler h, int what, Object obj)1319     public void registerForResendIncallMute(Handler h, int what, Object obj){
1320         mResendIncallMuteRegistrants.addUnique(h, what, obj);
1321     }
1322 
1323     /**
1324      * Unregisters for resend incall mute notifications.
1325      */
unregisterForResendIncallMute(Handler h)1326     public void unregisterForResendIncallMute(Handler h){
1327         mResendIncallMuteRegistrants.remove(h);
1328     }
1329 
1330     /**
1331      * Register for notifications of initiation of a new MMI code request.
1332      * MMI codes for GSM are discussed in 3GPP TS 22.030.<p>
1333      *
1334      * Example: If Phone.dial is called with "*#31#", then the app will
1335      * be notified here.<p>
1336      *
1337      * The returned <code>Message.obj</code> will contain an AsyncResult.
1338      *
1339      * <code>obj.result</code> will be an "MmiCode" object.
1340      */
registerForMmiInitiate(Handler h, int what, Object obj)1341     public void registerForMmiInitiate(Handler h, int what, Object obj){
1342         mMmiInitiateRegistrants.addUnique(h, what, obj);
1343     }
1344 
1345     /**
1346      * Unregisters for new MMI initiate notification.
1347      * Extraneous calls are tolerated silently
1348      */
unregisterForMmiInitiate(Handler h)1349     public void unregisterForMmiInitiate(Handler h){
1350         mMmiInitiateRegistrants.remove(h);
1351     }
1352 
1353     /**
1354      * Register for notifications that an MMI request has completed
1355      * its network activity and is in its final state. This may mean a state
1356      * of COMPLETE, FAILED, or CANCELLED.
1357      *
1358      * <code>Message.obj</code> will contain an AsyncResult.
1359      * <code>obj.result</code> will be an "MmiCode" object
1360      */
registerForMmiComplete(Handler h, int what, Object obj)1361     public void registerForMmiComplete(Handler h, int what, Object obj){
1362         Rlog.d(LOG_TAG, "registerForMmiComplete");
1363         mMmiCompleteRegistrants.addUnique(h, what, obj);
1364     }
1365 
1366     /**
1367      * Unregisters for MMI complete notification.
1368      * Extraneous calls are tolerated silently
1369      */
unregisterForMmiComplete(Handler h)1370     public void unregisterForMmiComplete(Handler h){
1371         mMmiCompleteRegistrants.remove(h);
1372     }
1373 
1374     /**
1375      * Registration point for Ecm timer reset
1376      * @param h handler to notify
1377      * @param what user-defined message code
1378      * @param obj placed in Message.obj
1379      */
registerForEcmTimerReset(Handler h, int what, Object obj)1380     public void registerForEcmTimerReset(Handler h, int what, Object obj){
1381         mEcmTimerResetRegistrants.addUnique(h, what, obj);
1382     }
1383 
1384     /**
1385      * Unregister for notification for Ecm timer reset
1386      * @param h Handler to be removed from the registrant list.
1387      */
unregisterForEcmTimerReset(Handler h)1388     public void unregisterForEcmTimerReset(Handler h){
1389         mEcmTimerResetRegistrants.remove(h);
1390     }
1391 
1392     /**
1393      * Register for ServiceState changed.
1394      * Message.obj will contain an AsyncResult.
1395      * AsyncResult.result will be a ServiceState instance
1396      */
registerForServiceStateChanged(Handler h, int what, Object obj)1397     public void registerForServiceStateChanged(Handler h, int what, Object obj){
1398         mServiceStateChangedRegistrants.addUnique(h, what, obj);
1399     }
1400 
1401     /**
1402      * Unregisters for ServiceStateChange notification.
1403      * Extraneous calls are tolerated silently
1404      */
unregisterForServiceStateChanged(Handler h)1405     public void unregisterForServiceStateChanged(Handler h){
1406         mServiceStateChangedRegistrants.remove(h);
1407     }
1408 
1409     /**
1410      * Register for notifications when a supplementary service attempt fails.
1411      * Message.obj will contain an AsyncResult.
1412      *
1413      * @param h Handler that receives the notification message.
1414      * @param what User-defined message code.
1415      * @param obj User object.
1416      */
registerForSuppServiceFailed(Handler h, int what, Object obj)1417     public void registerForSuppServiceFailed(Handler h, int what, Object obj){
1418         mSuppServiceFailedRegistrants.addUnique(h, what, obj);
1419     }
1420 
1421     /**
1422      * Unregister for notifications when a supplementary service attempt fails.
1423      * Extraneous calls are tolerated silently
1424      *
1425      * @param h Handler to be removed from the registrant list.
1426      */
unregisterForSuppServiceFailed(Handler h)1427     public void unregisterForSuppServiceFailed(Handler h){
1428         mSuppServiceFailedRegistrants.remove(h);
1429     }
1430 
1431     /**
1432      * Register for notifications when a sInCall VoicePrivacy is enabled
1433      *
1434      * @param h Handler that receives the notification message.
1435      * @param what User-defined message code.
1436      * @param obj User object.
1437      */
registerForInCallVoicePrivacyOn(Handler h, int what, Object obj)1438     public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
1439         mInCallVoicePrivacyOnRegistrants.addUnique(h, what, obj);
1440     }
1441 
1442     /**
1443      * Unregister for notifications when a sInCall VoicePrivacy is enabled
1444      *
1445      * @param h Handler to be removed from the registrant list.
1446      */
unregisterForInCallVoicePrivacyOn(Handler h)1447     public void unregisterForInCallVoicePrivacyOn(Handler h){
1448         mInCallVoicePrivacyOnRegistrants.remove(h);
1449     }
1450 
1451     /**
1452      * Register for notifications when a sInCall VoicePrivacy is disabled
1453      *
1454      * @param h Handler that receives the notification message.
1455      * @param what User-defined message code.
1456      * @param obj User object.
1457      */
registerForInCallVoicePrivacyOff(Handler h, int what, Object obj)1458     public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
1459         mInCallVoicePrivacyOffRegistrants.addUnique(h, what, obj);
1460     }
1461 
1462     /**
1463      * Unregister for notifications when a sInCall VoicePrivacy is disabled
1464      *
1465      * @param h Handler to be removed from the registrant list.
1466      */
unregisterForInCallVoicePrivacyOff(Handler h)1467     public void unregisterForInCallVoicePrivacyOff(Handler h){
1468         mInCallVoicePrivacyOffRegistrants.remove(h);
1469     }
1470 
1471     /**
1472      * Register for notifications when CDMA call waiting comes
1473      *
1474      * @param h Handler that receives the notification message.
1475      * @param what User-defined message code.
1476      * @param obj User object.
1477      */
registerForCallWaiting(Handler h, int what, Object obj)1478     public void registerForCallWaiting(Handler h, int what, Object obj){
1479         mCallWaitingRegistrants.addUnique(h, what, obj);
1480     }
1481 
1482     /**
1483      * Unregister for notifications when CDMA Call waiting comes
1484      * @param h Handler to be removed from the registrant list.
1485      */
unregisterForCallWaiting(Handler h)1486     public void unregisterForCallWaiting(Handler h){
1487         mCallWaitingRegistrants.remove(h);
1488     }
1489 
1490 
1491     /**
1492      * Register for signal information notifications from the network.
1493      * Message.obj will contain an AsyncResult.
1494      * AsyncResult.result will be a SuppServiceNotification instance.
1495      *
1496      * @param h Handler that receives the notification message.
1497      * @param what User-defined message code.
1498      * @param obj User object.
1499      */
1500 
registerForSignalInfo(Handler h, int what, Object obj)1501     public void registerForSignalInfo(Handler h, int what, Object obj){
1502         mSignalInfoRegistrants.addUnique(h, what, obj);
1503     }
1504 
1505     /**
1506      * Unregisters for signal information notifications.
1507      * Extraneous calls are tolerated silently
1508      *
1509      * @param h Handler to be removed from the registrant list.
1510      */
unregisterForSignalInfo(Handler h)1511     public void unregisterForSignalInfo(Handler h){
1512         mSignalInfoRegistrants.remove(h);
1513     }
1514 
1515     /**
1516      * Register for display information notifications from the network.
1517      * Message.obj will contain an AsyncResult.
1518      * AsyncResult.result will be a SuppServiceNotification instance.
1519      *
1520      * @param h Handler that receives the notification message.
1521      * @param what User-defined message code.
1522      * @param obj User object.
1523      */
registerForDisplayInfo(Handler h, int what, Object obj)1524     public void registerForDisplayInfo(Handler h, int what, Object obj){
1525         mDisplayInfoRegistrants.addUnique(h, what, obj);
1526     }
1527 
1528     /**
1529      * Unregisters for display information notifications.
1530      * Extraneous calls are tolerated silently
1531      *
1532      * @param h Handler to be removed from the registrant list.
1533      */
unregisterForDisplayInfo(Handler h)1534     public void unregisterForDisplayInfo(Handler h) {
1535         mDisplayInfoRegistrants.remove(h);
1536     }
1537 
1538     /**
1539      * Register for notifications when CDMA OTA Provision status change
1540      *
1541      * @param h Handler that receives the notification message.
1542      * @param what User-defined message code.
1543      * @param obj User object.
1544      */
registerForCdmaOtaStatusChange(Handler h, int what, Object obj)1545     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj){
1546         mCdmaOtaStatusChangeRegistrants.addUnique(h, what, obj);
1547     }
1548 
1549     /**
1550      * Unregister for notifications when CDMA OTA Provision status change
1551      * @param h Handler to be removed from the registrant list.
1552      */
unregisterForCdmaOtaStatusChange(Handler h)1553     public void unregisterForCdmaOtaStatusChange(Handler h){
1554         mCdmaOtaStatusChangeRegistrants.remove(h);
1555     }
1556 
1557     /**
1558      * Registration point for subscription info ready
1559      * @param h handler to notify
1560      * @param what what code of message when delivered
1561      * @param obj placed in Message.obj
1562      */
registerForSubscriptionInfoReady(Handler h, int what, Object obj)1563     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj){
1564         mSubscriptionInfoReadyRegistrants.addUnique(h, what, obj);
1565     }
1566 
1567     /**
1568      * Unregister for notifications for subscription info
1569      * @param h Handler to be removed from the registrant list.
1570      */
unregisterForSubscriptionInfoReady(Handler h)1571     public void unregisterForSubscriptionInfoReady(Handler h){
1572         mSubscriptionInfoReadyRegistrants.remove(h);
1573     }
1574 
1575     /**
1576      * Sets an event to be fired when the telephony system processes
1577      * a post-dial character on an outgoing call.<p>
1578      *
1579      * Messages of type <code>what</code> will be sent to <code>h</code>.
1580      * The <code>obj</code> field of these Message's will be instances of
1581      * <code>AsyncResult</code>. <code>Message.obj.result</code> will be
1582      * a Connection object.<p>
1583      *
1584      * Message.arg1 will be the post dial character being processed,
1585      * or 0 ('\0') if end of string.<p>
1586      *
1587      * If Connection.getPostDialState() == WAIT,
1588      * the application must call
1589      * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar()
1590      * Connection.proceedAfterWaitChar()} or
1591      * {@link com.android.internal.telephony.Connection#cancelPostDial()
1592      * Connection.cancelPostDial()}
1593      * for the telephony system to continue playing the post-dial
1594      * DTMF sequence.<p>
1595      *
1596      * If Connection.getPostDialState() == WILD,
1597      * the application must call
1598      * {@link com.android.internal.telephony.Connection#proceedAfterWildChar
1599      * Connection.proceedAfterWildChar()}
1600      * or
1601      * {@link com.android.internal.telephony.Connection#cancelPostDial()
1602      * Connection.cancelPostDial()}
1603      * for the telephony system to continue playing the
1604      * post-dial DTMF sequence.<p>
1605      *
1606      */
registerForPostDialCharacter(Handler h, int what, Object obj)1607     public void registerForPostDialCharacter(Handler h, int what, Object obj){
1608         mPostDialCharacterRegistrants.addUnique(h, what, obj);
1609     }
1610 
unregisterForPostDialCharacter(Handler h)1611     public void unregisterForPostDialCharacter(Handler h){
1612         mPostDialCharacterRegistrants.remove(h);
1613     }
1614 
1615     /**
1616      * Register for TTY mode change notifications from the network.
1617      * Message.obj will contain an AsyncResult.
1618      * AsyncResult.result will be an Integer containing new mode.
1619      *
1620      * @param h Handler that receives the notification message.
1621      * @param what User-defined message code.
1622      * @param obj User object.
1623      */
registerForTtyModeReceived(Handler h, int what, Object obj)1624     public void registerForTtyModeReceived(Handler h, int what, Object obj){
1625         mTtyModeReceivedRegistrants.addUnique(h, what, obj);
1626     }
1627 
1628     /**
1629      * Unregisters for TTY mode change notifications.
1630      * Extraneous calls are tolerated silently
1631      *
1632      * @param h Handler to be removed from the registrant list.
1633      */
unregisterForTtyModeReceived(Handler h)1634     public void unregisterForTtyModeReceived(Handler h) {
1635         mTtyModeReceivedRegistrants.remove(h);
1636     }
1637 
1638     /* APIs to access foregroudCalls, backgroudCalls, and ringingCalls
1639      * 1. APIs to access list of calls
1640      * 2. APIs to check if any active call, which has connection other than
1641      * disconnected ones, pleaser refer to Call.isIdle()
1642      * 3. APIs to return first active call
1643      * 4. APIs to return the connections of first active call
1644      * 5. APIs to return other property of first active call
1645      */
1646 
1647     /**
1648      * @return list of all ringing calls
1649      */
1650     @UnsupportedAppUsage
getRingingCalls()1651     public List<Call> getRingingCalls() {
1652         return Collections.unmodifiableList(mRingingCalls);
1653     }
1654 
1655     /**
1656      * @return list of all foreground calls
1657      */
getForegroundCalls()1658     public List<Call> getForegroundCalls() {
1659         return Collections.unmodifiableList(mForegroundCalls);
1660     }
1661 
1662     /**
1663      * @return list of all background calls
1664      */
1665     @UnsupportedAppUsage
getBackgroundCalls()1666     public List<Call> getBackgroundCalls() {
1667         return Collections.unmodifiableList(mBackgroundCalls);
1668     }
1669 
1670     /**
1671      * Return true if there is at least one active foreground call
1672      */
1673     @UnsupportedAppUsage
hasActiveFgCall()1674     public boolean hasActiveFgCall() {
1675         return (getFirstActiveCall(mForegroundCalls) != null);
1676     }
1677 
1678     /**
1679      * Return true if there is at least one active foreground call
1680      * on a particular subId or an active sip call
1681      */
1682     @UnsupportedAppUsage
hasActiveFgCall(int subId)1683     public boolean hasActiveFgCall(int subId) {
1684         return (getFirstActiveCall(mForegroundCalls, subId) != null);
1685     }
1686 
1687     /**
1688      * Return true if there is at least one active background call
1689      */
1690     @UnsupportedAppUsage
hasActiveBgCall()1691     public boolean hasActiveBgCall() {
1692         // TODO since hasActiveBgCall may get called often
1693         // better to cache it to improve performance
1694         return (getFirstActiveCall(mBackgroundCalls) != null);
1695     }
1696 
1697     /**
1698      * Return true if there is at least one active background call
1699      * on a particular subId or an active sip call
1700      */
1701     @UnsupportedAppUsage
hasActiveBgCall(int subId)1702     public boolean hasActiveBgCall(int subId) {
1703         // TODO since hasActiveBgCall may get called often
1704         // better to cache it to improve performance
1705         return (getFirstActiveCall(mBackgroundCalls, subId) != null);
1706     }
1707 
1708     /**
1709      * Return true if there is at least one active ringing call
1710      *
1711      */
hasActiveRingingCall()1712     public boolean hasActiveRingingCall() {
1713         return (getFirstActiveCall(mRingingCalls) != null);
1714     }
1715 
1716     /**
1717      * Return true if there is at least one active ringing call
1718      */
1719     @UnsupportedAppUsage
hasActiveRingingCall(int subId)1720     public boolean hasActiveRingingCall(int subId) {
1721         return (getFirstActiveCall(mRingingCalls, subId) != null);
1722     }
1723 
1724     /**
1725      * return the active foreground call from foreground calls
1726      *
1727      * Active call means the call is NOT in Call.State.IDLE
1728      *
1729      * 1. If there is active foreground call, return it
1730      * 2. If there is no active foreground call, return the
1731      *    foreground call associated with default phone, which state is IDLE.
1732      * 3. If there is no phone registered at all, return null.
1733      *
1734      */
getActiveFgCall()1735     public Call getActiveFgCall() {
1736         Call call = getFirstNonIdleCall(mForegroundCalls);
1737         if (call == null) {
1738             call = (mDefaultPhone == null)
1739                     ? null
1740                     : mDefaultPhone.getForegroundCall();
1741         }
1742         return call;
1743     }
1744 
1745     @UnsupportedAppUsage
getActiveFgCall(int subId)1746     public Call getActiveFgCall(int subId) {
1747         Call call = getFirstNonIdleCall(mForegroundCalls, subId);
1748         if (call == null) {
1749             Phone phone = getPhone(subId);
1750             call = (phone == null)
1751                     ? null
1752                     : phone.getForegroundCall();
1753         }
1754         return call;
1755     }
1756 
1757     // Returns the first call that is not in IDLE state. If both active calls
1758     // and disconnecting/disconnected calls exist, return the first active call.
getFirstNonIdleCall(List<Call> calls)1759     private Call getFirstNonIdleCall(List<Call> calls) {
1760         Call result = null;
1761         for (Call call : calls) {
1762             if (!call.isIdle()) {
1763                 return call;
1764             } else if (call.getState() != Call.State.IDLE) {
1765                 if (result == null) result = call;
1766             }
1767         }
1768         return result;
1769     }
1770 
1771     // Returns the first call that is not in IDLE state. If both active calls
1772     // and disconnecting/disconnected calls exist, return the first active call.
getFirstNonIdleCall(List<Call> calls, int subId)1773     private Call getFirstNonIdleCall(List<Call> calls, int subId) {
1774         Call result = null;
1775         for (Call call : calls) {
1776             if ((call.getPhone().getSubId() == subId) ||
1777                     (call.getPhone() instanceof SipPhone)) {
1778                 if (!call.isIdle()) {
1779                     return call;
1780                 } else if (call.getState() != Call.State.IDLE) {
1781                     if (result == null) result = call;
1782                 }
1783             }
1784         }
1785         return result;
1786     }
1787 
1788     /**
1789      * return one active background call from background calls
1790      *
1791      * Active call means the call is NOT idle defined by Call.isIdle()
1792      *
1793      * 1. If there is only one active background call, return it
1794      * 2. If there is more than one active background call, return the first one
1795      * 3. If there is no active background call, return the background call
1796      *    associated with default phone, which state is IDLE.
1797      * 4. If there is no background call at all, return null.
1798      *
1799      * Complete background calls list can be get by getBackgroundCalls()
1800      */
1801     @UnsupportedAppUsage
getFirstActiveBgCall()1802     public Call getFirstActiveBgCall() {
1803         Call call = getFirstNonIdleCall(mBackgroundCalls);
1804         if (call == null) {
1805             call = (mDefaultPhone == null)
1806                     ? null
1807                     : mDefaultPhone.getBackgroundCall();
1808         }
1809         return call;
1810     }
1811 
1812     /**
1813      * return one active background call from background calls of the
1814      * requested subId.
1815      *
1816      * Active call means the call is NOT idle defined by Call.isIdle()
1817      *
1818      * 1. If there is only one active background call on given sub or
1819      *    on SIP Phone, return it
1820      * 2. If there is more than one active background call, return the background call
1821      *    associated with the active sub.
1822      * 3. If there is no background call at all, return null.
1823      *
1824      * Complete background calls list can be get by getBackgroundCalls()
1825      */
1826     @UnsupportedAppUsage
getFirstActiveBgCall(int subId)1827     public Call getFirstActiveBgCall(int subId) {
1828         Phone phone = getPhone(subId);
1829         if (hasMoreThanOneHoldingCall(subId)) {
1830             return phone.getBackgroundCall();
1831         } else {
1832             Call call = getFirstNonIdleCall(mBackgroundCalls, subId);
1833             if (call == null) {
1834                 call = (phone == null)
1835                         ? null
1836                         : phone.getBackgroundCall();
1837             }
1838             return call;
1839         }
1840     }
1841 
1842     /**
1843      * return one active ringing call from ringing calls
1844      *
1845      * Active call means the call is NOT idle defined by Call.isIdle()
1846      *
1847      * 1. If there is only one active ringing call, return it
1848      * 2. If there is more than one active ringing call, return the first one
1849      * 3. If there is no active ringing call, return the ringing call
1850      *    associated with default phone, which state is IDLE.
1851      * 4. If there is no ringing call at all, return null.
1852      *
1853      * Complete ringing calls list can be get by getRingingCalls()
1854      */
1855     @UnsupportedAppUsage
getFirstActiveRingingCall()1856     public Call getFirstActiveRingingCall() {
1857         Call call = getFirstNonIdleCall(mRingingCalls);
1858         if (call == null) {
1859             call = (mDefaultPhone == null)
1860                     ? null
1861                     : mDefaultPhone.getRingingCall();
1862         }
1863         return call;
1864     }
1865 
1866     @UnsupportedAppUsage
getFirstActiveRingingCall(int subId)1867     public Call getFirstActiveRingingCall(int subId) {
1868         Phone phone = getPhone(subId);
1869         Call call = getFirstNonIdleCall(mRingingCalls, subId);
1870         if (call == null) {
1871             call = (phone == null)
1872                     ? null
1873                     : phone.getRingingCall();
1874         }
1875         return call;
1876     }
1877 
1878     /**
1879      * @return the state of active foreground call
1880      * return IDLE if there is no active foreground call
1881      */
getActiveFgCallState()1882     public Call.State getActiveFgCallState() {
1883         Call fgCall = getActiveFgCall();
1884 
1885         if (fgCall != null) {
1886             return fgCall.getState();
1887         }
1888 
1889         return Call.State.IDLE;
1890     }
1891 
1892     @UnsupportedAppUsage
getActiveFgCallState(int subId)1893     public Call.State getActiveFgCallState(int subId) {
1894         Call fgCall = getActiveFgCall(subId);
1895 
1896         if (fgCall != null) {
1897             return fgCall.getState();
1898         }
1899 
1900         return Call.State.IDLE;
1901     }
1902 
1903     /**
1904      * @return the connections of active foreground call
1905      * return empty list if there is no active foreground call
1906      */
1907     @UnsupportedAppUsage
getFgCallConnections()1908     public List<Connection> getFgCallConnections() {
1909         Call fgCall = getActiveFgCall();
1910         if ( fgCall != null) {
1911             return fgCall.getConnections();
1912         }
1913         return mEmptyConnections;
1914     }
1915 
1916     /**
1917      * @return the connections of active foreground call
1918      * return empty list if there is no active foreground call
1919      */
getFgCallConnections(int subId)1920     public List<Connection> getFgCallConnections(int subId) {
1921         Call fgCall = getActiveFgCall(subId);
1922         if ( fgCall != null) {
1923             return fgCall.getConnections();
1924         }
1925         return mEmptyConnections;
1926     }
1927 
1928     /**
1929      * @return the connections of active background call
1930      * return empty list if there is no active background call
1931      */
1932     @UnsupportedAppUsage
getBgCallConnections()1933     public List<Connection> getBgCallConnections() {
1934         Call bgCall = getFirstActiveBgCall();
1935         if ( bgCall != null) {
1936             return bgCall.getConnections();
1937         }
1938         return mEmptyConnections;
1939     }
1940 
1941     /**
1942      * @return true if there is at least one Foreground call in disconnected state
1943      */
hasDisconnectedFgCall()1944     public boolean hasDisconnectedFgCall() {
1945         return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED) != null);
1946     }
1947 
1948     /**
1949      * @return true if there is at least one Foreground call in disconnected state
1950      */
hasDisconnectedFgCall(int subId)1951     public boolean hasDisconnectedFgCall(int subId) {
1952         return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED,
1953                 subId) != null);
1954     }
1955 
1956     /**
1957      * @return true if there is at least one background call in disconnected state
1958      */
hasDisconnectedBgCall()1959     public boolean hasDisconnectedBgCall() {
1960         return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED) != null);
1961     }
1962 
1963     /**
1964      * @return true if there is at least one background call in disconnected state
1965      */
hasDisconnectedBgCall(int subId)1966     public boolean hasDisconnectedBgCall(int subId) {
1967         return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED,
1968                 subId) != null);
1969     }
1970 
1971 
1972     /**
1973      * @return the first active call from a call list
1974      */
getFirstActiveCall(ArrayList<Call> calls)1975     private  Call getFirstActiveCall(ArrayList<Call> calls) {
1976         for (Call call : calls) {
1977             if (!call.isIdle()) {
1978                 return call;
1979             }
1980         }
1981         return null;
1982     }
1983 
1984     /**
1985      * @return the first active call from a call list
1986      */
getFirstActiveCall(ArrayList<Call> calls, int subId)1987     private  Call getFirstActiveCall(ArrayList<Call> calls, int subId) {
1988         for (Call call : calls) {
1989             if ((!call.isIdle()) && ((call.getPhone().getSubId() == subId) ||
1990                     (call.getPhone() instanceof SipPhone))) {
1991                 return call;
1992             }
1993         }
1994         return null;
1995     }
1996 
1997     /**
1998      * @return the first call in a the Call.state from a call list
1999      */
getFirstCallOfState(ArrayList<Call> calls, Call.State state)2000     private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state) {
2001         for (Call call : calls) {
2002             if (call.getState() == state) {
2003                 return call;
2004             }
2005         }
2006         return null;
2007     }
2008 
2009     /**
2010      * @return the first call in a the Call.state from a call list
2011      */
getFirstCallOfState(ArrayList<Call> calls, Call.State state, int subId)2012     private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state,
2013             int subId) {
2014         for (Call call : calls) {
2015             if ((call.getState() == state) ||
2016                 ((call.getPhone().getSubId() == subId) ||
2017                 (call.getPhone() instanceof SipPhone))) {
2018                 return call;
2019             }
2020         }
2021         return null;
2022     }
2023 
2024     @UnsupportedAppUsage
hasMoreThanOneRingingCall()2025     private boolean hasMoreThanOneRingingCall() {
2026         int count = 0;
2027         for (Call call : mRingingCalls) {
2028             if (call.getState().isRinging()) {
2029                 if (++count > 1) return true;
2030             }
2031         }
2032         return false;
2033     }
2034 
2035     /**
2036      * @return true if more than one active ringing call exists on
2037      * the active subId.
2038      * This checks for the active calls on provided
2039      * subId and also active calls on SIP Phone.
2040      *
2041      */
2042     @UnsupportedAppUsage
hasMoreThanOneRingingCall(int subId)2043     private boolean hasMoreThanOneRingingCall(int subId) {
2044         int count = 0;
2045         for (Call call : mRingingCalls) {
2046             if ((call.getState().isRinging()) &&
2047                 ((call.getPhone().getSubId() == subId) ||
2048                 (call.getPhone() instanceof SipPhone))) {
2049                 if (++count > 1) return true;
2050             }
2051         }
2052         return false;
2053     }
2054 
2055     /**
2056      * @return true if more than one active background call exists on
2057      * the provided subId.
2058      * This checks for the background calls on provided
2059      * subId and also background calls on SIP Phone.
2060      *
2061      */
hasMoreThanOneHoldingCall(int subId)2062     private boolean hasMoreThanOneHoldingCall(int subId) {
2063         int count = 0;
2064         for (Call call : mBackgroundCalls) {
2065             if ((call.getState() == Call.State.HOLDING) &&
2066                 ((call.getPhone().getSubId() == subId) ||
2067                 (call.getPhone() instanceof SipPhone))) {
2068                 if (++count > 1) return true;
2069             }
2070         }
2071         return false;
2072     }
2073 
2074     private class CallManagerHandler extends Handler {
2075         @Override
handleMessage(Message msg)2076         public void handleMessage(Message msg) {
2077 
2078             switch (msg.what) {
2079                 case EVENT_DISCONNECT:
2080                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISCONNECT)");
2081                     mDisconnectRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2082                     // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2083                     //mIsEccDialing = false;
2084                     break;
2085                 case EVENT_PRECISE_CALL_STATE_CHANGED:
2086                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)");
2087                     mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2088                     break;
2089                 case EVENT_NEW_RINGING_CONNECTION:
2090                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)");
2091                     Connection c = (Connection) ((AsyncResult) msg.obj).result;
2092                     int subId = c.getCall().getPhone().getSubId();
2093                     if (getActiveFgCallState(subId).isDialing() || hasMoreThanOneRingingCall()) {
2094                         try {
2095                             Rlog.d(LOG_TAG, "silently drop incoming call: " + c.getCall());
2096                             c.getCall().hangup();
2097                         } catch (CallStateException e) {
2098                             Rlog.w(LOG_TAG, "new ringing connection", e);
2099                         }
2100                     } else {
2101                         mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2102                     }
2103                     break;
2104                 case EVENT_UNKNOWN_CONNECTION:
2105                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)");
2106                     mUnknownConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2107                     break;
2108                 case EVENT_INCOMING_RING:
2109                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_INCOMING_RING)");
2110                     // The event may come from RIL who's not aware of an ongoing fg call
2111                     if (!hasActiveFgCall()) {
2112                         mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2113                     }
2114                     break;
2115                 case EVENT_RINGBACK_TONE:
2116                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RINGBACK_TONE)");
2117                     mRingbackToneRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2118                     break;
2119                 case EVENT_IN_CALL_VOICE_PRIVACY_ON:
2120                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_ON)");
2121                     mInCallVoicePrivacyOnRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2122                     break;
2123                 case EVENT_IN_CALL_VOICE_PRIVACY_OFF:
2124                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_OFF)");
2125                     mInCallVoicePrivacyOffRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2126                     break;
2127                 case EVENT_CALL_WAITING:
2128                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CALL_WAITING)");
2129                     mCallWaitingRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2130                     break;
2131                 case EVENT_DISPLAY_INFO:
2132                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISPLAY_INFO)");
2133                     mDisplayInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2134                     break;
2135                 case EVENT_SIGNAL_INFO:
2136                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SIGNAL_INFO)");
2137                     mSignalInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2138                     break;
2139                 case EVENT_CDMA_OTA_STATUS_CHANGE:
2140                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CDMA_OTA_STATUS_CHANGE)");
2141                     mCdmaOtaStatusChangeRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2142                     break;
2143                 case EVENT_RESEND_INCALL_MUTE:
2144                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RESEND_INCALL_MUTE)");
2145                     mResendIncallMuteRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2146                     break;
2147                 case EVENT_MMI_INITIATE:
2148                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_INITIATE)");
2149                     mMmiInitiateRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2150                     break;
2151                 case EVENT_MMI_COMPLETE:
2152                     Rlog.d(LOG_TAG, "CallManager: handleMessage (EVENT_MMI_COMPLETE)");
2153                     mMmiCompleteRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2154                     break;
2155                 case EVENT_ECM_TIMER_RESET:
2156                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ECM_TIMER_RESET)");
2157                     mEcmTimerResetRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2158                     break;
2159                 case EVENT_SUBSCRIPTION_INFO_READY:
2160                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)");
2161                     mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2162                     break;
2163                 case EVENT_SUPP_SERVICE_FAILED:
2164                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)");
2165                     mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2166                     break;
2167                 case EVENT_SERVICE_STATE_CHANGED:
2168                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SERVICE_STATE_CHANGED)");
2169                     mServiceStateChangedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2170                     // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2171                     //setAudioMode();
2172                     break;
2173                 case EVENT_POST_DIAL_CHARACTER:
2174                     // we need send the character that is being processed in msg.arg1
2175                     // so can't use notifyRegistrants()
2176                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_POST_DIAL_CHARACTER)");
2177                     for(int i=0; i < mPostDialCharacterRegistrants.size(); i++) {
2178                         Message notifyMsg;
2179                         notifyMsg = ((Registrant)mPostDialCharacterRegistrants.get(i)).messageForRegistrant();
2180                         notifyMsg.obj = msg.obj;
2181                         notifyMsg.arg1 = msg.arg1;
2182                         notifyMsg.sendToTarget();
2183                     }
2184                     break;
2185                 case EVENT_ONHOLD_TONE:
2186                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ONHOLD_TONE)");
2187                     mOnHoldToneRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2188                     break;
2189                 case EVENT_TTY_MODE_RECEIVED:
2190                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_TTY_MODE_RECEIVED)");
2191                     mTtyModeReceivedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2192                     break;
2193                 /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2194                 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
2195                     if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RADIO_OFF_OR_NOT_AVAILABLE)");
2196                     setAudioMode();
2197                     break;
2198                 */
2199             }
2200         }
2201     };
2202 }
2203