Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2014 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 | |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 17 | package com.android.server.telecom; |
Ben Gilad | 9f2bed3 | 2013-12-12 17:43:26 -0800 | [diff] [blame] | 18 | |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 19 | import android.content.Context; |
Tyler Gunn | bbd78a7 | 2017-04-30 14:16:07 -0700 | [diff] [blame] | 20 | import android.content.Intent; |
Santos Cordon | 99c8a6f | 2014-05-28 18:28:47 -0700 | [diff] [blame] | 21 | import android.graphics.Bitmap; |
| 22 | import android.graphics.drawable.Drawable; |
Sailesh Nepal | ce704b9 | 2014-03-17 18:31:43 -0700 | [diff] [blame] | 23 | import android.net.Uri; |
Sanket Padawe | b5de1cd | 2018-01-05 14:27:30 -0800 | [diff] [blame] | 24 | import android.os.Build; |
Sailesh Nepal | 84fa5f8 | 2014-04-02 11:01:11 -0700 | [diff] [blame] | 25 | import android.os.Bundle; |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 26 | import android.os.Handler; |
Ihab Awad | e6dbc9d | 2015-03-26 10:33:44 -0700 | [diff] [blame] | 27 | import android.os.Looper; |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 28 | import android.os.ParcelFileDescriptor; |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 29 | import android.os.Parcelable; |
Tyler Gunn | 86014fc | 2015-06-12 14:31:25 -0700 | [diff] [blame] | 30 | import android.os.RemoteException; |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 31 | import android.os.SystemClock; |
Yorke Lee | e4a9c41 | 2014-11-14 16:59:42 -0800 | [diff] [blame] | 32 | import android.os.Trace; |
Yorke Lee | 8a736a8 | 2014-08-30 17:19:16 -0700 | [diff] [blame] | 33 | import android.provider.ContactsContract.Contacts; |
Christine Hallstrom | 96a0be6 | 2016-11-30 16:05:13 -0800 | [diff] [blame] | 34 | import android.telecom.CallAudioState; |
Tyler Gunn | 9b618b8 | 2016-10-17 15:54:35 -0700 | [diff] [blame] | 35 | import android.telecom.Conference; |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 36 | import android.telecom.ConnectionService; |
Andrew Lee | 701dc00 | 2014-09-11 21:29:12 -0700 | [diff] [blame] | 37 | import android.telecom.DisconnectCause; |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 38 | import android.telecom.Connection; |
| 39 | import android.telecom.GatewayInfo; |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 40 | import android.telecom.Log; |
| 41 | import android.telecom.Logging.EventManager; |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 42 | import android.telecom.ParcelableConnection; |
| 43 | import android.telecom.PhoneAccount; |
| 44 | import android.telecom.PhoneAccountHandle; |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 45 | import android.telecom.Response; |
| 46 | import android.telecom.StatusHints; |
| 47 | import android.telecom.TelecomManager; |
| 48 | import android.telecom.VideoProfile; |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 49 | import android.telephony.PhoneNumberUtils; |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 50 | import android.text.TextUtils; |
Tej Singh | 95daef7 | 2018-02-05 18:34:19 -0800 | [diff] [blame] | 51 | import android.util.StatsLog; |
Tony Mak | 578a4e6 | 2015-11-23 11:18:51 +0000 | [diff] [blame] | 52 | import android.os.UserHandle; |
Santos Cordon | 0b03b4b | 2014-01-29 18:01:59 -0800 | [diff] [blame] | 53 | |
Ihab Awad | a365390 | 2015-01-23 13:44:46 -0800 | [diff] [blame] | 54 | import com.android.internal.annotations.VisibleForTesting; |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 55 | import com.android.internal.telecom.IVideoProvider; |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 56 | import com.android.internal.telephony.CallerInfo; |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 57 | import com.android.internal.telephony.SmsApplication; |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 58 | import com.android.internal.util.Preconditions; |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 59 | |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 60 | import java.io.IOException; |
Bryce Lee | 41045b4 | 2015-08-05 13:10:39 -0700 | [diff] [blame] | 61 | import java.lang.String; |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 62 | import java.text.SimpleDateFormat; |
Santos Cordon | 12d6182 | 2014-07-29 16:02:20 -0700 | [diff] [blame] | 63 | import java.util.ArrayList; |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 64 | import java.util.Collections; |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 65 | import java.util.Date; |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 66 | import java.util.LinkedList; |
| 67 | import java.util.List; |
Sailesh Nepal | 9199078 | 2014-03-08 17:45:52 -0800 | [diff] [blame] | 68 | import java.util.Locale; |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 69 | import java.util.Objects; |
Ben Gilad | 6192561 | 2014-03-11 19:06:36 -0700 | [diff] [blame] | 70 | import java.util.Set; |
Jay Shrauner | a82c8f7 | 2014-08-14 15:49:16 -0700 | [diff] [blame] | 71 | import java.util.concurrent.ConcurrentHashMap; |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 72 | |
Ben Gilad | 2495d57 | 2014-01-09 17:26:19 -0800 | [diff] [blame] | 73 | /** |
| 74 | * Encapsulates all aspects of a given phone call throughout its lifecycle, starting |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 75 | * from the time the call intent was received by Telecom (vs. the time the call was |
Ben Gilad | 2495d57 | 2014-01-09 17:26:19 -0800 | [diff] [blame] | 76 | * connected etc). |
| 77 | */ |
Ihab Awad | a365390 | 2015-01-23 13:44:46 -0800 | [diff] [blame] | 78 | @VisibleForTesting |
Pengquan Meng | d7f92cf | 2017-11-21 17:52:42 -0800 | [diff] [blame] | 79 | public class Call implements CreateConnectionResponse, EventManager.Loggable, |
| 80 | ConnectionServiceFocusManager.CallFocus { |
Tyler Gunn | 8452be0 | 2015-09-17 09:57:02 -0700 | [diff] [blame] | 81 | public final static String CALL_ID_UNKNOWN = "-1"; |
Tyler Gunn | 7a1f823 | 2015-12-03 19:52:59 -0800 | [diff] [blame] | 82 | public final static long DATA_USAGE_NOT_SET = -1; |
Tyler Gunn | 8452be0 | 2015-09-17 09:57:02 -0700 | [diff] [blame] | 83 | |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 84 | public static final int CALL_DIRECTION_UNDEFINED = 0; |
| 85 | public static final int CALL_DIRECTION_OUTGOING = 1; |
| 86 | public static final int CALL_DIRECTION_INCOMING = 2; |
| 87 | public static final int CALL_DIRECTION_UNKNOWN = 3; |
| 88 | |
Tyler Gunn | 961694a | 2016-03-21 16:01:40 -0700 | [diff] [blame] | 89 | /** Identifies extras changes which originated from a connection service. */ |
| 90 | public static final int SOURCE_CONNECTION_SERVICE = 1; |
| 91 | /** Identifies extras changes which originated from an incall service. */ |
| 92 | public static final int SOURCE_INCALL_SERVICE = 2; |
| 93 | |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 94 | private static final int RTT_PIPE_READ_SIDE_INDEX = 0; |
| 95 | private static final int RTT_PIPE_WRITE_SIDE_INDEX = 1; |
Hall Liu | aeece4e | 2017-02-14 16:42:12 -0800 | [diff] [blame] | 96 | |
| 97 | private static final int INVALID_RTT_REQUEST_ID = -1; |
Tyler Gunn | ad97242 | 2017-11-13 13:36:35 -0800 | [diff] [blame] | 98 | |
| 99 | private static final char NO_DTMF_TONE = '\0'; |
| 100 | |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 101 | /** |
| 102 | * Listener for events on the call. |
| 103 | */ |
Hall Liu | 5b70c1c | 2016-03-03 18:42:57 -0800 | [diff] [blame] | 104 | @VisibleForTesting |
| 105 | public interface Listener { |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 106 | void onSuccessfulOutgoingCall(Call call, int callState); |
Andrew Lee | 701dc00 | 2014-09-11 21:29:12 -0700 | [diff] [blame] | 107 | void onFailedOutgoingCall(Call call, DisconnectCause disconnectCause); |
Hall Liu | 6d4b66d | 2016-04-01 16:31:13 -0700 | [diff] [blame] | 108 | void onSuccessfulIncomingCall(Call call); |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 109 | void onFailedIncomingCall(Call call); |
Yorke Lee | 9250e5f | 2014-10-01 13:39:09 -0700 | [diff] [blame] | 110 | void onSuccessfulUnknownCall(Call call, int callState); |
| 111 | void onFailedUnknownCall(Call call); |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 112 | void onRingbackRequested(Call call, boolean ringbackRequested); |
Evan Charlton | 352105c | 2014-06-03 14:10:54 -0700 | [diff] [blame] | 113 | void onPostDialWait(Call call, String remaining); |
Nancy Chen | a469f76 | 2014-12-09 18:29:20 -0800 | [diff] [blame] | 114 | void onPostDialChar(Call call, char nextChar); |
Ihab Awad | 07bc5ee | 2014-11-12 13:42:52 -0800 | [diff] [blame] | 115 | void onConnectionCapabilitiesChanged(Call call); |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 116 | void onConnectionPropertiesChanged(Call call, boolean didRttChange); |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 117 | void onParentChanged(Call call); |
| 118 | void onChildrenChanged(Call call); |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 119 | void onCannedSmsResponsesLoaded(Call call); |
Andrew Lee | 3bcf935 | 2014-07-23 12:36:05 -0700 | [diff] [blame] | 120 | void onVideoCallProviderChanged(Call call); |
Santos Cordon | 64c7e96 | 2014-07-02 15:15:27 -0700 | [diff] [blame] | 121 | void onCallerInfoChanged(Call call); |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 122 | void onIsVoipAudioModeChanged(Call call); |
Sailesh Nepal | 35faf8c | 2014-07-08 22:02:34 -0700 | [diff] [blame] | 123 | void onStatusHintsChanged(Call call); |
Tyler Gunn | 961694a | 2016-03-21 16:01:40 -0700 | [diff] [blame] | 124 | void onExtrasChanged(Call c, int source, Bundle extras); |
| 125 | void onExtrasRemoved(Call c, int source, List<String> keys); |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 126 | void onHandleChanged(Call call); |
| 127 | void onCallerDisplayNameChanged(Call call); |
Hall Liu | 9696c21 | 2016-06-24 16:09:02 -0700 | [diff] [blame] | 128 | void onVideoStateChanged(Call call, int previousVideoState, int newVideoState); |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 129 | void onTargetPhoneAccountChanged(Call call); |
| 130 | void onConnectionManagerPhoneAccountChanged(Call call); |
Santos Cordon | 12d6182 | 2014-07-29 16:02:20 -0700 | [diff] [blame] | 131 | void onPhoneAccountChanged(Call call); |
| 132 | void onConferenceableCallsChanged(Call call); |
Hall Liu | 63e690c | 2017-02-14 18:05:03 -0800 | [diff] [blame] | 133 | boolean onCanceledViaNewOutgoingCallBroadcast(Call call, long disconnectionTimeout); |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 134 | void onHoldToneRequested(Call call); |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 135 | void onConnectionEvent(Call call, String event, Bundle extras); |
Tyler Gunn | 1a40c4f | 2016-04-14 14:29:45 -0700 | [diff] [blame] | 136 | void onExternalCallChanged(Call call, boolean isExternalCall); |
Hall Liu | aeece4e | 2017-02-14 16:42:12 -0800 | [diff] [blame] | 137 | void onRttInitiationFailure(Call call, int reason); |
| 138 | void onRemoteRttRequest(Call call, int requestId); |
Tyler Gunn | 6f6f1c5 | 2017-04-17 18:22:04 -0700 | [diff] [blame] | 139 | void onHandoverRequested(Call call, PhoneAccountHandle handoverTo, int videoState, |
Sanket Padawe | 4ebc3ca | 2017-11-21 12:49:43 -0800 | [diff] [blame] | 140 | Bundle extras, boolean isLegacy); |
| 141 | void onHandoverFailed(Call call, int error); |
Tyler Gunn | 7c031f2 | 2018-01-18 15:00:41 -0800 | [diff] [blame] | 142 | void onHandoverComplete(Call call); |
Santos Cordon | 64c7e96 | 2014-07-02 15:15:27 -0700 | [diff] [blame] | 143 | } |
| 144 | |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 145 | public abstract static class ListenerBase implements Listener { |
Santos Cordon | 64c7e96 | 2014-07-02 15:15:27 -0700 | [diff] [blame] | 146 | @Override |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 147 | public void onSuccessfulOutgoingCall(Call call, int callState) {} |
Santos Cordon | 64c7e96 | 2014-07-02 15:15:27 -0700 | [diff] [blame] | 148 | @Override |
Andrew Lee | 701dc00 | 2014-09-11 21:29:12 -0700 | [diff] [blame] | 149 | public void onFailedOutgoingCall(Call call, DisconnectCause disconnectCause) {} |
Santos Cordon | 64c7e96 | 2014-07-02 15:15:27 -0700 | [diff] [blame] | 150 | @Override |
Hall Liu | 6d4b66d | 2016-04-01 16:31:13 -0700 | [diff] [blame] | 151 | public void onSuccessfulIncomingCall(Call call) {} |
Santos Cordon | 64c7e96 | 2014-07-02 15:15:27 -0700 | [diff] [blame] | 152 | @Override |
| 153 | public void onFailedIncomingCall(Call call) {} |
| 154 | @Override |
Yorke Lee | 9250e5f | 2014-10-01 13:39:09 -0700 | [diff] [blame] | 155 | public void onSuccessfulUnknownCall(Call call, int callState) {} |
| 156 | @Override |
| 157 | public void onFailedUnknownCall(Call call) {} |
| 158 | @Override |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 159 | public void onRingbackRequested(Call call, boolean ringbackRequested) {} |
Santos Cordon | 64c7e96 | 2014-07-02 15:15:27 -0700 | [diff] [blame] | 160 | @Override |
| 161 | public void onPostDialWait(Call call, String remaining) {} |
| 162 | @Override |
Nancy Chen | a469f76 | 2014-12-09 18:29:20 -0800 | [diff] [blame] | 163 | public void onPostDialChar(Call call, char nextChar) {} |
| 164 | @Override |
Ihab Awad | 07bc5ee | 2014-11-12 13:42:52 -0800 | [diff] [blame] | 165 | public void onConnectionCapabilitiesChanged(Call call) {} |
Santos Cordon | 64c7e96 | 2014-07-02 15:15:27 -0700 | [diff] [blame] | 166 | @Override |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 167 | public void onConnectionPropertiesChanged(Call call, boolean didRttChange) {} |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 168 | @Override |
Santos Cordon | 64c7e96 | 2014-07-02 15:15:27 -0700 | [diff] [blame] | 169 | public void onParentChanged(Call call) {} |
| 170 | @Override |
| 171 | public void onChildrenChanged(Call call) {} |
| 172 | @Override |
| 173 | public void onCannedSmsResponsesLoaded(Call call) {} |
| 174 | @Override |
Andrew Lee | 3bcf935 | 2014-07-23 12:36:05 -0700 | [diff] [blame] | 175 | public void onVideoCallProviderChanged(Call call) {} |
Santos Cordon | 64c7e96 | 2014-07-02 15:15:27 -0700 | [diff] [blame] | 176 | @Override |
Santos Cordon | 64c7e96 | 2014-07-02 15:15:27 -0700 | [diff] [blame] | 177 | public void onCallerInfoChanged(Call call) {} |
Sailesh Nepal | 7e66957 | 2014-07-08 21:29:12 -0700 | [diff] [blame] | 178 | @Override |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 179 | public void onIsVoipAudioModeChanged(Call call) {} |
Sailesh Nepal | 35faf8c | 2014-07-08 22:02:34 -0700 | [diff] [blame] | 180 | @Override |
| 181 | public void onStatusHintsChanged(Call call) {} |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 182 | @Override |
Tyler Gunn | 961694a | 2016-03-21 16:01:40 -0700 | [diff] [blame] | 183 | public void onExtrasChanged(Call c, int source, Bundle extras) {} |
| 184 | @Override |
| 185 | public void onExtrasRemoved(Call c, int source, List<String> keys) {} |
Santos Cordon | b3907b3 | 2015-05-27 17:39:59 -0700 | [diff] [blame] | 186 | @Override |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 187 | public void onHandleChanged(Call call) {} |
| 188 | @Override |
| 189 | public void onCallerDisplayNameChanged(Call call) {} |
Andrew Lee | 4a79660 | 2014-07-11 17:23:03 -0700 | [diff] [blame] | 190 | @Override |
Hall Liu | 9696c21 | 2016-06-24 16:09:02 -0700 | [diff] [blame] | 191 | public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {} |
Sailesh Nepal | 9d58de5 | 2014-07-18 14:53:19 -0700 | [diff] [blame] | 192 | @Override |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 193 | public void onTargetPhoneAccountChanged(Call call) {} |
| 194 | @Override |
| 195 | public void onConnectionManagerPhoneAccountChanged(Call call) {} |
Santos Cordon | 12d6182 | 2014-07-29 16:02:20 -0700 | [diff] [blame] | 196 | @Override |
| 197 | public void onPhoneAccountChanged(Call call) {} |
| 198 | @Override |
| 199 | public void onConferenceableCallsChanged(Call call) {} |
Santos Cordon | cf5b291 | 2014-11-05 21:57:54 -0800 | [diff] [blame] | 200 | @Override |
Hall Liu | 63e690c | 2017-02-14 18:05:03 -0800 | [diff] [blame] | 201 | public boolean onCanceledViaNewOutgoingCallBroadcast(Call call, long disconnectionTimeout) { |
Santos Cordon | cf5b291 | 2014-11-05 21:57:54 -0800 | [diff] [blame] | 202 | return false; |
| 203 | } |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 204 | @Override |
| 205 | public void onHoldToneRequested(Call call) {} |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 206 | @Override |
| 207 | public void onConnectionEvent(Call call, String event, Bundle extras) {} |
Tyler Gunn | 1a40c4f | 2016-04-14 14:29:45 -0700 | [diff] [blame] | 208 | @Override |
| 209 | public void onExternalCallChanged(Call call, boolean isExternalCall) {} |
Hall Liu | aeece4e | 2017-02-14 16:42:12 -0800 | [diff] [blame] | 210 | @Override |
| 211 | public void onRttInitiationFailure(Call call, int reason) {} |
| 212 | @Override |
| 213 | public void onRemoteRttRequest(Call call, int requestId) {} |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 214 | @Override |
Tyler Gunn | 6f6f1c5 | 2017-04-17 18:22:04 -0700 | [diff] [blame] | 215 | public void onHandoverRequested(Call call, PhoneAccountHandle handoverTo, int videoState, |
Sanket Padawe | 4ebc3ca | 2017-11-21 12:49:43 -0800 | [diff] [blame] | 216 | Bundle extras, boolean isLegacy) {} |
| 217 | @Override |
| 218 | public void onHandoverFailed(Call call, int error) {} |
Tyler Gunn | 7c031f2 | 2018-01-18 15:00:41 -0800 | [diff] [blame] | 219 | @Override |
| 220 | public void onHandoverComplete(Call call) {} |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 221 | } |
| 222 | |
Hall Liu | 5b70c1c | 2016-03-03 18:42:57 -0800 | [diff] [blame] | 223 | private final CallerInfoLookupHelper.OnQueryCompleteListener mCallerInfoQueryListener = |
| 224 | new CallerInfoLookupHelper.OnQueryCompleteListener() { |
Santos Cordon | 99c8a6f | 2014-05-28 18:28:47 -0700 | [diff] [blame] | 225 | /** ${inheritDoc} */ |
| 226 | @Override |
Hall Liu | 5b70c1c | 2016-03-03 18:42:57 -0800 | [diff] [blame] | 227 | public void onCallerInfoQueryComplete(Uri handle, CallerInfo callerInfo) { |
Ihab Awad | abcbce4 | 2015-04-07 14:04:01 -0700 | [diff] [blame] | 228 | synchronized (mLock) { |
Hall Liu | 5b70c1c | 2016-03-03 18:42:57 -0800 | [diff] [blame] | 229 | Call.this.setCallerInfo(handle, callerInfo); |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | @Override |
| 234 | public void onContactPhotoQueryComplete(Uri handle, CallerInfo callerInfo) { |
| 235 | synchronized (mLock) { |
| 236 | Call.this.setCallerInfo(handle, callerInfo); |
Santos Cordon | 99c8a6f | 2014-05-28 18:28:47 -0700 | [diff] [blame] | 237 | } |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 238 | } |
Santos Cordon | 99c8a6f | 2014-05-28 18:28:47 -0700 | [diff] [blame] | 239 | }; |
| 240 | |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 241 | /** |
| 242 | * One of CALL_DIRECTION_INCOMING, CALL_DIRECTION_OUTGOING, or CALL_DIRECTION_UNKNOWN |
Yorke Lee | 9250e5f | 2014-10-01 13:39:09 -0700 | [diff] [blame] | 243 | */ |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 244 | private final int mCallDirection; |
Yorke Lee | 9250e5f | 2014-10-01 13:39:09 -0700 | [diff] [blame] | 245 | |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 246 | /** |
Hall Liu | b8ce19c | 2015-10-14 15:13:51 -0700 | [diff] [blame] | 247 | * The post-dial digits that were dialed after the network portion of the number |
| 248 | */ |
| 249 | private final String mPostDialDigits; |
| 250 | |
| 251 | /** |
Brad Ebinger | baf52ba | 2016-03-21 16:38:32 -0700 | [diff] [blame] | 252 | * The secondary line number that an incoming call has been received on if the SIM subscription |
| 253 | * has multiple associated numbers. |
| 254 | */ |
| 255 | private String mViaNumber = ""; |
| 256 | |
| 257 | /** |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 258 | * The wall clock time this call was created. Beyond logging and such, may also be used for |
| 259 | * bookkeeping and specifically for marking certain call attempts as failed attempts. |
| 260 | * Note: This timestamp should NOT be used for calculating call duration. |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 261 | */ |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 262 | private long mCreationTimeMillis; |
Sailesh Nepal | 8c85dee | 2014-04-07 22:21:40 -0700 | [diff] [blame] | 263 | |
Santos Cordon | 40f9b17 | 2014-11-17 10:49:29 -0800 | [diff] [blame] | 264 | /** The time this call was made active. */ |
| 265 | private long mConnectTimeMillis = 0; |
| 266 | |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 267 | /** |
| 268 | * The time, in millis, since boot when this call was connected. This should ONLY be used when |
| 269 | * calculating the duration of the call. |
| 270 | * |
| 271 | * The reason for this is that the {@link SystemClock#elapsedRealtime()} is based on the |
| 272 | * elapsed time since the device was booted. Changes to the system clock (e.g. due to NITZ |
| 273 | * time sync, time zone changes user initiated clock changes) would cause a duration calculated |
| 274 | * based on {@link #mConnectTimeMillis} to change based on the delta in the time. |
| 275 | * Using the {@link SystemClock#elapsedRealtime()} ensures that changes to the wall clock do |
| 276 | * not impact the call duration. |
| 277 | */ |
| 278 | private long mConnectElapsedTimeMillis = 0; |
| 279 | |
| 280 | /** The wall clock time this call was disconnected. */ |
Santos Cordon | 40f9b17 | 2014-11-17 10:49:29 -0800 | [diff] [blame] | 281 | private long mDisconnectTimeMillis = 0; |
| 282 | |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 283 | /** |
| 284 | * The elapsed time since boot when this call was disconnected. Recorded as the |
| 285 | * {@link SystemClock#elapsedRealtime()}. This ensures that the call duration is not impacted |
| 286 | * by changes in the wall time clock. |
| 287 | */ |
| 288 | private long mDisconnectElapsedTimeMillis = 0; |
| 289 | |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 290 | /** The gateway information associated with this call. This stores the original call handle |
| 291 | * that the user is attempting to connect to via the gateway, the actual handle to dial in |
| 292 | * order to connect the call via the gateway, as well as the package name of the gateway |
| 293 | * service. */ |
Nancy Chen | 0d3076c | 2014-07-30 14:45:44 -0700 | [diff] [blame] | 294 | private GatewayInfo mGatewayInfo; |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 295 | |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 296 | private PhoneAccountHandle mConnectionManagerPhoneAccountHandle; |
| 297 | |
| 298 | private PhoneAccountHandle mTargetPhoneAccountHandle; |
Nancy Chen | 77d2d0e | 2014-06-24 12:06:03 -0700 | [diff] [blame] | 299 | |
Tony Mak | 578a4e6 | 2015-11-23 11:18:51 +0000 | [diff] [blame] | 300 | private UserHandle mInitiatingUser; |
| 301 | |
Ihab Awad | e6dbc9d | 2015-03-26 10:33:44 -0700 | [diff] [blame] | 302 | private final Handler mHandler = new Handler(Looper.getMainLooper()); |
Santos Cordon | 2174fb5 | 2014-05-29 08:22:56 -0700 | [diff] [blame] | 303 | |
Santos Cordon | 12d6182 | 2014-07-29 16:02:20 -0700 | [diff] [blame] | 304 | private final List<Call> mConferenceableCalls = new ArrayList<>(); |
| 305 | |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 306 | /** The state of the call. */ |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 307 | private int mState; |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 308 | |
| 309 | /** The handle with which to establish this call. */ |
Sailesh Nepal | ce704b9 | 2014-03-17 18:31:43 -0700 | [diff] [blame] | 310 | private Uri mHandle; |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 311 | |
Nancy Chen | 201b437 | 2014-09-08 14:18:24 -0700 | [diff] [blame] | 312 | /** |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 313 | * The presentation requirements for the handle. See {@link TelecomManager} for valid values. |
Nancy Chen | 201b437 | 2014-09-08 14:18:24 -0700 | [diff] [blame] | 314 | */ |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 315 | private int mHandlePresentation; |
| 316 | |
| 317 | /** The caller display name (CNAP) set by the connection service. */ |
| 318 | private String mCallerDisplayName; |
| 319 | |
Nancy Chen | 201b437 | 2014-09-08 14:18:24 -0700 | [diff] [blame] | 320 | /** |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 321 | * The presentation requirements for the handle. See {@link TelecomManager} for valid values. |
Nancy Chen | 201b437 | 2014-09-08 14:18:24 -0700 | [diff] [blame] | 322 | */ |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 323 | private int mCallerDisplayNamePresentation; |
| 324 | |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 325 | /** |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 326 | * The connection service which is attempted or already connecting this call. |
Santos Cordon | 681663d | 2014-01-30 04:32:15 -0800 | [diff] [blame] | 327 | */ |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 328 | private ConnectionServiceWrapper mConnectionService; |
Ben Gilad | 6192561 | 2014-03-11 19:06:36 -0700 | [diff] [blame] | 329 | |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 330 | private boolean mIsEmergencyCall; |
| 331 | |
Sai Cheemalapati | b7157e9 | 2014-06-11 17:51:55 -0700 | [diff] [blame] | 332 | private boolean mSpeakerphoneOn; |
| 333 | |
Srikanth Chintala | 5bf7502 | 2017-02-03 10:10:35 +0530 | [diff] [blame] | 334 | private boolean mIsDisconnectingChildCall = false; |
| 335 | |
Tyler Gunn | 0a388fc | 2014-07-17 12:21:17 -0700 | [diff] [blame] | 336 | /** |
| 337 | * Tracks the video states which were applicable over the duration of a call. |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 338 | * See {@link VideoProfile} for a list of valid video states. |
Tyler Gunn | 5fb7840 | 2015-04-29 10:09:40 -0700 | [diff] [blame] | 339 | * <p> |
| 340 | * Video state history is tracked when the call is active, and when a call is rejected or |
| 341 | * missed. |
Tyler Gunn | 0a388fc | 2014-07-17 12:21:17 -0700 | [diff] [blame] | 342 | */ |
| 343 | private int mVideoStateHistory; |
| 344 | |
Tyler Gunn | c4abd91 | 2014-07-08 14:22:10 -0700 | [diff] [blame] | 345 | private int mVideoState; |
| 346 | |
Ben Gilad | 6192561 | 2014-03-11 19:06:36 -0700 | [diff] [blame] | 347 | /** |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 348 | * Disconnect cause for the call. Only valid if the state of the call is STATE_DISCONNECTED. |
Andrew Lee | 701dc00 | 2014-09-11 21:29:12 -0700 | [diff] [blame] | 349 | * See {@link android.telecom.DisconnectCause}. |
Santos Cordon | 79ff2bc | 2014-03-27 15:31:27 -0700 | [diff] [blame] | 350 | */ |
Andrew Lee | 701dc00 | 2014-09-11 21:29:12 -0700 | [diff] [blame] | 351 | private DisconnectCause mDisconnectCause = new DisconnectCause(DisconnectCause.UNKNOWN); |
Santos Cordon | 79ff2bc | 2014-03-27 15:31:27 -0700 | [diff] [blame] | 352 | |
Santos Cordon | b3907b3 | 2015-05-27 17:39:59 -0700 | [diff] [blame] | 353 | private Bundle mIntentExtras = new Bundle(); |
Sailesh Nepal | 84fa5f8 | 2014-04-02 11:01:11 -0700 | [diff] [blame] | 354 | |
Tyler Gunn | bbd78a7 | 2017-04-30 14:16:07 -0700 | [diff] [blame] | 355 | /** |
| 356 | * The {@link Intent} which originally created this call. Only populated when we are putting a |
| 357 | * call into a pending state and need to pick up initiation of the call later. |
| 358 | */ |
| 359 | private Intent mOriginalCallIntent = null; |
| 360 | |
Jay Shrauner | a82c8f7 | 2014-08-14 15:49:16 -0700 | [diff] [blame] | 361 | /** Set of listeners on this call. |
| 362 | * |
| 363 | * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is |
| 364 | * load factor before resizing, 1 means we only expect a single thread to |
| 365 | * access the map so make only a single shard |
| 366 | */ |
| 367 | private final Set<Listener> mListeners = Collections.newSetFromMap( |
| 368 | new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 369 | |
Sailesh Nepal | 664837f | 2014-07-14 16:31:51 -0700 | [diff] [blame] | 370 | private CreateConnectionProcessor mCreateConnectionProcessor; |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 371 | |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 372 | /** Caller information retrieved from the latest contact query. */ |
| 373 | private CallerInfo mCallerInfo; |
| 374 | |
| 375 | /** The latest token used with a contact info query. */ |
| 376 | private int mQueryToken = 0; |
| 377 | |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 378 | /** Whether this call is requesting that Telecom play the ringback tone on its behalf. */ |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 379 | private boolean mRingbackRequested = false; |
Ihab Awad | cb387ac | 2014-05-28 16:49:38 -0700 | [diff] [blame] | 380 | |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 381 | /** Whether direct-to-voicemail query is pending. */ |
| 382 | private boolean mDirectToVoicemailQueryPending; |
Santos Cordon | 2174fb5 | 2014-05-29 08:22:56 -0700 | [diff] [blame] | 383 | |
Ihab Awad | 07bc5ee | 2014-11-12 13:42:52 -0800 | [diff] [blame] | 384 | private int mConnectionCapabilities; |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 385 | |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 386 | private int mConnectionProperties; |
| 387 | |
Christine Hallstrom | 96a0be6 | 2016-11-30 16:05:13 -0800 | [diff] [blame] | 388 | private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL; |
| 389 | |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 390 | private boolean mIsConference = false; |
| 391 | |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 392 | private final boolean mShouldAttachToExistingConnection; |
| 393 | |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 394 | private Call mParentCall = null; |
| 395 | |
| 396 | private List<Call> mChildCalls = new LinkedList<>(); |
| 397 | |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 398 | /** Set of text message responses allowed for this call, if applicable. */ |
| 399 | private List<String> mCannedSmsResponses = Collections.EMPTY_LIST; |
| 400 | |
| 401 | /** Whether an attempt has been made to load the text message responses. */ |
| 402 | private boolean mCannedSmsResponsesLoadingStarted = false; |
| 403 | |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 404 | private IVideoProvider mVideoProvider; |
Tyler Gunn | 86014fc | 2015-06-12 14:31:25 -0700 | [diff] [blame] | 405 | private VideoProviderProxy mVideoProviderProxy; |
Nancy Chen | a65d41f | 2014-06-24 12:06:03 -0700 | [diff] [blame] | 406 | |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 407 | private boolean mIsVoipAudioMode; |
Sailesh Nepal | 35faf8c | 2014-07-08 22:02:34 -0700 | [diff] [blame] | 408 | private StatusHints mStatusHints; |
Santos Cordon | b3907b3 | 2015-05-27 17:39:59 -0700 | [diff] [blame] | 409 | private Bundle mExtras; |
Sailesh Nepal | 664837f | 2014-07-14 16:31:51 -0700 | [diff] [blame] | 410 | private final ConnectionServiceRepository mRepository; |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 411 | private final Context mContext; |
Ihab Awad | 78a5e6b | 2015-02-06 10:13:05 -0800 | [diff] [blame] | 412 | private final CallsManager mCallsManager; |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 413 | private final ClockProxy mClockProxy; |
Ihab Awad | e6dbc9d | 2015-03-26 10:33:44 -0700 | [diff] [blame] | 414 | private final TelecomSystem.SyncRoot mLock; |
Tyler Gunn | 8452be0 | 2015-09-17 09:57:02 -0700 | [diff] [blame] | 415 | private final String mId; |
Brad Ebinger | 6e8f3d7 | 2016-06-20 11:35:42 -0700 | [diff] [blame] | 416 | private String mConnectionId; |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 417 | private Analytics.CallInfo mAnalytics; |
Tyler Gunn | ad97242 | 2017-11-13 13:36:35 -0800 | [diff] [blame] | 418 | private char mPlayingDtmfTone; |
Sailesh Nepal | 7e66957 | 2014-07-08 21:29:12 -0700 | [diff] [blame] | 419 | |
Santos Cordon | 88a4a60 | 2014-09-29 19:32:21 -0700 | [diff] [blame] | 420 | private boolean mWasConferencePreviouslyMerged = false; |
Kazuya Ohshiro | 0063a19 | 2017-09-29 14:52:17 +0900 | [diff] [blame] | 421 | private boolean mWasHighDefAudio = false; |
Santos Cordon | 88a4a60 | 2014-09-29 19:32:21 -0700 | [diff] [blame] | 422 | |
Santos Cordon | 9269451 | 2015-04-23 14:47:28 -0700 | [diff] [blame] | 423 | // For conferences which support merge/swap at their level, we retain a notion of an active |
| 424 | // call. This is used for BluetoothPhoneService. In order to support hold/merge, it must have |
| 425 | // the notion of the current "active" call within the conference call. This maintains the |
| 426 | // "active" call and switches every time the user hits "swap". |
Santos Cordon | 88a4a60 | 2014-09-29 19:32:21 -0700 | [diff] [blame] | 427 | private Call mConferenceLevelActiveCall = null; |
| 428 | |
Tyler Gunn | aa47937 | 2014-10-07 10:18:42 -0700 | [diff] [blame] | 429 | private boolean mIsLocallyDisconnecting = false; |
| 430 | |
Sailesh Nepal | 8c85dee | 2014-04-07 22:21:40 -0700 | [diff] [blame] | 431 | /** |
Tyler Gunn | 7a1f823 | 2015-12-03 19:52:59 -0800 | [diff] [blame] | 432 | * Tracks the current call data usage as reported by the video provider. |
| 433 | */ |
| 434 | private long mCallDataUsage = DATA_USAGE_NOT_SET; |
| 435 | |
Tony Mak | d29d937 | 2016-02-08 18:23:41 +0000 | [diff] [blame] | 436 | private boolean mIsWorkCall; |
Tony Mak | 3ae2dc8 | 2016-01-07 11:49:38 +0000 | [diff] [blame] | 437 | |
Tyler Gunn | 5d66e1d | 2018-01-25 20:22:49 -0800 | [diff] [blame] | 438 | /** |
| 439 | * Tracks whether this {@link Call}'s {@link #getTargetPhoneAccount()} has |
| 440 | * {@link PhoneAccount#EXTRA_PLAY_CALL_RECORDING_TONE} set. |
| 441 | */ |
| 442 | private boolean mUseCallRecordingTone; |
| 443 | |
Hall Liu | 4b1759d | 2016-02-02 18:17:40 -0800 | [diff] [blame] | 444 | // Set to true once the NewOutgoingCallIntentBroadcast comes back and is processed. |
| 445 | private boolean mIsNewOutgoingCallIntentBroadcastDone = false; |
| 446 | |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 447 | /** |
| 448 | * Indicates whether the call is remotely held. A call is considered remotely held when |
| 449 | * {@link #onConnectionEvent(String)} receives the {@link Connection#EVENT_ON_HOLD_TONE_START} |
| 450 | * event. |
| 451 | */ |
| 452 | private boolean mIsRemotelyHeld = false; |
| 453 | |
Tyler Gunn | 7a1f823 | 2015-12-03 19:52:59 -0800 | [diff] [blame] | 454 | /** |
Tyler Gunn | acb3bc8 | 2017-01-09 09:43:56 -0800 | [diff] [blame] | 455 | * Indicates whether the {@link PhoneAccount} associated with this call is self-managed. |
| 456 | * See {@link PhoneAccount#CAPABILITY_SELF_MANAGED} for more information. |
| 457 | */ |
| 458 | private boolean mIsSelfManaged = false; |
| 459 | |
| 460 | /** |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 461 | * Indicates whether the {@link PhoneAccount} associated with this call supports video calling. |
| 462 | * {@code True} if the phone account supports video calling, {@code false} otherwise. |
| 463 | */ |
| 464 | private boolean mIsVideoCallingSupported = false; |
| 465 | |
Brad Ebinger | 6e8f3d7 | 2016-06-20 11:35:42 -0700 | [diff] [blame] | 466 | private PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter; |
| 467 | |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 468 | /** |
Tyler Gunn | 9b618b8 | 2016-10-17 15:54:35 -0700 | [diff] [blame] | 469 | * For {@link Connection}s or {@link android.telecom.Conference}s added via a ConnectionManager |
| 470 | * using the {@link android.telecom.ConnectionService#addExistingConnection(PhoneAccountHandle, |
| 471 | * Connection)} or {@link android.telecom.ConnectionService#addConference(Conference)}, |
| 472 | * indicates the ID of this call as it was referred to by the {@code ConnectionService} which |
| 473 | * originally created it. |
| 474 | * |
| 475 | * See {@link Connection#EXTRA_ORIGINAL_CONNECTION_ID} for more information. |
| 476 | */ |
| 477 | private String mOriginalConnectionId; |
| 478 | |
| 479 | /** |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 480 | * Two pairs of {@link android.os.ParcelFileDescriptor}s that handle RTT text communication |
| 481 | * between the in-call app and the connection service. If both non-null, this call should be |
| 482 | * treated as an RTT call. |
| 483 | * Each array should be of size 2. First one is the read side and the second one is the write |
| 484 | * side. |
| 485 | */ |
| 486 | private ParcelFileDescriptor[] mInCallToConnectionServiceStreams; |
| 487 | private ParcelFileDescriptor[] mConnectionServiceToInCallStreams; |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 488 | |
| 489 | /** |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 490 | * True if we're supposed to start this call with RTT, either due to the master switch or due |
| 491 | * to an extra. |
| 492 | */ |
| 493 | private boolean mDidRequestToStartWithRtt = false; |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 494 | /** |
| 495 | * Integer constant from {@link android.telecom.Call.RttCall}. Describes the current RTT mode. |
| 496 | */ |
| 497 | private int mRttMode; |
Hall Liu | 3a75c62 | 2017-11-20 17:45:33 -0800 | [diff] [blame] | 498 | /** |
| 499 | * True if the call was ever an RTT call. |
| 500 | */ |
| 501 | private boolean mWasEverRtt = false; |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 502 | |
| 503 | /** |
Hall Liu | aeece4e | 2017-02-14 16:42:12 -0800 | [diff] [blame] | 504 | * Integer indicating the remote RTT request ID that is pending a response from the user. |
| 505 | */ |
| 506 | private int mPendingRttRequestId = INVALID_RTT_REQUEST_ID; |
| 507 | |
| 508 | /** |
Tyler Gunn | 15d096b | 2017-05-03 15:02:25 -0700 | [diff] [blame] | 509 | * When a call handover has been initiated via {@link #requestHandover(PhoneAccountHandle, |
Sanket Padawe | 4ebc3ca | 2017-11-21 12:49:43 -0800 | [diff] [blame] | 510 | * int, Bundle, boolean)}, contains the call which this call is being handed over to. |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 511 | */ |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 512 | private Call mHandoverDestinationCall = null; |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 513 | |
| 514 | /** |
Tyler Gunn | 15d096b | 2017-05-03 15:02:25 -0700 | [diff] [blame] | 515 | * When a call handover has been initiated via {@link #requestHandover(PhoneAccountHandle, |
Sanket Padawe | 4ebc3ca | 2017-11-21 12:49:43 -0800 | [diff] [blame] | 516 | * int, Bundle, boolean)}, contains the call which this call is being handed over from. |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 517 | */ |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 518 | private Call mHandoverSourceCall = null; |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 519 | |
| 520 | /** |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 521 | * Indicates the current state of this call if it is in the process of a handover. |
Tyler Gunn | 15d096b | 2017-05-03 15:02:25 -0700 | [diff] [blame] | 522 | */ |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 523 | private int mHandoverState = HandoverState.HANDOVER_NONE; |
Tyler Gunn | 15d096b | 2017-05-03 15:02:25 -0700 | [diff] [blame] | 524 | |
| 525 | /** |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 526 | * Persists the specified parameters and initializes the new instance. |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 527 | * @param context The context. |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 528 | * @param repository The connection service repository. |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 529 | * @param handle The handle to dial. |
Yorke Lee | 3350163 | 2014-03-17 19:24:12 -0700 | [diff] [blame] | 530 | * @param gatewayInfo Gateway information to use for the call. |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 531 | * @param connectionManagerPhoneAccountHandle Account to use for the service managing the call. |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 532 | * This account must be one that was registered with the |
| 533 | * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} flag. |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 534 | * @param targetPhoneAccountHandle Account information to use for the call. This account must be |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 535 | * one that was registered with the {@link PhoneAccount#CAPABILITY_CALL_PROVIDER} flag. |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 536 | * @param callDirection one of CALL_DIRECTION_INCOMING, CALL_DIRECTION_OUTGOING, |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 537 | * or CALL_DIRECTION_UNKNOWN. |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 538 | * @param shouldAttachToExistingConnection Set to true to attach the call to an existing |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 539 | * @param clockProxy |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 540 | */ |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 541 | public Call( |
Tyler Gunn | 8452be0 | 2015-09-17 09:57:02 -0700 | [diff] [blame] | 542 | String callId, |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 543 | Context context, |
Ihab Awad | 78a5e6b | 2015-02-06 10:13:05 -0800 | [diff] [blame] | 544 | CallsManager callsManager, |
Ihab Awad | e6dbc9d | 2015-03-26 10:33:44 -0700 | [diff] [blame] | 545 | TelecomSystem.SyncRoot lock, |
Sailesh Nepal | 664837f | 2014-07-14 16:31:51 -0700 | [diff] [blame] | 546 | ConnectionServiceRepository repository, |
Ihab Awad | 8d5d9dd | 2015-03-12 11:11:06 -0700 | [diff] [blame] | 547 | ContactsAsyncHelper contactsAsyncHelper, |
Ihab Awad | abcbce4 | 2015-04-07 14:04:01 -0700 | [diff] [blame] | 548 | CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory, |
Brad Ebinger | 6e8f3d7 | 2016-06-20 11:35:42 -0700 | [diff] [blame] | 549 | PhoneNumberUtilsAdapter phoneNumberUtilsAdapter, |
Sailesh Nepal | 664837f | 2014-07-14 16:31:51 -0700 | [diff] [blame] | 550 | Uri handle, |
| 551 | GatewayInfo gatewayInfo, |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 552 | PhoneAccountHandle connectionManagerPhoneAccountHandle, |
| 553 | PhoneAccountHandle targetPhoneAccountHandle, |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 554 | int callDirection, |
| 555 | boolean shouldAttachToExistingConnection, |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 556 | boolean isConference, |
| 557 | ClockProxy clockProxy) { |
Tyler Gunn | 8452be0 | 2015-09-17 09:57:02 -0700 | [diff] [blame] | 558 | mId = callId; |
Brad Ebinger | 6e8f3d7 | 2016-06-20 11:35:42 -0700 | [diff] [blame] | 559 | mConnectionId = callId; |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 560 | mState = isConference ? CallState.ACTIVE : CallState.NEW; |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 561 | mContext = context; |
Ihab Awad | 78a5e6b | 2015-02-06 10:13:05 -0800 | [diff] [blame] | 562 | mCallsManager = callsManager; |
Ihab Awad | e6dbc9d | 2015-03-26 10:33:44 -0700 | [diff] [blame] | 563 | mLock = lock; |
Sailesh Nepal | 664837f | 2014-07-14 16:31:51 -0700 | [diff] [blame] | 564 | mRepository = repository; |
Brad Ebinger | 6e8f3d7 | 2016-06-20 11:35:42 -0700 | [diff] [blame] | 565 | mPhoneNumberUtilsAdapter = phoneNumberUtilsAdapter; |
Nancy Chen | 0d3076c | 2014-07-30 14:45:44 -0700 | [diff] [blame] | 566 | setHandle(handle); |
Dianne Hackborn | 6df5eb4 | 2015-10-26 17:16:21 -0700 | [diff] [blame] | 567 | mPostDialDigits = handle != null |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 568 | ? PhoneNumberUtils.extractPostDialPortion(handle.getSchemeSpecificPart()) : ""; |
Yorke Lee | 3350163 | 2014-03-17 19:24:12 -0700 | [diff] [blame] | 569 | mGatewayInfo = gatewayInfo; |
Santos Cordon | f193ba4 | 2014-09-12 06:37:39 -0700 | [diff] [blame] | 570 | setConnectionManagerPhoneAccount(connectionManagerPhoneAccountHandle); |
| 571 | setTargetPhoneAccount(targetPhoneAccountHandle); |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 572 | mCallDirection = callDirection; |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 573 | mIsConference = isConference; |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 574 | mShouldAttachToExistingConnection = shouldAttachToExistingConnection |
| 575 | || callDirection == CALL_DIRECTION_INCOMING; |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 576 | maybeLoadCannedSmsResponses(); |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 577 | mAnalytics = new Analytics.CallInfo(); |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 578 | mClockProxy = clockProxy; |
| 579 | mCreationTimeMillis = mClockProxy.currentTimeMillis(); |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 580 | } |
| 581 | |
Tyler Gunn | d92e737 | 2015-01-09 15:59:45 -0800 | [diff] [blame] | 582 | /** |
| 583 | * Persists the specified parameters and initializes the new instance. |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 584 | * @param context The context. |
Tyler Gunn | d92e737 | 2015-01-09 15:59:45 -0800 | [diff] [blame] | 585 | * @param repository The connection service repository. |
| 586 | * @param handle The handle to dial. |
| 587 | * @param gatewayInfo Gateway information to use for the call. |
| 588 | * @param connectionManagerPhoneAccountHandle Account to use for the service managing the call. |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 589 | * This account must be one that was registered with the |
| 590 | * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} flag. |
Tyler Gunn | d92e737 | 2015-01-09 15:59:45 -0800 | [diff] [blame] | 591 | * @param targetPhoneAccountHandle Account information to use for the call. This account must be |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 592 | * one that was registered with the {@link PhoneAccount#CAPABILITY_CALL_PROVIDER} flag. |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 593 | * @param callDirection one of CALL_DIRECTION_INCOMING, CALL_DIRECTION_OUTGOING, |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 594 | * or CALL_DIRECTION_UNKNOWN |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 595 | * @param shouldAttachToExistingConnection Set to true to attach the call to an existing |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 596 | * connection, regardless of whether it's incoming or outgoing. |
Tyler Gunn | d92e737 | 2015-01-09 15:59:45 -0800 | [diff] [blame] | 597 | * @param connectTimeMillis The connection time of the call. |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 598 | * @param clockProxy |
Tyler Gunn | d92e737 | 2015-01-09 15:59:45 -0800 | [diff] [blame] | 599 | */ |
| 600 | Call( |
Tyler Gunn | 8452be0 | 2015-09-17 09:57:02 -0700 | [diff] [blame] | 601 | String callId, |
Tyler Gunn | d92e737 | 2015-01-09 15:59:45 -0800 | [diff] [blame] | 602 | Context context, |
Ihab Awad | 78a5e6b | 2015-02-06 10:13:05 -0800 | [diff] [blame] | 603 | CallsManager callsManager, |
Ihab Awad | e6dbc9d | 2015-03-26 10:33:44 -0700 | [diff] [blame] | 604 | TelecomSystem.SyncRoot lock, |
Tyler Gunn | d92e737 | 2015-01-09 15:59:45 -0800 | [diff] [blame] | 605 | ConnectionServiceRepository repository, |
Ihab Awad | 8d5d9dd | 2015-03-12 11:11:06 -0700 | [diff] [blame] | 606 | ContactsAsyncHelper contactsAsyncHelper, |
Ihab Awad | abcbce4 | 2015-04-07 14:04:01 -0700 | [diff] [blame] | 607 | CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory, |
Brad Ebinger | 6e8f3d7 | 2016-06-20 11:35:42 -0700 | [diff] [blame] | 608 | PhoneNumberUtilsAdapter phoneNumberUtilsAdapter, |
Tyler Gunn | d92e737 | 2015-01-09 15:59:45 -0800 | [diff] [blame] | 609 | Uri handle, |
| 610 | GatewayInfo gatewayInfo, |
| 611 | PhoneAccountHandle connectionManagerPhoneAccountHandle, |
| 612 | PhoneAccountHandle targetPhoneAccountHandle, |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 613 | int callDirection, |
| 614 | boolean shouldAttachToExistingConnection, |
Tyler Gunn | d92e737 | 2015-01-09 15:59:45 -0800 | [diff] [blame] | 615 | boolean isConference, |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 616 | long connectTimeMillis, |
| 617 | long connectElapsedTimeMillis, |
| 618 | ClockProxy clockProxy) { |
Tyler Gunn | 8452be0 | 2015-09-17 09:57:02 -0700 | [diff] [blame] | 619 | this(callId, context, callsManager, lock, repository, contactsAsyncHelper, |
Brad Ebinger | 6e8f3d7 | 2016-06-20 11:35:42 -0700 | [diff] [blame] | 620 | callerInfoAsyncQueryFactory, phoneNumberUtilsAdapter, handle, gatewayInfo, |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 621 | connectionManagerPhoneAccountHandle, targetPhoneAccountHandle, callDirection, |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 622 | shouldAttachToExistingConnection, isConference, clockProxy); |
Tyler Gunn | d92e737 | 2015-01-09 15:59:45 -0800 | [diff] [blame] | 623 | |
| 624 | mConnectTimeMillis = connectTimeMillis; |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 625 | mConnectElapsedTimeMillis = connectElapsedTimeMillis; |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 626 | mAnalytics.setCallStartTime(connectTimeMillis); |
Tyler Gunn | d92e737 | 2015-01-09 15:59:45 -0800 | [diff] [blame] | 627 | } |
| 628 | |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 629 | public void addListener(Listener listener) { |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 630 | mListeners.add(listener); |
| 631 | } |
| 632 | |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 633 | public void removeListener(Listener listener) { |
Jay Shrauner | a82c8f7 | 2014-08-14 15:49:16 -0700 | [diff] [blame] | 634 | if (listener != null) { |
| 635 | mListeners.remove(listener); |
| 636 | } |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 637 | } |
| 638 | |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 639 | public void initAnalytics() { |
| 640 | int analyticsDirection; |
| 641 | switch (mCallDirection) { |
| 642 | case CALL_DIRECTION_OUTGOING: |
| 643 | analyticsDirection = Analytics.OUTGOING_DIRECTION; |
| 644 | break; |
| 645 | case CALL_DIRECTION_INCOMING: |
| 646 | analyticsDirection = Analytics.INCOMING_DIRECTION; |
| 647 | break; |
| 648 | case CALL_DIRECTION_UNKNOWN: |
| 649 | case CALL_DIRECTION_UNDEFINED: |
| 650 | default: |
| 651 | analyticsDirection = Analytics.UNKNOWN_DIRECTION; |
| 652 | } |
| 653 | mAnalytics = Analytics.initiateCallAnalytics(mId, analyticsDirection); |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 654 | Log.addEvent(this, LogUtils.Events.CREATED); |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 655 | } |
| 656 | |
| 657 | public Analytics.CallInfo getAnalytics() { |
| 658 | return mAnalytics; |
| 659 | } |
| 660 | |
Santos Cordon | 2685dab | 2015-04-17 17:12:09 -0700 | [diff] [blame] | 661 | public void destroy() { |
Brad Ebinger | a219bf9 | 2017-05-24 11:06:49 -0700 | [diff] [blame] | 662 | // We should not keep these bitmaps around because the Call objects may be held for logging |
| 663 | // purposes. |
| 664 | // TODO: Make a container object that only stores the information we care about for Logging. |
| 665 | if (mCallerInfo != null) { |
| 666 | mCallerInfo.cachedPhotoIcon = null; |
| 667 | mCallerInfo.cachedPhoto = null; |
| 668 | } |
Hall Liu | ea67a76 | 2018-02-09 16:48:57 -0800 | [diff] [blame] | 669 | |
| 670 | Log.addEvent(this, LogUtils.Events.DESTROYED); |
| 671 | } |
| 672 | |
| 673 | private void closeRttStreams() { |
| 674 | if (mConnectionServiceToInCallStreams != null) { |
| 675 | for (ParcelFileDescriptor fd : mConnectionServiceToInCallStreams) { |
| 676 | if (fd != null) { |
| 677 | try { |
| 678 | fd.close(); |
| 679 | } catch (IOException e) { |
| 680 | // ignore |
| 681 | } |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 682 | } |
| 683 | } |
| 684 | } |
Hall Liu | ea67a76 | 2018-02-09 16:48:57 -0800 | [diff] [blame] | 685 | if (mInCallToConnectionServiceStreams != null) { |
| 686 | for (ParcelFileDescriptor fd : mInCallToConnectionServiceStreams) { |
| 687 | if (fd != null) { |
| 688 | try { |
| 689 | fd.close(); |
| 690 | } catch (IOException e) { |
| 691 | // ignore |
| 692 | } |
| 693 | } |
| 694 | } |
| 695 | } |
Santos Cordon | 2685dab | 2015-04-17 17:12:09 -0700 | [diff] [blame] | 696 | } |
| 697 | |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 698 | /** {@inheritDoc} */ |
Santos Cordon | 12d6182 | 2014-07-29 16:02:20 -0700 | [diff] [blame] | 699 | @Override |
| 700 | public String toString() { |
Sailesh Nepal | 4538f01 | 2014-04-15 11:40:33 -0700 | [diff] [blame] | 701 | String component = null; |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 702 | if (mConnectionService != null && mConnectionService.getComponentName() != null) { |
| 703 | component = mConnectionService.getComponentName().flattenToShortString(); |
Sailesh Nepal | 4538f01 | 2014-04-15 11:40:33 -0700 | [diff] [blame] | 704 | } |
Tyler Gunn | 0a388fc | 2014-07-17 12:21:17 -0700 | [diff] [blame] | 705 | |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 706 | return String.format(Locale.US, "[%s, %s, %s, %s, %s, childs(%d), has_parent(%b), %s, %s]", |
Tyler Gunn | 8452be0 | 2015-09-17 09:57:02 -0700 | [diff] [blame] | 707 | mId, |
Santos Cordon | 66fe882 | 2014-10-10 16:10:58 -0700 | [diff] [blame] | 708 | CallState.toString(mState), |
| 709 | component, |
| 710 | Log.piiHandle(mHandle), |
Tyler Gunn | 959afe0 | 2015-04-07 16:34:45 -0700 | [diff] [blame] | 711 | getVideoStateDescription(getVideoState()), |
Santos Cordon | 66fe882 | 2014-10-10 16:10:58 -0700 | [diff] [blame] | 712 | getChildCalls().size(), |
| 713 | getParentCall() != null, |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 714 | Connection.capabilitiesToString(getConnectionCapabilities()), |
| 715 | Connection.propertiesToString(getConnectionProperties())); |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 716 | } |
| 717 | |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 718 | @Override |
| 719 | public String getDescription() { |
Tyler Gunn | 2b17f23 | 2017-03-08 08:51:00 -0800 | [diff] [blame] | 720 | StringBuilder s = new StringBuilder(); |
| 721 | if (isSelfManaged()) { |
| 722 | s.append("SelfMgd Call"); |
| 723 | } else if (isExternalCall()) { |
| 724 | s.append("External Call"); |
| 725 | } else { |
| 726 | s.append("Call"); |
| 727 | } |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 728 | s.append(getId()); |
| 729 | s.append(" ["); |
| 730 | s.append(SimpleDateFormat.getDateTimeInstance().format(new Date(getCreationTimeMillis()))); |
| 731 | s.append("]"); |
| 732 | s.append(isIncoming() ? "(MT - incoming)" : "(MO - outgoing)"); |
Tyler Gunn | 2b17f23 | 2017-03-08 08:51:00 -0800 | [diff] [blame] | 733 | s.append("\n\tVia PhoneAccount: "); |
| 734 | PhoneAccountHandle targetPhoneAccountHandle = getTargetPhoneAccount(); |
| 735 | if (targetPhoneAccountHandle != null) { |
| 736 | s.append(targetPhoneAccountHandle); |
| 737 | s.append(" ("); |
| 738 | s.append(getTargetPhoneAccountLabel()); |
| 739 | s.append(")"); |
| 740 | } else { |
| 741 | s.append("not set"); |
| 742 | } |
| 743 | |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 744 | s.append("\n\tTo address: "); |
| 745 | s.append(Log.piiHandle(getHandle())); |
Tyler Gunn | 26d478f | 2017-06-20 11:16:57 -0700 | [diff] [blame] | 746 | s.append(" Presentation: "); |
| 747 | switch (getHandlePresentation()) { |
| 748 | case TelecomManager.PRESENTATION_ALLOWED: |
| 749 | s.append("Allowed"); |
| 750 | break; |
| 751 | case TelecomManager.PRESENTATION_PAYPHONE: |
| 752 | s.append("Payphone"); |
| 753 | break; |
| 754 | case TelecomManager.PRESENTATION_RESTRICTED: |
| 755 | s.append("Restricted"); |
| 756 | break; |
| 757 | case TelecomManager.PRESENTATION_UNKNOWN: |
| 758 | s.append("Unknown"); |
| 759 | break; |
| 760 | default: |
| 761 | s.append("<undefined>"); |
| 762 | } |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 763 | s.append("\n"); |
| 764 | return s.toString(); |
| 765 | } |
| 766 | |
Tyler Gunn | 959afe0 | 2015-04-07 16:34:45 -0700 | [diff] [blame] | 767 | /** |
| 768 | * Builds a debug-friendly description string for a video state. |
| 769 | * <p> |
| 770 | * A = audio active, T = video transmission active, R = video reception active, P = video |
| 771 | * paused. |
| 772 | * |
| 773 | * @param videoState The video state. |
| 774 | * @return A string indicating which bits are set in the video state. |
| 775 | */ |
| 776 | private String getVideoStateDescription(int videoState) { |
| 777 | StringBuilder sb = new StringBuilder(); |
| 778 | sb.append("A"); |
| 779 | |
Tyler Gunn | 5b88249 | 2015-06-03 10:03:13 -0700 | [diff] [blame] | 780 | if (VideoProfile.isTransmissionEnabled(videoState)) { |
Tyler Gunn | 959afe0 | 2015-04-07 16:34:45 -0700 | [diff] [blame] | 781 | sb.append("T"); |
| 782 | } |
| 783 | |
Tyler Gunn | 5b88249 | 2015-06-03 10:03:13 -0700 | [diff] [blame] | 784 | if (VideoProfile.isReceptionEnabled(videoState)) { |
Tyler Gunn | 959afe0 | 2015-04-07 16:34:45 -0700 | [diff] [blame] | 785 | sb.append("R"); |
| 786 | } |
| 787 | |
Tyler Gunn | 5b88249 | 2015-06-03 10:03:13 -0700 | [diff] [blame] | 788 | if (VideoProfile.isPaused(videoState)) { |
Tyler Gunn | 959afe0 | 2015-04-07 16:34:45 -0700 | [diff] [blame] | 789 | sb.append("P"); |
| 790 | } |
| 791 | |
| 792 | return sb.toString(); |
| 793 | } |
| 794 | |
Pengquan Meng | d7f92cf | 2017-11-21 17:52:42 -0800 | [diff] [blame] | 795 | @Override |
| 796 | public ConnectionServiceFocusManager.ConnectionServiceFocus getConnectionServiceWrapper() { |
| 797 | return mConnectionService; |
| 798 | } |
| 799 | |
Brad Ebinger | d931a01 | 2015-10-21 12:54:08 -0700 | [diff] [blame] | 800 | @VisibleForTesting |
| 801 | public int getState() { |
Santos Cordon | 0fbe632 | 2014-08-14 04:04:25 -0700 | [diff] [blame] | 802 | return mState; |
Santos Cordon | 0b03b4b | 2014-01-29 18:01:59 -0800 | [diff] [blame] | 803 | } |
| 804 | |
Sailesh Nepal | 646fa3d | 2015-01-28 02:55:36 -0800 | [diff] [blame] | 805 | private boolean shouldContinueProcessingAfterDisconnect() { |
| 806 | // Stop processing once the call is active. |
| 807 | if (!CreateConnectionTimeout.isCallBeingPlaced(this)) { |
| 808 | return false; |
| 809 | } |
| 810 | |
Brad Ebinger | 3ff5edd | 2016-07-11 15:09:55 -0700 | [diff] [blame] | 811 | // Only Redial a Call in the case of it being an Emergency Call. |
| 812 | if(!isEmergencyCall()) { |
| 813 | return false; |
| 814 | } |
| 815 | |
Sailesh Nepal | 646fa3d | 2015-01-28 02:55:36 -0800 | [diff] [blame] | 816 | // Make sure that there are additional connection services to process. |
| 817 | if (mCreateConnectionProcessor == null |
| 818 | || !mCreateConnectionProcessor.isProcessingComplete() |
| 819 | || !mCreateConnectionProcessor.hasMorePhoneAccounts()) { |
| 820 | return false; |
| 821 | } |
| 822 | |
| 823 | if (mDisconnectCause == null) { |
| 824 | return false; |
| 825 | } |
| 826 | |
| 827 | // Continue processing if the current attempt failed or timed out. |
| 828 | return mDisconnectCause.getCode() == DisconnectCause.ERROR || |
| 829 | mCreateConnectionProcessor.isCallTimedOut(); |
| 830 | } |
| 831 | |
Santos Cordon | 0b03b4b | 2014-01-29 18:01:59 -0800 | [diff] [blame] | 832 | /** |
Tyler Gunn | 8452be0 | 2015-09-17 09:57:02 -0700 | [diff] [blame] | 833 | * Returns the unique ID for this call as it exists in Telecom. |
| 834 | * @return The call ID. |
| 835 | */ |
| 836 | public String getId() { |
| 837 | return mId; |
| 838 | } |
| 839 | |
| 840 | /** |
Brad Ebinger | 6e8f3d7 | 2016-06-20 11:35:42 -0700 | [diff] [blame] | 841 | * Returns the unique ID for this call (see {@link #getId}) along with an attempt indicator that |
| 842 | * iterates based on attempts to establish a {@link Connection} using createConnectionProcessor. |
| 843 | * @return The call ID with an appended attempt id. |
| 844 | */ |
| 845 | public String getConnectionId() { |
| 846 | if(mCreateConnectionProcessor != null) { |
| 847 | mConnectionId = mId + "_" + |
| 848 | String.valueOf(mCreateConnectionProcessor.getConnectionAttempt()); |
| 849 | return mConnectionId; |
| 850 | } else { |
| 851 | return mConnectionId; |
| 852 | } |
| 853 | } |
| 854 | |
| 855 | /** |
Santos Cordon | 0b03b4b | 2014-01-29 18:01:59 -0800 | [diff] [blame] | 856 | * Sets the call state. Although there exists the notion of appropriate state transitions |
| 857 | * (see {@link CallState}), in practice those expectations break down when cellular systems |
| 858 | * misbehave and they do this very often. The result is that we do not enforce state transitions |
| 859 | * and instead keep the code resilient to unexpected state changes. |
| 860 | */ |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 861 | public void setState(int newState, String tag) { |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 862 | if (mState != newState) { |
| 863 | Log.v(this, "setState %s -> %s", mState, newState); |
Sailesh Nepal | 2767926 | 2014-12-02 17:07:00 -0800 | [diff] [blame] | 864 | |
Sailesh Nepal | 646fa3d | 2015-01-28 02:55:36 -0800 | [diff] [blame] | 865 | if (newState == CallState.DISCONNECTED && shouldContinueProcessingAfterDisconnect()) { |
| 866 | Log.w(this, "continuing processing disconnected call with another service"); |
Sailesh Nepal | 2767926 | 2014-12-02 17:07:00 -0800 | [diff] [blame] | 867 | mCreateConnectionProcessor.continueProcessingIfPossible(this, mDisconnectCause); |
| 868 | return; |
| 869 | } |
| 870 | |
Brad Ebinger | b079fc5 | 2017-07-07 15:59:13 -0700 | [diff] [blame] | 871 | updateVideoHistoryViaState(mState, newState); |
| 872 | |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 873 | mState = newState; |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 874 | maybeLoadCannedSmsResponses(); |
Santos Cordon | 672321e | 2014-08-21 14:38:58 -0700 | [diff] [blame] | 875 | |
Santos Cordon | 40f9b17 | 2014-11-17 10:49:29 -0800 | [diff] [blame] | 876 | if (mState == CallState.ACTIVE || mState == CallState.ON_HOLD) { |
| 877 | if (mConnectTimeMillis == 0) { |
| 878 | // We check to see if mConnectTime is already set to prevent the |
| 879 | // call from resetting active time when it goes in and out of |
| 880 | // ACTIVE/ON_HOLD |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 881 | mConnectTimeMillis = mClockProxy.currentTimeMillis(); |
| 882 | mConnectElapsedTimeMillis = mClockProxy.elapsedRealtime(); |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 883 | mAnalytics.setCallStartTime(mConnectTimeMillis); |
Santos Cordon | 40f9b17 | 2014-11-17 10:49:29 -0800 | [diff] [blame] | 884 | } |
| 885 | |
| 886 | // We're clearly not disconnected, so reset the disconnected time. |
| 887 | mDisconnectTimeMillis = 0; |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 888 | mDisconnectElapsedTimeMillis = 0; |
Santos Cordon | 40f9b17 | 2014-11-17 10:49:29 -0800 | [diff] [blame] | 889 | } else if (mState == CallState.DISCONNECTED) { |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 890 | mDisconnectTimeMillis = mClockProxy.currentTimeMillis(); |
| 891 | mDisconnectElapsedTimeMillis = mClockProxy.elapsedRealtime(); |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 892 | mAnalytics.setCallEndTime(mDisconnectTimeMillis); |
Santos Cordon | 5dfd380 | 2014-10-08 20:32:13 -0700 | [diff] [blame] | 893 | setLocallyDisconnecting(false); |
Santos Cordon | 672321e | 2014-08-21 14:38:58 -0700 | [diff] [blame] | 894 | fixParentAfterDisconnect(); |
| 895 | } |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 896 | |
| 897 | // Log the state transition event |
| 898 | String event = null; |
| 899 | Object data = null; |
| 900 | switch (newState) { |
| 901 | case CallState.ACTIVE: |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 902 | event = LogUtils.Events.SET_ACTIVE; |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 903 | break; |
| 904 | case CallState.CONNECTING: |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 905 | event = LogUtils.Events.SET_CONNECTING; |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 906 | break; |
| 907 | case CallState.DIALING: |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 908 | event = LogUtils.Events.SET_DIALING; |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 909 | break; |
Tyler Gunn | 1e37be5 | 2016-07-11 08:54:23 -0700 | [diff] [blame] | 910 | case CallState.PULLING: |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 911 | event = LogUtils.Events.SET_PULLING; |
Tyler Gunn | 1e37be5 | 2016-07-11 08:54:23 -0700 | [diff] [blame] | 912 | break; |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 913 | case CallState.DISCONNECTED: |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 914 | event = LogUtils.Events.SET_DISCONNECTED; |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 915 | data = getDisconnectCause(); |
| 916 | break; |
| 917 | case CallState.DISCONNECTING: |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 918 | event = LogUtils.Events.SET_DISCONNECTING; |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 919 | break; |
| 920 | case CallState.ON_HOLD: |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 921 | event = LogUtils.Events.SET_HOLD; |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 922 | break; |
| 923 | case CallState.SELECT_PHONE_ACCOUNT: |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 924 | event = LogUtils.Events.SET_SELECT_PHONE_ACCOUNT; |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 925 | break; |
| 926 | case CallState.RINGING: |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 927 | event = LogUtils.Events.SET_RINGING; |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 928 | break; |
| 929 | } |
| 930 | if (event != null) { |
| 931 | // The string data should be just the tag. |
| 932 | String stringData = tag; |
| 933 | if (data != null) { |
| 934 | // If data exists, add it to tag. If no tag, just use data.toString(). |
| 935 | stringData = stringData == null ? data.toString() : stringData + "> " + data; |
| 936 | } |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 937 | Log.addEvent(this, event, stringData); |
Santos Cordon | 5fa4e4f | 2015-06-10 14:56:01 -0700 | [diff] [blame] | 938 | } |
Tej Singh | 95daef7 | 2018-02-05 18:34:19 -0800 | [diff] [blame] | 939 | int statsdDisconnectCause = (newState == CallState.DISCONNECTED) ? |
| 940 | getDisconnectCause().getCode() : DisconnectCause.UNKNOWN; |
| 941 | StatsLog.write(StatsLog.CALL_STATE_CHANGED, newState, statsdDisconnectCause, |
| 942 | isSelfManaged(), isExternalCall()); |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 943 | } |
Santos Cordon | 0b03b4b | 2014-01-29 18:01:59 -0800 | [diff] [blame] | 944 | } |
| 945 | |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 946 | void setRingbackRequested(boolean ringbackRequested) { |
| 947 | mRingbackRequested = ringbackRequested; |
Ihab Awad | cb387ac | 2014-05-28 16:49:38 -0700 | [diff] [blame] | 948 | for (Listener l : mListeners) { |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 949 | l.onRingbackRequested(this, mRingbackRequested); |
Ihab Awad | cb387ac | 2014-05-28 16:49:38 -0700 | [diff] [blame] | 950 | } |
| 951 | } |
| 952 | |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 953 | boolean isRingbackRequested() { |
| 954 | return mRingbackRequested; |
Ihab Awad | cb387ac | 2014-05-28 16:49:38 -0700 | [diff] [blame] | 955 | } |
| 956 | |
Hall Liu | ada0301 | 2015-10-26 15:44:00 -0700 | [diff] [blame] | 957 | @VisibleForTesting |
| 958 | public boolean isConference() { |
Santos Cordon | 672321e | 2014-08-21 14:38:58 -0700 | [diff] [blame] | 959 | return mIsConference; |
| 960 | } |
| 961 | |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 962 | public Uri getHandle() { |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 963 | return mHandle; |
| 964 | } |
| 965 | |
Hall Liu | b8ce19c | 2015-10-14 15:13:51 -0700 | [diff] [blame] | 966 | public String getPostDialDigits() { |
| 967 | return mPostDialDigits; |
| 968 | } |
| 969 | |
Brad Ebinger | baf52ba | 2016-03-21 16:38:32 -0700 | [diff] [blame] | 970 | public String getViaNumber() { |
| 971 | return mViaNumber; |
| 972 | } |
| 973 | |
| 974 | public void setViaNumber(String viaNumber) { |
| 975 | // If at any point the via number is not empty throughout the call, save that via number. |
| 976 | if (!TextUtils.isEmpty(viaNumber)) { |
| 977 | mViaNumber = viaNumber; |
| 978 | } |
| 979 | } |
| 980 | |
Tyler Gunn | aee51f2 | 2018-03-09 02:33:54 +0000 | [diff] [blame] | 981 | public int getHandlePresentation() { |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 982 | return mHandlePresentation; |
| 983 | } |
| 984 | |
Nancy Chen | 0d3076c | 2014-07-30 14:45:44 -0700 | [diff] [blame] | 985 | |
| 986 | void setHandle(Uri handle) { |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 987 | setHandle(handle, TelecomManager.PRESENTATION_ALLOWED); |
Nancy Chen | 0d3076c | 2014-07-30 14:45:44 -0700 | [diff] [blame] | 988 | } |
| 989 | |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 990 | public void setHandle(Uri handle, int presentation) { |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 991 | if (!Objects.equals(handle, mHandle) || presentation != mHandlePresentation) { |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 992 | mHandlePresentation = presentation; |
Santos Cordon | ecaaeac | 2014-11-05 20:59:04 -0800 | [diff] [blame] | 993 | if (mHandlePresentation == TelecomManager.PRESENTATION_RESTRICTED || |
| 994 | mHandlePresentation == TelecomManager.PRESENTATION_UNKNOWN) { |
| 995 | mHandle = null; |
| 996 | } else { |
| 997 | mHandle = handle; |
Yorke Lee | 96e662d | 2014-11-06 13:02:49 -0800 | [diff] [blame] | 998 | if (mHandle != null && !PhoneAccount.SCHEME_VOICEMAIL.equals(mHandle.getScheme()) |
| 999 | && TextUtils.isEmpty(mHandle.getSchemeSpecificPart())) { |
| 1000 | // If the number is actually empty, set it to null, unless this is a |
| 1001 | // SCHEME_VOICEMAIL uri which always has an empty number. |
Santos Cordon | ecaaeac | 2014-11-05 20:59:04 -0800 | [diff] [blame] | 1002 | mHandle = null; |
| 1003 | } |
| 1004 | } |
| 1005 | |
Roshan Pius | 17010e5 | 2015-08-13 13:05:35 -0700 | [diff] [blame] | 1006 | // Let's not allow resetting of the emergency flag. Once a call becomes an emergency |
| 1007 | // call, it will remain so for the rest of it's lifetime. |
| 1008 | if (!mIsEmergencyCall) { |
Brad Ebinger | 6e8f3d7 | 2016-06-20 11:35:42 -0700 | [diff] [blame] | 1009 | mIsEmergencyCall = mHandle != null && |
| 1010 | mPhoneNumberUtilsAdapter.isLocalEmergencyNumber(mContext, |
| 1011 | mHandle.getSchemeSpecificPart()); |
Roshan Pius | 17010e5 | 2015-08-13 13:05:35 -0700 | [diff] [blame] | 1012 | } |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 1013 | startCallerInfoLookup(); |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 1014 | for (Listener l : mListeners) { |
| 1015 | l.onHandleChanged(this); |
| 1016 | } |
| 1017 | } |
| 1018 | } |
| 1019 | |
Tyler Gunn | 2b17f23 | 2017-03-08 08:51:00 -0800 | [diff] [blame] | 1020 | public String getCallerDisplayName() { |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 1021 | return mCallerDisplayName; |
| 1022 | } |
| 1023 | |
Tyler Gunn | 2b17f23 | 2017-03-08 08:51:00 -0800 | [diff] [blame] | 1024 | public int getCallerDisplayNamePresentation() { |
Sailesh Nepal | e8ecb98 | 2014-07-11 17:19:42 -0700 | [diff] [blame] | 1025 | return mCallerDisplayNamePresentation; |
| 1026 | } |
| 1027 | |
| 1028 | void setCallerDisplayName(String callerDisplayName, int presentation) { |
| 1029 | if (!TextUtils.equals(callerDisplayName, mCallerDisplayName) || |
| 1030 | presentation != mCallerDisplayNamePresentation) { |
| 1031 | mCallerDisplayName = callerDisplayName; |
| 1032 | mCallerDisplayNamePresentation = presentation; |
| 1033 | for (Listener l : mListeners) { |
| 1034 | l.onCallerDisplayNameChanged(this); |
| 1035 | } |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 1036 | } |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 1037 | } |
| 1038 | |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 1039 | public String getName() { |
Santos Cordon | 99c8a6f | 2014-05-28 18:28:47 -0700 | [diff] [blame] | 1040 | return mCallerInfo == null ? null : mCallerInfo.name; |
| 1041 | } |
| 1042 | |
Bryce Lee | 41045b4 | 2015-08-05 13:10:39 -0700 | [diff] [blame] | 1043 | public String getPhoneNumber() { |
| 1044 | return mCallerInfo == null ? null : mCallerInfo.phoneNumber; |
| 1045 | } |
| 1046 | |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 1047 | public Bitmap getPhotoIcon() { |
Santos Cordon | 99c8a6f | 2014-05-28 18:28:47 -0700 | [diff] [blame] | 1048 | return mCallerInfo == null ? null : mCallerInfo.cachedPhotoIcon; |
| 1049 | } |
| 1050 | |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 1051 | public Drawable getPhoto() { |
Santos Cordon | 99c8a6f | 2014-05-28 18:28:47 -0700 | [diff] [blame] | 1052 | return mCallerInfo == null ? null : mCallerInfo.cachedPhoto; |
| 1053 | } |
| 1054 | |
Santos Cordon | 79ff2bc | 2014-03-27 15:31:27 -0700 | [diff] [blame] | 1055 | /** |
Andrew Lee | 701dc00 | 2014-09-11 21:29:12 -0700 | [diff] [blame] | 1056 | * @param disconnectCause The reason for the disconnection, represented by |
| 1057 | * {@link android.telecom.DisconnectCause}. |
Santos Cordon | 79ff2bc | 2014-03-27 15:31:27 -0700 | [diff] [blame] | 1058 | */ |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 1059 | public void setDisconnectCause(DisconnectCause disconnectCause) { |
Santos Cordon | 79ff2bc | 2014-03-27 15:31:27 -0700 | [diff] [blame] | 1060 | // TODO: Consider combining this method with a setDisconnected() method that is totally |
| 1061 | // separate from setState. |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 1062 | mAnalytics.setCallDisconnectCause(disconnectCause); |
Santos Cordon | 79ff2bc | 2014-03-27 15:31:27 -0700 | [diff] [blame] | 1063 | mDisconnectCause = disconnectCause; |
Santos Cordon | 79ff2bc | 2014-03-27 15:31:27 -0700 | [diff] [blame] | 1064 | } |
| 1065 | |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 1066 | public DisconnectCause getDisconnectCause() { |
Santos Cordon | 79ff2bc | 2014-03-27 15:31:27 -0700 | [diff] [blame] | 1067 | return mDisconnectCause; |
| 1068 | } |
| 1069 | |
Brad Ebinger | f190007 | 2015-11-12 17:25:06 -0800 | [diff] [blame] | 1070 | @VisibleForTesting |
| 1071 | public boolean isEmergencyCall() { |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 1072 | return mIsEmergencyCall; |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 1073 | } |
| 1074 | |
Yorke Lee | 3350163 | 2014-03-17 19:24:12 -0700 | [diff] [blame] | 1075 | /** |
| 1076 | * @return The original handle this call is associated with. In-call services should use this |
| 1077 | * handle when indicating in their UI the handle that is being called. |
| 1078 | */ |
| 1079 | public Uri getOriginalHandle() { |
| 1080 | if (mGatewayInfo != null && !mGatewayInfo.isEmpty()) { |
Nancy Chen | 201b437 | 2014-09-08 14:18:24 -0700 | [diff] [blame] | 1081 | return mGatewayInfo.getOriginalAddress(); |
Yorke Lee | 3350163 | 2014-03-17 19:24:12 -0700 | [diff] [blame] | 1082 | } |
| 1083 | return getHandle(); |
| 1084 | } |
| 1085 | |
Brad Ebinger | 5385513 | 2015-10-30 10:58:19 -0700 | [diff] [blame] | 1086 | @VisibleForTesting |
| 1087 | public GatewayInfo getGatewayInfo() { |
Yorke Lee | 3350163 | 2014-03-17 19:24:12 -0700 | [diff] [blame] | 1088 | return mGatewayInfo; |
| 1089 | } |
| 1090 | |
Nancy Chen | 0d3076c | 2014-07-30 14:45:44 -0700 | [diff] [blame] | 1091 | void setGatewayInfo(GatewayInfo gatewayInfo) { |
| 1092 | mGatewayInfo = gatewayInfo; |
| 1093 | } |
| 1094 | |
Brad Ebinger | f190007 | 2015-11-12 17:25:06 -0800 | [diff] [blame] | 1095 | @VisibleForTesting |
| 1096 | public PhoneAccountHandle getConnectionManagerPhoneAccount() { |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 1097 | return mConnectionManagerPhoneAccountHandle; |
Nancy Chen | 77d2d0e | 2014-06-24 12:06:03 -0700 | [diff] [blame] | 1098 | } |
| 1099 | |
Brad Ebinger | f190007 | 2015-11-12 17:25:06 -0800 | [diff] [blame] | 1100 | @VisibleForTesting |
| 1101 | public void setConnectionManagerPhoneAccount(PhoneAccountHandle accountHandle) { |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 1102 | if (!Objects.equals(mConnectionManagerPhoneAccountHandle, accountHandle)) { |
| 1103 | mConnectionManagerPhoneAccountHandle = accountHandle; |
Ihab Awad | 69eb0f5 | 2014-07-18 11:20:37 -0700 | [diff] [blame] | 1104 | for (Listener l : mListeners) { |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 1105 | l.onConnectionManagerPhoneAccountChanged(this); |
| 1106 | } |
| 1107 | } |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 1108 | checkIfRttCapable(); |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 1109 | } |
| 1110 | |
Hall Liu | ada0301 | 2015-10-26 15:44:00 -0700 | [diff] [blame] | 1111 | @VisibleForTesting |
| 1112 | public PhoneAccountHandle getTargetPhoneAccount() { |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 1113 | return mTargetPhoneAccountHandle; |
| 1114 | } |
| 1115 | |
Brad Ebinger | f190007 | 2015-11-12 17:25:06 -0800 | [diff] [blame] | 1116 | @VisibleForTesting |
| 1117 | public void setTargetPhoneAccount(PhoneAccountHandle accountHandle) { |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 1118 | if (!Objects.equals(mTargetPhoneAccountHandle, accountHandle)) { |
| 1119 | mTargetPhoneAccountHandle = accountHandle; |
| 1120 | for (Listener l : mListeners) { |
| 1121 | l.onTargetPhoneAccountChanged(this); |
Ihab Awad | 69eb0f5 | 2014-07-18 11:20:37 -0700 | [diff] [blame] | 1122 | } |
Tyler Gunn | 5d66e1d | 2018-01-25 20:22:49 -0800 | [diff] [blame] | 1123 | configureCallAttributes(); |
Ihab Awad | 69eb0f5 | 2014-07-18 11:20:37 -0700 | [diff] [blame] | 1124 | } |
Tyler Gunn | ddec589 | 2016-09-28 10:26:13 -0700 | [diff] [blame] | 1125 | checkIfVideoCapable(); |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 1126 | checkIfRttCapable(); |
Nancy Chen | 53ceedc | 2014-07-08 18:56:51 -0700 | [diff] [blame] | 1127 | } |
| 1128 | |
Tyler Gunn | 2b17f23 | 2017-03-08 08:51:00 -0800 | [diff] [blame] | 1129 | public CharSequence getTargetPhoneAccountLabel() { |
| 1130 | if (getTargetPhoneAccount() == null) { |
| 1131 | return null; |
| 1132 | } |
| 1133 | PhoneAccount phoneAccount = mCallsManager.getPhoneAccountRegistrar() |
| 1134 | .getPhoneAccountUnchecked(getTargetPhoneAccount()); |
| 1135 | |
| 1136 | if (phoneAccount == null) { |
| 1137 | return null; |
| 1138 | } |
| 1139 | |
| 1140 | return phoneAccount.getLabel(); |
| 1141 | } |
| 1142 | |
Tyler Gunn | 6f6f1c5 | 2017-04-17 18:22:04 -0700 | [diff] [blame] | 1143 | /** |
| 1144 | * Determines if this Call should be written to the call log. |
| 1145 | * @return {@code true} for managed calls or for self-managed calls which have the |
| 1146 | * {@link PhoneAccount#EXTRA_LOG_SELF_MANAGED_CALLS} extra set. |
| 1147 | */ |
| 1148 | public boolean isLoggedSelfManaged() { |
| 1149 | if (!isSelfManaged()) { |
| 1150 | // Managed calls are always logged. |
| 1151 | return true; |
| 1152 | } |
| 1153 | if (getTargetPhoneAccount() == null) { |
| 1154 | return false; |
| 1155 | } |
| 1156 | PhoneAccount phoneAccount = mCallsManager.getPhoneAccountRegistrar() |
| 1157 | .getPhoneAccountUnchecked(getTargetPhoneAccount()); |
| 1158 | |
| 1159 | if (phoneAccount == null) { |
| 1160 | return false; |
| 1161 | } |
| 1162 | |
| 1163 | return phoneAccount.getExtras() != null && phoneAccount.getExtras().getBoolean( |
| 1164 | PhoneAccount.EXTRA_LOG_SELF_MANAGED_CALLS, false); |
| 1165 | } |
| 1166 | |
Brad Ebinger | d931a01 | 2015-10-21 12:54:08 -0700 | [diff] [blame] | 1167 | @VisibleForTesting |
| 1168 | public boolean isIncoming() { |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 1169 | return mCallDirection == CALL_DIRECTION_INCOMING; |
| 1170 | } |
| 1171 | |
Tyler Gunn | 4fe861d | 2016-03-29 19:33:56 -0700 | [diff] [blame] | 1172 | public boolean isExternalCall() { |
| 1173 | return (getConnectionProperties() & Connection.PROPERTY_IS_EXTERNAL_CALL) == |
| 1174 | Connection.PROPERTY_IS_EXTERNAL_CALL; |
| 1175 | } |
| 1176 | |
Tony Mak | d29d937 | 2016-02-08 18:23:41 +0000 | [diff] [blame] | 1177 | public boolean isWorkCall() { |
| 1178 | return mIsWorkCall; |
| 1179 | } |
| 1180 | |
Tyler Gunn | 5d66e1d | 2018-01-25 20:22:49 -0800 | [diff] [blame] | 1181 | public boolean isUsingCallRecordingTone() { |
| 1182 | return mUseCallRecordingTone; |
| 1183 | } |
| 1184 | |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 1185 | public boolean isVideoCallingSupported() { |
| 1186 | return mIsVideoCallingSupported; |
| 1187 | } |
| 1188 | |
Tyler Gunn | acb3bc8 | 2017-01-09 09:43:56 -0800 | [diff] [blame] | 1189 | public boolean isSelfManaged() { |
| 1190 | return mIsSelfManaged; |
| 1191 | } |
| 1192 | |
| 1193 | public void setIsSelfManaged(boolean isSelfManaged) { |
| 1194 | mIsSelfManaged = isSelfManaged; |
| 1195 | |
| 1196 | // Connection properties will add/remove the PROPERTY_SELF_MANAGED. |
| 1197 | setConnectionProperties(getConnectionProperties()); |
| 1198 | } |
| 1199 | |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 1200 | public void markFinishedHandoverStateAndCleanup(int handoverState) { |
| 1201 | if (mHandoverSourceCall != null) { |
| 1202 | mHandoverSourceCall.setHandoverState(handoverState); |
| 1203 | } else if (mHandoverDestinationCall != null) { |
| 1204 | mHandoverDestinationCall.setHandoverState(handoverState); |
Tyler Gunn | 6f6f1c5 | 2017-04-17 18:22:04 -0700 | [diff] [blame] | 1205 | } |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 1206 | setHandoverState(handoverState); |
| 1207 | maybeCleanupHandover(); |
| 1208 | } |
| 1209 | |
| 1210 | public void maybeCleanupHandover() { |
| 1211 | if (mHandoverSourceCall != null) { |
| 1212 | mHandoverSourceCall.setHandoverSourceCall(null); |
| 1213 | mHandoverSourceCall.setHandoverDestinationCall(null); |
| 1214 | mHandoverSourceCall = null; |
| 1215 | } else if (mHandoverDestinationCall != null) { |
| 1216 | mHandoverDestinationCall.setHandoverSourceCall(null); |
| 1217 | mHandoverDestinationCall.setHandoverDestinationCall(null); |
| 1218 | mHandoverDestinationCall = null; |
| 1219 | } |
Tyler Gunn | 6f6f1c5 | 2017-04-17 18:22:04 -0700 | [diff] [blame] | 1220 | } |
| 1221 | |
| 1222 | public boolean isHandoverInProgress() { |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 1223 | return mHandoverSourceCall != null || mHandoverDestinationCall != null; |
Tyler Gunn | 6f6f1c5 | 2017-04-17 18:22:04 -0700 | [diff] [blame] | 1224 | } |
| 1225 | |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 1226 | public Call getHandoverDestinationCall() { |
| 1227 | return mHandoverDestinationCall; |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 1228 | } |
| 1229 | |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 1230 | public void setHandoverDestinationCall(Call call) { |
| 1231 | mHandoverDestinationCall = call; |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 1232 | } |
| 1233 | |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 1234 | public Call getHandoverSourceCall() { |
| 1235 | return mHandoverSourceCall; |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 1236 | } |
| 1237 | |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 1238 | public void setHandoverSourceCall(Call call) { |
| 1239 | mHandoverSourceCall = call; |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 1240 | } |
| 1241 | |
Tyler Gunn | 141ef58 | 2017-05-26 13:38:13 -0700 | [diff] [blame] | 1242 | public void setHandoverState(int handoverState) { |
| 1243 | Log.d(this, "setHandoverState: callId=%s, handoverState=%s", getId(), |
| 1244 | HandoverState.stateToString(handoverState)); |
| 1245 | mHandoverState = handoverState; |
| 1246 | } |
| 1247 | |
| 1248 | public int getHandoverState() { |
| 1249 | return mHandoverState; |
Tyler Gunn | 15d096b | 2017-05-03 15:02:25 -0700 | [diff] [blame] | 1250 | } |
| 1251 | |
Tyler Gunn | 5d66e1d | 2018-01-25 20:22:49 -0800 | [diff] [blame] | 1252 | private void configureCallAttributes() { |
Tony Mak | d29d937 | 2016-02-08 18:23:41 +0000 | [diff] [blame] | 1253 | PhoneAccountRegistrar phoneAccountRegistrar = mCallsManager.getPhoneAccountRegistrar(); |
| 1254 | boolean isWorkCall = false; |
Tyler Gunn | 5d66e1d | 2018-01-25 20:22:49 -0800 | [diff] [blame] | 1255 | boolean isCallRecordingToneSupported = false; |
Tony Mak | d29d937 | 2016-02-08 18:23:41 +0000 | [diff] [blame] | 1256 | PhoneAccount phoneAccount = |
| 1257 | phoneAccountRegistrar.getPhoneAccountUnchecked(mTargetPhoneAccountHandle); |
| 1258 | if (phoneAccount != null) { |
Brad Ebinger | c113360 | 2016-01-11 18:03:36 -0800 | [diff] [blame] | 1259 | final UserHandle userHandle; |
| 1260 | if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) { |
| 1261 | userHandle = mInitiatingUser; |
| 1262 | } else { |
Tony Mak | 3ae2dc8 | 2016-01-07 11:49:38 +0000 | [diff] [blame] | 1263 | userHandle = mTargetPhoneAccountHandle.getUserHandle(); |
| 1264 | } |
Tony Mak | d29d937 | 2016-02-08 18:23:41 +0000 | [diff] [blame] | 1265 | if (userHandle != null) { |
| 1266 | isWorkCall = UserUtil.isManagedProfile(mContext, userHandle); |
Tony Mak | 3ae2dc8 | 2016-01-07 11:49:38 +0000 | [diff] [blame] | 1267 | } |
Tyler Gunn | 5d66e1d | 2018-01-25 20:22:49 -0800 | [diff] [blame] | 1268 | |
| 1269 | isCallRecordingToneSupported = (phoneAccount.hasCapabilities( |
| 1270 | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) && phoneAccount.getExtras() != null |
| 1271 | && phoneAccount.getExtras().getBoolean( |
| 1272 | PhoneAccount.EXTRA_PLAY_CALL_RECORDING_TONE, false)); |
Tony Mak | 3ae2dc8 | 2016-01-07 11:49:38 +0000 | [diff] [blame] | 1273 | } |
Tony Mak | d29d937 | 2016-02-08 18:23:41 +0000 | [diff] [blame] | 1274 | mIsWorkCall = isWorkCall; |
Tyler Gunn | 5d66e1d | 2018-01-25 20:22:49 -0800 | [diff] [blame] | 1275 | mUseCallRecordingTone = isCallRecordingToneSupported; |
Tony Mak | 3ae2dc8 | 2016-01-07 11:49:38 +0000 | [diff] [blame] | 1276 | } |
| 1277 | |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 1278 | /** |
| 1279 | * Caches the state of the {@link PhoneAccount#CAPABILITY_VIDEO_CALLING} {@link PhoneAccount} |
Tyler Gunn | ddec589 | 2016-09-28 10:26:13 -0700 | [diff] [blame] | 1280 | * capability and ensures that the video state is updated if the phone account does not support |
| 1281 | * video calling. |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 1282 | */ |
| 1283 | private void checkIfVideoCapable() { |
| 1284 | PhoneAccountRegistrar phoneAccountRegistrar = mCallsManager.getPhoneAccountRegistrar(); |
Tyler Gunn | ddec589 | 2016-09-28 10:26:13 -0700 | [diff] [blame] | 1285 | if (mTargetPhoneAccountHandle == null) { |
| 1286 | // If no target phone account handle is specified, assume we can potentially perform a |
| 1287 | // video call; once the phone account is set, we can confirm that it is video capable. |
| 1288 | mIsVideoCallingSupported = true; |
| 1289 | Log.d(this, "checkIfVideoCapable: no phone account selected; assume video capable."); |
| 1290 | return; |
| 1291 | } |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 1292 | PhoneAccount phoneAccount = |
| 1293 | phoneAccountRegistrar.getPhoneAccountUnchecked(mTargetPhoneAccountHandle); |
| 1294 | mIsVideoCallingSupported = phoneAccount != null && phoneAccount.hasCapabilities( |
| 1295 | PhoneAccount.CAPABILITY_VIDEO_CALLING); |
Tyler Gunn | ddec589 | 2016-09-28 10:26:13 -0700 | [diff] [blame] | 1296 | |
| 1297 | if (!mIsVideoCallingSupported && VideoProfile.isVideo(getVideoState())) { |
| 1298 | // The PhoneAccount for the Call was set to one which does not support video calling, |
| 1299 | // and the current call is configured to be a video call; downgrade to audio-only. |
| 1300 | setVideoState(VideoProfile.STATE_AUDIO_ONLY); |
| 1301 | Log.d(this, "checkIfVideoCapable: selected phone account doesn't support video."); |
| 1302 | } |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 1303 | } |
| 1304 | |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 1305 | private void checkIfRttCapable() { |
| 1306 | PhoneAccountRegistrar phoneAccountRegistrar = mCallsManager.getPhoneAccountRegistrar(); |
| 1307 | if (mTargetPhoneAccountHandle == null) { |
| 1308 | return; |
| 1309 | } |
| 1310 | |
| 1311 | // Check both the target phone account and the connection manager phone account -- if |
| 1312 | // either support RTT, just set the streams and have them set/unset the RTT property as |
| 1313 | // needed. |
| 1314 | PhoneAccount phoneAccount = |
| 1315 | phoneAccountRegistrar.getPhoneAccountUnchecked(mTargetPhoneAccountHandle); |
| 1316 | PhoneAccount connectionManagerPhoneAccount = phoneAccountRegistrar.getPhoneAccountUnchecked( |
| 1317 | mConnectionManagerPhoneAccountHandle); |
| 1318 | boolean isRttSupported = phoneAccount != null && phoneAccount.hasCapabilities( |
| 1319 | PhoneAccount.CAPABILITY_RTT); |
| 1320 | boolean isConnectionManagerRttSupported = connectionManagerPhoneAccount != null |
| 1321 | && connectionManagerPhoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_RTT); |
| 1322 | |
| 1323 | if ((isConnectionManagerRttSupported || isRttSupported) |
| 1324 | && mDidRequestToStartWithRtt && !areRttStreamsInitialized()) { |
| 1325 | // If the phone account got set to an RTT capable one and we haven't set the streams |
| 1326 | // yet, do so now. |
Hall Liu | ea67a76 | 2018-02-09 16:48:57 -0800 | [diff] [blame] | 1327 | createRttStreams(); |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 1328 | Log.i(this, "Setting RTT streams after target phone account selected"); |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 1329 | } |
| 1330 | } |
| 1331 | |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 1332 | boolean shouldAttachToExistingConnection() { |
| 1333 | return mShouldAttachToExistingConnection; |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 1334 | } |
| 1335 | |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 1336 | /** |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 1337 | * Note: This method relies on {@link #mConnectElapsedTimeMillis} and |
| 1338 | * {@link #mDisconnectElapsedTimeMillis} which are independent of the wall clock (which could |
| 1339 | * change due to clock changes). |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 1340 | * @return The "age" of this call object in milliseconds, which typically also represents the |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 1341 | * period since this call was added to the set pending outgoing calls. |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 1342 | */ |
Hall Liu | ada0301 | 2015-10-26 15:44:00 -0700 | [diff] [blame] | 1343 | @VisibleForTesting |
| 1344 | public long getAgeMillis() { |
Santos Cordon | 40f9b17 | 2014-11-17 10:49:29 -0800 | [diff] [blame] | 1345 | if (mState == CallState.DISCONNECTED && |
| 1346 | (mDisconnectCause.getCode() == DisconnectCause.REJECTED || |
| 1347 | mDisconnectCause.getCode() == DisconnectCause.MISSED)) { |
| 1348 | // Rejected and missed calls have no age. They're immortal!! |
| 1349 | return 0; |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 1350 | } else if (mConnectElapsedTimeMillis == 0) { |
Santos Cordon | 40f9b17 | 2014-11-17 10:49:29 -0800 | [diff] [blame] | 1351 | // Age is measured in the amount of time the call was active. A zero connect time |
| 1352 | // indicates that we never went active, so return 0 for the age. |
| 1353 | return 0; |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 1354 | } else if (mDisconnectElapsedTimeMillis == 0) { |
Santos Cordon | 40f9b17 | 2014-11-17 10:49:29 -0800 | [diff] [blame] | 1355 | // We connected, but have not yet disconnected |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 1356 | return mClockProxy.elapsedRealtime() - mConnectElapsedTimeMillis; |
Santos Cordon | 40f9b17 | 2014-11-17 10:49:29 -0800 | [diff] [blame] | 1357 | } |
| 1358 | |
Tyler Gunn | 8bb2b01 | 2017-08-04 09:28:59 -0700 | [diff] [blame] | 1359 | return mDisconnectElapsedTimeMillis - mConnectElapsedTimeMillis; |
Ben Gilad | 0407fb2 | 2014-01-09 16:18:41 -0800 | [diff] [blame] | 1360 | } |
Santos Cordon | 0b03b4b | 2014-01-29 18:01:59 -0800 | [diff] [blame] | 1361 | |
Yorke Lee | f98fb57 | 2014-03-05 10:56:55 -0800 | [diff] [blame] | 1362 | /** |
| 1363 | * @return The time when this call object was created and added to the set of pending outgoing |
| 1364 | * calls. |
| 1365 | */ |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 1366 | public long getCreationTimeMillis() { |
Sailesh Nepal | 8c85dee | 2014-04-07 22:21:40 -0700 | [diff] [blame] | 1367 | return mCreationTimeMillis; |
| 1368 | } |
| 1369 | |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 1370 | public void setCreationTimeMillis(long time) { |
Yorke Lee | 0c1e4f6 | 2014-10-14 16:56:45 -0700 | [diff] [blame] | 1371 | mCreationTimeMillis = time; |
| 1372 | } |
| 1373 | |
Sailesh Nepal | 8c85dee | 2014-04-07 22:21:40 -0700 | [diff] [blame] | 1374 | long getConnectTimeMillis() { |
| 1375 | return mConnectTimeMillis; |
| 1376 | } |
| 1377 | |
Ihab Awad | 07bc5ee | 2014-11-12 13:42:52 -0800 | [diff] [blame] | 1378 | int getConnectionCapabilities() { |
| 1379 | return mConnectionCapabilities; |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 1380 | } |
| 1381 | |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 1382 | int getConnectionProperties() { |
| 1383 | return mConnectionProperties; |
| 1384 | } |
| 1385 | |
Ihab Awad | 07bc5ee | 2014-11-12 13:42:52 -0800 | [diff] [blame] | 1386 | void setConnectionCapabilities(int connectionCapabilities) { |
| 1387 | setConnectionCapabilities(connectionCapabilities, false /* forceUpdate */); |
Yorke Lee | 604a90f | 2014-10-20 12:13:32 -0700 | [diff] [blame] | 1388 | } |
| 1389 | |
Ihab Awad | 07bc5ee | 2014-11-12 13:42:52 -0800 | [diff] [blame] | 1390 | void setConnectionCapabilities(int connectionCapabilities, boolean forceUpdate) { |
| 1391 | Log.v(this, "setConnectionCapabilities: %s", Connection.capabilitiesToString( |
| 1392 | connectionCapabilities)); |
| 1393 | if (forceUpdate || mConnectionCapabilities != connectionCapabilities) { |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 1394 | // If the phone account does not support video calling, and the connection capabilities |
| 1395 | // passed in indicate that the call supports video, remove those video capabilities. |
| 1396 | if (!isVideoCallingSupported() && doesCallSupportVideo(connectionCapabilities)) { |
| 1397 | Log.w(this, "setConnectionCapabilities: attempt to set connection as video " + |
| 1398 | "capable when not supported by the phone account."); |
| 1399 | connectionCapabilities = removeVideoCapabilities(connectionCapabilities); |
| 1400 | } |
| 1401 | |
Santos Cordon | 0d7a00a | 2016-07-26 15:33:00 -0700 | [diff] [blame] | 1402 | int previousCapabilities = mConnectionCapabilities; |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 1403 | mConnectionCapabilities = connectionCapabilities; |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 1404 | for (Listener l : mListeners) { |
Ihab Awad | 07bc5ee | 2014-11-12 13:42:52 -0800 | [diff] [blame] | 1405 | l.onConnectionCapabilitiesChanged(this); |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 1406 | } |
Santos Cordon | 0d7a00a | 2016-07-26 15:33:00 -0700 | [diff] [blame] | 1407 | |
| 1408 | int xorCaps = previousCapabilities ^ mConnectionCapabilities; |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 1409 | Log.addEvent(this, LogUtils.Events.CAPABILITY_CHANGE, |
Santos Cordon | 0d7a00a | 2016-07-26 15:33:00 -0700 | [diff] [blame] | 1410 | "Current: [%s], Removed [%s], Added [%s]", |
| 1411 | Connection.capabilitiesToStringShort(mConnectionCapabilities), |
| 1412 | Connection.capabilitiesToStringShort(previousCapabilities & xorCaps), |
| 1413 | Connection.capabilitiesToStringShort(mConnectionCapabilities & xorCaps)); |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 1414 | } |
| 1415 | } |
| 1416 | |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 1417 | void setConnectionProperties(int connectionProperties) { |
| 1418 | Log.v(this, "setConnectionProperties: %s", Connection.propertiesToString( |
| 1419 | connectionProperties)); |
Tyler Gunn | acb3bc8 | 2017-01-09 09:43:56 -0800 | [diff] [blame] | 1420 | |
| 1421 | // Ensure the ConnectionService can't change the state of the self-managed property. |
| 1422 | if (isSelfManaged()) { |
| 1423 | connectionProperties |= Connection.PROPERTY_SELF_MANAGED; |
| 1424 | } else { |
| 1425 | connectionProperties &= ~Connection.PROPERTY_SELF_MANAGED; |
| 1426 | } |
| 1427 | |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 1428 | int changedProperties = mConnectionProperties ^ connectionProperties; |
| 1429 | |
| 1430 | if (changedProperties != 0) { |
Tyler Gunn | 1a40c4f | 2016-04-14 14:29:45 -0700 | [diff] [blame] | 1431 | int previousProperties = mConnectionProperties; |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 1432 | mConnectionProperties = connectionProperties; |
Hall Liu | ea67a76 | 2018-02-09 16:48:57 -0800 | [diff] [blame] | 1433 | if ((mConnectionProperties & Connection.PROPERTY_IS_RTT) == |
| 1434 | Connection.PROPERTY_IS_RTT) { |
| 1435 | createRttStreams(); |
| 1436 | } |
Kazuya Ohshiro | 0063a19 | 2017-09-29 14:52:17 +0900 | [diff] [blame] | 1437 | mWasHighDefAudio = (connectionProperties & Connection.PROPERTY_HIGH_DEF_AUDIO) == |
| 1438 | Connection.PROPERTY_HIGH_DEF_AUDIO; |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 1439 | boolean didRttChange = |
| 1440 | (changedProperties & Connection.PROPERTY_IS_RTT) == Connection.PROPERTY_IS_RTT; |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 1441 | for (Listener l : mListeners) { |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 1442 | l.onConnectionPropertiesChanged(this, didRttChange); |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 1443 | } |
Tyler Gunn | 1a40c4f | 2016-04-14 14:29:45 -0700 | [diff] [blame] | 1444 | |
| 1445 | boolean wasExternal = (previousProperties & Connection.PROPERTY_IS_EXTERNAL_CALL) |
| 1446 | == Connection.PROPERTY_IS_EXTERNAL_CALL; |
| 1447 | boolean isExternal = (connectionProperties & Connection.PROPERTY_IS_EXTERNAL_CALL) |
| 1448 | == Connection.PROPERTY_IS_EXTERNAL_CALL; |
| 1449 | if (wasExternal != isExternal) { |
| 1450 | Log.v(this, "setConnectionProperties: external call changed isExternal = %b", |
| 1451 | isExternal); |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 1452 | Log.addEvent(this, LogUtils.Events.IS_EXTERNAL, isExternal); |
Tyler Gunn | 1a40c4f | 2016-04-14 14:29:45 -0700 | [diff] [blame] | 1453 | for (Listener l : mListeners) { |
| 1454 | l.onExternalCallChanged(this, isExternal); |
| 1455 | } |
Tyler Gunn | 1a40c4f | 2016-04-14 14:29:45 -0700 | [diff] [blame] | 1456 | } |
Santos Cordon | 0d7a00a | 2016-07-26 15:33:00 -0700 | [diff] [blame] | 1457 | |
Hall Liu | d7fe686 | 2016-09-09 16:36:14 -0700 | [diff] [blame] | 1458 | mAnalytics.addCallProperties(mConnectionProperties); |
| 1459 | |
Santos Cordon | 0d7a00a | 2016-07-26 15:33:00 -0700 | [diff] [blame] | 1460 | int xorProps = previousProperties ^ mConnectionProperties; |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 1461 | Log.addEvent(this, LogUtils.Events.PROPERTY_CHANGE, |
Santos Cordon | 0d7a00a | 2016-07-26 15:33:00 -0700 | [diff] [blame] | 1462 | "Current: [%s], Removed [%s], Added [%s]", |
| 1463 | Connection.propertiesToStringShort(mConnectionProperties), |
| 1464 | Connection.propertiesToStringShort(previousProperties & xorProps), |
| 1465 | Connection.propertiesToStringShort(mConnectionProperties & xorProps)); |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 1466 | } |
| 1467 | } |
| 1468 | |
Hall Liu | cff959e | 2016-12-07 14:04:57 -0800 | [diff] [blame] | 1469 | public int getSupportedAudioRoutes() { |
Christine Hallstrom | 96a0be6 | 2016-11-30 16:05:13 -0800 | [diff] [blame] | 1470 | return mSupportedAudioRoutes; |
| 1471 | } |
| 1472 | |
| 1473 | void setSupportedAudioRoutes(int audioRoutes) { |
| 1474 | if (mSupportedAudioRoutes != audioRoutes) { |
| 1475 | mSupportedAudioRoutes = audioRoutes; |
| 1476 | } |
| 1477 | } |
| 1478 | |
Brad Ebinger | 5385513 | 2015-10-30 10:58:19 -0700 | [diff] [blame] | 1479 | @VisibleForTesting |
| 1480 | public Call getParentCall() { |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 1481 | return mParentCall; |
| 1482 | } |
| 1483 | |
Brad Ebinger | 5385513 | 2015-10-30 10:58:19 -0700 | [diff] [blame] | 1484 | @VisibleForTesting |
| 1485 | public List<Call> getChildCalls() { |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 1486 | return mChildCalls; |
| 1487 | } |
| 1488 | |
Brad Ebinger | 5385513 | 2015-10-30 10:58:19 -0700 | [diff] [blame] | 1489 | @VisibleForTesting |
| 1490 | public boolean wasConferencePreviouslyMerged() { |
Santos Cordon | 88a4a60 | 2014-09-29 19:32:21 -0700 | [diff] [blame] | 1491 | return mWasConferencePreviouslyMerged; |
| 1492 | } |
| 1493 | |
Srikanth Chintala | 5bf7502 | 2017-02-03 10:10:35 +0530 | [diff] [blame] | 1494 | public boolean isDisconnectingChildCall() { |
| 1495 | return mIsDisconnectingChildCall; |
| 1496 | } |
| 1497 | |
| 1498 | /** |
| 1499 | * Sets whether this call is a child call. |
| 1500 | */ |
| 1501 | private void maybeSetCallAsDisconnectingChild() { |
| 1502 | if (mParentCall != null) { |
| 1503 | mIsDisconnectingChildCall = true; |
| 1504 | } |
| 1505 | } |
| 1506 | |
Brad Ebinger | 5385513 | 2015-10-30 10:58:19 -0700 | [diff] [blame] | 1507 | @VisibleForTesting |
| 1508 | public Call getConferenceLevelActiveCall() { |
Santos Cordon | 88a4a60 | 2014-09-29 19:32:21 -0700 | [diff] [blame] | 1509 | return mConferenceLevelActiveCall; |
| 1510 | } |
| 1511 | |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 1512 | @VisibleForTesting |
| 1513 | public ConnectionServiceWrapper getConnectionService() { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1514 | return mConnectionService; |
Santos Cordon | 681663d | 2014-01-30 04:32:15 -0800 | [diff] [blame] | 1515 | } |
| 1516 | |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 1517 | /** |
| 1518 | * Retrieves the {@link Context} for the call. |
| 1519 | * |
| 1520 | * @return The {@link Context}. |
| 1521 | */ |
Hall Liu | 5507671 | 2017-02-28 19:59:30 -0800 | [diff] [blame] | 1522 | public Context getContext() { |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 1523 | return mContext; |
| 1524 | } |
| 1525 | |
Brad Ebinger | f190007 | 2015-11-12 17:25:06 -0800 | [diff] [blame] | 1526 | @VisibleForTesting |
| 1527 | public void setConnectionService(ConnectionServiceWrapper service) { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1528 | Preconditions.checkNotNull(service); |
| 1529 | |
| 1530 | clearConnectionService(); |
| 1531 | |
| 1532 | service.incrementAssociatedCallCount(); |
| 1533 | mConnectionService = service; |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 1534 | mAnalytics.setCallConnectionService(service.getComponentName().flattenToShortString()); |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1535 | mConnectionService.addCall(this); |
Sailesh Nepal | 0e5410a | 2014-04-04 01:20:58 -0700 | [diff] [blame] | 1536 | } |
| 1537 | |
| 1538 | /** |
Tyler Gunn | 9b618b8 | 2016-10-17 15:54:35 -0700 | [diff] [blame] | 1539 | * Perform an in-place replacement of the {@link ConnectionServiceWrapper} for this Call. |
| 1540 | * Removes the call from its former {@link ConnectionServiceWrapper}, ensuring that the |
| 1541 | * ConnectionService is NOT unbound if the call count hits zero. |
| 1542 | * This is used by the {@link ConnectionServiceWrapper} when handling {@link Connection} and |
| 1543 | * {@link Conference} additions via a ConnectionManager. |
| 1544 | * The original {@link android.telecom.ConnectionService} will directly add external calls and |
| 1545 | * conferences to Telecom as well as the ConnectionManager, which will add to Telecom. In these |
| 1546 | * cases since its first added to via the original CS, we want to change the CS responsible for |
| 1547 | * the call to the ConnectionManager rather than adding it again as another call/conference. |
| 1548 | * |
| 1549 | * @param service The new {@link ConnectionServiceWrapper}. |
| 1550 | */ |
| 1551 | public void replaceConnectionService(ConnectionServiceWrapper service) { |
| 1552 | Preconditions.checkNotNull(service); |
| 1553 | |
| 1554 | if (mConnectionService != null) { |
| 1555 | ConnectionServiceWrapper serviceTemp = mConnectionService; |
| 1556 | mConnectionService = null; |
| 1557 | serviceTemp.removeCall(this); |
| 1558 | serviceTemp.decrementAssociatedCallCount(true /*isSuppressingUnbind*/); |
| 1559 | } |
| 1560 | |
| 1561 | service.incrementAssociatedCallCount(); |
| 1562 | mConnectionService = service; |
| 1563 | mAnalytics.setCallConnectionService(service.getComponentName().flattenToShortString()); |
| 1564 | } |
| 1565 | |
| 1566 | /** |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1567 | * Clears the associated connection service. |
Sailesh Nepal | 0e5410a | 2014-04-04 01:20:58 -0700 | [diff] [blame] | 1568 | */ |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1569 | void clearConnectionService() { |
| 1570 | if (mConnectionService != null) { |
| 1571 | ConnectionServiceWrapper serviceTemp = mConnectionService; |
| 1572 | mConnectionService = null; |
| 1573 | serviceTemp.removeCall(this); |
Santos Cordon | c499c1c | 2014-04-14 17:13:14 -0700 | [diff] [blame] | 1574 | |
| 1575 | // Decrementing the count can cause the service to unbind, which itself can trigger the |
| 1576 | // service-death code. Since the service death code tries to clean up any associated |
| 1577 | // calls, we need to make sure to remove that information (e.g., removeCall()) before |
| 1578 | // we decrement. Technically, invoking removeCall() prior to decrementing is all that is |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1579 | // necessary, but cleaning up mConnectionService prior to triggering an unbind is good |
| 1580 | // to do. |
| 1581 | decrementAssociatedCallCount(serviceTemp); |
Yorke Lee | adee12d | 2014-03-13 12:08:30 -0700 | [diff] [blame] | 1582 | } |
Ben Gilad | 8e55d1d | 2014-02-26 16:25:56 -0800 | [diff] [blame] | 1583 | } |
| 1584 | |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 1585 | /** |
Sailesh Nepal | 664837f | 2014-07-14 16:31:51 -0700 | [diff] [blame] | 1586 | * Starts the create connection sequence. Upon completion, there should exist an active |
| 1587 | * connection through a connection service (or the call will have failed). |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 1588 | * |
| 1589 | * @param phoneAccountRegistrar The phone account registrar. |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 1590 | */ |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 1591 | void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) { |
Hall Liu | 4b1759d | 2016-02-02 18:17:40 -0800 | [diff] [blame] | 1592 | if (mCreateConnectionProcessor != null) { |
| 1593 | Log.w(this, "mCreateConnectionProcessor in startCreateConnection is not null. This is" + |
| 1594 | " due to a race between NewOutgoingCallIntentBroadcaster and " + |
| 1595 | "phoneAccountSelected, but is harmlessly resolved by ignoring the second " + |
| 1596 | "invocation."); |
| 1597 | return; |
| 1598 | } |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 1599 | mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this, |
| 1600 | phoneAccountRegistrar, mContext); |
Sailesh Nepal | 664837f | 2014-07-14 16:31:51 -0700 | [diff] [blame] | 1601 | mCreateConnectionProcessor.process(); |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 1602 | } |
| 1603 | |
Sailesh Nepal | 5a73b03 | 2014-06-25 15:53:21 -0700 | [diff] [blame] | 1604 | @Override |
Ihab Awad | 8000845 | 2014-08-23 20:35:44 -0700 | [diff] [blame] | 1605 | public void handleCreateConnectionSuccess( |
| 1606 | CallIdMapper idMapper, |
| 1607 | ParcelableConnection connection) { |
Santos Cordon | 12d6182 | 2014-07-29 16:02:20 -0700 | [diff] [blame] | 1608 | Log.v(this, "handleCreateConnectionSuccessful %s", connection); |
Ihab Awad | b78b276 | 2014-07-25 15:16:23 -0700 | [diff] [blame] | 1609 | setTargetPhoneAccount(connection.getPhoneAccount()); |
Santos Cordon | 72890ce | 2014-07-21 01:32:04 -0700 | [diff] [blame] | 1610 | setHandle(connection.getHandle(), connection.getHandlePresentation()); |
| 1611 | setCallerDisplayName( |
| 1612 | connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation()); |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 1613 | |
Ihab Awad | 07bc5ee | 2014-11-12 13:42:52 -0800 | [diff] [blame] | 1614 | setConnectionCapabilities(connection.getConnectionCapabilities()); |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 1615 | setConnectionProperties(connection.getConnectionProperties()); |
Hall Liu | e67e318 | 2018-03-13 15:09:38 -0700 | [diff] [blame] | 1616 | setIsVoipAudioMode(connection.getIsVoipAudioMode()); |
Christine Hallstrom | 96a0be6 | 2016-11-30 16:05:13 -0800 | [diff] [blame] | 1617 | setSupportedAudioRoutes(connection.getSupportedAudioRoutes()); |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 1618 | setVideoProvider(connection.getVideoProvider()); |
Tyler Gunn | 13e8a69 | 2016-08-03 18:38:00 -0700 | [diff] [blame] | 1619 | setVideoState(connection.getVideoState()); |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 1620 | setRingbackRequested(connection.isRingbackRequested()); |
Sailesh Nepal | 604a4fe | 2014-08-14 18:03:43 -0700 | [diff] [blame] | 1621 | setStatusHints(connection.getStatusHints()); |
Tyler Gunn | 961694a | 2016-03-21 16:01:40 -0700 | [diff] [blame] | 1622 | putExtras(SOURCE_CONNECTION_SERVICE, connection.getExtras()); |
Sailesh Nepal | 664837f | 2014-07-14 16:31:51 -0700 | [diff] [blame] | 1623 | |
Ihab Awad | 8000845 | 2014-08-23 20:35:44 -0700 | [diff] [blame] | 1624 | mConferenceableCalls.clear(); |
| 1625 | for (String id : connection.getConferenceableConnectionIds()) { |
| 1626 | mConferenceableCalls.add(idMapper.getCall(id)); |
| 1627 | } |
| 1628 | |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 1629 | switch (mCallDirection) { |
| 1630 | case CALL_DIRECTION_INCOMING: |
Hall Liu | 6d4b66d | 2016-04-01 16:31:13 -0700 | [diff] [blame] | 1631 | // Listeners (just CallsManager for now) will be responsible for checking whether |
| 1632 | // the call should be blocked. |
| 1633 | for (Listener l : mListeners) { |
| 1634 | l.onSuccessfulIncomingCall(this); |
| 1635 | } |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 1636 | break; |
| 1637 | case CALL_DIRECTION_OUTGOING: |
| 1638 | for (Listener l : mListeners) { |
| 1639 | l.onSuccessfulOutgoingCall(this, |
| 1640 | getStateFromConnectionState(connection.getState())); |
| 1641 | } |
| 1642 | break; |
| 1643 | case CALL_DIRECTION_UNKNOWN: |
| 1644 | for (Listener l : mListeners) { |
| 1645 | l.onSuccessfulUnknownCall(this, getStateFromConnectionState(connection |
| 1646 | .getState())); |
| 1647 | } |
| 1648 | break; |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 1649 | } |
| 1650 | } |
| 1651 | |
Sailesh Nepal | 5a73b03 | 2014-06-25 15:53:21 -0700 | [diff] [blame] | 1652 | @Override |
Andrew Lee | 701dc00 | 2014-09-11 21:29:12 -0700 | [diff] [blame] | 1653 | public void handleCreateConnectionFailure(DisconnectCause disconnectCause) { |
Ihab Awad | fb5560d | 2014-08-18 09:32:51 -0700 | [diff] [blame] | 1654 | clearConnectionService(); |
Andrew Lee | 701dc00 | 2014-09-11 21:29:12 -0700 | [diff] [blame] | 1655 | setDisconnectCause(disconnectCause); |
Ihab Awad | 78a5e6b | 2015-02-06 10:13:05 -0800 | [diff] [blame] | 1656 | mCallsManager.markCallAsDisconnected(this, disconnectCause); |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 1657 | |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 1658 | switch (mCallDirection) { |
| 1659 | case CALL_DIRECTION_INCOMING: |
| 1660 | for (Listener listener : mListeners) { |
| 1661 | listener.onFailedIncomingCall(this); |
| 1662 | } |
| 1663 | break; |
| 1664 | case CALL_DIRECTION_OUTGOING: |
| 1665 | for (Listener listener : mListeners) { |
| 1666 | listener.onFailedOutgoingCall(this, disconnectCause); |
| 1667 | } |
| 1668 | break; |
| 1669 | case CALL_DIRECTION_UNKNOWN: |
| 1670 | for (Listener listener : mListeners) { |
| 1671 | listener.onFailedUnknownCall(this); |
| 1672 | } |
| 1673 | break; |
Sailesh Nepal | 664837f | 2014-07-14 16:31:51 -0700 | [diff] [blame] | 1674 | } |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 1675 | } |
| 1676 | |
| 1677 | /** |
Ihab Awad | 74549ec | 2014-03-10 15:33:25 -0700 | [diff] [blame] | 1678 | * Plays the specified DTMF tone. |
| 1679 | */ |
Tyler Gunn | ad97242 | 2017-11-13 13:36:35 -0800 | [diff] [blame] | 1680 | @VisibleForTesting |
| 1681 | public void playDtmfTone(char digit) { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1682 | if (mConnectionService == null) { |
| 1683 | Log.w(this, "playDtmfTone() request on a call without a connection service."); |
Ihab Awad | 74549ec | 2014-03-10 15:33:25 -0700 | [diff] [blame] | 1684 | } else { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1685 | Log.i(this, "Send playDtmfTone to connection service for call %s", this); |
| 1686 | mConnectionService.playDtmfTone(this, digit); |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 1687 | Log.addEvent(this, LogUtils.Events.START_DTMF, Log.pii(digit)); |
Ihab Awad | 74549ec | 2014-03-10 15:33:25 -0700 | [diff] [blame] | 1688 | } |
Tyler Gunn | ad97242 | 2017-11-13 13:36:35 -0800 | [diff] [blame] | 1689 | mPlayingDtmfTone = digit; |
Ihab Awad | 74549ec | 2014-03-10 15:33:25 -0700 | [diff] [blame] | 1690 | } |
| 1691 | |
| 1692 | /** |
| 1693 | * Stops playing any currently playing DTMF tone. |
| 1694 | */ |
Tyler Gunn | ad97242 | 2017-11-13 13:36:35 -0800 | [diff] [blame] | 1695 | @VisibleForTesting |
| 1696 | public void stopDtmfTone() { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1697 | if (mConnectionService == null) { |
Jay Shrauner | fd4d7b5 | 2014-08-14 14:14:43 -0700 | [diff] [blame] | 1698 | Log.w(this, "stopDtmfTone() request on a call without a connection service."); |
Ihab Awad | 74549ec | 2014-03-10 15:33:25 -0700 | [diff] [blame] | 1699 | } else { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1700 | Log.i(this, "Send stopDtmfTone to connection service for call %s", this); |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 1701 | Log.addEvent(this, LogUtils.Events.STOP_DTMF); |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1702 | mConnectionService.stopDtmfTone(this); |
Ihab Awad | 74549ec | 2014-03-10 15:33:25 -0700 | [diff] [blame] | 1703 | } |
Tyler Gunn | ad97242 | 2017-11-13 13:36:35 -0800 | [diff] [blame] | 1704 | mPlayingDtmfTone = NO_DTMF_TONE; |
| 1705 | } |
| 1706 | |
| 1707 | /** |
| 1708 | * @return {@code true} if a DTMF tone has been started via {@link #playDtmfTone(char)} but has |
| 1709 | * not been stopped via {@link #stopDtmfTone()}, {@code false} otherwise. |
| 1710 | */ |
| 1711 | boolean isDtmfTonePlaying() { |
| 1712 | return mPlayingDtmfTone != NO_DTMF_TONE; |
Ihab Awad | 74549ec | 2014-03-10 15:33:25 -0700 | [diff] [blame] | 1713 | } |
| 1714 | |
Bryce Lee | 6d96252 | 2015-11-30 10:28:37 -0800 | [diff] [blame] | 1715 | /** |
| 1716 | * Silences the ringer. |
| 1717 | */ |
| 1718 | void silence() { |
| 1719 | if (mConnectionService == null) { |
| 1720 | Log.w(this, "silence() request on a call without a connection service."); |
| 1721 | } else { |
| 1722 | Log.i(this, "Send silence to connection service for call %s", this); |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 1723 | Log.addEvent(this, LogUtils.Events.SILENCE); |
Bryce Lee | 6d96252 | 2015-11-30 10:28:37 -0800 | [diff] [blame] | 1724 | mConnectionService.silence(this); |
| 1725 | } |
| 1726 | } |
| 1727 | |
Hall Liu | 0a6dd30 | 2015-12-16 15:06:49 -0800 | [diff] [blame] | 1728 | @VisibleForTesting |
| 1729 | public void disconnect() { |
Hall Liu | 63e690c | 2017-02-14 18:05:03 -0800 | [diff] [blame] | 1730 | disconnect(0); |
Santos Cordon | cf5b291 | 2014-11-05 21:57:54 -0800 | [diff] [blame] | 1731 | } |
| 1732 | |
Hall Liu | 220b419 | 2015-12-11 11:33:08 -0800 | [diff] [blame] | 1733 | @VisibleForTesting |
Tyler Gunn | f4f0539 | 2018-03-26 18:57:59 +0000 | [diff] [blame^] | 1734 | public void disconnect(String reason) { |
| 1735 | disconnect(0, reason); |
Tyler Gunn | 587fc27 | 2018-02-07 16:07:29 -0800 | [diff] [blame] | 1736 | } |
| 1737 | |
| 1738 | /** |
| 1739 | * Attempts to disconnect the call through the connection service. |
| 1740 | */ |
| 1741 | @VisibleForTesting |
Tyler Gunn | f4f0539 | 2018-03-26 18:57:59 +0000 | [diff] [blame^] | 1742 | public void disconnect(long disconnectionTimeout) { |
| 1743 | disconnect(disconnectionTimeout, "internal" /** reason */); |
| 1744 | } |
| 1745 | |
| 1746 | /** |
| 1747 | * Attempts to disconnect the call through the connection service. |
| 1748 | * @param reason the reason for the disconnect; used for logging purposes only. In some cases |
| 1749 | * this can be a package name if the disconnect was initiated through an API such |
| 1750 | * as TelecomManager. |
| 1751 | */ |
| 1752 | @VisibleForTesting |
| 1753 | public void disconnect(long disconnectionTimeout, String reason) { |
| 1754 | Log.addEvent(this, LogUtils.Events.REQUEST_DISCONNECT, reason); |
Santos Cordon | 2685dab | 2015-04-17 17:12:09 -0700 | [diff] [blame] | 1755 | |
Tyler Gunn | aa47937 | 2014-10-07 10:18:42 -0700 | [diff] [blame] | 1756 | // Track that the call is now locally disconnecting. |
| 1757 | setLocallyDisconnecting(true); |
Srikanth Chintala | 5bf7502 | 2017-02-03 10:10:35 +0530 | [diff] [blame] | 1758 | maybeSetCallAsDisconnectingChild(); |
Tyler Gunn | aa47937 | 2014-10-07 10:18:42 -0700 | [diff] [blame] | 1759 | |
Santos Cordon | 9269451 | 2015-04-23 14:47:28 -0700 | [diff] [blame] | 1760 | if (mState == CallState.NEW || mState == CallState.SELECT_PHONE_ACCOUNT || |
Jay Shrauner | fd4d7b5 | 2014-08-14 14:14:43 -0700 | [diff] [blame] | 1761 | mState == CallState.CONNECTING) { |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 1762 | Log.v(this, "Aborting call %s", this); |
Hall Liu | 63e690c | 2017-02-14 18:05:03 -0800 | [diff] [blame] | 1763 | abort(disconnectionTimeout); |
Santos Cordon | 74d420b | 2014-05-07 14:38:47 -0700 | [diff] [blame] | 1764 | } else if (mState != CallState.ABORTED && mState != CallState.DISCONNECTED) { |
Jay Shrauner | fd4d7b5 | 2014-08-14 14:14:43 -0700 | [diff] [blame] | 1765 | if (mConnectionService == null) { |
| 1766 | Log.e(this, new Exception(), "disconnect() request on a call without a" |
| 1767 | + " connection service."); |
| 1768 | } else { |
| 1769 | Log.i(this, "Send disconnect to connection service for call: %s", this); |
| 1770 | // The call isn't officially disconnected until the connection service |
| 1771 | // confirms that the call was actually disconnected. Only then is the |
| 1772 | // association between call and connection service severed, see |
| 1773 | // {@link CallsManager#markCallAsDisconnected}. |
| 1774 | mConnectionService.disconnect(this); |
| 1775 | } |
Santos Cordon | 049b7b6 | 2014-01-30 05:34:26 -0800 | [diff] [blame] | 1776 | } |
| 1777 | } |
| 1778 | |
Hall Liu | 63e690c | 2017-02-14 18:05:03 -0800 | [diff] [blame] | 1779 | void abort(long disconnectionTimeout) { |
Sailesh Nepal | 752cacb | 2014-11-06 12:35:26 -0800 | [diff] [blame] | 1780 | if (mCreateConnectionProcessor != null && |
| 1781 | !mCreateConnectionProcessor.isProcessingComplete()) { |
Sailesh Nepal | 664837f | 2014-07-14 16:31:51 -0700 | [diff] [blame] | 1782 | mCreateConnectionProcessor.abort(); |
Santos Cordon | 9269451 | 2015-04-23 14:47:28 -0700 | [diff] [blame] | 1783 | } else if (mState == CallState.NEW || mState == CallState.SELECT_PHONE_ACCOUNT |
Yorke Lee | 43df90f | 2014-08-20 10:56:09 -0700 | [diff] [blame] | 1784 | || mState == CallState.CONNECTING) { |
Hall Liu | 63e690c | 2017-02-14 18:05:03 -0800 | [diff] [blame] | 1785 | if (disconnectionTimeout > 0) { |
| 1786 | // If the cancelation was from NEW_OUTGOING_CALL with a timeout of > 0 |
| 1787 | // milliseconds, do not destroy the call. |
| 1788 | // Instead, we announce the cancellation and CallsManager handles |
Santos Cordon | cf5b291 | 2014-11-05 21:57:54 -0800 | [diff] [blame] | 1789 | // it through a timer. Since apps often cancel calls through NEW_OUTGOING_CALL and |
| 1790 | // then re-dial them quickly using a gateway, allowing the first call to end |
| 1791 | // causes jank. This timeout allows CallsManager to transition the first call into |
| 1792 | // the second call so that in-call only ever sees a single call...eliminating the |
Hall Liu | 63e690c | 2017-02-14 18:05:03 -0800 | [diff] [blame] | 1793 | // jank altogether. The app will also be able to set the timeout via an extra on |
| 1794 | // the ordered broadcast. |
Santos Cordon | cf5b291 | 2014-11-05 21:57:54 -0800 | [diff] [blame] | 1795 | for (Listener listener : mListeners) { |
Hall Liu | 63e690c | 2017-02-14 18:05:03 -0800 | [diff] [blame] | 1796 | if (listener.onCanceledViaNewOutgoingCallBroadcast( |
| 1797 | this, disconnectionTimeout)) { |
Santos Cordon | cf5b291 | 2014-11-05 21:57:54 -0800 | [diff] [blame] | 1798 | // The first listener to handle this wins. A return value of true means that |
| 1799 | // the listener will handle the disconnection process later and so we |
| 1800 | // should not continue it here. |
| 1801 | setLocallyDisconnecting(false); |
| 1802 | return; |
| 1803 | } |
| 1804 | } |
| 1805 | } |
| 1806 | |
Tyler Gunn | 504eb83 | 2014-10-13 14:15:27 -0700 | [diff] [blame] | 1807 | handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.CANCELED)); |
Santos Cordon | 2d0b331 | 2014-08-15 15:04:17 -0700 | [diff] [blame] | 1808 | } else { |
Santos Cordon | 9269451 | 2015-04-23 14:47:28 -0700 | [diff] [blame] | 1809 | Log.v(this, "Cannot abort a call which is neither SELECT_PHONE_ACCOUNT or CONNECTING"); |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 1810 | } |
| 1811 | } |
| 1812 | |
Santos Cordon | 0b03b4b | 2014-01-29 18:01:59 -0800 | [diff] [blame] | 1813 | /** |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 1814 | * Answers the call if it is ringing. |
Andrew Lee | 38931d0 | 2014-07-16 10:17:36 -0700 | [diff] [blame] | 1815 | * |
| 1816 | * @param videoState The video state in which to answer the call. |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 1817 | */ |
Hall Liu | 0a6dd30 | 2015-12-16 15:06:49 -0800 | [diff] [blame] | 1818 | @VisibleForTesting |
| 1819 | public void answer(int videoState) { |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 1820 | // Check to verify that the call is still in the ringing state. A call can change states |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 1821 | // between the time the user hits 'answer' and Telecom receives the command. |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 1822 | if (isRinging("answer")) { |
Tyler Gunn | 13e8a69 | 2016-08-03 18:38:00 -0700 | [diff] [blame] | 1823 | if (!isVideoCallingSupported() && VideoProfile.isVideo(videoState)) { |
| 1824 | // Video calling is not supported, yet the InCallService is attempting to answer as |
| 1825 | // video. We will simply answer as audio-only. |
| 1826 | videoState = VideoProfile.STATE_AUDIO_ONLY; |
| 1827 | } |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1828 | // At this point, we are asking the connection service to answer but we don't assume |
| 1829 | // that it will work. Instead, we wait until confirmation from the connectino service |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 1830 | // that the call is in a non-STATE_RINGING state before changing the UI. See |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 1831 | // {@link ConnectionServiceAdapter#setActive} and other set* methods. |
Tyler Gunn | 165ee75 | 2016-09-06 13:40:10 -0700 | [diff] [blame] | 1832 | if (mConnectionService != null) { |
| 1833 | mConnectionService.answer(this, videoState); |
| 1834 | } else { |
| 1835 | Log.e(this, new NullPointerException(), |
| 1836 | "answer call failed due to null CS callId=%s", getId()); |
| 1837 | } |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 1838 | Log.addEvent(this, LogUtils.Events.REQUEST_ACCEPT); |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 1839 | } |
| 1840 | } |
| 1841 | |
| 1842 | /** |
Pooja Jain | ad4ebc0 | 2017-12-28 14:23:13 +0530 | [diff] [blame] | 1843 | * Deflects the call if it is ringing. |
| 1844 | * |
| 1845 | * @param address address to be deflected to. |
| 1846 | */ |
| 1847 | @VisibleForTesting |
| 1848 | public void deflect(Uri address) { |
| 1849 | // Check to verify that the call is still in the ringing state. A call can change states |
| 1850 | // between the time the user hits 'deflect' and Telecomm receives the command. |
| 1851 | if (isRinging("deflect")) { |
| 1852 | // At this point, we are asking the connection service to deflect but we don't assume |
| 1853 | // that it will work. Instead, we wait until confirmation from the connection service |
| 1854 | // that the call is in a non-STATE_RINGING state before changing the UI. See |
| 1855 | // {@link ConnectionServiceAdapter#setActive} and other set* methods. |
| 1856 | mVideoStateHistory |= mVideoState; |
| 1857 | if (mConnectionService != null) { |
| 1858 | mConnectionService.deflect(this, address); |
| 1859 | } else { |
| 1860 | Log.e(this, new NullPointerException(), |
| 1861 | "deflect call failed due to null CS callId=%s", getId()); |
| 1862 | } |
| 1863 | Log.addEvent(this, LogUtils.Events.REQUEST_DEFLECT, Log.pii(address)); |
| 1864 | } |
| 1865 | } |
| 1866 | |
| 1867 | /** |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 1868 | * Rejects the call if it is ringing. |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 1869 | * |
| 1870 | * @param rejectWithMessage Whether to send a text message as part of the call rejection. |
| 1871 | * @param textMessage An optional text message to send as part of the rejection. |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 1872 | */ |
Hall Liu | 0a6dd30 | 2015-12-16 15:06:49 -0800 | [diff] [blame] | 1873 | @VisibleForTesting |
| 1874 | public void reject(boolean rejectWithMessage, String textMessage) { |
Tyler Gunn | f4f0539 | 2018-03-26 18:57:59 +0000 | [diff] [blame^] | 1875 | reject(rejectWithMessage, textMessage, "internal" /** reason */); |
Tyler Gunn | 587fc27 | 2018-02-07 16:07:29 -0800 | [diff] [blame] | 1876 | } |
| 1877 | |
| 1878 | /** |
| 1879 | * Rejects the call if it is ringing. |
| 1880 | * |
| 1881 | * @param rejectWithMessage Whether to send a text message as part of the call rejection. |
| 1882 | * @param textMessage An optional text message to send as part of the rejection. |
Tyler Gunn | f4f0539 | 2018-03-26 18:57:59 +0000 | [diff] [blame^] | 1883 | * @param reason The reason for the reject; used for logging purposes. May be a package name |
| 1884 | * if the reject is initiated from an API such as TelecomManager. |
Tyler Gunn | 587fc27 | 2018-02-07 16:07:29 -0800 | [diff] [blame] | 1885 | */ |
| 1886 | @VisibleForTesting |
Tyler Gunn | f4f0539 | 2018-03-26 18:57:59 +0000 | [diff] [blame^] | 1887 | public void reject(boolean rejectWithMessage, String textMessage, String reason) { |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 1888 | // Check to verify that the call is still in the ringing state. A call can change states |
| 1889 | // between the time the user hits 'reject' and Telecomm receives the command. |
| 1890 | if (isRinging("reject")) { |
Tyler Gunn | 5fb7840 | 2015-04-29 10:09:40 -0700 | [diff] [blame] | 1891 | // Ensure video state history tracks video state at time of rejection. |
| 1892 | mVideoStateHistory |= mVideoState; |
| 1893 | |
Tyler Gunn | 165ee75 | 2016-09-06 13:40:10 -0700 | [diff] [blame] | 1894 | if (mConnectionService != null) { |
| 1895 | mConnectionService.reject(this, rejectWithMessage, textMessage); |
| 1896 | } else { |
| 1897 | Log.e(this, new NullPointerException(), |
| 1898 | "reject call failed due to null CS callId=%s", getId()); |
| 1899 | } |
Tyler Gunn | f4f0539 | 2018-03-26 18:57:59 +0000 | [diff] [blame^] | 1900 | Log.addEvent(this, LogUtils.Events.REQUEST_REJECT, reason); |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 1901 | } |
| 1902 | } |
| 1903 | |
| 1904 | /** |
Yorke Lee | cdf3ebd | 2014-03-12 18:31:41 -0700 | [diff] [blame] | 1905 | * Puts the call on hold if it is currently active. |
| 1906 | */ |
Pengquan Meng | 4832f20 | 2017-12-20 16:13:04 -0800 | [diff] [blame] | 1907 | @VisibleForTesting |
| 1908 | public void hold() { |
Tyler Gunn | f4f0539 | 2018-03-26 18:57:59 +0000 | [diff] [blame^] | 1909 | hold(null /* reason */); |
| 1910 | } |
| 1911 | |
| 1912 | public void hold(String reason) { |
Yorke Lee | cdf3ebd | 2014-03-12 18:31:41 -0700 | [diff] [blame] | 1913 | if (mState == CallState.ACTIVE) { |
Tyler Gunn | 165ee75 | 2016-09-06 13:40:10 -0700 | [diff] [blame] | 1914 | if (mConnectionService != null) { |
| 1915 | mConnectionService.hold(this); |
| 1916 | } else { |
| 1917 | Log.e(this, new NullPointerException(), |
| 1918 | "hold call failed due to null CS callId=%s", getId()); |
| 1919 | } |
Tyler Gunn | f4f0539 | 2018-03-26 18:57:59 +0000 | [diff] [blame^] | 1920 | Log.addEvent(this, LogUtils.Events.REQUEST_HOLD, reason); |
Yorke Lee | cdf3ebd | 2014-03-12 18:31:41 -0700 | [diff] [blame] | 1921 | } |
| 1922 | } |
| 1923 | |
| 1924 | /** |
| 1925 | * Releases the call from hold if it is currently active. |
| 1926 | */ |
Pengquan Meng | 4832f20 | 2017-12-20 16:13:04 -0800 | [diff] [blame] | 1927 | @VisibleForTesting |
| 1928 | public void unhold() { |
Tyler Gunn | f4f0539 | 2018-03-26 18:57:59 +0000 | [diff] [blame^] | 1929 | unhold(null /* reason */); |
| 1930 | } |
| 1931 | |
| 1932 | public void unhold(String reason) { |
Yorke Lee | cdf3ebd | 2014-03-12 18:31:41 -0700 | [diff] [blame] | 1933 | if (mState == CallState.ON_HOLD) { |
Tyler Gunn | 165ee75 | 2016-09-06 13:40:10 -0700 | [diff] [blame] | 1934 | if (mConnectionService != null) { |
| 1935 | mConnectionService.unhold(this); |
| 1936 | } else { |
| 1937 | Log.e(this, new NullPointerException(), |
| 1938 | "unhold call failed due to null CS callId=%s", getId()); |
| 1939 | } |
Tyler Gunn | f4f0539 | 2018-03-26 18:57:59 +0000 | [diff] [blame^] | 1940 | Log.addEvent(this, LogUtils.Events.REQUEST_UNHOLD, reason); |
Yorke Lee | cdf3ebd | 2014-03-12 18:31:41 -0700 | [diff] [blame] | 1941 | } |
| 1942 | } |
| 1943 | |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 1944 | /** Checks if this is a live call or not. */ |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 1945 | @VisibleForTesting |
| 1946 | public boolean isAlive() { |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 1947 | switch (mState) { |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 1948 | case CallState.NEW: |
| 1949 | case CallState.RINGING: |
| 1950 | case CallState.DISCONNECTED: |
| 1951 | case CallState.ABORTED: |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 1952 | return false; |
| 1953 | default: |
| 1954 | return true; |
| 1955 | } |
| 1956 | } |
| 1957 | |
Santos Cordon | 40f78c2 | 2014-04-07 02:11:42 -0700 | [diff] [blame] | 1958 | boolean isActive() { |
Ihab Awad | 84bfe47 | 2014-07-13 17:11:57 -0700 | [diff] [blame] | 1959 | return mState == CallState.ACTIVE; |
Santos Cordon | 40f78c2 | 2014-04-07 02:11:42 -0700 | [diff] [blame] | 1960 | } |
| 1961 | |
Sailesh Nepal | 84fa5f8 | 2014-04-02 11:01:11 -0700 | [diff] [blame] | 1962 | Bundle getExtras() { |
| 1963 | return mExtras; |
| 1964 | } |
| 1965 | |
Tyler Gunn | 961694a | 2016-03-21 16:01:40 -0700 | [diff] [blame] | 1966 | /** |
| 1967 | * Adds extras to the extras bundle associated with this {@link Call}. |
| 1968 | * |
| 1969 | * Note: this method needs to know the source of the extras change (see |
| 1970 | * {@link #SOURCE_CONNECTION_SERVICE}, {@link #SOURCE_INCALL_SERVICE}). Extras changes which |
| 1971 | * originate from a connection service will only be notified to incall services. Likewise, |
| 1972 | * changes originating from the incall services will only notify the connection service of the |
| 1973 | * change. |
| 1974 | * |
| 1975 | * @param source The source of the extras addition. |
| 1976 | * @param extras The extras. |
| 1977 | */ |
| 1978 | void putExtras(int source, Bundle extras) { |
| 1979 | if (extras == null) { |
| 1980 | return; |
| 1981 | } |
| 1982 | if (mExtras == null) { |
| 1983 | mExtras = new Bundle(); |
| 1984 | } |
| 1985 | mExtras.putAll(extras); |
| 1986 | |
Santos Cordon | b3907b3 | 2015-05-27 17:39:59 -0700 | [diff] [blame] | 1987 | for (Listener l : mListeners) { |
Tyler Gunn | 961694a | 2016-03-21 16:01:40 -0700 | [diff] [blame] | 1988 | l.onExtrasChanged(this, source, extras); |
| 1989 | } |
| 1990 | |
| 1991 | // If the change originated from an InCallService, notify the connection service. |
| 1992 | if (source == SOURCE_INCALL_SERVICE) { |
Tyler Gunn | 165ee75 | 2016-09-06 13:40:10 -0700 | [diff] [blame] | 1993 | if (mConnectionService != null) { |
| 1994 | mConnectionService.onExtrasChanged(this, mExtras); |
| 1995 | } else { |
| 1996 | Log.e(this, new NullPointerException(), |
| 1997 | "putExtras failed due to null CS callId=%s", getId()); |
| 1998 | } |
Tyler Gunn | 961694a | 2016-03-21 16:01:40 -0700 | [diff] [blame] | 1999 | } |
| 2000 | } |
| 2001 | |
| 2002 | /** |
| 2003 | * Removes extras from the extras bundle associated with this {@link Call}. |
| 2004 | * |
| 2005 | * Note: this method needs to know the source of the extras change (see |
| 2006 | * {@link #SOURCE_CONNECTION_SERVICE}, {@link #SOURCE_INCALL_SERVICE}). Extras changes which |
| 2007 | * originate from a connection service will only be notified to incall services. Likewise, |
| 2008 | * changes originating from the incall services will only notify the connection service of the |
| 2009 | * change. |
| 2010 | * |
| 2011 | * @param source The source of the extras removal. |
| 2012 | * @param keys The extra keys to remove. |
| 2013 | */ |
| 2014 | void removeExtras(int source, List<String> keys) { |
| 2015 | if (mExtras == null) { |
| 2016 | return; |
| 2017 | } |
| 2018 | for (String key : keys) { |
| 2019 | mExtras.remove(key); |
| 2020 | } |
| 2021 | |
| 2022 | for (Listener l : mListeners) { |
| 2023 | l.onExtrasRemoved(this, source, keys); |
| 2024 | } |
| 2025 | |
| 2026 | // If the change originated from an InCallService, notify the connection service. |
| 2027 | if (source == SOURCE_INCALL_SERVICE) { |
Tyler Gunn | 165ee75 | 2016-09-06 13:40:10 -0700 | [diff] [blame] | 2028 | if (mConnectionService != null) { |
| 2029 | mConnectionService.onExtrasChanged(this, mExtras); |
| 2030 | } else { |
| 2031 | Log.e(this, new NullPointerException(), |
| 2032 | "removeExtras failed due to null CS callId=%s", getId()); |
| 2033 | } |
Santos Cordon | b3907b3 | 2015-05-27 17:39:59 -0700 | [diff] [blame] | 2034 | } |
| 2035 | } |
| 2036 | |
Santos Cordon | f0f99f3 | 2016-02-18 16:13:57 -0800 | [diff] [blame] | 2037 | @VisibleForTesting |
| 2038 | public Bundle getIntentExtras() { |
Santos Cordon | b3907b3 | 2015-05-27 17:39:59 -0700 | [diff] [blame] | 2039 | return mIntentExtras; |
| 2040 | } |
| 2041 | |
| 2042 | void setIntentExtras(Bundle extras) { |
| 2043 | mIntentExtras = extras; |
Sailesh Nepal | 84fa5f8 | 2014-04-02 11:01:11 -0700 | [diff] [blame] | 2044 | } |
| 2045 | |
Tyler Gunn | bbd78a7 | 2017-04-30 14:16:07 -0700 | [diff] [blame] | 2046 | public Intent getOriginalCallIntent() { |
| 2047 | return mOriginalCallIntent; |
| 2048 | } |
| 2049 | |
| 2050 | public void setOriginalCallIntent(Intent intent) { |
| 2051 | mOriginalCallIntent = intent; |
| 2052 | } |
| 2053 | |
Yorke Lee | 8a736a8 | 2014-08-30 17:19:16 -0700 | [diff] [blame] | 2054 | /** |
| 2055 | * @return the uri of the contact associated with this call. |
| 2056 | */ |
Brad Ebinger | d931a01 | 2015-10-21 12:54:08 -0700 | [diff] [blame] | 2057 | @VisibleForTesting |
| 2058 | public Uri getContactUri() { |
Yorke Lee | 8a736a8 | 2014-08-30 17:19:16 -0700 | [diff] [blame] | 2059 | if (mCallerInfo == null || !mCallerInfo.contactExists) { |
Yorke Lee | a7fa743 | 2014-09-22 13:34:29 -0700 | [diff] [blame] | 2060 | return getHandle(); |
Yorke Lee | 8a736a8 | 2014-08-30 17:19:16 -0700 | [diff] [blame] | 2061 | } |
| 2062 | return Contacts.getLookupUri(mCallerInfo.contactIdOrZero, mCallerInfo.lookupKey); |
| 2063 | } |
| 2064 | |
Santos Cordon | 5ba7f27 | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 2065 | Uri getRingtone() { |
| 2066 | return mCallerInfo == null ? null : mCallerInfo.contactRingtoneUri; |
| 2067 | } |
| 2068 | |
Evan Charlton | 352105c | 2014-06-03 14:10:54 -0700 | [diff] [blame] | 2069 | void onPostDialWait(String remaining) { |
| 2070 | for (Listener l : mListeners) { |
| 2071 | l.onPostDialWait(this, remaining); |
| 2072 | } |
| 2073 | } |
| 2074 | |
Nancy Chen | a469f76 | 2014-12-09 18:29:20 -0800 | [diff] [blame] | 2075 | void onPostDialChar(char nextChar) { |
| 2076 | for (Listener l : mListeners) { |
| 2077 | l.onPostDialChar(this, nextChar); |
| 2078 | } |
| 2079 | } |
| 2080 | |
Evan Charlton | 352105c | 2014-06-03 14:10:54 -0700 | [diff] [blame] | 2081 | void postDialContinue(boolean proceed) { |
Tyler Gunn | 165ee75 | 2016-09-06 13:40:10 -0700 | [diff] [blame] | 2082 | if (mConnectionService != null) { |
| 2083 | mConnectionService.onPostDialContinue(this, proceed); |
| 2084 | } else { |
| 2085 | Log.e(this, new NullPointerException(), |
| 2086 | "postDialContinue failed due to null CS callId=%s", getId()); |
| 2087 | } |
Evan Charlton | 352105c | 2014-06-03 14:10:54 -0700 | [diff] [blame] | 2088 | } |
| 2089 | |
Santos Cordon | 0fbe632 | 2014-08-14 04:04:25 -0700 | [diff] [blame] | 2090 | void conferenceWith(Call otherCall) { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 2091 | if (mConnectionService == null) { |
| 2092 | Log.w(this, "conference requested on a call without a connection service."); |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 2093 | } else { |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 2094 | Log.addEvent(this, LogUtils.Events.CONFERENCE_WITH, otherCall); |
Santos Cordon | 0fbe632 | 2014-08-14 04:04:25 -0700 | [diff] [blame] | 2095 | mConnectionService.conference(this, otherCall); |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 2096 | } |
| 2097 | } |
| 2098 | |
| 2099 | void splitFromConference() { |
Santos Cordon | 672321e | 2014-08-21 14:38:58 -0700 | [diff] [blame] | 2100 | if (mConnectionService == null) { |
| 2101 | Log.w(this, "splitting from conference call without a connection service"); |
| 2102 | } else { |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 2103 | Log.addEvent(this, LogUtils.Events.SPLIT_FROM_CONFERENCE); |
Santos Cordon | 672321e | 2014-08-21 14:38:58 -0700 | [diff] [blame] | 2104 | mConnectionService.splitFromConference(this); |
| 2105 | } |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 2106 | } |
| 2107 | |
Brad Ebinger | 5385513 | 2015-10-30 10:58:19 -0700 | [diff] [blame] | 2108 | @VisibleForTesting |
| 2109 | public void mergeConference() { |
Santos Cordon | 6805923 | 2014-09-04 20:09:42 -0700 | [diff] [blame] | 2110 | if (mConnectionService == null) { |
| 2111 | Log.w(this, "merging conference calls without a connection service."); |
Ihab Awad | 07bc5ee | 2014-11-12 13:42:52 -0800 | [diff] [blame] | 2112 | } else if (can(Connection.CAPABILITY_MERGE_CONFERENCE)) { |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 2113 | Log.addEvent(this, LogUtils.Events.CONFERENCE_WITH); |
Santos Cordon | 6805923 | 2014-09-04 20:09:42 -0700 | [diff] [blame] | 2114 | mConnectionService.mergeConference(this); |
Santos Cordon | 88a4a60 | 2014-09-29 19:32:21 -0700 | [diff] [blame] | 2115 | mWasConferencePreviouslyMerged = true; |
Santos Cordon | 6805923 | 2014-09-04 20:09:42 -0700 | [diff] [blame] | 2116 | } |
| 2117 | } |
| 2118 | |
Brad Ebinger | 5385513 | 2015-10-30 10:58:19 -0700 | [diff] [blame] | 2119 | @VisibleForTesting |
| 2120 | public void swapConference() { |
Santos Cordon | 6805923 | 2014-09-04 20:09:42 -0700 | [diff] [blame] | 2121 | if (mConnectionService == null) { |
| 2122 | Log.w(this, "swapping conference calls without a connection service."); |
Ihab Awad | 07bc5ee | 2014-11-12 13:42:52 -0800 | [diff] [blame] | 2123 | } else if (can(Connection.CAPABILITY_SWAP_CONFERENCE)) { |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 2124 | Log.addEvent(this, LogUtils.Events.SWAP); |
Santos Cordon | 6805923 | 2014-09-04 20:09:42 -0700 | [diff] [blame] | 2125 | mConnectionService.swapConference(this); |
Santos Cordon | 88a4a60 | 2014-09-29 19:32:21 -0700 | [diff] [blame] | 2126 | switch (mChildCalls.size()) { |
| 2127 | case 1: |
| 2128 | mConferenceLevelActiveCall = mChildCalls.get(0); |
| 2129 | break; |
| 2130 | case 2: |
| 2131 | // swap |
| 2132 | mConferenceLevelActiveCall = mChildCalls.get(0) == mConferenceLevelActiveCall ? |
| 2133 | mChildCalls.get(1) : mChildCalls.get(0); |
| 2134 | break; |
| 2135 | default: |
| 2136 | // For anything else 0, or 3+, set it to null since it is impossible to tell. |
| 2137 | mConferenceLevelActiveCall = null; |
| 2138 | break; |
| 2139 | } |
Santos Cordon | 6805923 | 2014-09-04 20:09:42 -0700 | [diff] [blame] | 2140 | } |
| 2141 | } |
| 2142 | |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 2143 | /** |
| 2144 | * Initiates a request to the connection service to pull this call. |
| 2145 | * <p> |
| 2146 | * This method can only be used for calls that have the |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 2147 | * {@link android.telecom.Connection#CAPABILITY_CAN_PULL_CALL} capability and |
| 2148 | * {@link android.telecom.Connection#PROPERTY_IS_EXTERNAL_CALL} property set. |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 2149 | * <p> |
| 2150 | * An external call is a representation of a call which is taking place on another device |
Santos Cordon | 0d7a00a | 2016-07-26 15:33:00 -0700 | [diff] [blame] | 2151 | * associated with a PhoneAccount on this device. Issuing a request to pull the external call |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 2152 | * tells the {@link android.telecom.ConnectionService} that it should move the call from the |
| 2153 | * other device to this one. An example of this is the IMS multi-endpoint functionality. A |
| 2154 | * user may have two phones with the same phone number. If the user is engaged in an active |
| 2155 | * call on their first device, the network will inform the second device of that ongoing call in |
| 2156 | * the form of an external call. The user may wish to continue their conversation on the second |
| 2157 | * device, so will issue a request to pull the call to the second device. |
| 2158 | * <p> |
| 2159 | * Requests to pull a call which is not external, or a call which is not pullable are ignored. |
| 2160 | */ |
| 2161 | public void pullExternalCall() { |
| 2162 | if (mConnectionService == null) { |
| 2163 | Log.w(this, "pulling a call without a connection service."); |
| 2164 | } |
| 2165 | |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 2166 | if (!hasProperty(Connection.PROPERTY_IS_EXTERNAL_CALL)) { |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 2167 | Log.w(this, "pullExternalCall - call %s is not an external call.", mId); |
| 2168 | return; |
| 2169 | } |
| 2170 | |
| 2171 | if (!can(Connection.CAPABILITY_CAN_PULL_CALL)) { |
| 2172 | Log.w(this, "pullExternalCall - call %s is external but cannot be pulled.", mId); |
| 2173 | return; |
| 2174 | } |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 2175 | Log.addEvent(this, LogUtils.Events.REQUEST_PULL); |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 2176 | mConnectionService.pullExternalCall(this); |
| 2177 | } |
| 2178 | |
| 2179 | /** |
Sanket Padawe | b5de1cd | 2018-01-05 14:27:30 -0800 | [diff] [blame] | 2180 | * Sends a call event to the {@link ConnectionService} for this call. This function is |
| 2181 | * called for event other than {@link Call#EVENT_REQUEST_HANDOVER} |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 2182 | * |
| 2183 | * @param event The call event. |
| 2184 | * @param extras Associated extras. |
| 2185 | */ |
| 2186 | public void sendCallEvent(String event, Bundle extras) { |
Sanket Padawe | b5de1cd | 2018-01-05 14:27:30 -0800 | [diff] [blame] | 2187 | sendCallEvent(event, 0/*For Event != EVENT_REQUEST_HANDOVER*/, extras); |
| 2188 | } |
| 2189 | |
| 2190 | /** |
| 2191 | * Sends a call event to the {@link ConnectionService} for this call. |
| 2192 | * |
| 2193 | * See {@link Call#sendCallEvent(String, Bundle)}. |
| 2194 | * |
| 2195 | * @param event The call event. |
| 2196 | * @param targetSdkVer SDK version of the app calling this api |
| 2197 | * @param extras Associated extras. |
| 2198 | */ |
| 2199 | public void sendCallEvent(String event, int targetSdkVer, Bundle extras) { |
Tyler Gunn | 165ee75 | 2016-09-06 13:40:10 -0700 | [diff] [blame] | 2200 | if (mConnectionService != null) { |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 2201 | if (android.telecom.Call.EVENT_REQUEST_HANDOVER.equals(event)) { |
Sanket Padawe | b5de1cd | 2018-01-05 14:27:30 -0800 | [diff] [blame] | 2202 | if (targetSdkVer > Build.VERSION_CODES.O_MR1) { |
| 2203 | Log.e(this, new Exception(), "sendCallEvent failed. Use public api handoverTo" + |
| 2204 | " for API > 27(O-MR1)"); |
| 2205 | // TODO: Add "return" after DUO team adds new API support for handover |
| 2206 | } |
| 2207 | |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 2208 | // Handover requests are targeted at Telecom, not the ConnectionService. |
| 2209 | if (extras == null) { |
| 2210 | Log.w(this, "sendCallEvent: %s event received with null extras.", |
| 2211 | android.telecom.Call.EVENT_REQUEST_HANDOVER); |
| 2212 | mConnectionService.sendCallEvent(this, |
| 2213 | android.telecom.Call.EVENT_HANDOVER_FAILED, null); |
| 2214 | return; |
| 2215 | } |
| 2216 | Parcelable parcelable = extras.getParcelable( |
| 2217 | android.telecom.Call.EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE); |
| 2218 | if (!(parcelable instanceof PhoneAccountHandle) || parcelable == null) { |
| 2219 | Log.w(this, "sendCallEvent: %s event received with invalid handover acct.", |
| 2220 | android.telecom.Call.EVENT_REQUEST_HANDOVER); |
| 2221 | mConnectionService.sendCallEvent(this, |
| 2222 | android.telecom.Call.EVENT_HANDOVER_FAILED, null); |
| 2223 | return; |
| 2224 | } |
| 2225 | PhoneAccountHandle phoneAccountHandle = (PhoneAccountHandle) parcelable; |
| 2226 | int videoState = extras.getInt(android.telecom.Call.EXTRA_HANDOVER_VIDEO_STATE, |
| 2227 | VideoProfile.STATE_AUDIO_ONLY); |
Tyler Gunn | 6f6f1c5 | 2017-04-17 18:22:04 -0700 | [diff] [blame] | 2228 | Parcelable handoverExtras = extras.getParcelable( |
| 2229 | android.telecom.Call.EXTRA_HANDOVER_EXTRAS); |
| 2230 | Bundle handoverExtrasBundle = null; |
| 2231 | if (handoverExtras instanceof Bundle) { |
| 2232 | handoverExtrasBundle = (Bundle) handoverExtras; |
| 2233 | } |
Sanket Padawe | 4ebc3ca | 2017-11-21 12:49:43 -0800 | [diff] [blame] | 2234 | requestHandover(phoneAccountHandle, videoState, handoverExtrasBundle, true); |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 2235 | } else { |
| 2236 | Log.addEvent(this, LogUtils.Events.CALL_EVENT, event); |
| 2237 | mConnectionService.sendCallEvent(this, event, extras); |
| 2238 | } |
Tyler Gunn | 165ee75 | 2016-09-06 13:40:10 -0700 | [diff] [blame] | 2239 | } else { |
| 2240 | Log.e(this, new NullPointerException(), |
| 2241 | "sendCallEvent failed due to null CS callId=%s", getId()); |
| 2242 | } |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 2243 | } |
| 2244 | |
Tyler Gunn | 7658171 | 2017-05-09 14:39:42 -0700 | [diff] [blame] | 2245 | /** |
Sanket Padawe | ccdf364 | 2017-11-10 14:49:05 -0800 | [diff] [blame] | 2246 | * Initiates a handover of this Call to the {@link ConnectionService} identified |
| 2247 | * by destAcct. |
| 2248 | * @param destAcct ConnectionService to which the call should be handed over. |
| 2249 | * @param videoState The video state desired after the handover. |
| 2250 | * @param extras Extra information to be passed to ConnectionService |
| 2251 | */ |
| 2252 | public void handoverTo(PhoneAccountHandle destAcct, int videoState, Bundle extras) { |
Sanket Padawe | 4ebc3ca | 2017-11-21 12:49:43 -0800 | [diff] [blame] | 2253 | requestHandover(destAcct, videoState, extras, false); |
Sanket Padawe | ccdf364 | 2017-11-10 14:49:05 -0800 | [diff] [blame] | 2254 | } |
| 2255 | |
| 2256 | /** |
Tyler Gunn | 7658171 | 2017-05-09 14:39:42 -0700 | [diff] [blame] | 2257 | * Sets this {@link Call} to has the specified {@code parentCall}. Also sets the parent to |
| 2258 | * have this call as a child. |
| 2259 | * @param parentCall |
| 2260 | */ |
| 2261 | void setParentAndChildCall(Call parentCall) { |
Tyler Gunn | 988ccc8 | 2017-06-01 11:22:10 -0700 | [diff] [blame] | 2262 | boolean isParentChanging = (mParentCall != parentCall); |
Tyler Gunn | 7658171 | 2017-05-09 14:39:42 -0700 | [diff] [blame] | 2263 | setParentCall(parentCall); |
| 2264 | setChildOf(parentCall); |
Tyler Gunn | 988ccc8 | 2017-06-01 11:22:10 -0700 | [diff] [blame] | 2265 | if (isParentChanging) { |
| 2266 | notifyParentChanged(parentCall); |
| 2267 | } |
| 2268 | } |
| 2269 | |
| 2270 | /** |
| 2271 | * Notifies listeners when the parent call changes. |
| 2272 | * Used by {@link #setParentAndChildCall(Call)}, and in {@link CallsManager}. |
| 2273 | * @param parentCall The new parent call for this call. |
| 2274 | */ |
| 2275 | void notifyParentChanged(Call parentCall) { |
| 2276 | Log.addEvent(this, LogUtils.Events.SET_PARENT, parentCall); |
| 2277 | for (Listener l : mListeners) { |
| 2278 | l.onParentChanged(this); |
| 2279 | } |
Tyler Gunn | 7658171 | 2017-05-09 14:39:42 -0700 | [diff] [blame] | 2280 | } |
| 2281 | |
| 2282 | /** |
| 2283 | * Unlike {@link #setParentAndChildCall(Call)}, only sets the parent call but does NOT set |
| 2284 | * the child. |
| 2285 | * TODO: This is only required when adding existing connections as a workaround so that we |
| 2286 | * can avoid sending the "onParentChanged" callback until later. |
| 2287 | * @param parentCall The new parent call. |
| 2288 | */ |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 2289 | void setParentCall(Call parentCall) { |
| 2290 | if (parentCall == this) { |
| 2291 | Log.e(this, new Exception(), "setting the parent to self"); |
| 2292 | return; |
| 2293 | } |
Santos Cordon | 0fbe632 | 2014-08-14 04:04:25 -0700 | [diff] [blame] | 2294 | if (parentCall == mParentCall) { |
| 2295 | // nothing to do |
| 2296 | return; |
| 2297 | } |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 2298 | if (mParentCall != null) { |
| 2299 | mParentCall.removeChildCall(this); |
| 2300 | } |
| 2301 | mParentCall = parentCall; |
Tyler Gunn | 7658171 | 2017-05-09 14:39:42 -0700 | [diff] [blame] | 2302 | } |
| 2303 | |
| 2304 | /** |
| 2305 | * To be called after {@link #setParentCall(Call)} to complete setting the parent by adding |
| 2306 | * this call as a child of another call. |
| 2307 | * <p> |
Tyler Gunn | 988ccc8 | 2017-06-01 11:22:10 -0700 | [diff] [blame] | 2308 | * Note: if using this method alone, the caller must call {@link #notifyParentChanged(Call)} to |
| 2309 | * ensure the InCall UI is updated with the change in parent. |
Tyler Gunn | 7658171 | 2017-05-09 14:39:42 -0700 | [diff] [blame] | 2310 | * @param parentCall The new parent for this call. |
| 2311 | */ |
| 2312 | void setChildOf(Call parentCall) { |
Tyler Gunn | 988ccc8 | 2017-06-01 11:22:10 -0700 | [diff] [blame] | 2313 | if (parentCall != null && !parentCall.getChildCalls().contains(this)) { |
Tyler Gunn | 7658171 | 2017-05-09 14:39:42 -0700 | [diff] [blame] | 2314 | parentCall.addChildCall(this); |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 2315 | } |
| 2316 | } |
| 2317 | |
Santos Cordon | 12d6182 | 2014-07-29 16:02:20 -0700 | [diff] [blame] | 2318 | void setConferenceableCalls(List<Call> conferenceableCalls) { |
| 2319 | mConferenceableCalls.clear(); |
| 2320 | mConferenceableCalls.addAll(conferenceableCalls); |
Tyler Gunn | 703d7cf | 2014-10-02 15:22:30 -0700 | [diff] [blame] | 2321 | |
| 2322 | for (Listener l : mListeners) { |
| 2323 | l.onConferenceableCallsChanged(this); |
| 2324 | } |
Santos Cordon | 12d6182 | 2014-07-29 16:02:20 -0700 | [diff] [blame] | 2325 | } |
| 2326 | |
Brad Ebinger | 5385513 | 2015-10-30 10:58:19 -0700 | [diff] [blame] | 2327 | @VisibleForTesting |
| 2328 | public List<Call> getConferenceableCalls() { |
Santos Cordon | 12d6182 | 2014-07-29 16:02:20 -0700 | [diff] [blame] | 2329 | return mConferenceableCalls; |
| 2330 | } |
| 2331 | |
Brad Ebinger | 5385513 | 2015-10-30 10:58:19 -0700 | [diff] [blame] | 2332 | @VisibleForTesting |
| 2333 | public boolean can(int capability) { |
Ihab Awad | 07bc5ee | 2014-11-12 13:42:52 -0800 | [diff] [blame] | 2334 | return (mConnectionCapabilities & capability) == capability; |
Santos Cordon | 6805923 | 2014-09-04 20:09:42 -0700 | [diff] [blame] | 2335 | } |
| 2336 | |
Tyler Gunn | 571d5e6 | 2016-03-15 15:55:18 -0700 | [diff] [blame] | 2337 | @VisibleForTesting |
| 2338 | public boolean hasProperty(int property) { |
| 2339 | return (mConnectionProperties & property) == property; |
| 2340 | } |
| 2341 | |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 2342 | private void addChildCall(Call call) { |
| 2343 | if (!mChildCalls.contains(call)) { |
Santos Cordon | 88a4a60 | 2014-09-29 19:32:21 -0700 | [diff] [blame] | 2344 | // Set the pseudo-active call to the latest child added to the conference. |
| 2345 | // See definition of mConferenceLevelActiveCall for more detail. |
| 2346 | mConferenceLevelActiveCall = call; |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 2347 | mChildCalls.add(call); |
| 2348 | |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 2349 | Log.addEvent(this, LogUtils.Events.ADD_CHILD, call); |
Santos Cordon | 165c1ce | 2015-07-10 16:07:59 -0700 | [diff] [blame] | 2350 | |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 2351 | for (Listener l : mListeners) { |
| 2352 | l.onChildrenChanged(this); |
| 2353 | } |
| 2354 | } |
| 2355 | } |
| 2356 | |
| 2357 | private void removeChildCall(Call call) { |
| 2358 | if (mChildCalls.remove(call)) { |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 2359 | Log.addEvent(this, LogUtils.Events.REMOVE_CHILD, call); |
Santos Cordon | a161070 | 2014-06-04 20:22:56 -0700 | [diff] [blame] | 2360 | for (Listener l : mListeners) { |
| 2361 | l.onChildrenChanged(this); |
| 2362 | } |
| 2363 | } |
| 2364 | } |
| 2365 | |
Santos Cordon | 0b03b4b | 2014-01-29 18:01:59 -0800 | [diff] [blame] | 2366 | /** |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 2367 | * Return whether the user can respond to this {@code Call} via an SMS message. |
| 2368 | * |
| 2369 | * @return true if the "Respond via SMS" feature should be enabled |
| 2370 | * for this incoming call. |
| 2371 | * |
| 2372 | * The general rule is that we *do* allow "Respond via SMS" except for |
| 2373 | * the few (relatively rare) cases where we know for sure it won't |
| 2374 | * work, namely: |
| 2375 | * - a bogus or blank incoming number |
| 2376 | * - a call from a SIP address |
| 2377 | * - a "call presentation" that doesn't allow the number to be revealed |
| 2378 | * |
| 2379 | * In all other cases, we allow the user to respond via SMS. |
| 2380 | * |
| 2381 | * Note that this behavior isn't perfect; for example we have no way |
| 2382 | * to detect whether the incoming call is from a landline (with most |
| 2383 | * networks at least), so we still enable this feature even though |
| 2384 | * SMSes to that number will silently fail. |
| 2385 | */ |
| 2386 | boolean isRespondViaSmsCapable() { |
| 2387 | if (mState != CallState.RINGING) { |
| 2388 | return false; |
| 2389 | } |
| 2390 | |
| 2391 | if (getHandle() == null) { |
| 2392 | // No incoming number known or call presentation is "PRESENTATION_RESTRICTED", in |
| 2393 | // other words, the user should not be able to see the incoming phone number. |
| 2394 | return false; |
| 2395 | } |
| 2396 | |
Brad Ebinger | 6e8f3d7 | 2016-06-20 11:35:42 -0700 | [diff] [blame] | 2397 | if (mPhoneNumberUtilsAdapter.isUriNumber(getHandle().toString())) { |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 2398 | // The incoming number is actually a URI (i.e. a SIP address), |
| 2399 | // not a regular PSTN phone number, and we can't send SMSes to |
| 2400 | // SIP addresses. |
| 2401 | // (TODO: That might still be possible eventually, though. Is |
| 2402 | // there some SIP-specific equivalent to sending a text message?) |
| 2403 | return false; |
| 2404 | } |
| 2405 | |
| 2406 | // Is there a valid SMS application on the phone? |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 2407 | if (SmsApplication.getDefaultRespondViaMessageApplication(mContext, |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 2408 | true /*updateIfNeeded*/) == null) { |
| 2409 | return false; |
| 2410 | } |
| 2411 | |
| 2412 | // TODO: with some carriers (in certain countries) you *can* actually |
| 2413 | // tell whether a given number is a mobile phone or not. So in that |
| 2414 | // case we could potentially return false here if the incoming call is |
| 2415 | // from a land line. |
| 2416 | |
| 2417 | // If none of the above special cases apply, it's OK to enable the |
| 2418 | // "Respond via SMS" feature. |
| 2419 | return true; |
| 2420 | } |
| 2421 | |
| 2422 | List<String> getCannedSmsResponses() { |
| 2423 | return mCannedSmsResponses; |
| 2424 | } |
| 2425 | |
| 2426 | /** |
Santos Cordon | 672321e | 2014-08-21 14:38:58 -0700 | [diff] [blame] | 2427 | * We need to make sure that before we move a call to the disconnected state, it no |
| 2428 | * longer has any parent/child relationships. We want to do this to ensure that the InCall |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 2429 | * Service always has the right data in the right order. We also want to do it in telecom so |
Santos Cordon | 672321e | 2014-08-21 14:38:58 -0700 | [diff] [blame] | 2430 | * that the insurance policy lives in the framework side of things. |
| 2431 | */ |
| 2432 | private void fixParentAfterDisconnect() { |
Tyler Gunn | 7658171 | 2017-05-09 14:39:42 -0700 | [diff] [blame] | 2433 | setParentAndChildCall(null); |
Santos Cordon | 672321e | 2014-08-21 14:38:58 -0700 | [diff] [blame] | 2434 | } |
| 2435 | |
| 2436 | /** |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 2437 | * @return True if the call is ringing, else logs the action name. |
| 2438 | */ |
| 2439 | private boolean isRinging(String actionName) { |
| 2440 | if (mState == CallState.RINGING) { |
| 2441 | return true; |
| 2442 | } |
| 2443 | |
Sailesh Nepal | f1c191d | 2014-03-07 18:17:39 -0800 | [diff] [blame] | 2444 | Log.i(this, "Request to %s a non-ringing call %s", actionName, this); |
Santos Cordon | 61d0f70 | 2014-02-19 02:52:23 -0800 | [diff] [blame] | 2445 | return false; |
| 2446 | } |
| 2447 | |
Ben Gilad | 8e55d1d | 2014-02-26 16:25:56 -0800 | [diff] [blame] | 2448 | @SuppressWarnings("rawtypes") |
| 2449 | private void decrementAssociatedCallCount(ServiceBinder binder) { |
| 2450 | if (binder != null) { |
| 2451 | binder.decrementAssociatedCallCount(); |
| 2452 | } |
| 2453 | } |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 2454 | |
| 2455 | /** |
| 2456 | * Looks up contact information based on the current handle. |
| 2457 | */ |
| 2458 | private void startCallerInfoLookup() { |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 2459 | mCallerInfo = null; |
Hall Liu | 5b70c1c | 2016-03-03 18:42:57 -0800 | [diff] [blame] | 2460 | mCallsManager.getCallerInfoLookupHelper().startLookup(mHandle, mCallerInfoQueryListener); |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 2461 | } |
| 2462 | |
| 2463 | /** |
Santos Cordon | 99c8a6f | 2014-05-28 18:28:47 -0700 | [diff] [blame] | 2464 | * Saves the specified caller info if the specified token matches that of the last query |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 2465 | * that was made. |
| 2466 | * |
| 2467 | * @param callerInfo The new caller information to set. |
Santos Cordon | fd71f4a | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 2468 | */ |
Hall Liu | 5b70c1c | 2016-03-03 18:42:57 -0800 | [diff] [blame] | 2469 | private void setCallerInfo(Uri handle, CallerInfo callerInfo) { |
Yorke Lee | e4a9c41 | 2014-11-14 16:59:42 -0800 | [diff] [blame] | 2470 | Trace.beginSection("setCallerInfo"); |
Shigeru Murai | f2373e1 | 2016-09-12 10:26:23 +0900 | [diff] [blame] | 2471 | if (callerInfo == null) { |
| 2472 | Log.i(this, "CallerInfo lookup returned null, skipping update"); |
| 2473 | return; |
| 2474 | } |
Santos Cordon | 99c8a6f | 2014-05-28 18:28:47 -0700 | [diff] [blame] | 2475 | |
Srikanth Chintala | 3bf2228 | 2017-09-06 10:24:26 +0530 | [diff] [blame] | 2476 | if ((handle != null) && !handle.equals(mHandle)) { |
Hall Liu | 5b70c1c | 2016-03-03 18:42:57 -0800 | [diff] [blame] | 2477 | Log.i(this, "setCallerInfo received stale caller info for an old handle. Ignoring."); |
| 2478 | return; |
Santos Cordon | 99c8a6f | 2014-05-28 18:28:47 -0700 | [diff] [blame] | 2479 | } |
Hall Liu | 5b70c1c | 2016-03-03 18:42:57 -0800 | [diff] [blame] | 2480 | |
| 2481 | mCallerInfo = callerInfo; |
| 2482 | Log.i(this, "CallerInfo received for %s: %s", Log.piiHandle(mHandle), callerInfo); |
| 2483 | |
| 2484 | if (mCallerInfo.contactDisplayPhotoUri == null || |
| 2485 | mCallerInfo.cachedPhotoIcon != null || mCallerInfo.cachedPhoto != null) { |
| 2486 | for (Listener l : mListeners) { |
| 2487 | l.onCallerInfoChanged(this); |
| 2488 | } |
| 2489 | } |
| 2490 | |
Yorke Lee | e4a9c41 | 2014-11-14 16:59:42 -0800 | [diff] [blame] | 2491 | Trace.endSection(); |
Santos Cordon | 99c8a6f | 2014-05-28 18:28:47 -0700 | [diff] [blame] | 2492 | } |
| 2493 | |
Victor Chang | 9e7f98a | 2016-01-04 16:03:27 +0000 | [diff] [blame] | 2494 | public CallerInfo getCallerInfo() { |
Yorke Lee | 6f3f7af | 2014-07-11 10:59:46 -0700 | [diff] [blame] | 2495 | return mCallerInfo; |
| 2496 | } |
| 2497 | |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 2498 | private void maybeLoadCannedSmsResponses() { |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 2499 | if (mCallDirection == CALL_DIRECTION_INCOMING |
| 2500 | && isRespondViaSmsCapable() |
| 2501 | && !mCannedSmsResponsesLoadingStarted) { |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 2502 | Log.d(this, "maybeLoadCannedSmsResponses: starting task to load messages"); |
| 2503 | mCannedSmsResponsesLoadingStarted = true; |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 2504 | mCallsManager.getRespondViaSmsManager().loadCannedTextMessages( |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 2505 | new Response<Void, List<String>>() { |
| 2506 | @Override |
| 2507 | public void onResult(Void request, List<String>... result) { |
| 2508 | if (result.length > 0) { |
| 2509 | Log.d(this, "maybeLoadCannedSmsResponses: got %s", result[0]); |
| 2510 | mCannedSmsResponses = result[0]; |
| 2511 | for (Listener l : mListeners) { |
| 2512 | l.onCannedSmsResponsesLoaded(Call.this); |
| 2513 | } |
| 2514 | } |
| 2515 | } |
| 2516 | |
| 2517 | @Override |
| 2518 | public void onError(Void request, int code, String msg) { |
| 2519 | Log.w(Call.this, "Error obtaining canned SMS responses: %d %s", code, |
| 2520 | msg); |
| 2521 | } |
Tyler Gunn | 91d43cf | 2014-09-17 12:19:39 -0700 | [diff] [blame] | 2522 | }, |
| 2523 | mContext |
Ihab Awad | ff7493a | 2014-06-10 13:47:44 -0700 | [diff] [blame] | 2524 | ); |
| 2525 | } else { |
| 2526 | Log.d(this, "maybeLoadCannedSmsResponses: doing nothing"); |
| 2527 | } |
| 2528 | } |
Sai Cheemalapati | b7157e9 | 2014-06-11 17:51:55 -0700 | [diff] [blame] | 2529 | |
| 2530 | /** |
| 2531 | * Sets speakerphone option on when call begins. |
| 2532 | */ |
| 2533 | public void setStartWithSpeakerphoneOn(boolean startWithSpeakerphone) { |
| 2534 | mSpeakerphoneOn = startWithSpeakerphone; |
| 2535 | } |
| 2536 | |
| 2537 | /** |
| 2538 | * Returns speakerphone option. |
| 2539 | * |
| 2540 | * @return Whether or not speakerphone should be set automatically when call begins. |
| 2541 | */ |
| 2542 | public boolean getStartWithSpeakerphoneOn() { |
| 2543 | return mSpeakerphoneOn; |
| 2544 | } |
Andrew Lee | e9a7765 | 2014-06-26 13:07:57 -0700 | [diff] [blame] | 2545 | |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 2546 | public void setRequestedToStartWithRtt() { |
| 2547 | mDidRequestToStartWithRtt = true; |
| 2548 | } |
| 2549 | |
Hall Liu | aeece4e | 2017-02-14 16:42:12 -0800 | [diff] [blame] | 2550 | public void stopRtt() { |
| 2551 | if (mConnectionService != null) { |
| 2552 | mConnectionService.stopRtt(this); |
| 2553 | } else { |
| 2554 | // If this gets called by the in-call app before the connection service is set, we'll |
| 2555 | // just ignore it since it's really not supposed to happen. |
| 2556 | Log.w(this, "stopRtt() called before connection service is set."); |
| 2557 | } |
| 2558 | } |
| 2559 | |
| 2560 | public void sendRttRequest() { |
Hall Liu | ea67a76 | 2018-02-09 16:48:57 -0800 | [diff] [blame] | 2561 | createRttStreams(); |
Hall Liu | aeece4e | 2017-02-14 16:42:12 -0800 | [diff] [blame] | 2562 | mConnectionService.startRtt(this, getInCallToCsRttPipeForCs(), getCsToInCallRttPipeForCs()); |
| 2563 | } |
| 2564 | |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 2565 | private boolean areRttStreamsInitialized() { |
| 2566 | return mInCallToConnectionServiceStreams != null |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 2567 | && mConnectionServiceToInCallStreams != null; |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 2568 | } |
| 2569 | |
Hall Liu | ea67a76 | 2018-02-09 16:48:57 -0800 | [diff] [blame] | 2570 | public void createRttStreams() { |
| 2571 | if (!areRttStreamsInitialized()) { |
| 2572 | Log.i(this, "Initializing RTT streams"); |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 2573 | try { |
Hall Liu | 3a75c62 | 2017-11-20 17:45:33 -0800 | [diff] [blame] | 2574 | mWasEverRtt = true; |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 2575 | mInCallToConnectionServiceStreams = ParcelFileDescriptor.createReliablePipe(); |
| 2576 | mConnectionServiceToInCallStreams = ParcelFileDescriptor.createReliablePipe(); |
| 2577 | } catch (IOException e) { |
| 2578 | Log.e(this, e, "Failed to create pipes for RTT call."); |
| 2579 | } |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 2580 | } |
| 2581 | } |
| 2582 | |
Hall Liu | aeece4e | 2017-02-14 16:42:12 -0800 | [diff] [blame] | 2583 | public void onRttConnectionFailure(int reason) { |
Hall Liu | 825f6ad | 2018-01-29 17:34:54 -0800 | [diff] [blame] | 2584 | Log.i(this, "Got RTT initiation failure with reason %d", reason); |
Hall Liu | aeece4e | 2017-02-14 16:42:12 -0800 | [diff] [blame] | 2585 | for (Listener l : mListeners) { |
| 2586 | l.onRttInitiationFailure(this, reason); |
| 2587 | } |
| 2588 | } |
| 2589 | |
| 2590 | public void onRemoteRttRequest() { |
| 2591 | if (isRttCall()) { |
| 2592 | Log.w(this, "Remote RTT request on a call that's already RTT"); |
| 2593 | return; |
| 2594 | } |
| 2595 | |
| 2596 | mPendingRttRequestId = mCallsManager.getNextRttRequestId(); |
| 2597 | for (Listener l : mListeners) { |
| 2598 | l.onRemoteRttRequest(this, mPendingRttRequestId); |
| 2599 | } |
| 2600 | } |
| 2601 | |
| 2602 | public void handleRttRequestResponse(int id, boolean accept) { |
| 2603 | if (mPendingRttRequestId == INVALID_RTT_REQUEST_ID) { |
| 2604 | Log.w(this, "Response received to a nonexistent RTT request: %d", id); |
| 2605 | return; |
| 2606 | } |
| 2607 | if (id != mPendingRttRequestId) { |
| 2608 | Log.w(this, "Response ID %d does not match expected %d", id, mPendingRttRequestId); |
| 2609 | return; |
| 2610 | } |
Hall Liu | aeece4e | 2017-02-14 16:42:12 -0800 | [diff] [blame] | 2611 | if (accept) { |
Hall Liu | ea67a76 | 2018-02-09 16:48:57 -0800 | [diff] [blame] | 2612 | createRttStreams(); |
Hall Liu | aeece4e | 2017-02-14 16:42:12 -0800 | [diff] [blame] | 2613 | Log.i(this, "RTT request %d accepted.", id); |
| 2614 | mConnectionService.respondToRttRequest( |
| 2615 | this, getInCallToCsRttPipeForCs(), getCsToInCallRttPipeForCs()); |
| 2616 | } else { |
| 2617 | Log.i(this, "RTT request %d rejected.", id); |
| 2618 | mConnectionService.respondToRttRequest(this, null, null); |
| 2619 | } |
| 2620 | } |
| 2621 | |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 2622 | public boolean isRttCall() { |
| 2623 | return (mConnectionProperties & Connection.PROPERTY_IS_RTT) == Connection.PROPERTY_IS_RTT; |
| 2624 | } |
| 2625 | |
Hall Liu | 3a75c62 | 2017-11-20 17:45:33 -0800 | [diff] [blame] | 2626 | public boolean wasEverRttCall() { |
| 2627 | return mWasEverRtt; |
| 2628 | } |
| 2629 | |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 2630 | public ParcelFileDescriptor getCsToInCallRttPipeForCs() { |
| 2631 | return mConnectionServiceToInCallStreams == null ? null |
| 2632 | : mConnectionServiceToInCallStreams[RTT_PIPE_WRITE_SIDE_INDEX]; |
| 2633 | } |
| 2634 | |
| 2635 | public ParcelFileDescriptor getInCallToCsRttPipeForCs() { |
| 2636 | return mInCallToConnectionServiceStreams == null ? null |
| 2637 | : mInCallToConnectionServiceStreams[RTT_PIPE_READ_SIDE_INDEX]; |
| 2638 | } |
| 2639 | |
| 2640 | public ParcelFileDescriptor getCsToInCallRttPipeForInCall() { |
| 2641 | return mConnectionServiceToInCallStreams == null ? null |
| 2642 | : mConnectionServiceToInCallStreams[RTT_PIPE_READ_SIDE_INDEX]; |
| 2643 | } |
| 2644 | |
| 2645 | public ParcelFileDescriptor getInCallToCsRttPipeForInCall() { |
| 2646 | return mInCallToConnectionServiceStreams == null ? null |
| 2647 | : mInCallToConnectionServiceStreams[RTT_PIPE_WRITE_SIDE_INDEX]; |
| 2648 | } |
| 2649 | |
| 2650 | public int getRttMode() { |
| 2651 | return mRttMode; |
| 2652 | } |
| 2653 | |
Andrew Lee | e9a7765 | 2014-06-26 13:07:57 -0700 | [diff] [blame] | 2654 | /** |
Andrew Lee | 3bcf935 | 2014-07-23 12:36:05 -0700 | [diff] [blame] | 2655 | * Sets a video call provider for the call. |
Andrew Lee | e9a7765 | 2014-06-26 13:07:57 -0700 | [diff] [blame] | 2656 | */ |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 2657 | public void setVideoProvider(IVideoProvider videoProvider) { |
Tyler Gunn | 86014fc | 2015-06-12 14:31:25 -0700 | [diff] [blame] | 2658 | Log.v(this, "setVideoProvider"); |
| 2659 | |
Ravi Paluri | b4088ee | 2016-12-20 20:00:00 +0530 | [diff] [blame] | 2660 | if (mVideoProviderProxy != null) { |
| 2661 | mVideoProviderProxy.clearVideoCallback(); |
| 2662 | mVideoProviderProxy = null; |
| 2663 | } |
| 2664 | |
Tyler Gunn | 86014fc | 2015-06-12 14:31:25 -0700 | [diff] [blame] | 2665 | if (videoProvider != null ) { |
| 2666 | try { |
Tyler Gunn | 1bf0e6b | 2016-11-30 15:19:13 -0800 | [diff] [blame] | 2667 | mVideoProviderProxy = new VideoProviderProxy(mLock, videoProvider, this, |
| 2668 | mCallsManager); |
Tyler Gunn | 86014fc | 2015-06-12 14:31:25 -0700 | [diff] [blame] | 2669 | } catch (RemoteException ignored) { |
| 2670 | // Ignore RemoteException. |
| 2671 | } |
Tyler Gunn | 86014fc | 2015-06-12 14:31:25 -0700 | [diff] [blame] | 2672 | } |
| 2673 | |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 2674 | mVideoProvider = videoProvider; |
Tyler Gunn | 86014fc | 2015-06-12 14:31:25 -0700 | [diff] [blame] | 2675 | |
Nancy Chen | a65d41f | 2014-06-24 12:06:03 -0700 | [diff] [blame] | 2676 | for (Listener l : mListeners) { |
Andrew Lee | 3bcf935 | 2014-07-23 12:36:05 -0700 | [diff] [blame] | 2677 | l.onVideoCallProviderChanged(Call.this); |
Nancy Chen | a65d41f | 2014-06-24 12:06:03 -0700 | [diff] [blame] | 2678 | } |
| 2679 | } |
| 2680 | |
| 2681 | /** |
Tyler Gunn | 86014fc | 2015-06-12 14:31:25 -0700 | [diff] [blame] | 2682 | * @return The {@link Connection.VideoProvider} binder. |
Nancy Chen | a65d41f | 2014-06-24 12:06:03 -0700 | [diff] [blame] | 2683 | */ |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 2684 | public IVideoProvider getVideoProvider() { |
Tyler Gunn | 86014fc | 2015-06-12 14:31:25 -0700 | [diff] [blame] | 2685 | if (mVideoProviderProxy == null) { |
| 2686 | return null; |
| 2687 | } |
| 2688 | |
| 2689 | return mVideoProviderProxy.getInterface(); |
| 2690 | } |
| 2691 | |
| 2692 | /** |
| 2693 | * @return The {@link VideoProviderProxy} for this call. |
| 2694 | */ |
| 2695 | public VideoProviderProxy getVideoProviderProxy() { |
| 2696 | return mVideoProviderProxy; |
Andrew Lee | e9a7765 | 2014-06-26 13:07:57 -0700 | [diff] [blame] | 2697 | } |
Tyler Gunn | e19cc00 | 2014-07-01 11:32:53 -0700 | [diff] [blame] | 2698 | |
| 2699 | /** |
Tyler Gunn | c4abd91 | 2014-07-08 14:22:10 -0700 | [diff] [blame] | 2700 | * The current video state for the call. |
Tyler Gunn | 5b88249 | 2015-06-03 10:03:13 -0700 | [diff] [blame] | 2701 | * See {@link VideoProfile} for a list of valid video states. |
Tyler Gunn | c4abd91 | 2014-07-08 14:22:10 -0700 | [diff] [blame] | 2702 | */ |
| 2703 | public int getVideoState() { |
| 2704 | return mVideoState; |
| 2705 | } |
| 2706 | |
| 2707 | /** |
Tyler Gunn | 0a388fc | 2014-07-17 12:21:17 -0700 | [diff] [blame] | 2708 | * Returns the video states which were applicable over the duration of a call. |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 2709 | * See {@link VideoProfile} for a list of valid video states. |
Tyler Gunn | 0a388fc | 2014-07-17 12:21:17 -0700 | [diff] [blame] | 2710 | * |
| 2711 | * @return The video states applicable over the duration of the call. |
| 2712 | */ |
| 2713 | public int getVideoStateHistory() { |
| 2714 | return mVideoStateHistory; |
| 2715 | } |
| 2716 | |
| 2717 | /** |
| 2718 | * Determines the current video state for the call. |
| 2719 | * For an outgoing call determines the desired video state for the call. |
Tyler Gunn | 5b88249 | 2015-06-03 10:03:13 -0700 | [diff] [blame] | 2720 | * Valid values: see {@link VideoProfile} |
Tyler Gunn | c4abd91 | 2014-07-08 14:22:10 -0700 | [diff] [blame] | 2721 | * |
Tyler Gunn | 0a388fc | 2014-07-17 12:21:17 -0700 | [diff] [blame] | 2722 | * @param videoState The video state for the call. |
Tyler Gunn | c4abd91 | 2014-07-08 14:22:10 -0700 | [diff] [blame] | 2723 | */ |
| 2724 | public void setVideoState(int videoState) { |
Tyler Gunn | 13e8a69 | 2016-08-03 18:38:00 -0700 | [diff] [blame] | 2725 | // If the phone account associated with this call does not support video calling, then we |
| 2726 | // will automatically set the video state to audio-only. |
| 2727 | if (!isVideoCallingSupported()) { |
Tyler Gunn | ddec589 | 2016-09-28 10:26:13 -0700 | [diff] [blame] | 2728 | Log.d(this, "setVideoState: videoState=%s defaulted to audio (video not supported)", |
| 2729 | VideoProfile.videoStateToString(videoState)); |
Tyler Gunn | 13e8a69 | 2016-08-03 18:38:00 -0700 | [diff] [blame] | 2730 | videoState = VideoProfile.STATE_AUDIO_ONLY; |
| 2731 | } |
| 2732 | |
Brad Ebinger | b079fc5 | 2017-07-07 15:59:13 -0700 | [diff] [blame] | 2733 | // Track Video State history during the duration of the call. |
| 2734 | // Only update the history when the call is active or disconnected. This ensures we do |
| 2735 | // not include the video state history when: |
Tyler Gunn | eb39aa2 | 2015-04-03 11:47:28 -0700 | [diff] [blame] | 2736 | // - Call is incoming (but not answered). |
| 2737 | // - Call it outgoing (but not answered). |
| 2738 | // We include the video state when disconnected to ensure that rejected calls reflect the |
| 2739 | // appropriate video state. |
Brad Ebinger | b079fc5 | 2017-07-07 15:59:13 -0700 | [diff] [blame] | 2740 | // For all other times we add to the video state history, see #setState. |
Tyler Gunn | eb39aa2 | 2015-04-03 11:47:28 -0700 | [diff] [blame] | 2741 | if (isActive() || getState() == CallState.DISCONNECTED) { |
| 2742 | mVideoStateHistory = mVideoStateHistory | videoState; |
| 2743 | } |
Tyler Gunn | 0a388fc | 2014-07-17 12:21:17 -0700 | [diff] [blame] | 2744 | |
Hall Liu | 9696c21 | 2016-06-24 16:09:02 -0700 | [diff] [blame] | 2745 | int previousVideoState = mVideoState; |
Tyler Gunn | c4abd91 | 2014-07-08 14:22:10 -0700 | [diff] [blame] | 2746 | mVideoState = videoState; |
Hall Liu | 9696c21 | 2016-06-24 16:09:02 -0700 | [diff] [blame] | 2747 | if (mVideoState != previousVideoState) { |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 2748 | Log.addEvent(this, LogUtils.Events.VIDEO_STATE_CHANGED, |
Hall Liu | 9696c21 | 2016-06-24 16:09:02 -0700 | [diff] [blame] | 2749 | VideoProfile.videoStateToString(videoState)); |
| 2750 | for (Listener l : mListeners) { |
| 2751 | l.onVideoStateChanged(this, previousVideoState, mVideoState); |
| 2752 | } |
Andrew Lee | 4a79660 | 2014-07-11 17:23:03 -0700 | [diff] [blame] | 2753 | } |
Hall Liu | 4640c4f | 2016-06-22 17:13:20 -0700 | [diff] [blame] | 2754 | |
| 2755 | if (VideoProfile.isVideo(videoState)) { |
| 2756 | mAnalytics.setCallIsVideo(true); |
| 2757 | } |
Tyler Gunn | c4abd91 | 2014-07-08 14:22:10 -0700 | [diff] [blame] | 2758 | } |
Sailesh Nepal | 7e66957 | 2014-07-08 21:29:12 -0700 | [diff] [blame] | 2759 | |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 2760 | public boolean getIsVoipAudioMode() { |
| 2761 | return mIsVoipAudioMode; |
Sailesh Nepal | 7e66957 | 2014-07-08 21:29:12 -0700 | [diff] [blame] | 2762 | } |
| 2763 | |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 2764 | public void setIsVoipAudioMode(boolean audioModeIsVoip) { |
| 2765 | mIsVoipAudioMode = audioModeIsVoip; |
Sailesh Nepal | 7e66957 | 2014-07-08 21:29:12 -0700 | [diff] [blame] | 2766 | for (Listener l : mListeners) { |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 2767 | l.onIsVoipAudioModeChanged(this); |
Sailesh Nepal | 35faf8c | 2014-07-08 22:02:34 -0700 | [diff] [blame] | 2768 | } |
| 2769 | } |
| 2770 | |
| 2771 | public StatusHints getStatusHints() { |
| 2772 | return mStatusHints; |
| 2773 | } |
| 2774 | |
| 2775 | public void setStatusHints(StatusHints statusHints) { |
| 2776 | mStatusHints = statusHints; |
| 2777 | for (Listener l : mListeners) { |
| 2778 | l.onStatusHintsChanged(this); |
Sailesh Nepal | 7e66957 | 2014-07-08 21:29:12 -0700 | [diff] [blame] | 2779 | } |
| 2780 | } |
Sailesh Nepal | 9d58de5 | 2014-07-18 14:53:19 -0700 | [diff] [blame] | 2781 | |
Yorke Lee | 9250e5f | 2014-10-01 13:39:09 -0700 | [diff] [blame] | 2782 | public boolean isUnknown() { |
Hall Liu | 3258720 | 2015-11-18 11:10:08 -0800 | [diff] [blame] | 2783 | return mCallDirection == CALL_DIRECTION_UNKNOWN; |
Yorke Lee | 9250e5f | 2014-10-01 13:39:09 -0700 | [diff] [blame] | 2784 | } |
| 2785 | |
Tyler Gunn | aa47937 | 2014-10-07 10:18:42 -0700 | [diff] [blame] | 2786 | /** |
| 2787 | * Determines if this call is in a disconnecting state. |
| 2788 | * |
| 2789 | * @return {@code true} if this call is locally disconnecting. |
| 2790 | */ |
| 2791 | public boolean isLocallyDisconnecting() { |
| 2792 | return mIsLocallyDisconnecting; |
| 2793 | } |
| 2794 | |
| 2795 | /** |
| 2796 | * Sets whether this call is in a disconnecting state. |
| 2797 | * |
| 2798 | * @param isLocallyDisconnecting {@code true} if this call is locally disconnecting. |
| 2799 | */ |
| 2800 | private void setLocallyDisconnecting(boolean isLocallyDisconnecting) { |
| 2801 | mIsLocallyDisconnecting = isLocallyDisconnecting; |
| 2802 | } |
| 2803 | |
Tony Mak | 578a4e6 | 2015-11-23 11:18:51 +0000 | [diff] [blame] | 2804 | /** |
| 2805 | * @return user handle of user initiating the outgoing call. |
| 2806 | */ |
| 2807 | public UserHandle getInitiatingUser() { |
| 2808 | return mInitiatingUser; |
| 2809 | } |
| 2810 | |
| 2811 | /** |
| 2812 | * Set the user handle of user initiating the outgoing call. |
| 2813 | * @param initiatingUser |
| 2814 | */ |
| 2815 | public void setInitiatingUser(UserHandle initiatingUser) { |
| 2816 | Preconditions.checkNotNull(initiatingUser); |
| 2817 | mInitiatingUser = initiatingUser; |
| 2818 | } |
| 2819 | |
Santos Cordon | 0fbe632 | 2014-08-14 04:04:25 -0700 | [diff] [blame] | 2820 | static int getStateFromConnectionState(int state) { |
Santos Cordon | 72890ce | 2014-07-21 01:32:04 -0700 | [diff] [blame] | 2821 | switch (state) { |
Ihab Awad | a02bef5 | 2014-08-13 18:18:42 -0700 | [diff] [blame] | 2822 | case Connection.STATE_INITIALIZING: |
| 2823 | return CallState.CONNECTING; |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 2824 | case Connection.STATE_ACTIVE: |
Santos Cordon | 72890ce | 2014-07-21 01:32:04 -0700 | [diff] [blame] | 2825 | return CallState.ACTIVE; |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 2826 | case Connection.STATE_DIALING: |
Santos Cordon | 72890ce | 2014-07-21 01:32:04 -0700 | [diff] [blame] | 2827 | return CallState.DIALING; |
Tyler Gunn | 1e37be5 | 2016-07-11 08:54:23 -0700 | [diff] [blame] | 2828 | case Connection.STATE_PULLING_CALL: |
| 2829 | return CallState.PULLING; |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 2830 | case Connection.STATE_DISCONNECTED: |
Santos Cordon | 72890ce | 2014-07-21 01:32:04 -0700 | [diff] [blame] | 2831 | return CallState.DISCONNECTED; |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 2832 | case Connection.STATE_HOLDING: |
Santos Cordon | 72890ce | 2014-07-21 01:32:04 -0700 | [diff] [blame] | 2833 | return CallState.ON_HOLD; |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 2834 | case Connection.STATE_NEW: |
Santos Cordon | 72890ce | 2014-07-21 01:32:04 -0700 | [diff] [blame] | 2835 | return CallState.NEW; |
Ihab Awad | 6fb37c8 | 2014-08-07 19:48:57 -0700 | [diff] [blame] | 2836 | case Connection.STATE_RINGING: |
Santos Cordon | 72890ce | 2014-07-21 01:32:04 -0700 | [diff] [blame] | 2837 | return CallState.RINGING; |
| 2838 | } |
| 2839 | return CallState.DISCONNECTED; |
| 2840 | } |
Roshan Pius | 669f90b | 2015-09-02 16:21:39 -0700 | [diff] [blame] | 2841 | |
| 2842 | /** |
| 2843 | * Determines if this call is in disconnected state and waiting to be destroyed. |
| 2844 | * |
| 2845 | * @return {@code true} if this call is disconected. |
| 2846 | */ |
| 2847 | public boolean isDisconnected() { |
| 2848 | return (getState() == CallState.DISCONNECTED || getState() == CallState.ABORTED); |
| 2849 | } |
Tyler Gunn | 7a1f823 | 2015-12-03 19:52:59 -0800 | [diff] [blame] | 2850 | |
| 2851 | /** |
Brad Ebinger | 3da5764 | 2016-04-04 17:32:19 -0700 | [diff] [blame] | 2852 | * Determines if this call has just been created and has not been configured properly yet. |
| 2853 | * |
| 2854 | * @return {@code true} if this call is new. |
| 2855 | */ |
| 2856 | public boolean isNew() { |
| 2857 | return getState() == CallState.NEW; |
| 2858 | } |
| 2859 | |
| 2860 | /** |
Tyler Gunn | 7a1f823 | 2015-12-03 19:52:59 -0800 | [diff] [blame] | 2861 | * Sets the call data usage for the call. |
| 2862 | * |
| 2863 | * @param callDataUsage The new call data usage (in bytes). |
| 2864 | */ |
| 2865 | public void setCallDataUsage(long callDataUsage) { |
| 2866 | mCallDataUsage = callDataUsage; |
| 2867 | } |
| 2868 | |
| 2869 | /** |
| 2870 | * Returns the call data usage for the call. |
| 2871 | * |
| 2872 | * @return The call data usage (in bytes). |
| 2873 | */ |
| 2874 | public long getCallDataUsage() { |
| 2875 | return mCallDataUsage; |
| 2876 | } |
Tony Mak | 3ae2dc8 | 2016-01-07 11:49:38 +0000 | [diff] [blame] | 2877 | |
Hall Liu | dd68bc3 | 2017-01-25 17:14:23 -0800 | [diff] [blame] | 2878 | public void setRttMode(int mode) { |
| 2879 | mRttMode = mode; |
| 2880 | // TODO: hook this up to CallAudioManager |
| 2881 | } |
| 2882 | |
Hall Liu | 4b1759d | 2016-02-02 18:17:40 -0800 | [diff] [blame] | 2883 | /** |
| 2884 | * Returns true if the call is outgoing and the NEW_OUTGOING_CALL ordered broadcast intent |
| 2885 | * has come back to telecom and was processed. |
| 2886 | */ |
| 2887 | public boolean isNewOutgoingCallIntentBroadcastDone() { |
| 2888 | return mIsNewOutgoingCallIntentBroadcastDone; |
| 2889 | } |
| 2890 | |
| 2891 | public void setNewOutgoingCallIntentBroadcastIsDone() { |
| 2892 | mIsNewOutgoingCallIntentBroadcastDone = true; |
| 2893 | } |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 2894 | |
| 2895 | /** |
| 2896 | * Determines if the call has been held by the remote party. |
| 2897 | * |
| 2898 | * @return {@code true} if the call is remotely held, {@code false} otherwise. |
| 2899 | */ |
| 2900 | public boolean isRemotelyHeld() { |
| 2901 | return mIsRemotelyHeld; |
| 2902 | } |
| 2903 | |
| 2904 | /** |
| 2905 | * Handles Connection events received from a {@link ConnectionService}. |
| 2906 | * |
| 2907 | * @param event The event. |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 2908 | * @param extras The extras. |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 2909 | */ |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 2910 | public void onConnectionEvent(String event, Bundle extras) { |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 2911 | Log.addEvent(this, LogUtils.Events.CONNECTION_EVENT, event); |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 2912 | if (Connection.EVENT_ON_HOLD_TONE_START.equals(event)) { |
| 2913 | mIsRemotelyHeld = true; |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 2914 | Log.addEvent(this, LogUtils.Events.REMOTELY_HELD); |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 2915 | // Inform listeners of the fact that a call hold tone was received. This will trigger |
| 2916 | // the CallAudioManager to play a tone via the InCallTonePlayer. |
| 2917 | for (Listener l : mListeners) { |
| 2918 | l.onHoldToneRequested(this); |
| 2919 | } |
| 2920 | } else if (Connection.EVENT_ON_HOLD_TONE_END.equals(event)) { |
| 2921 | mIsRemotelyHeld = false; |
Brad Ebinger | a3eccfe | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 2922 | Log.addEvent(this, LogUtils.Events.REMOTELY_UNHELD); |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 2923 | for (Listener l : mListeners) { |
| 2924 | l.onHoldToneRequested(this); |
| 2925 | } |
Tyler Gunn | d45e6d9 | 2016-03-10 20:15:39 -0800 | [diff] [blame] | 2926 | } else { |
| 2927 | for (Listener l : mListeners) { |
| 2928 | l.onConnectionEvent(this, event, extras); |
| 2929 | } |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 2930 | } |
| 2931 | } |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 2932 | |
Tyler Gunn | 7c031f2 | 2018-01-18 15:00:41 -0800 | [diff] [blame] | 2933 | /** |
| 2934 | * Notifies interested parties that the handover has completed. |
| 2935 | * Notifies: |
| 2936 | * 1. {@link InCallController} which communicates this to the |
| 2937 | * {@link android.telecom.InCallService} via {@link Listener#onHandoverComplete()}. |
| 2938 | * 2. {@link ConnectionServiceWrapper} which informs the {@link android.telecom.Connection} of |
| 2939 | * the successful handover. |
| 2940 | */ |
| 2941 | public void onHandoverComplete() { |
| 2942 | Log.i(this, "onHandoverComplete; callId=%s", getId()); |
| 2943 | if (mConnectionService != null) { |
| 2944 | mConnectionService.handoverComplete(this); |
| 2945 | } |
| 2946 | for (Listener l : mListeners) { |
| 2947 | l.onHandoverComplete(this); |
| 2948 | } |
| 2949 | } |
| 2950 | |
Sanket Padawe | 4ebc3ca | 2017-11-21 12:49:43 -0800 | [diff] [blame] | 2951 | public void onHandoverFailed(int handoverError) { |
Tyler Gunn | 7c031f2 | 2018-01-18 15:00:41 -0800 | [diff] [blame] | 2952 | Log.i(this, "onHandoverFailed; callId=%s, handoverError=%d", getId(), handoverError); |
Sanket Padawe | 4ebc3ca | 2017-11-21 12:49:43 -0800 | [diff] [blame] | 2953 | for (Listener l : mListeners) { |
| 2954 | l.onHandoverFailed(this, handoverError); |
| 2955 | } |
| 2956 | } |
| 2957 | |
Tyler Gunn | 9b618b8 | 2016-10-17 15:54:35 -0700 | [diff] [blame] | 2958 | public void setOriginalConnectionId(String originalConnectionId) { |
| 2959 | mOriginalConnectionId = originalConnectionId; |
| 2960 | } |
| 2961 | |
| 2962 | /** |
| 2963 | * For calls added via a ConnectionManager using the |
| 2964 | * {@link android.telecom.ConnectionService#addExistingConnection(PhoneAccountHandle, |
| 2965 | * Connection)}, or {@link android.telecom.ConnectionService#addConference(Conference)} APIS, |
| 2966 | * indicates the ID of this call as it was referred to by the {@code ConnectionService} which |
| 2967 | * originally created it. |
| 2968 | * |
| 2969 | * See {@link Connection#EXTRA_ORIGINAL_CONNECTION_ID}. |
| 2970 | * @return The original connection ID. |
| 2971 | */ |
| 2972 | public String getOriginalConnectionId() { |
| 2973 | return mOriginalConnectionId; |
| 2974 | } |
| 2975 | |
Pengquan Meng | 4832f20 | 2017-12-20 16:13:04 -0800 | [diff] [blame] | 2976 | ConnectionServiceFocusManager getConnectionServiceFocusManager() { |
| 2977 | return mCallsManager.getConnectionServiceFocusManager(); |
| 2978 | } |
| 2979 | |
Tyler Gunn | fa1e97e | 2016-04-25 21:36:37 -0700 | [diff] [blame] | 2980 | /** |
| 2981 | * Determines if a {@link Call}'s capabilities bitmask indicates that video is supported either |
| 2982 | * remotely or locally. |
| 2983 | * |
| 2984 | * @param capabilities The {@link Connection} capabilities for the call. |
| 2985 | * @return {@code true} if video is supported, {@code false} otherwise. |
| 2986 | */ |
| 2987 | private boolean doesCallSupportVideo(int capabilities) { |
| 2988 | return (capabilities & Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL) != 0 || |
| 2989 | (capabilities & Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL) != 0; |
| 2990 | } |
| 2991 | |
| 2992 | /** |
| 2993 | * Remove any video capabilities set on a {@link Connection} capabilities bitmask. |
| 2994 | * |
| 2995 | * @param capabilities The capabilities. |
| 2996 | * @return The bitmask with video capabilities removed. |
| 2997 | */ |
| 2998 | private int removeVideoCapabilities(int capabilities) { |
| 2999 | return capabilities & ~(Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL | |
| 3000 | Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL); |
| 3001 | } |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 3002 | |
| 3003 | /** |
| 3004 | * Initiates a handover of this {@link Call} to another {@link PhoneAccount}. |
| 3005 | * @param handoverToHandle The {@link PhoneAccountHandle} to handover to. |
| 3006 | * @param videoState The video state of the call when handed over. |
Tyler Gunn | 6f6f1c5 | 2017-04-17 18:22:04 -0700 | [diff] [blame] | 3007 | * @param extras Optional extras {@link Bundle} provided by the initiating |
| 3008 | * {@link android.telecom.InCallService}. |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 3009 | */ |
Tyler Gunn | 6f6f1c5 | 2017-04-17 18:22:04 -0700 | [diff] [blame] | 3010 | private void requestHandover(PhoneAccountHandle handoverToHandle, int videoState, |
Sanket Padawe | 4ebc3ca | 2017-11-21 12:49:43 -0800 | [diff] [blame] | 3011 | Bundle extras, boolean isLegacy) { |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 3012 | for (Listener l : mListeners) { |
Sanket Padawe | 4ebc3ca | 2017-11-21 12:49:43 -0800 | [diff] [blame] | 3013 | l.onHandoverRequested(this, handoverToHandle, videoState, extras, isLegacy); |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 3014 | } |
| 3015 | } |
Brad Ebinger | b079fc5 | 2017-07-07 15:59:13 -0700 | [diff] [blame] | 3016 | |
| 3017 | /** |
| 3018 | * Sets the video history based on the state and state transitions of the call. Always add the |
| 3019 | * current video state to the video state history during a call transition except for the |
| 3020 | * transitions DIALING->ACTIVE and RINGING->ACTIVE. In these cases, clear the history. If a |
| 3021 | * call starts dialing/ringing as a VT call and gets downgraded to audio, we need to record |
| 3022 | * the history as an audio call. |
| 3023 | */ |
| 3024 | private void updateVideoHistoryViaState(int oldState, int newState) { |
| 3025 | if ((oldState == CallState.DIALING || oldState == CallState.RINGING) |
| 3026 | && newState == CallState.ACTIVE) { |
| 3027 | mVideoStateHistory = mVideoState; |
| 3028 | } |
| 3029 | |
| 3030 | mVideoStateHistory |= mVideoState; |
| 3031 | } |
| 3032 | |
Kazuya Ohshiro | 0063a19 | 2017-09-29 14:52:17 +0900 | [diff] [blame] | 3033 | /** |
| 3034 | * Returns whether or not high definition audio was used. |
| 3035 | * |
| 3036 | * @return true if high definition audio was used during this call. |
| 3037 | */ |
| 3038 | boolean wasHighDefAudio() { |
| 3039 | return mWasHighDefAudio; |
| 3040 | } |
Ben Gilad | 9f2bed3 | 2013-12-12 17:43:26 -0800 | [diff] [blame] | 3041 | } |