summaryrefslogtreecommitdiff
path: root/src/com/android/server/telecom/CallAudioModeStateMachine.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/server/telecom/CallAudioModeStateMachine.java')
-rw-r--r--src/com/android/server/telecom/CallAudioModeStateMachine.java171
1 files changed, 143 insertions, 28 deletions
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index a1c5f4bdd..9ad9094ef 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -19,12 +19,12 @@ package com.android.server.telecom;
import android.media.AudioManager;
import android.os.Looper;
import android.os.Message;
+import android.os.Trace;
import android.telecom.Log;
import android.telecom.Logging.Runnable;
import android.telecom.Logging.Session;
import android.util.LocalLog;
import android.util.SparseArray;
-
import com.android.internal.util.IState;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.State;
@@ -50,17 +50,19 @@ public class CallAudioModeStateMachine extends StateMachine {
public boolean hasAudioProcessingCalls;
public boolean isTonePlaying;
public boolean foregroundCallIsVoip;
+ public boolean isStreaming;
public Session session;
private MessageArgs(boolean hasActiveOrDialingCalls, boolean hasRingingCalls,
boolean hasHoldingCalls, boolean hasAudioProcessingCalls, boolean isTonePlaying,
- boolean foregroundCallIsVoip, Session session) {
+ boolean foregroundCallIsVoip, boolean isStreaming, Session session) {
this.hasActiveOrDialingCalls = hasActiveOrDialingCalls;
this.hasRingingCalls = hasRingingCalls;
this.hasHoldingCalls = hasHoldingCalls;
this.hasAudioProcessingCalls = hasAudioProcessingCalls;
this.isTonePlaying = isTonePlaying;
this.foregroundCallIsVoip = foregroundCallIsVoip;
+ this.isStreaming = isStreaming;
this.session = session;
}
@@ -73,6 +75,7 @@ public class CallAudioModeStateMachine extends StateMachine {
", hasAudioProcessingCalls=" + hasAudioProcessingCalls +
", isTonePlaying=" + isTonePlaying +
", foregroundCallIsVoip=" + foregroundCallIsVoip +
+ ", isStreaming=" + isStreaming +
", session=" + session +
'}';
}
@@ -84,6 +87,7 @@ public class CallAudioModeStateMachine extends StateMachine {
private boolean mHasAudioProcessingCalls;
private boolean mIsTonePlaying;
private boolean mForegroundCallIsVoip;
+ private boolean mIsStreaming;
private Session mSession;
public Builder setHasActiveOrDialingCalls(boolean hasActiveOrDialingCalls) {
@@ -121,9 +125,15 @@ public class CallAudioModeStateMachine extends StateMachine {
return this;
}
+ public Builder setIsStreaming(boolean isStraeming) {
+ mIsStreaming = isStraeming;
+ return this;
+ }
+
public MessageArgs build() {
return new MessageArgs(mHasActiveOrDialingCalls, mHasRingingCalls, mHasHoldingCalls,
- mHasAudioProcessingCalls, mIsTonePlaying, mForegroundCallIsVoip, mSession);
+ mHasAudioProcessingCalls, mIsTonePlaying, mForegroundCallIsVoip,
+ mIsStreaming, mSession);
}
}
}
@@ -138,7 +148,8 @@ public class CallAudioModeStateMachine extends StateMachine {
public static final int ENTER_RING_FOCUS_FOR_TESTING = 4;
public static final int ENTER_TONE_OR_HOLD_FOCUS_FOR_TESTING = 5;
public static final int ENTER_AUDIO_PROCESSING_FOCUS_FOR_TESTING = 6;
- public static final int ABANDON_FOCUS_FOR_TESTING = 7;
+ public static final int ENTER_STREAMING_FOCUS_FOR_TESTING = 7;
+ public static final int ABANDON_FOCUS_FOR_TESTING = 8;
public static final int NO_MORE_ACTIVE_OR_DIALING_CALLS = 1001;
public static final int NO_MORE_RINGING_CALLS = 1002;
@@ -161,6 +172,9 @@ public class CallAudioModeStateMachine extends StateMachine {
// to release focus for other apps to take over.
public static final int AUDIO_OPERATIONS_COMPLETE = 6001;
+ public static final int START_CALL_STREAMING = 7001;
+ public static final int STOP_CALL_STREAMING = 7002;
+
public static final int RUN_RUNNABLE = 9001;
private static final SparseArray<String> MESSAGE_CODE_TO_NAME = new SparseArray<String>() {{
@@ -183,6 +197,8 @@ public class CallAudioModeStateMachine extends StateMachine {
put(FOREGROUND_VOIP_MODE_CHANGE, "FOREGROUND_VOIP_MODE_CHANGE");
put(RINGER_MODE_CHANGE, "RINGER_MODE_CHANGE");
put(AUDIO_OPERATIONS_COMPLETE, "AUDIO_OPERATIONS_COMPLETE");
+ put(START_CALL_STREAMING, "START_CALL_STREAMING");
+ put(STOP_CALL_STREAMING, "STOP_CALL_STREAMING");
put(RUN_RUNNABLE, "RUN_RUNNABLE");
}};
@@ -193,6 +209,7 @@ public class CallAudioModeStateMachine extends StateMachine {
AudioProcessingFocusState.class.getSimpleName();
public static final String CALL_STATE_NAME = SimCallFocusState.class.getSimpleName();
public static final String RING_STATE_NAME = RingingFocusState.class.getSimpleName();
+ public static final String STREAMING_STATE_NAME = StreamingFocusState.class.getSimpleName();
public static final String COMMS_STATE_NAME = VoipCallFocusState.class.getSimpleName();
private class BaseState extends State {
@@ -214,6 +231,9 @@ public class CallAudioModeStateMachine extends StateMachine {
case ENTER_AUDIO_PROCESSING_FOCUS_FOR_TESTING:
transitionTo(mAudioProcessingFocusState);
return HANDLED;
+ case ENTER_STREAMING_FOCUS_FOR_TESTING:
+ transitionTo(mStreamingFocusState);
+ return HANDLED;
case ABANDON_FOCUS_FOR_TESTING:
transitionTo(mUnfocusedState);
return HANDLED;
@@ -280,6 +300,9 @@ public class CallAudioModeStateMachine extends StateMachine {
" Args are: \n" + args.toString());
transitionTo(mOtherFocusState);
return HANDLED;
+ case START_CALL_STREAMING:
+ transitionTo(mStreamingFocusState);
+ return HANDLED;
case TONE_STARTED_PLAYING:
// This shouldn't happen either, but perform the action anyway.
Log.w(LOG_TAG, "Tone started playing unexpectedly. Args are: \n"
@@ -353,6 +376,9 @@ public class CallAudioModeStateMachine extends StateMachine {
Log.w(LOG_TAG, "Tone started playing unexpectedly. Args are: \n"
+ args.toString());
return HANDLED;
+ case START_CALL_STREAMING:
+ transitionTo(mStreamingFocusState);
+ return HANDLED;
case AUDIO_OPERATIONS_COMPLETE:
Log.i(LOG_TAG, "Abandoning audio focus: now AUDIO_PROCESSING");
mAudioManager.abandonAudioFocusForCall();
@@ -370,26 +396,33 @@ public class CallAudioModeStateMachine extends StateMachine {
private boolean mHasFocus = false;
private void tryStartRinging() {
- if (mHasFocus && mCallAudioManager.isRingtonePlaying()) {
- Log.i(LOG_TAG, "RingingFocusState#tryStartRinging -- audio focus previously"
- + " acquired and ringtone already playing -- skipping.");
- return;
- }
-
- if (mCallAudioManager.startRinging()) {
- mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
- // Do not set MODE_RINGTONE if we were previously in the CALL_SCREENING mode -- this
- // trips up the audio system.
- if (mAudioManager.getMode() != AudioManager.MODE_CALL_SCREENING) {
- mAudioManager.setMode(AudioManager.MODE_RINGTONE);
- mLocalLog.log("Mode MODE_RINGTONE");
+ Trace.traceBegin(Trace.TRACE_TAG_AUDIO, "CallAudioMode.tryStartRinging");
+ try {
+ if (mHasFocus && mCallAudioManager.isRingtonePlaying()) {
+ Log.i(LOG_TAG,
+ "RingingFocusState#tryStartRinging -- audio focus previously"
+ + " acquired and ringtone already playing -- skipping.");
+ return;
}
- mCallAudioManager.setCallAudioRouteFocusState(
+
+ if (mCallAudioManager.startRinging()) {
+ mAudioManager.requestAudioFocusForCall(
+ AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ // Do not set MODE_RINGTONE if we were previously in the CALL_SCREENING mode --
+ // this trips up the audio system.
+ if (mAudioManager.getMode() != AudioManager.MODE_CALL_SCREENING) {
+ mAudioManager.setMode(AudioManager.MODE_RINGTONE);
+ mLocalLog.log("Mode MODE_RINGTONE");
+ }
+ mCallAudioManager.setCallAudioRouteFocusState(
CallAudioRouteStateMachine.RINGING_FOCUS);
- mHasFocus = true;
- } else {
- Log.i(LOG_TAG, "RINGING state, try start ringing but not acquiring audio focus");
+ mHasFocus = true;
+ } else {
+ Log.i(
+ LOG_TAG, "RINGING state, try start ringing but not acquiring audio focus");
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_AUDIO);
}
}
@@ -618,6 +651,82 @@ public class CallAudioModeStateMachine extends StateMachine {
Log.w(LOG_TAG, "Should not be seeing AUDIO_OPERATIONS_COMPLETE in a focused"
+ " state");
return HANDLED;
+ case START_CALL_STREAMING:
+ transitionTo(mStreamingFocusState);
+ return HANDLED;
+ default:
+ // The forced focus switch commands are handled by BaseState.
+ return NOT_HANDLED;
+ }
+ }
+ }
+
+ private class StreamingFocusState extends BaseState {
+ @Override
+ public void enter() {
+ Log.i(LOG_TAG, "Audio focus entering streaming state");
+ mLocalLog.log("Enter Streaming");
+ mLocalLog.log("Mode MODE_COMMUNICATION_REDIRECT");
+ mAudioManager.setMode(AudioManager.MODE_COMMUNICATION_REDIRECT);
+ mMostRecentMode = AudioManager.MODE_NORMAL;
+ mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS);
+ mCallAudioManager.getCallAudioRouteStateMachine().sendMessageWithSessionInfo(
+ CallAudioRouteStateMachine.STREAMING_FORCE_ENABLED);
+ }
+
+ private void preExit() {
+ mCallAudioManager.getCallAudioRouteStateMachine().sendMessageWithSessionInfo(
+ CallAudioRouteStateMachine.STREAMING_FORCE_DISABLED);
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (super.processMessage(msg) == HANDLED) {
+ return HANDLED;
+ }
+ MessageArgs args = (MessageArgs) msg.obj;
+ switch (msg.what) {
+ case NO_MORE_ACTIVE_OR_DIALING_CALLS:
+ // Switch to either ringing, holding, or inactive
+ transitionTo(calculateProperStateFromArgs(args));
+ return HANDLED;
+ case NO_MORE_RINGING_CALLS:
+ // Do nothing.
+ return HANDLED;
+ case NO_MORE_HOLDING_CALLS:
+ // Do nothing.
+ return HANDLED;
+ case NO_MORE_AUDIO_PROCESSING_CALLS:
+ // Do nothing.
+ return HANDLED;
+ case NEW_ACTIVE_OR_DIALING_CALL:
+ // Only possible for emergency call
+ BaseState destState = calculateProperStateFromArgs(args);
+ if (destState != this) {
+ preExit();
+ transitionTo(destState);
+ }
+ return HANDLED;
+ case NEW_RINGING_CALL:
+ // Only possible for emergency call
+ preExit();
+ transitionTo(mRingingFocusState);
+ return HANDLED;
+ case NEW_HOLDING_CALL:
+ // Do nothing.
+ return HANDLED;
+ case NEW_AUDIO_PROCESSING_CALL:
+ // Do nothing.
+ return HANDLED;
+ case START_CALL_STREAMING:
+ // Can happen as a duplicate message
+ return HANDLED;
+ case TONE_STARTED_PLAYING:
+ // Do nothing.
+ return HANDLED;
+ case STOP_CALL_STREAMING:
+ transitionTo(calculateProperStateFromArgs(args));
+ return HANDLED;
default:
// The forced focus switch commands are handled by BaseState.
return NOT_HANDLED;
@@ -700,6 +809,7 @@ public class CallAudioModeStateMachine extends StateMachine {
private final BaseState mSimCallFocusState = new SimCallFocusState();
private final BaseState mVoipCallFocusState = new VoipCallFocusState();
private final BaseState mAudioProcessingFocusState = new AudioProcessingFocusState();
+ private final BaseState mStreamingFocusState = new StreamingFocusState();
private final BaseState mOtherFocusState = new OtherFocusState();
private final AudioManager mAudioManager;
@@ -738,6 +848,7 @@ public class CallAudioModeStateMachine extends StateMachine {
addState(mSimCallFocusState);
addState(mVoipCallFocusState);
addState(mAudioProcessingFocusState);
+ addState(mStreamingFocusState);
addState(mOtherFocusState);
setInitialState(mUnfocusedState);
start();
@@ -747,6 +858,7 @@ public class CallAudioModeStateMachine extends StateMachine {
.setHasHoldingCalls(false)
.setIsTonePlaying(false)
.setForegroundCallIsVoip(false)
+ .setIsStreaming(false)
.setSession(Log.createSubsession())
.build());
}
@@ -800,12 +912,15 @@ public class CallAudioModeStateMachine extends StateMachine {
// switch to the appropriate focus.
// Otherwise abandon focus.
- // The order matters here. If there are active calls, holding focus for them takes priority.
- // After that, we want to prioritize holding calls over ringing calls so that when a
- // call-waiting call gets answered, there's no transition in and out of the ringing focus
- // state. After that, we want tones since we actually hold focus during them, then the
- // audio processing state because that will release focus.
- if (args.hasActiveOrDialingCalls) {
+ // The order matters here. If there is streaming call, holding streaming route for them
+ // takes priority. After that, holding focus for active calls takes priority. After that, we
+ // want to prioritize holding calls over ringing calls so that when a call-waiting call gets
+ // answered, there's no transition in and out of the ringing focus state. After that, we
+ // want tones since we actually hold focus during them, then the audio processing state
+ // because that will release focus.
+ if (args.isStreaming) {
+ return mSimCallFocusState;
+ } else if (args.hasActiveOrDialingCalls) {
if (args.foregroundCallIsVoip) {
return mVoipCallFocusState;
} else {