Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 1 | /* |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 2 | * Copyright (C) 2015 The Android Open Source Project |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 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 |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 14 | * limitations under the License |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 15 | */ |
| 16 | |
Tyler Gunn | 7cc70b4 | 2014-09-12 22:17:27 -0700 | [diff] [blame] | 17 | package com.android.server.telecom; |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 18 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 19 | import android.annotation.NonNull; |
Santos Cordon | 7686cd1 | 2015-10-05 15:20:55 -0700 | [diff] [blame] | 20 | import android.media.IAudioService; |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 21 | import android.media.ToneGenerator; |
Yorke Lee | 2a66f7b | 2015-05-13 14:21:19 -0700 | [diff] [blame] | 22 | import android.telecom.CallAudioState; |
Brad Ebinger | 953e1af | 2016-10-05 15:45:22 -0700 | [diff] [blame] | 23 | import android.telecom.Log; |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 24 | import android.telecom.VideoProfile; |
| 25 | import android.util.SparseArray; |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 26 | |
Brad Ebinger | d931a01 | 2015-10-21 12:54:08 -0700 | [diff] [blame] | 27 | import com.android.internal.annotations.VisibleForTesting; |
Tyler Gunn | 9787e0e | 2014-10-14 14:36:12 -0700 | [diff] [blame] | 28 | import com.android.internal.util.IndentingPrintWriter; |
Hall Liu | 784a496 | 2018-03-06 11:03:17 -0800 | [diff] [blame] | 29 | import com.android.server.telecom.bluetooth.BluetoothStateReceiver; |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 30 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 31 | import java.util.Collection; |
| 32 | import java.util.HashSet; |
| 33 | import java.util.Set; |
| 34 | import java.util.LinkedHashSet; |
| 35 | |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 36 | public class CallAudioManager extends CallsManagerListenerBase { |
Ihab Awad | b60f006 | 2015-05-26 16:20:32 -0700 | [diff] [blame] | 37 | |
Hall Liu | 8fb1fb7 | 2015-10-22 15:24:40 -0700 | [diff] [blame] | 38 | public interface AudioServiceFactory { |
| 39 | IAudioService getAudioService(); |
| 40 | } |
| 41 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 42 | private final String LOG_TAG = CallAudioManager.class.getSimpleName(); |
| 43 | |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 44 | private final LinkedHashSet<Call> mActiveDialingOrConnectingCalls; |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 45 | private final LinkedHashSet<Call> mRingingCalls; |
| 46 | private final LinkedHashSet<Call> mHoldingCalls; |
| 47 | private final Set<Call> mCalls; |
| 48 | private final SparseArray<LinkedHashSet<Call>> mCallStateToCalls; |
| 49 | |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 50 | private final CallAudioRouteStateMachine mCallAudioRouteStateMachine; |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 51 | private final CallAudioModeStateMachine mCallAudioModeStateMachine; |
Hall Liu | 784a496 | 2018-03-06 11:03:17 -0800 | [diff] [blame] | 52 | private final BluetoothStateReceiver mBluetoothStateReceiver; |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 53 | private final CallsManager mCallsManager; |
| 54 | private final InCallTonePlayer.Factory mPlayerFactory; |
| 55 | private final Ringer mRinger; |
| 56 | private final RingbackPlayer mRingbackPlayer; |
| 57 | private final DtmfLocalTonePlayer mDtmfLocalTonePlayer; |
Santos Cordon | deb8c89 | 2014-05-30 01:38:03 -0700 | [diff] [blame] | 58 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 59 | private Call mForegroundCall; |
| 60 | private boolean mIsTonePlaying = false; |
Honggang | b3ccbb3 | 2016-05-31 14:46:22 +0800 | [diff] [blame] | 61 | private boolean mIsDisconnectedTonePlaying = false; |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 62 | private InCallTonePlayer mHoldTonePlayer; |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 63 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 64 | public CallAudioManager(CallAudioRouteStateMachine callAudioRouteStateMachine, |
Hall Liu | 8fb1fb7 | 2015-10-22 15:24:40 -0700 | [diff] [blame] | 65 | CallsManager callsManager, |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 66 | CallAudioModeStateMachine callAudioModeStateMachine, |
| 67 | InCallTonePlayer.Factory playerFactory, |
| 68 | Ringer ringer, |
| 69 | RingbackPlayer ringbackPlayer, |
Hall Liu | 784a496 | 2018-03-06 11:03:17 -0800 | [diff] [blame] | 70 | BluetoothStateReceiver bluetoothStateReceiver, |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 71 | DtmfLocalTonePlayer dtmfLocalTonePlayer) { |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 72 | mActiveDialingOrConnectingCalls = new LinkedHashSet<>(); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 73 | mRingingCalls = new LinkedHashSet<>(); |
| 74 | mHoldingCalls = new LinkedHashSet<>(); |
| 75 | mCalls = new HashSet<>(); |
| 76 | mCallStateToCalls = new SparseArray<LinkedHashSet<Call>>() {{ |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 77 | put(CallState.CONNECTING, mActiveDialingOrConnectingCalls); |
| 78 | put(CallState.ACTIVE, mActiveDialingOrConnectingCalls); |
| 79 | put(CallState.DIALING, mActiveDialingOrConnectingCalls); |
Tyler Gunn | 1e37be5 | 2016-07-11 08:54:23 -0700 | [diff] [blame] | 80 | put(CallState.PULLING, mActiveDialingOrConnectingCalls); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 81 | put(CallState.RINGING, mRingingCalls); |
| 82 | put(CallState.ON_HOLD, mHoldingCalls); |
| 83 | }}; |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 84 | |
| 85 | mCallAudioRouteStateMachine = callAudioRouteStateMachine; |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 86 | mCallAudioModeStateMachine = callAudioModeStateMachine; |
| 87 | mCallsManager = callsManager; |
| 88 | mPlayerFactory = playerFactory; |
| 89 | mRinger = ringer; |
| 90 | mRingbackPlayer = ringbackPlayer; |
Hall Liu | 784a496 | 2018-03-06 11:03:17 -0800 | [diff] [blame] | 91 | mBluetoothStateReceiver = bluetoothStateReceiver; |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 92 | mDtmfLocalTonePlayer = dtmfLocalTonePlayer; |
| 93 | |
| 94 | mPlayerFactory.setCallAudioManager(this); |
| 95 | mCallAudioModeStateMachine.setCallAudioManager(this); |
Jack He | d0c6cab | 2018-02-13 18:33:57 -0800 | [diff] [blame] | 96 | mCallAudioRouteStateMachine.setCallAudioManager(this); |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 97 | } |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 98 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 99 | @Override |
| 100 | public void onCallStateChanged(Call call, int oldState, int newState) { |
Tyler Gunn | 4fe861d | 2016-03-29 19:33:56 -0700 | [diff] [blame] | 101 | if (shouldIgnoreCallForAudio(call)) { |
| 102 | // No audio management for calls in a conference, or external calls. |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 103 | return; |
| 104 | } |
| 105 | Log.d(LOG_TAG, "Call state changed for TC@%s: %s -> %s", call.getId(), |
| 106 | CallState.toString(oldState), CallState.toString(newState)); |
Brad Ebinger | 72930a8 | 2015-11-23 10:06:40 -0800 | [diff] [blame] | 107 | |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 108 | for (int i = 0; i < mCallStateToCalls.size(); i++) { |
| 109 | mCallStateToCalls.valueAt(i).remove(call); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 110 | } |
| 111 | if (mCallStateToCalls.get(newState) != null) { |
| 112 | mCallStateToCalls.get(newState).add(call); |
| 113 | } |
| 114 | |
| 115 | updateForegroundCall(); |
Hall Liu | 9029d1c | 2016-07-28 16:07:51 -0700 | [diff] [blame] | 116 | if (shouldPlayDisconnectTone(oldState, newState)) { |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 117 | playToneForDisconnectedCall(call); |
| 118 | } |
| 119 | |
| 120 | onCallLeavingState(call, oldState); |
| 121 | onCallEnteringState(call, newState); |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 122 | } |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 123 | |
| 124 | @Override |
| 125 | public void onCallAdded(Call call) { |
Tyler Gunn | 4fe861d | 2016-03-29 19:33:56 -0700 | [diff] [blame] | 126 | if (shouldIgnoreCallForAudio(call)) { |
| 127 | return; // Don't do audio handling for calls in a conference, or external calls. |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 128 | } |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 129 | |
Tyler Gunn | 1a40c4f | 2016-04-14 14:29:45 -0700 | [diff] [blame] | 130 | addCall(call); |
| 131 | } |
| 132 | |
| 133 | @Override |
| 134 | public void onCallRemoved(Call call) { |
| 135 | if (shouldIgnoreCallForAudio(call)) { |
| 136 | return; // Don't do audio handling for calls in a conference, or external calls. |
| 137 | } |
| 138 | |
| 139 | removeCall(call); |
| 140 | } |
| 141 | |
| 142 | private void addCall(Call call) { |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 143 | if (mCalls.contains(call)) { |
| 144 | Log.w(LOG_TAG, "Call TC@%s is being added twice.", call.getId()); |
| 145 | return; // No guarantees that the same call won't get added twice. |
| 146 | } |
| 147 | |
| 148 | Log.d(LOG_TAG, "Call added with id TC@%s in state %s", call.getId(), |
| 149 | CallState.toString(call.getState())); |
| 150 | |
| 151 | if (mCallStateToCalls.get(call.getState()) != null) { |
| 152 | mCallStateToCalls.get(call.getState()).add(call); |
| 153 | } |
| 154 | updateForegroundCall(); |
| 155 | mCalls.add(call); |
Hall Liu | 784a496 | 2018-03-06 11:03:17 -0800 | [diff] [blame] | 156 | if (mCalls.size() == 1) { |
| 157 | mBluetoothStateReceiver.setIsInCall(true); |
| 158 | } |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 159 | |
| 160 | onCallEnteringState(call, call.getState()); |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 161 | } |
| 162 | |
Tyler Gunn | 1a40c4f | 2016-04-14 14:29:45 -0700 | [diff] [blame] | 163 | private void removeCall(Call call) { |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 164 | if (!mCalls.contains(call)) { |
| 165 | return; // No guarantees that the same call won't get removed twice. |
| 166 | } |
| 167 | |
| 168 | Log.d(LOG_TAG, "Call removed with id TC@%s in state %s", call.getId(), |
| 169 | CallState.toString(call.getState())); |
| 170 | |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 171 | for (int i = 0; i < mCallStateToCalls.size(); i++) { |
| 172 | mCallStateToCalls.valueAt(i).remove(call); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | updateForegroundCall(); |
| 176 | mCalls.remove(call); |
Hall Liu | 784a496 | 2018-03-06 11:03:17 -0800 | [diff] [blame] | 177 | if (mCalls.size() == 0) { |
| 178 | mBluetoothStateReceiver.setIsInCall(false); |
| 179 | } |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 180 | |
| 181 | onCallLeavingState(call, call.getState()); |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 182 | } |
| 183 | |
Tyler Gunn | 4fe861d | 2016-03-29 19:33:56 -0700 | [diff] [blame] | 184 | /** |
Tyler Gunn | 1a40c4f | 2016-04-14 14:29:45 -0700 | [diff] [blame] | 185 | * Handles changes to the external state of a call. External calls which become regular calls |
| 186 | * should be tracked, and regular calls which become external should no longer be tracked. |
| 187 | * |
| 188 | * @param call The call. |
| 189 | * @param isExternalCall {@code True} if the call is now external, {@code false} if it is now |
| 190 | * a regular call. |
| 191 | */ |
| 192 | @Override |
| 193 | public void onExternalCallChanged(Call call, boolean isExternalCall) { |
Tyler Gunn | fe6d79e | 2016-07-11 16:08:38 -0700 | [diff] [blame] | 194 | if (isExternalCall) { |
Tyler Gunn | 1a40c4f | 2016-04-14 14:29:45 -0700 | [diff] [blame] | 195 | Log.d(LOG_TAG, "Removing call which became external ID %s", call.getId()); |
| 196 | removeCall(call); |
| 197 | } else if (!isExternalCall) { |
| 198 | Log.d(LOG_TAG, "Adding external call which was pulled with ID %s", call.getId()); |
| 199 | addCall(call); |
Tyler Gunn | fe6d79e | 2016-07-11 16:08:38 -0700 | [diff] [blame] | 200 | |
| 201 | if (mCallsManager.isSpeakerphoneAutoEnabledForVideoCalls(call.getVideoState())) { |
| 202 | // When pulling a video call, automatically enable the speakerphone. |
| 203 | Log.d(LOG_TAG, "Switching to speaker because external video call %s was pulled." + |
| 204 | call.getId()); |
| 205 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
| 206 | CallAudioRouteStateMachine.SWITCH_SPEAKER); |
| 207 | } |
Tyler Gunn | 1a40c4f | 2016-04-14 14:29:45 -0700 | [diff] [blame] | 208 | } |
| 209 | } |
| 210 | |
| 211 | /** |
Tyler Gunn | 4fe861d | 2016-03-29 19:33:56 -0700 | [diff] [blame] | 212 | * Determines if {@link CallAudioManager} should do any audio routing operations for a call. |
| 213 | * We ignore child calls of a conference and external calls for audio routing purposes. |
| 214 | * |
| 215 | * @param call The call to check. |
| 216 | * @return {@code true} if the call should be ignored for audio routing, {@code false} |
| 217 | * otherwise |
| 218 | */ |
| 219 | private boolean shouldIgnoreCallForAudio(Call call) { |
| 220 | return call.getParentCall() != null || call.isExternalCall(); |
| 221 | } |
| 222 | |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 223 | @Override |
| 224 | public void onIncomingCallAnswered(Call call) { |
Hall Liu | 8c7e256 | 2016-04-13 18:26:03 -0700 | [diff] [blame] | 225 | if (!mCalls.contains(call)) { |
| 226 | return; |
| 227 | } |
| 228 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 229 | // This is called after the UI answers the call, but before the connection service |
| 230 | // sets the call to active. Only thing to handle for mode here is the audio speedup thing. |
Santos Cordon | c7e85d4 | 2014-05-22 02:51:48 -0700 | [diff] [blame] | 231 | |
Dong Zhou | 3d4bafb | 2015-03-12 11:41:50 -0500 | [diff] [blame] | 232 | if (call.can(android.telecom.Call.Details.CAPABILITY_SPEED_UP_MT_AUDIO)) { |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 233 | if (mForegroundCall == call) { |
| 234 | Log.i(LOG_TAG, "Invoking the MT_AUDIO_SPEEDUP mechanism. Transitioning into " + |
| 235 | "an active in-call audio state before connection service has " + |
| 236 | "connected the call."); |
| 237 | if (mCallStateToCalls.get(call.getState()) != null) { |
| 238 | mCallStateToCalls.get(call.getState()).remove(call); |
| 239 | } |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 240 | mActiveDialingOrConnectingCalls.add(call); |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 241 | mCallAudioModeStateMachine.sendMessageWithArgs( |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 242 | CallAudioModeStateMachine.MT_AUDIO_SPEEDUP_FOR_RINGING_CALL, |
| 243 | makeArgsForModeStateMachine()); |
| 244 | } |
| 245 | } |
| 246 | |
Hall Liu | 25921e8 | 2017-07-24 17:58:55 -0700 | [diff] [blame] | 247 | // Turn off mute when a new incoming call is answered iff it's not a handover. |
| 248 | if (!call.isHandoverInProgress()) { |
| 249 | mute(false /* shouldMute */); |
| 250 | } |
Tyler Gunn | 8e154db | 2016-11-10 13:47:22 -0800 | [diff] [blame] | 251 | |
Hall Liu | 600b099 | 2016-03-14 17:56:25 -0700 | [diff] [blame] | 252 | maybeStopRingingAndCallWaitingForAnsweredOrRejectedCall(call); |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 253 | } |
| 254 | |
| 255 | @Override |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 256 | public void onSessionModifyRequestReceived(Call call, VideoProfile videoProfile) { |
| 257 | if (videoProfile == null) { |
| 258 | return; |
| 259 | } |
| 260 | |
| 261 | if (call != mForegroundCall) { |
| 262 | // We only play tones for foreground calls. |
| 263 | return; |
| 264 | } |
| 265 | |
| 266 | int previousVideoState = call.getVideoState(); |
| 267 | int newVideoState = videoProfile.getVideoState(); |
| 268 | Log.v(this, "onSessionModifyRequestReceived : videoProfile = " + VideoProfile |
| 269 | .videoStateToString(newVideoState)); |
| 270 | |
| 271 | boolean isUpgradeRequest = !VideoProfile.isReceptionEnabled(previousVideoState) && |
| 272 | VideoProfile.isReceptionEnabled(newVideoState); |
| 273 | |
| 274 | if (isUpgradeRequest) { |
| 275 | mPlayerFactory.createPlayer(InCallTonePlayer.TONE_VIDEO_UPGRADE).startTone(); |
| 276 | } |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 277 | } |
| 278 | |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 279 | /** |
| 280 | * Play or stop a call hold tone for a call. Triggered via |
| 281 | * {@link Connection#sendConnectionEvent(String)} when the |
| 282 | * {@link Connection#EVENT_ON_HOLD_TONE_START} event or |
| 283 | * {@link Connection#EVENT_ON_HOLD_TONE_STOP} event is passed through to the |
| 284 | * |
| 285 | * @param call The call which requested the hold tone. |
| 286 | */ |
| 287 | @Override |
| 288 | public void onHoldToneRequested(Call call) { |
| 289 | maybePlayHoldTone(); |
| 290 | } |
| 291 | |
Sailesh Nepal | 7e66957 | 2014-07-08 21:29:12 -0700 | [diff] [blame] | 292 | @Override |
Andrew Lee | 5be64bc | 2014-09-08 18:35:15 -0700 | [diff] [blame] | 293 | public void onIsVoipAudioModeChanged(Call call) { |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 294 | if (call != mForegroundCall) { |
| 295 | return; |
| 296 | } |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 297 | mCallAudioModeStateMachine.sendMessageWithArgs( |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 298 | CallAudioModeStateMachine.FOREGROUND_VOIP_MODE_CHANGE, |
| 299 | makeArgsForModeStateMachine()); |
| 300 | } |
| 301 | |
| 302 | @Override |
| 303 | public void onRingbackRequested(Call call, boolean shouldRingback) { |
| 304 | if (call == mForegroundCall && shouldRingback) { |
| 305 | mRingbackPlayer.startRingbackForCall(call); |
| 306 | } else { |
| 307 | mRingbackPlayer.stopRingbackForCall(call); |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | @Override |
| 312 | public void onIncomingCallRejected(Call call, boolean rejectWithMessage, String message) { |
Hall Liu | 600b099 | 2016-03-14 17:56:25 -0700 | [diff] [blame] | 313 | maybeStopRingingAndCallWaitingForAnsweredOrRejectedCall(call); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 314 | } |
| 315 | |
| 316 | @Override |
| 317 | public void onIsConferencedChanged(Call call) { |
| 318 | // This indicates a conferencing change, which shouldn't impact any audio mode stuff. |
| 319 | Call parentCall = call.getParentCall(); |
| 320 | if (parentCall == null) { |
| 321 | // Indicates that the call should be tracked for audio purposes. Treat it as if it were |
| 322 | // just added. |
| 323 | Log.i(LOG_TAG, "Call TC@" + call.getId() + " left conference and will" + |
| 324 | " now be tracked by CallAudioManager."); |
| 325 | onCallAdded(call); |
| 326 | } else { |
| 327 | // The call joined a conference, so stop tracking it. |
| 328 | if (mCallStateToCalls.get(call.getState()) != null) { |
| 329 | mCallStateToCalls.get(call.getState()).remove(call); |
| 330 | } |
| 331 | |
| 332 | updateForegroundCall(); |
| 333 | mCalls.remove(call); |
| 334 | } |
| 335 | } |
| 336 | |
Hall Liu | fd33fef | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 337 | @Override |
| 338 | public void onConnectionServiceChanged(Call call, ConnectionServiceWrapper oldCs, |
| 339 | ConnectionServiceWrapper newCs) { |
| 340 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
| 341 | CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE); |
| 342 | } |
| 343 | |
Hall Liu | 9696c21 | 2016-06-24 16:09:02 -0700 | [diff] [blame] | 344 | @Override |
| 345 | public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) { |
| 346 | if (call != getForegroundCall()) { |
| 347 | Log.d(LOG_TAG, "Ignoring video state change from %s to %s for call %s -- not " + |
| 348 | "foreground.", VideoProfile.videoStateToString(previousVideoState), |
| 349 | VideoProfile.videoStateToString(newVideoState), call.getId()); |
| 350 | return; |
| 351 | } |
| 352 | |
| 353 | if (!VideoProfile.isVideo(previousVideoState) && |
| 354 | mCallsManager.isSpeakerphoneAutoEnabledForVideoCalls(newVideoState)) { |
| 355 | Log.d(LOG_TAG, "Switching to speaker because call %s transitioned video state from %s" + |
| 356 | " to %s", call.getId(), VideoProfile.videoStateToString(previousVideoState), |
| 357 | VideoProfile.videoStateToString(newVideoState)); |
| 358 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
| 359 | CallAudioRouteStateMachine.SWITCH_SPEAKER); |
| 360 | } |
| 361 | } |
| 362 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 363 | public CallAudioState getCallAudioState() { |
| 364 | return mCallAudioRouteStateMachine.getCurrentCallAudioState(); |
| 365 | } |
| 366 | |
Hall Liu | 2a3455b | 2016-02-22 17:09:00 -0800 | [diff] [blame] | 367 | public Call getPossiblyHeldForegroundCall() { |
| 368 | return mForegroundCall; |
| 369 | } |
| 370 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 371 | public Call getForegroundCall() { |
| 372 | if (mForegroundCall != null && mForegroundCall.getState() != CallState.ON_HOLD) { |
| 373 | return mForegroundCall; |
| 374 | } |
| 375 | return null; |
Sailesh Nepal | 7e66957 | 2014-07-08 21:29:12 -0700 | [diff] [blame] | 376 | } |
| 377 | |
Omata Shou | 6bc865c | 2017-07-26 13:39:27 +0900 | [diff] [blame] | 378 | @VisibleForTesting |
| 379 | public void toggleMute() { |
| 380 | // Don't mute if there are any emergency calls. |
| 381 | if (mCallsManager.hasEmergencyCall()) { |
| 382 | Log.v(this, "ignoring toggleMute for emergency call"); |
| 383 | return; |
| 384 | } |
Brad Ebinger | 72930a8 | 2015-11-23 10:06:40 -0800 | [diff] [blame] | 385 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
| 386 | CallAudioRouteStateMachine.TOGGLE_MUTE); |
Santos Cordon | deb8c89 | 2014-05-30 01:38:03 -0700 | [diff] [blame] | 387 | } |
| 388 | |
Jack He | d0c6cab | 2018-02-13 18:33:57 -0800 | [diff] [blame] | 389 | @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) |
| 390 | public void onRingerModeChange() { |
Jack He | 1f3efbd | 2018-03-24 00:19:00 -0700 | [diff] [blame] | 391 | mCallAudioModeStateMachine.sendMessageWithArgs( |
| 392 | CallAudioModeStateMachine.RINGER_MODE_CHANGE, makeArgsForModeStateMachine()); |
Jack He | d0c6cab | 2018-02-13 18:33:57 -0800 | [diff] [blame] | 393 | } |
| 394 | |
Tyler Gunn | 8e154db | 2016-11-10 13:47:22 -0800 | [diff] [blame] | 395 | @VisibleForTesting |
| 396 | public void mute(boolean shouldMute) { |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 397 | Log.v(this, "mute, shouldMute: %b", shouldMute); |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 398 | |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 399 | // Don't mute if there are any emergency calls. |
Ihab Awad | 8de7691 | 2015-02-17 12:25:52 -0800 | [diff] [blame] | 400 | if (mCallsManager.hasEmergencyCall()) { |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 401 | shouldMute = false; |
| 402 | Log.v(this, "ignoring mute for emergency call"); |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 403 | } |
| 404 | |
Brad Ebinger | 72930a8 | 2015-11-23 10:06:40 -0800 | [diff] [blame] | 405 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo(shouldMute |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 406 | ? CallAudioRouteStateMachine.MUTE_ON : CallAudioRouteStateMachine.MUTE_OFF); |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 407 | } |
| 408 | |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 409 | /** |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 410 | * Changed the audio route, for example from earpiece to speaker phone. |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 411 | * |
Yorke Lee | 2a66f7b | 2015-05-13 14:21:19 -0700 | [diff] [blame] | 412 | * @param route The new audio route to use. See {@link CallAudioState}. |
Hall Liu | 9086fb1 | 2017-11-07 18:01:53 -0800 | [diff] [blame] | 413 | * @param bluetoothAddress the address of the desired bluetooth device, if route is |
| 414 | * {@link CallAudioState#ROUTE_BLUETOOTH}. |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 415 | */ |
Hall Liu | 9086fb1 | 2017-11-07 18:01:53 -0800 | [diff] [blame] | 416 | void setAudioRoute(int route, String bluetoothAddress) { |
Yorke Lee | 2a66f7b | 2015-05-13 14:21:19 -0700 | [diff] [blame] | 417 | Log.v(this, "setAudioRoute, route: %s", CallAudioState.audioRouteToString(route)); |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 418 | switch (route) { |
| 419 | case CallAudioState.ROUTE_BLUETOOTH: |
Brad Ebinger | 72930a8 | 2015-11-23 10:06:40 -0800 | [diff] [blame] | 420 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
Hall Liu | 9086fb1 | 2017-11-07 18:01:53 -0800 | [diff] [blame] | 421 | CallAudioRouteStateMachine.USER_SWITCH_BLUETOOTH, 0, bluetoothAddress); |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 422 | return; |
| 423 | case CallAudioState.ROUTE_SPEAKER: |
Brad Ebinger | 72930a8 | 2015-11-23 10:06:40 -0800 | [diff] [blame] | 424 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
Hall Liu | 4f296ba | 2016-02-18 14:46:57 -0800 | [diff] [blame] | 425 | CallAudioRouteStateMachine.USER_SWITCH_SPEAKER); |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 426 | return; |
| 427 | case CallAudioState.ROUTE_WIRED_HEADSET: |
Brad Ebinger | 72930a8 | 2015-11-23 10:06:40 -0800 | [diff] [blame] | 428 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
Hall Liu | 4f296ba | 2016-02-18 14:46:57 -0800 | [diff] [blame] | 429 | CallAudioRouteStateMachine.USER_SWITCH_HEADSET); |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 430 | return; |
| 431 | case CallAudioState.ROUTE_EARPIECE: |
Brad Ebinger | 72930a8 | 2015-11-23 10:06:40 -0800 | [diff] [blame] | 432 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
Hall Liu | 4f296ba | 2016-02-18 14:46:57 -0800 | [diff] [blame] | 433 | CallAudioRouteStateMachine.USER_SWITCH_EARPIECE); |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 434 | return; |
| 435 | case CallAudioState.ROUTE_WIRED_OR_EARPIECE: |
Brad Ebinger | 72930a8 | 2015-11-23 10:06:40 -0800 | [diff] [blame] | 436 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
Hall Liu | 95f2db9 | 2017-06-19 18:32:55 -0700 | [diff] [blame] | 437 | CallAudioRouteStateMachine.USER_SWITCH_BASELINE_ROUTE, |
| 438 | CallAudioRouteStateMachine.NO_INCLUDE_BLUETOOTH_IN_BASELINE); |
Hall Liu | f62630a | 2015-10-27 14:53:39 -0700 | [diff] [blame] | 439 | return; |
| 440 | default: |
| 441 | Log.wtf(this, "Invalid route specified: %d", route); |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 442 | } |
| 443 | } |
| 444 | |
Tyler Gunn | 911d4de | 2017-12-19 08:11:35 -0800 | [diff] [blame] | 445 | /** |
| 446 | * Switch call audio routing to the baseline route, including bluetooth headsets if there are |
| 447 | * any connected. |
| 448 | */ |
| 449 | void switchBaseline() { |
| 450 | Log.i(this, "switchBaseline"); |
| 451 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
| 452 | CallAudioRouteStateMachine.USER_SWITCH_BASELINE_ROUTE, |
| 453 | CallAudioRouteStateMachine.INCLUDE_BLUETOOTH_IN_BASELINE); |
| 454 | } |
| 455 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 456 | void silenceRingers() { |
| 457 | for (Call call : mRingingCalls) { |
| 458 | call.silence(); |
| 459 | } |
| 460 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 461 | mRinger.stopRinging(); |
| 462 | mRinger.stopCallWaiting(); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 463 | } |
| 464 | |
Hall Liu | fbed016 | 2016-01-14 18:06:29 -0800 | [diff] [blame] | 465 | @VisibleForTesting |
Hall Liu | 6a5995e | 2016-09-08 16:00:14 -0700 | [diff] [blame] | 466 | public boolean startRinging() { |
Hall Liu | 136f4c9 | 2017-04-04 13:35:18 -0700 | [diff] [blame] | 467 | return mRinger.startRinging(mForegroundCall, |
| 468 | mCallAudioRouteStateMachine.isHfpDeviceAvailable()); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 469 | } |
| 470 | |
Hall Liu | fbed016 | 2016-01-14 18:06:29 -0800 | [diff] [blame] | 471 | @VisibleForTesting |
| 472 | public void startCallWaiting() { |
xulicheng | 27437d9 | 2017-07-20 09:48:03 +0800 | [diff] [blame] | 473 | if (mRingingCalls.size() == 1) { |
| 474 | mRinger.startCallWaiting(mRingingCalls.iterator().next()); |
| 475 | } |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 476 | } |
| 477 | |
Hall Liu | fbed016 | 2016-01-14 18:06:29 -0800 | [diff] [blame] | 478 | @VisibleForTesting |
| 479 | public void stopRinging() { |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 480 | mRinger.stopRinging(); |
| 481 | } |
| 482 | |
Hall Liu | fbed016 | 2016-01-14 18:06:29 -0800 | [diff] [blame] | 483 | @VisibleForTesting |
| 484 | public void stopCallWaiting() { |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 485 | mRinger.stopCallWaiting(); |
| 486 | } |
| 487 | |
Hall Liu | fbed016 | 2016-01-14 18:06:29 -0800 | [diff] [blame] | 488 | @VisibleForTesting |
| 489 | public void setCallAudioRouteFocusState(int focusState) { |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 490 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
| 491 | CallAudioRouteStateMachine.SWITCH_FOCUS, focusState); |
| 492 | } |
| 493 | |
Hall Liu | 9ecbb1c | 2016-04-14 14:35:48 -0700 | [diff] [blame] | 494 | @VisibleForTesting |
| 495 | public CallAudioRouteStateMachine getCallAudioRouteStateMachine() { |
| 496 | return mCallAudioRouteStateMachine; |
| 497 | } |
| 498 | |
Hall Liu | 609992b | 2016-08-31 15:48:51 -0700 | [diff] [blame] | 499 | @VisibleForTesting |
| 500 | public CallAudioModeStateMachine getCallAudioModeStateMachine() { |
| 501 | return mCallAudioModeStateMachine; |
| 502 | } |
| 503 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 504 | void dump(IndentingPrintWriter pw) { |
Hall Liu | 8c7e256 | 2016-04-13 18:26:03 -0700 | [diff] [blame] | 505 | pw.println("All calls:"); |
| 506 | pw.increaseIndent(); |
| 507 | dumpCallsInCollection(pw, mCalls); |
| 508 | pw.decreaseIndent(); |
| 509 | |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 510 | pw.println("Active dialing, or connecting calls:"); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 511 | pw.increaseIndent(); |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 512 | dumpCallsInCollection(pw, mActiveDialingOrConnectingCalls); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 513 | pw.decreaseIndent(); |
| 514 | |
| 515 | pw.println("Ringing calls:"); |
| 516 | pw.increaseIndent(); |
| 517 | dumpCallsInCollection(pw, mRingingCalls); |
| 518 | pw.decreaseIndent(); |
| 519 | |
| 520 | pw.println("Holding calls:"); |
| 521 | pw.increaseIndent(); |
| 522 | dumpCallsInCollection(pw, mHoldingCalls); |
| 523 | pw.decreaseIndent(); |
| 524 | |
| 525 | pw.println("Foreground call:"); |
| 526 | pw.println(mForegroundCall); |
Hall Liu | a51c99f | 2017-03-13 16:39:26 -0700 | [diff] [blame] | 527 | |
| 528 | pw.println("CallAudioModeStateMachine pending messages:"); |
| 529 | pw.increaseIndent(); |
| 530 | mCallAudioModeStateMachine.dumpPendingMessages(pw); |
| 531 | pw.decreaseIndent(); |
| 532 | |
| 533 | pw.println("CallAudioRouteStateMachine pending messages:"); |
| 534 | pw.increaseIndent(); |
| 535 | mCallAudioRouteStateMachine.dumpPendingMessages(pw); |
| 536 | pw.decreaseIndent(); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 537 | } |
| 538 | |
Brad Ebinger | d931a01 | 2015-10-21 12:54:08 -0700 | [diff] [blame] | 539 | @VisibleForTesting |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 540 | public void setIsTonePlaying(boolean isTonePlaying) { |
| 541 | mIsTonePlaying = isTonePlaying; |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 542 | mCallAudioModeStateMachine.sendMessageWithArgs( |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 543 | isTonePlaying ? CallAudioModeStateMachine.TONE_STARTED_PLAYING |
| 544 | : CallAudioModeStateMachine.TONE_STOPPED_PLAYING, |
| 545 | makeArgsForModeStateMachine()); |
Honggang | b3ccbb3 | 2016-05-31 14:46:22 +0800 | [diff] [blame] | 546 | |
| 547 | if (!isTonePlaying && mIsDisconnectedTonePlaying) { |
| 548 | mCallsManager.onDisconnectedTonePlaying(false); |
| 549 | mIsDisconnectedTonePlaying = false; |
| 550 | } |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 551 | } |
| 552 | |
| 553 | private void onCallLeavingState(Call call, int state) { |
| 554 | switch (state) { |
| 555 | case CallState.ACTIVE: |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 556 | case CallState.CONNECTING: |
| 557 | onCallLeavingActiveDialingOrConnecting(); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 558 | break; |
| 559 | case CallState.RINGING: |
| 560 | onCallLeavingRinging(); |
| 561 | break; |
| 562 | case CallState.ON_HOLD: |
| 563 | onCallLeavingHold(); |
| 564 | break; |
Tyler Gunn | 1e37be5 | 2016-07-11 08:54:23 -0700 | [diff] [blame] | 565 | case CallState.PULLING: |
| 566 | onCallLeavingActiveDialingOrConnecting(); |
| 567 | break; |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 568 | case CallState.DIALING: |
| 569 | stopRingbackForCall(call); |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 570 | onCallLeavingActiveDialingOrConnecting(); |
Tyler Gunn | 1e37be5 | 2016-07-11 08:54:23 -0700 | [diff] [blame] | 571 | break; |
Santos Cordon | 1ae2b85 | 2014-03-19 03:03:10 -0700 | [diff] [blame] | 572 | } |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 573 | } |
| 574 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 575 | private void onCallEnteringState(Call call, int state) { |
| 576 | switch (state) { |
| 577 | case CallState.ACTIVE: |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 578 | case CallState.CONNECTING: |
| 579 | onCallEnteringActiveDialingOrConnecting(); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 580 | break; |
| 581 | case CallState.RINGING: |
| 582 | onCallEnteringRinging(); |
| 583 | break; |
| 584 | case CallState.ON_HOLD: |
| 585 | onCallEnteringHold(); |
| 586 | break; |
Tyler Gunn | 1e37be5 | 2016-07-11 08:54:23 -0700 | [diff] [blame] | 587 | case CallState.PULLING: |
| 588 | onCallEnteringActiveDialingOrConnecting(); |
| 589 | break; |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 590 | case CallState.DIALING: |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 591 | onCallEnteringActiveDialingOrConnecting(); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 592 | playRingbackForCall(call); |
| 593 | break; |
Santos Cordon | a56f276 | 2014-03-24 15:55:53 -0700 | [diff] [blame] | 594 | } |
| 595 | } |
| 596 | |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 597 | private void onCallLeavingActiveDialingOrConnecting() { |
| 598 | if (mActiveDialingOrConnectingCalls.size() == 0) { |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 599 | mCallAudioModeStateMachine.sendMessageWithArgs( |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 600 | CallAudioModeStateMachine.NO_MORE_ACTIVE_OR_DIALING_CALLS, |
| 601 | makeArgsForModeStateMachine()); |
Dong Zhou | 3d4bafb | 2015-03-12 11:41:50 -0500 | [diff] [blame] | 602 | } |
Santos Cordon | 14ff838 | 2014-08-05 20:44:27 -0700 | [diff] [blame] | 603 | } |
| 604 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 605 | private void onCallLeavingRinging() { |
| 606 | if (mRingingCalls.size() == 0) { |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 607 | mCallAudioModeStateMachine.sendMessageWithArgs( |
| 608 | CallAudioModeStateMachine.NO_MORE_RINGING_CALLS, |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 609 | makeArgsForModeStateMachine()); |
| 610 | } |
Tyler Gunn | 9670326 | 2015-06-23 14:36:55 -0700 | [diff] [blame] | 611 | } |
| 612 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 613 | private void onCallLeavingHold() { |
| 614 | if (mHoldingCalls.size() == 0) { |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 615 | mCallAudioModeStateMachine.sendMessageWithArgs( |
| 616 | CallAudioModeStateMachine.NO_MORE_HOLDING_CALLS, |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 617 | makeArgsForModeStateMachine()); |
| 618 | } |
| 619 | } |
Tyler Gunn | 9670326 | 2015-06-23 14:36:55 -0700 | [diff] [blame] | 620 | |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 621 | private void onCallEnteringActiveDialingOrConnecting() { |
| 622 | if (mActiveDialingOrConnectingCalls.size() == 1) { |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 623 | mCallAudioModeStateMachine.sendMessageWithArgs( |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 624 | CallAudioModeStateMachine.NEW_ACTIVE_OR_DIALING_CALL, |
| 625 | makeArgsForModeStateMachine()); |
| 626 | } |
| 627 | } |
| 628 | |
| 629 | private void onCallEnteringRinging() { |
| 630 | if (mRingingCalls.size() == 1) { |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 631 | mCallAudioModeStateMachine.sendMessageWithArgs( |
| 632 | CallAudioModeStateMachine.NEW_RINGING_CALL, |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 633 | makeArgsForModeStateMachine()); |
| 634 | } |
| 635 | } |
| 636 | |
| 637 | private void onCallEnteringHold() { |
| 638 | if (mHoldingCalls.size() == 1) { |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 639 | mCallAudioModeStateMachine.sendMessageWithArgs( |
| 640 | CallAudioModeStateMachine.NEW_HOLDING_CALL, |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 641 | makeArgsForModeStateMachine()); |
| 642 | } |
| 643 | } |
| 644 | |
| 645 | private void updateForegroundCall() { |
| 646 | Call oldForegroundCall = mForegroundCall; |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 647 | if (mActiveDialingOrConnectingCalls.size() > 0) { |
| 648 | // Give preference for connecting calls over active/dialing for foreground-ness. |
| 649 | Call possibleConnectingCall = null; |
| 650 | for (Call call : mActiveDialingOrConnectingCalls) { |
| 651 | if (call.getState() == CallState.CONNECTING) { |
| 652 | possibleConnectingCall = call; |
| 653 | } |
| 654 | } |
| 655 | mForegroundCall = possibleConnectingCall == null ? |
| 656 | mActiveDialingOrConnectingCalls.iterator().next() : possibleConnectingCall; |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 657 | } else if (mRingingCalls.size() > 0) { |
| 658 | mForegroundCall = mRingingCalls.iterator().next(); |
| 659 | } else if (mHoldingCalls.size() > 0) { |
| 660 | mForegroundCall = mHoldingCalls.iterator().next(); |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 661 | } else { |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 662 | mForegroundCall = null; |
| 663 | } |
| 664 | |
| 665 | if (mForegroundCall != oldForegroundCall) { |
Hall Liu | 8c7e256 | 2016-04-13 18:26:03 -0700 | [diff] [blame] | 666 | mCallAudioRouteStateMachine.sendMessageWithSessionInfo( |
| 667 | CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 668 | mDtmfLocalTonePlayer.onForegroundCallChanged(oldForegroundCall, mForegroundCall); |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 669 | maybePlayHoldTone(); |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 670 | } |
| 671 | } |
| 672 | |
| 673 | @NonNull |
| 674 | private CallAudioModeStateMachine.MessageArgs makeArgsForModeStateMachine() { |
| 675 | return new CallAudioModeStateMachine.MessageArgs( |
Hall Liu | 59c77e6 | 2016-03-10 18:03:45 -0800 | [diff] [blame] | 676 | mActiveDialingOrConnectingCalls.size() > 0, |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 677 | mRingingCalls.size() > 0, |
| 678 | mHoldingCalls.size() > 0, |
| 679 | mIsTonePlaying, |
| 680 | mForegroundCall != null && mForegroundCall.getIsVoipAudioMode(), |
| 681 | Log.createSubsession()); |
| 682 | } |
| 683 | |
| 684 | private void playToneForDisconnectedCall(Call call) { |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 685 | // If this call is being disconnected as a result of being handed over to another call, |
| 686 | // we will not play a disconnect tone. |
Tyler Gunn | 6f6f1c5 | 2017-04-17 18:22:04 -0700 | [diff] [blame] | 687 | if (call.isHandoverInProgress()) { |
Tyler Gunn | 6f9ceb2 | 2017-04-06 08:47:01 -0700 | [diff] [blame] | 688 | Log.i(LOG_TAG, "Omitting tone because %s is being handed over.", call); |
| 689 | return; |
| 690 | } |
| 691 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 692 | if (mForegroundCall != null && call != mForegroundCall && mCalls.size() > 1) { |
| 693 | Log.v(LOG_TAG, "Omitting tone because we are not foreground" + |
| 694 | " and there is another call."); |
| 695 | return; |
| 696 | } |
| 697 | |
| 698 | if (call.getDisconnectCause() != null) { |
| 699 | int toneToPlay = InCallTonePlayer.TONE_INVALID; |
| 700 | |
| 701 | Log.v(this, "Disconnect cause: %s.", call.getDisconnectCause()); |
| 702 | |
| 703 | switch(call.getDisconnectCause().getTone()) { |
| 704 | case ToneGenerator.TONE_SUP_BUSY: |
| 705 | toneToPlay = InCallTonePlayer.TONE_BUSY; |
| 706 | break; |
| 707 | case ToneGenerator.TONE_SUP_CONGESTION: |
| 708 | toneToPlay = InCallTonePlayer.TONE_CONGESTION; |
| 709 | break; |
| 710 | case ToneGenerator.TONE_CDMA_REORDER: |
| 711 | toneToPlay = InCallTonePlayer.TONE_REORDER; |
| 712 | break; |
| 713 | case ToneGenerator.TONE_CDMA_ABBR_INTERCEPT: |
| 714 | toneToPlay = InCallTonePlayer.TONE_INTERCEPT; |
| 715 | break; |
| 716 | case ToneGenerator.TONE_CDMA_CALLDROP_LITE: |
| 717 | toneToPlay = InCallTonePlayer.TONE_CDMA_DROP; |
| 718 | break; |
| 719 | case ToneGenerator.TONE_SUP_ERROR: |
| 720 | toneToPlay = InCallTonePlayer.TONE_UNOBTAINABLE_NUMBER; |
| 721 | break; |
| 722 | case ToneGenerator.TONE_PROP_PROMPT: |
| 723 | toneToPlay = InCallTonePlayer.TONE_CALL_ENDED; |
| 724 | break; |
| 725 | } |
| 726 | |
| 727 | Log.d(this, "Found a disconnected call with tone to play %d.", toneToPlay); |
| 728 | |
| 729 | if (toneToPlay != InCallTonePlayer.TONE_INVALID) { |
| 730 | mPlayerFactory.createPlayer(toneToPlay).startTone(); |
Honggang | b3ccbb3 | 2016-05-31 14:46:22 +0800 | [diff] [blame] | 731 | mCallsManager.onDisconnectedTonePlaying(true); |
| 732 | mIsDisconnectedTonePlaying = true; |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 733 | } |
| 734 | } |
| 735 | } |
| 736 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 737 | private void playRingbackForCall(Call call) { |
| 738 | if (call == mForegroundCall && call.isRingbackRequested()) { |
| 739 | mRingbackPlayer.startRingbackForCall(call); |
Sailesh Nepal | 6aca10a | 2014-03-24 16:11:02 -0700 | [diff] [blame] | 740 | } |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 741 | } |
Santos Cordon | 5ba7f27 | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 742 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 743 | private void stopRingbackForCall(Call call) { |
| 744 | mRingbackPlayer.stopRingbackForCall(call); |
| 745 | } |
Santos Cordon | 5ba7f27 | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 746 | |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 747 | /** |
| 748 | * Determines if a hold tone should be played and then starts or stops it accordingly. |
| 749 | */ |
| 750 | private void maybePlayHoldTone() { |
| 751 | if (shouldPlayHoldTone()) { |
| 752 | if (mHoldTonePlayer == null) { |
| 753 | mHoldTonePlayer = mPlayerFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING); |
Hall Liu | b626c02 | 2016-06-23 13:16:51 -0700 | [diff] [blame] | 754 | mHoldTonePlayer.startTone(); |
Tyler Gunn | db82191 | 2016-02-16 14:35:25 -0800 | [diff] [blame] | 755 | } |
| 756 | } else { |
| 757 | if (mHoldTonePlayer != null) { |
| 758 | mHoldTonePlayer.stopTone(); |
| 759 | mHoldTonePlayer = null; |
| 760 | } |
| 761 | } |
| 762 | } |
| 763 | |
| 764 | /** |
| 765 | * Determines if a hold tone should be played. |
| 766 | * A hold tone should be played only if foreground call is equals with call which is |
| 767 | * remotely held. |
| 768 | * |
| 769 | * @return {@code true} if the the hold tone should be played, {@code false} otherwise. |
| 770 | */ |
| 771 | private boolean shouldPlayHoldTone() { |
| 772 | Call foregroundCall = getForegroundCall(); |
| 773 | // If there is no foreground call, no hold tone should play. |
| 774 | if (foregroundCall == null) { |
| 775 | return false; |
| 776 | } |
| 777 | |
| 778 | // If another call is ringing, no hold tone should play. |
| 779 | if (mCallsManager.hasRingingCall()) { |
| 780 | return false; |
| 781 | } |
| 782 | |
| 783 | // If the foreground call isn't active, no hold tone should play. This might happen, for |
| 784 | // example, if the user puts a remotely held call on hold itself. |
| 785 | if (!foregroundCall.isActive()) { |
| 786 | return false; |
| 787 | } |
| 788 | |
| 789 | return foregroundCall.isRemotelyHeld(); |
| 790 | } |
| 791 | |
Hall Liu | e091ab9 | 2015-12-18 17:05:30 -0800 | [diff] [blame] | 792 | private void dumpCallsInCollection(IndentingPrintWriter pw, Collection<Call> calls) { |
| 793 | for (Call call : calls) { |
| 794 | if (call != null) pw.println(call.getId()); |
Santos Cordon | 5ba7f27 | 2014-05-28 13:59:49 -0700 | [diff] [blame] | 795 | } |
Tyler Gunn | 9787e0e | 2014-10-14 14:36:12 -0700 | [diff] [blame] | 796 | } |
Hall Liu | 600b099 | 2016-03-14 17:56:25 -0700 | [diff] [blame] | 797 | |
| 798 | private void maybeStopRingingAndCallWaitingForAnsweredOrRejectedCall(Call call) { |
| 799 | // Check to see if the call being answered/rejected is the only ringing call, since this |
| 800 | // will be called before the connection service acknowledges the state change. |
| 801 | if (mRingingCalls.size() == 0 || |
| 802 | (mRingingCalls.size() == 1 && call == mRingingCalls.iterator().next())) { |
| 803 | mRinger.stopRinging(); |
| 804 | mRinger.stopCallWaiting(); |
| 805 | } |
| 806 | } |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 807 | |
Hall Liu | 9029d1c | 2016-07-28 16:07:51 -0700 | [diff] [blame] | 808 | private boolean shouldPlayDisconnectTone(int oldState, int newState) { |
| 809 | if (newState != CallState.DISCONNECTED) { |
| 810 | return false; |
| 811 | } |
| 812 | return oldState == CallState.ACTIVE || |
| 813 | oldState == CallState.DIALING || |
| 814 | oldState == CallState.ON_HOLD; |
| 815 | } |
| 816 | |
Hall Liu | e792b33 | 2016-04-19 14:23:09 -0700 | [diff] [blame] | 817 | @VisibleForTesting |
| 818 | public Set<Call> getTrackedCalls() { |
| 819 | return mCalls; |
| 820 | } |
| 821 | |
| 822 | @VisibleForTesting |
| 823 | public SparseArray<LinkedHashSet<Call>> getCallStateToCalls() { |
| 824 | return mCallStateToCalls; |
| 825 | } |
Honggang | b3ccbb3 | 2016-05-31 14:46:22 +0800 | [diff] [blame] | 826 | } |