blob: 716f23a91e8a35c3ee4dfa46eebb55f74538fd33 [file] [log] [blame]
Hall Liue091ab92015-12-18 17:05:30 -08001/*
2 * Copyright (C) 2015 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
17package com.android.server.telecom;
18
Hall Liue091ab92015-12-18 17:05:30 -080019import android.media.AudioManager;
20import android.os.Message;
Brad Ebinger953e1af2016-10-05 15:45:22 -070021import android.telecom.Log;
22import android.telecom.Logging.Runnable;
23import android.telecom.Logging.Session;
Hall Liue091ab92015-12-18 17:05:30 -080024import android.util.SparseArray;
25
Hall Liufbed0162016-01-14 18:06:29 -080026import com.android.internal.util.IState;
Hall Liua51c99f2017-03-13 16:39:26 -070027import com.android.internal.util.IndentingPrintWriter;
Hall Liue091ab92015-12-18 17:05:30 -080028import com.android.internal.util.State;
29import com.android.internal.util.StateMachine;
30
31public class CallAudioModeStateMachine extends StateMachine {
32 public static class MessageArgs {
Hall Liufbed0162016-01-14 18:06:29 -080033 public boolean hasActiveOrDialingCalls;
Hall Liue091ab92015-12-18 17:05:30 -080034 public boolean hasRingingCalls;
35 public boolean hasHoldingCalls;
36 public boolean isTonePlaying;
37 public boolean foregroundCallIsVoip;
38 public Session session;
39
Hall Liufbed0162016-01-14 18:06:29 -080040 public MessageArgs(boolean hasActiveOrDialingCalls, boolean hasRingingCalls,
41 boolean hasHoldingCalls, boolean isTonePlaying, boolean foregroundCallIsVoip,
42 Session session) {
43 this.hasActiveOrDialingCalls = hasActiveOrDialingCalls;
Hall Liue091ab92015-12-18 17:05:30 -080044 this.hasRingingCalls = hasRingingCalls;
45 this.hasHoldingCalls = hasHoldingCalls;
46 this.isTonePlaying = isTonePlaying;
47 this.foregroundCallIsVoip = foregroundCallIsVoip;
48 this.session = session;
49 }
50
Brad Ebinger83bc4112016-04-01 15:30:14 -070051 public MessageArgs() {
52 this.session = Log.createSubsession();
53 }
54
Hall Liue091ab92015-12-18 17:05:30 -080055 @Override
56 public String toString() {
57 return "MessageArgs{" +
Hall Liufbed0162016-01-14 18:06:29 -080058 "hasActiveCalls=" + hasActiveOrDialingCalls +
Hall Liue091ab92015-12-18 17:05:30 -080059 ", hasRingingCalls=" + hasRingingCalls +
60 ", hasHoldingCalls=" + hasHoldingCalls +
61 ", isTonePlaying=" + isTonePlaying +
62 ", foregroundCallIsVoip=" + foregroundCallIsVoip +
63 ", session=" + session +
64 '}';
65 }
66 }
67
68 public static final int INITIALIZE = 1;
69 // These ENTER_*_FOCUS commands are for testing.
70 public static final int ENTER_CALL_FOCUS_FOR_TESTING = 2;
71 public static final int ENTER_COMMS_FOCUS_FOR_TESTING = 3;
72 public static final int ENTER_RING_FOCUS_FOR_TESTING = 4;
Hall Liufbed0162016-01-14 18:06:29 -080073 public static final int ENTER_TONE_OR_HOLD_FOCUS_FOR_TESTING = 5;
74 public static final int ABANDON_FOCUS_FOR_TESTING = 6;
Hall Liue091ab92015-12-18 17:05:30 -080075
76 public static final int NO_MORE_ACTIVE_OR_DIALING_CALLS = 1001;
77 public static final int NO_MORE_RINGING_CALLS = 1002;
78 public static final int NO_MORE_HOLDING_CALLS = 1003;
79
80 public static final int NEW_ACTIVE_OR_DIALING_CALL = 2001;
81 public static final int NEW_RINGING_CALL = 2002;
82 public static final int NEW_HOLDING_CALL = 2003;
83 public static final int MT_AUDIO_SPEEDUP_FOR_RINGING_CALL = 2004;
84
85 public static final int TONE_STARTED_PLAYING = 3001;
86 public static final int TONE_STOPPED_PLAYING = 3002;
87
88 public static final int FOREGROUND_VOIP_MODE_CHANGE = 4001;
89
Jack Hed0c6cab2018-02-13 18:33:57 -080090 public static final int RINGER_MODE_CHANGE = 5001;
91
Hall Liufbed0162016-01-14 18:06:29 -080092 public static final int RUN_RUNNABLE = 9001;
93
Hall Liue091ab92015-12-18 17:05:30 -080094 private static final SparseArray<String> MESSAGE_CODE_TO_NAME = new SparseArray<String>() {{
95 put(ENTER_CALL_FOCUS_FOR_TESTING, "ENTER_CALL_FOCUS_FOR_TESTING");
96 put(ENTER_COMMS_FOCUS_FOR_TESTING, "ENTER_COMMS_FOCUS_FOR_TESTING");
97 put(ENTER_RING_FOCUS_FOR_TESTING, "ENTER_RING_FOCUS_FOR_TESTING");
Hall Liufbed0162016-01-14 18:06:29 -080098 put(ENTER_TONE_OR_HOLD_FOCUS_FOR_TESTING, "ENTER_TONE_OR_HOLD_FOCUS_FOR_TESTING");
Hall Liue091ab92015-12-18 17:05:30 -080099 put(ABANDON_FOCUS_FOR_TESTING, "ABANDON_FOCUS_FOR_TESTING");
100 put(NO_MORE_ACTIVE_OR_DIALING_CALLS, "NO_MORE_ACTIVE_OR_DIALING_CALLS");
101 put(NO_MORE_RINGING_CALLS, "NO_MORE_RINGING_CALLS");
102 put(NO_MORE_HOLDING_CALLS, "NO_MORE_HOLDING_CALLS");
103 put(NEW_ACTIVE_OR_DIALING_CALL, "NEW_ACTIVE_OR_DIALING_CALL");
104 put(NEW_RINGING_CALL, "NEW_RINGING_CALL");
105 put(NEW_HOLDING_CALL, "NEW_HOLDING_CALL");
106 put(MT_AUDIO_SPEEDUP_FOR_RINGING_CALL, "MT_AUDIO_SPEEDUP_FOR_RINGING_CALL");
107 put(TONE_STARTED_PLAYING, "TONE_STARTED_PLAYING");
108 put(TONE_STOPPED_PLAYING, "TONE_STOPPED_PLAYING");
109 put(FOREGROUND_VOIP_MODE_CHANGE, "FOREGROUND_VOIP_MODE_CHANGE");
Jack Hed0c6cab2018-02-13 18:33:57 -0800110 put(RINGER_MODE_CHANGE, "RINGER_MODE_CHANGE");
Hall Liufbed0162016-01-14 18:06:29 -0800111
112 put(RUN_RUNNABLE, "RUN_RUNNABLE");
Hall Liue091ab92015-12-18 17:05:30 -0800113 }};
114
Hall Liufbed0162016-01-14 18:06:29 -0800115 public static final String TONE_HOLD_STATE_NAME = OtherFocusState.class.getSimpleName();
116 public static final String UNFOCUSED_STATE_NAME = UnfocusedState.class.getSimpleName();
117 public static final String CALL_STATE_NAME = SimCallFocusState.class.getSimpleName();
118 public static final String RING_STATE_NAME = RingingFocusState.class.getSimpleName();
119 public static final String COMMS_STATE_NAME = VoipCallFocusState.class.getSimpleName();
120
Hall Liue091ab92015-12-18 17:05:30 -0800121 private class BaseState extends State {
122 @Override
123 public boolean processMessage(Message msg) {
124 switch (msg.what) {
125 case ENTER_CALL_FOCUS_FOR_TESTING:
126 transitionTo(mSimCallFocusState);
127 return HANDLED;
128 case ENTER_COMMS_FOCUS_FOR_TESTING:
129 transitionTo(mVoipCallFocusState);
130 return HANDLED;
131 case ENTER_RING_FOCUS_FOR_TESTING:
132 transitionTo(mRingingFocusState);
133 return HANDLED;
Hall Liufbed0162016-01-14 18:06:29 -0800134 case ENTER_TONE_OR_HOLD_FOCUS_FOR_TESTING:
135 transitionTo(mOtherFocusState);
136 return HANDLED;
Hall Liue091ab92015-12-18 17:05:30 -0800137 case ABANDON_FOCUS_FOR_TESTING:
138 transitionTo(mUnfocusedState);
139 return HANDLED;
140 case INITIALIZE:
141 mIsInitialized = true;
142 return HANDLED;
Hall Liufbed0162016-01-14 18:06:29 -0800143 case RUN_RUNNABLE:
Brad Ebingere62e9e82016-02-01 18:26:40 -0800144 java.lang.Runnable r = (java.lang.Runnable) msg.obj;
Hall Liufbed0162016-01-14 18:06:29 -0800145 r.run();
146 return HANDLED;
Hall Liue091ab92015-12-18 17:05:30 -0800147 default:
148 return NOT_HANDLED;
149 }
150 }
151 }
152
153 private class UnfocusedState extends BaseState {
154 @Override
155 public void enter() {
156 if (mIsInitialized) {
157 Log.i(LOG_TAG, "Abandoning audio focus: now UNFOCUSED");
158 mAudioManager.abandonAudioFocusForCall();
159 mAudioManager.setMode(AudioManager.MODE_NORMAL);
160
161 mMostRecentMode = AudioManager.MODE_NORMAL;
162 mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.NO_FOCUS);
163 }
164 }
165
166 @Override
167 public boolean processMessage(Message msg) {
168 if (super.processMessage(msg) == HANDLED) {
169 return HANDLED;
170 }
171 MessageArgs args = (MessageArgs) msg.obj;
172 switch (msg.what) {
173 case NO_MORE_ACTIVE_OR_DIALING_CALLS:
174 // Do nothing.
175 return HANDLED;
176 case NO_MORE_RINGING_CALLS:
177 // Do nothing.
178 return HANDLED;
179 case NO_MORE_HOLDING_CALLS:
180 // Do nothing.
181 return HANDLED;
182 case NEW_ACTIVE_OR_DIALING_CALL:
Hall Liue091ab92015-12-18 17:05:30 -0800183 transitionTo(args.foregroundCallIsVoip
184 ? mVoipCallFocusState : mSimCallFocusState);
185 return HANDLED;
186 case NEW_RINGING_CALL:
187 transitionTo(mRingingFocusState);
188 return HANDLED;
189 case NEW_HOLDING_CALL:
190 // This really shouldn't happen, but transition to the focused state anyway.
191 Log.w(LOG_TAG, "Call was surprisingly put into hold from an unknown state." +
192 " Args are: \n" + args.toString());
193 transitionTo(mOtherFocusState);
194 return HANDLED;
195 case TONE_STARTED_PLAYING:
196 // This shouldn't happen either, but perform the action anyway.
197 Log.w(LOG_TAG, "Tone started playing unexpectedly. Args are: \n"
198 + args.toString());
199 return HANDLED;
200 default:
201 // The forced focus switch commands are handled by BaseState.
202 return NOT_HANDLED;
203 }
204 }
205 }
206
207 private class RingingFocusState extends BaseState {
Jack Hed0c6cab2018-02-13 18:33:57 -0800208 private void tryStartRinging() {
Hall Liu6a5995e2016-09-08 16:00:14 -0700209 if (mCallAudioManager.startRinging()) {
210 mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
211 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
Hall Liu6a5995e2016-09-08 16:00:14 -0700212 mAudioManager.setMode(AudioManager.MODE_RINGTONE);
Jack Hed0c6cab2018-02-13 18:33:57 -0800213 mCallAudioManager.setCallAudioRouteFocusState(
214 CallAudioRouteStateMachine.RINGING_FOCUS);
Hall Liu6a5995e2016-09-08 16:00:14 -0700215 } else {
Jack Hed0c6cab2018-02-13 18:33:57 -0800216 Log.i(LOG_TAG, "RINGING state, try start ringing but not acquiring audio focus");
Hall Liue091ab92015-12-18 17:05:30 -0800217 }
Jack Hed0c6cab2018-02-13 18:33:57 -0800218 }
Hall Liue091ab92015-12-18 17:05:30 -0800219
Jack Hed0c6cab2018-02-13 18:33:57 -0800220 @Override
221 public void enter() {
222 Log.i(LOG_TAG, "Audio focus entering RINGING state");
223 tryStartRinging();
Hall Liufbed0162016-01-14 18:06:29 -0800224 mCallAudioManager.stopCallWaiting();
Hall Liue091ab92015-12-18 17:05:30 -0800225 }
226
227 @Override
228 public void exit() {
229 // Audio mode and audio stream will be set by the next state.
230 mCallAudioManager.stopRinging();
231 }
232
233 @Override
234 public boolean processMessage(Message msg) {
235 if (super.processMessage(msg) == HANDLED) {
236 return HANDLED;
237 }
238 MessageArgs args = (MessageArgs) msg.obj;
239 switch (msg.what) {
240 case NO_MORE_ACTIVE_OR_DIALING_CALLS:
241 // Do nothing. Loss of an active call should not impact ringer.
242 return HANDLED;
243 case NO_MORE_HOLDING_CALLS:
244 // Do nothing and keep ringing.
245 return HANDLED;
246 case NO_MORE_RINGING_CALLS:
247 // If there are active or holding calls, switch to the appropriate focus.
248 // Otherwise abandon focus.
Hall Liufbed0162016-01-14 18:06:29 -0800249 if (args.hasActiveOrDialingCalls) {
Hall Liue091ab92015-12-18 17:05:30 -0800250 if (args.foregroundCallIsVoip) {
251 transitionTo(mVoipCallFocusState);
252 } else {
253 transitionTo(mSimCallFocusState);
254 }
255 } else if (args.hasHoldingCalls || args.isTonePlaying) {
256 transitionTo(mOtherFocusState);
257 } else {
258 transitionTo(mUnfocusedState);
259 }
260 return HANDLED;
261 case NEW_ACTIVE_OR_DIALING_CALL:
262 // If a call becomes active suddenly, give it priority over ringing.
263 transitionTo(args.foregroundCallIsVoip
264 ? mVoipCallFocusState : mSimCallFocusState);
265 return HANDLED;
266 case NEW_RINGING_CALL:
267 Log.w(LOG_TAG, "Unexpected behavior! New ringing call appeared while in " +
268 "ringing state.");
269 return HANDLED;
270 case NEW_HOLDING_CALL:
271 // This really shouldn't happen, but transition to the focused state anyway.
272 Log.w(LOG_TAG, "Call was surprisingly put into hold while ringing." +
273 " Args are: " + args.toString());
274 transitionTo(mOtherFocusState);
275 return HANDLED;
276 case MT_AUDIO_SPEEDUP_FOR_RINGING_CALL:
277 // This happens when an IMS call is answered by the in-call UI. Special case
278 // that we have to deal with for some reason.
279
Jimmy Wu4c919d12017-05-29 23:37:18 +0800280 // The IMS audio routing may be via modem or via RTP stream. In case via RTP
281 // stream, the state machine should transit to mVoipCallFocusState.
282 transitionTo(args.foregroundCallIsVoip
283 ? mVoipCallFocusState : mSimCallFocusState);
Hall Liue091ab92015-12-18 17:05:30 -0800284 return HANDLED;
Jack Hed0c6cab2018-02-13 18:33:57 -0800285 case RINGER_MODE_CHANGE: {
286 Log.i(LOG_TAG, "RINGING state, received RINGER_MODE_CHANGE");
287 tryStartRinging();
288 return HANDLED;
289 }
Hall Liue091ab92015-12-18 17:05:30 -0800290 default:
291 // The forced focus switch commands are handled by BaseState.
292 return NOT_HANDLED;
293 }
294 }
295 }
296
297 private class SimCallFocusState extends BaseState {
298 @Override
299 public void enter() {
300 Log.i(LOG_TAG, "Audio focus entering SIM CALL state");
301 mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
302 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
303 mAudioManager.setMode(AudioManager.MODE_IN_CALL);
304 mMostRecentMode = AudioManager.MODE_IN_CALL;
Hall Liue271f222016-08-15 18:04:06 -0700305 mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS);
Hall Liue091ab92015-12-18 17:05:30 -0800306 }
307
308 @Override
309 public boolean processMessage(Message msg) {
310 if (super.processMessage(msg) == HANDLED) {
311 return HANDLED;
312 }
313 MessageArgs args = (MessageArgs) msg.obj;
314 switch (msg.what) {
315 case NO_MORE_ACTIVE_OR_DIALING_CALLS:
316 // Switch to either ringing, holding, or inactive
Hall Liufbed0162016-01-14 18:06:29 -0800317 transitionTo(destinationStateAfterNoMoreActiveCalls(args));
Hall Liue091ab92015-12-18 17:05:30 -0800318 return HANDLED;
319 case NO_MORE_RINGING_CALLS:
320 // Don't transition state, but stop any call-waiting tones that may have been
321 // playing.
Hall Liufbed0162016-01-14 18:06:29 -0800322 if (args.isTonePlaying) {
323 mCallAudioManager.stopCallWaiting();
324 }
Hall Liue792b332016-04-19 14:23:09 -0700325 // If a MT-audio-speedup call gets disconnected by the connection service
326 // concurrently with the user answering it, we may get this message
327 // indicating that a ringing call has disconnected while this state machine
328 // is in the SimCallFocusState.
329 if (!args.hasActiveOrDialingCalls) {
330 transitionTo(destinationStateAfterNoMoreActiveCalls(args));
331 }
Hall Liue091ab92015-12-18 17:05:30 -0800332 return HANDLED;
333 case NO_MORE_HOLDING_CALLS:
334 // Do nothing.
335 return HANDLED;
336 case NEW_ACTIVE_OR_DIALING_CALL:
337 // Do nothing. Already active.
338 return HANDLED;
339 case NEW_RINGING_CALL:
340 // Don't make a call ring over an active call, but do play a call waiting tone.
341 mCallAudioManager.startCallWaiting();
342 return HANDLED;
343 case NEW_HOLDING_CALL:
344 // Don't do anything now. Putting an active call on hold will be handled when
345 // NO_MORE_ACTIVE_CALLS is processed.
346 return HANDLED;
347 case FOREGROUND_VOIP_MODE_CHANGE:
348 if (args.foregroundCallIsVoip) {
349 transitionTo(mVoipCallFocusState);
350 }
351 return HANDLED;
352 default:
353 // The forced focus switch commands are handled by BaseState.
354 return NOT_HANDLED;
355 }
356 }
357 }
358
359 private class VoipCallFocusState extends BaseState {
360 @Override
361 public void enter() {
362 Log.i(LOG_TAG, "Audio focus entering VOIP CALL state");
363 mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
364 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
365 mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
366 mMostRecentMode = AudioManager.MODE_IN_COMMUNICATION;
Hall Liue271f222016-08-15 18:04:06 -0700367 mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS);
Hall Liue091ab92015-12-18 17:05:30 -0800368 }
369
370 @Override
371 public boolean processMessage(Message msg) {
372 if (super.processMessage(msg) == HANDLED) {
373 return HANDLED;
374 }
375 MessageArgs args = (MessageArgs) msg.obj;
376 switch (msg.what) {
377 case NO_MORE_ACTIVE_OR_DIALING_CALLS:
378 // Switch to either ringing, holding, or inactive
Hall Liufbed0162016-01-14 18:06:29 -0800379 transitionTo(destinationStateAfterNoMoreActiveCalls(args));
Hall Liue091ab92015-12-18 17:05:30 -0800380 return HANDLED;
381 case NO_MORE_RINGING_CALLS:
382 // Don't transition state, but stop any call-waiting tones that may have been
383 // playing.
Hall Liufbed0162016-01-14 18:06:29 -0800384 if (args.isTonePlaying) {
385 mCallAudioManager.stopCallWaiting();
386 }
Hall Liue091ab92015-12-18 17:05:30 -0800387 return HANDLED;
388 case NO_MORE_HOLDING_CALLS:
389 // Do nothing.
390 return HANDLED;
391 case NEW_ACTIVE_OR_DIALING_CALL:
392 // Do nothing. Already active.
393 return HANDLED;
394 case NEW_RINGING_CALL:
395 // Don't make a call ring over an active call, but do play a call waiting tone.
396 mCallAudioManager.startCallWaiting();
397 return HANDLED;
398 case NEW_HOLDING_CALL:
399 // Don't do anything now. Putting an active call on hold will be handled when
400 // NO_MORE_ACTIVE_CALLS is processed.
401 return HANDLED;
402 case FOREGROUND_VOIP_MODE_CHANGE:
403 if (!args.foregroundCallIsVoip) {
404 transitionTo(mSimCallFocusState);
405 }
406 return HANDLED;
407 default:
408 // The forced focus switch commands are handled by BaseState.
409 return NOT_HANDLED;
410 }
411 }
412 }
413
414 /**
415 * This class is used for calls on hold and end-of-call tones.
416 */
417 private class OtherFocusState extends BaseState {
418 @Override
419 public void enter() {
420 Log.i(LOG_TAG, "Audio focus entering TONE/HOLDING state");
421 mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
422 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
423 mAudioManager.setMode(mMostRecentMode);
Hall Liue271f222016-08-15 18:04:06 -0700424 mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS);
Hall Liue091ab92015-12-18 17:05:30 -0800425 }
426
427 @Override
428 public boolean processMessage(Message msg) {
429 if (super.processMessage(msg) == HANDLED) {
430 return HANDLED;
431 }
432 MessageArgs args = (MessageArgs) msg.obj;
433 switch (msg.what) {
434 case NO_MORE_HOLDING_CALLS:
Hall Liufbed0162016-01-14 18:06:29 -0800435 if (args.hasActiveOrDialingCalls) {
Hall Liue091ab92015-12-18 17:05:30 -0800436 transitionTo(args.foregroundCallIsVoip
437 ? mVoipCallFocusState : mSimCallFocusState);
438 } else if (args.hasRingingCalls) {
439 transitionTo(mRingingFocusState);
440 } else if (!args.isTonePlaying) {
441 transitionTo(mUnfocusedState);
442 }
443 // Do nothing if a tone is playing.
444 return HANDLED;
445 case NEW_ACTIVE_OR_DIALING_CALL:
446 transitionTo(args.foregroundCallIsVoip
447 ? mVoipCallFocusState : mSimCallFocusState);
448 return HANDLED;
449 case NEW_RINGING_CALL:
450 // Apparently this is current behavior. Should this be the case?
451 transitionTo(mRingingFocusState);
452 return HANDLED;
453 case NEW_HOLDING_CALL:
454 // Do nothing.
455 return HANDLED;
456 case NO_MORE_RINGING_CALLS:
457 // If there are no more ringing calls in this state, then stop any call-waiting
458 // tones that may be playing.
459 mCallAudioManager.stopCallWaiting();
460 return HANDLED;
461 case TONE_STOPPED_PLAYING:
Hall Liu6a11ed72016-03-30 17:09:22 -0700462 transitionTo(destinationStateAfterNoMoreActiveCalls(args));
Hall Liue091ab92015-12-18 17:05:30 -0800463 default:
464 return NOT_HANDLED;
465 }
466 }
467 }
468
469 private static final String LOG_TAG = CallAudioModeStateMachine.class.getSimpleName();
470
Hall Liufbed0162016-01-14 18:06:29 -0800471 private final BaseState mUnfocusedState = new UnfocusedState();
472 private final BaseState mRingingFocusState = new RingingFocusState();
473 private final BaseState mSimCallFocusState = new SimCallFocusState();
474 private final BaseState mVoipCallFocusState = new VoipCallFocusState();
475 private final BaseState mOtherFocusState = new OtherFocusState();
Hall Liue091ab92015-12-18 17:05:30 -0800476
Hall Liue091ab92015-12-18 17:05:30 -0800477 private final AudioManager mAudioManager;
478 private CallAudioManager mCallAudioManager;
479
480 private int mMostRecentMode;
481 private boolean mIsInitialized = false;
482
Hall Liufbed0162016-01-14 18:06:29 -0800483 public CallAudioModeStateMachine(AudioManager audioManager) {
Hall Liue091ab92015-12-18 17:05:30 -0800484 super(CallAudioModeStateMachine.class.getSimpleName());
Hall Liufbed0162016-01-14 18:06:29 -0800485 mAudioManager = audioManager;
Hall Liue091ab92015-12-18 17:05:30 -0800486 mMostRecentMode = AudioManager.MODE_NORMAL;
487
488 addState(mUnfocusedState);
489 addState(mRingingFocusState);
490 addState(mSimCallFocusState);
491 addState(mVoipCallFocusState);
492 addState(mOtherFocusState);
493 setInitialState(mUnfocusedState);
494 start();
Brad Ebinger83bc4112016-04-01 15:30:14 -0700495 sendMessage(INITIALIZE, new MessageArgs());
Hall Liue091ab92015-12-18 17:05:30 -0800496 }
497
498 public void setCallAudioManager(CallAudioManager callAudioManager) {
499 mCallAudioManager = callAudioManager;
500 }
501
Hall Liufbed0162016-01-14 18:06:29 -0800502 public String getCurrentStateName() {
503 IState currentState = getCurrentState();
504 return currentState == null ? "no state" : currentState.getName();
505 }
506
Hall Liue792b332016-04-19 14:23:09 -0700507 public void sendMessageWithArgs(int messageCode, MessageArgs args) {
508 sendMessage(messageCode, args);
509 }
510
Hall Liue091ab92015-12-18 17:05:30 -0800511 @Override
512 protected void onPreHandleMessage(Message msg) {
513 if (msg.obj != null && msg.obj instanceof MessageArgs) {
514 Log.continueSession(((MessageArgs) msg.obj).session, "CAMSM.pM_" + msg.what);
515 Log.i(LOG_TAG, "Message received: %s.", MESSAGE_CODE_TO_NAME.get(msg.what));
Hall Liufbed0162016-01-14 18:06:29 -0800516 } else if (msg.what == RUN_RUNNABLE && msg.obj instanceof Runnable) {
517 Log.i(LOG_TAG, "Running runnable for testing");
Hall Liue091ab92015-12-18 17:05:30 -0800518 } else {
Hall Liufbed0162016-01-14 18:06:29 -0800519 Log.w(LOG_TAG, "Message sent must be of type nonnull MessageArgs, but got " +
520 (msg.obj == null ? "null" : msg.obj.getClass().getSimpleName()));
521 Log.w(LOG_TAG, "The message was of code %d = %s",
522 msg.what, MESSAGE_CODE_TO_NAME.get(msg.what));
Hall Liue091ab92015-12-18 17:05:30 -0800523 }
524 }
525
Hall Liua51c99f2017-03-13 16:39:26 -0700526 public void dumpPendingMessages(IndentingPrintWriter pw) {
527 getHandler().getLooper().dump(pw::println, "");
528 }
529
Hall Liue091ab92015-12-18 17:05:30 -0800530 @Override
531 protected void onPostHandleMessage(Message msg) {
532 Log.endSession();
533 }
534
Hall Liufbed0162016-01-14 18:06:29 -0800535 private BaseState destinationStateAfterNoMoreActiveCalls(MessageArgs args) {
Hall Liu6a11ed72016-03-30 17:09:22 -0700536 if (args.hasHoldingCalls) {
537 return mOtherFocusState;
538 } else if (args.hasRingingCalls) {
539 return mRingingFocusState;
540 } else if (args.isTonePlaying) {
541 return mOtherFocusState;
Hall Liufbed0162016-01-14 18:06:29 -0800542 } else {
Hall Liu6a11ed72016-03-30 17:09:22 -0700543 return mUnfocusedState;
Hall Liufbed0162016-01-14 18:06:29 -0800544 }
Hall Liue091ab92015-12-18 17:05:30 -0800545 }
Hall Liu2cc27432016-10-31 14:00:16 -0700546}