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