1e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu/* 2e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * Copyright (C) 2015 The Android Open Source Project 3e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * 4e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * Licensed under the Apache License, Version 2.0 (the "License"); 5e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * you may not use this file except in compliance with the License. 6e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * You may obtain a copy of the License at 7e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * 8e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * http://www.apache.org/licenses/LICENSE-2.0 9e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * 10e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * Unless required by applicable law or agreed to in writing, software 11e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * distributed under the License is distributed on an "AS IS" BASIS, 12e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * See the License for the specific language governing permissions and 14e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * limitations under the License 15e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu */ 16e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 17e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liupackage com.android.server.telecom; 18e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 19e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liuimport android.media.AudioManager; 20e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liuimport android.os.Message; 21e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liuimport android.util.SparseArray; 22e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 23fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liuimport com.android.internal.util.IState; 24e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liuimport com.android.internal.util.State; 25e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liuimport com.android.internal.util.StateMachine; 26e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 27e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liupublic class CallAudioModeStateMachine extends StateMachine { 28e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static class MessageArgs { 29fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public boolean hasActiveOrDialingCalls; 30e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public boolean hasRingingCalls; 31e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public boolean hasHoldingCalls; 32e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public boolean isTonePlaying; 33e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public boolean foregroundCallIsVoip; 34e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public Session session; 35e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 36fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public MessageArgs(boolean hasActiveOrDialingCalls, boolean hasRingingCalls, 37fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu boolean hasHoldingCalls, boolean isTonePlaying, boolean foregroundCallIsVoip, 38fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu Session session) { 39fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu this.hasActiveOrDialingCalls = hasActiveOrDialingCalls; 40e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu this.hasRingingCalls = hasRingingCalls; 41e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu this.hasHoldingCalls = hasHoldingCalls; 42e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu this.isTonePlaying = isTonePlaying; 43e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu this.foregroundCallIsVoip = foregroundCallIsVoip; 44e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu this.session = session; 45e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 46e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 4783bc41189494799f48c50a5a0c47560d2859dedaBrad Ebinger public MessageArgs() { 4883bc41189494799f48c50a5a0c47560d2859dedaBrad Ebinger this.session = Log.createSubsession(); 4983bc41189494799f48c50a5a0c47560d2859dedaBrad Ebinger } 5083bc41189494799f48c50a5a0c47560d2859dedaBrad Ebinger 51e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 52e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public String toString() { 53e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return "MessageArgs{" + 54fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu "hasActiveCalls=" + hasActiveOrDialingCalls + 55e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu ", hasRingingCalls=" + hasRingingCalls + 56e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu ", hasHoldingCalls=" + hasHoldingCalls + 57e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu ", isTonePlaying=" + isTonePlaying + 58e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu ", foregroundCallIsVoip=" + foregroundCallIsVoip + 59e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu ", session=" + session + 60e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu '}'; 61e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 62e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 63e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 64e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int INITIALIZE = 1; 65e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // These ENTER_*_FOCUS commands are for testing. 66e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int ENTER_CALL_FOCUS_FOR_TESTING = 2; 67e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int ENTER_COMMS_FOCUS_FOR_TESTING = 3; 68e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int ENTER_RING_FOCUS_FOR_TESTING = 4; 69fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public static final int ENTER_TONE_OR_HOLD_FOCUS_FOR_TESTING = 5; 70fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public static final int ABANDON_FOCUS_FOR_TESTING = 6; 71e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 72e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int NO_MORE_ACTIVE_OR_DIALING_CALLS = 1001; 73e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int NO_MORE_RINGING_CALLS = 1002; 74e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int NO_MORE_HOLDING_CALLS = 1003; 75e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 76e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int NEW_ACTIVE_OR_DIALING_CALL = 2001; 77e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int NEW_RINGING_CALL = 2002; 78e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int NEW_HOLDING_CALL = 2003; 79e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int MT_AUDIO_SPEEDUP_FOR_RINGING_CALL = 2004; 80e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 81e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int TONE_STARTED_PLAYING = 3001; 82e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int TONE_STOPPED_PLAYING = 3002; 83e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 84e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public static final int FOREGROUND_VOIP_MODE_CHANGE = 4001; 85e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 86fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public static final int RUN_RUNNABLE = 9001; 87fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu 88e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private static final SparseArray<String> MESSAGE_CODE_TO_NAME = new SparseArray<String>() {{ 89e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(ENTER_CALL_FOCUS_FOR_TESTING, "ENTER_CALL_FOCUS_FOR_TESTING"); 90e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(ENTER_COMMS_FOCUS_FOR_TESTING, "ENTER_COMMS_FOCUS_FOR_TESTING"); 91e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(ENTER_RING_FOCUS_FOR_TESTING, "ENTER_RING_FOCUS_FOR_TESTING"); 92fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu put(ENTER_TONE_OR_HOLD_FOCUS_FOR_TESTING, "ENTER_TONE_OR_HOLD_FOCUS_FOR_TESTING"); 93e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(ABANDON_FOCUS_FOR_TESTING, "ABANDON_FOCUS_FOR_TESTING"); 94e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(NO_MORE_ACTIVE_OR_DIALING_CALLS, "NO_MORE_ACTIVE_OR_DIALING_CALLS"); 95e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(NO_MORE_RINGING_CALLS, "NO_MORE_RINGING_CALLS"); 96e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(NO_MORE_HOLDING_CALLS, "NO_MORE_HOLDING_CALLS"); 97e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(NEW_ACTIVE_OR_DIALING_CALL, "NEW_ACTIVE_OR_DIALING_CALL"); 98e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(NEW_RINGING_CALL, "NEW_RINGING_CALL"); 99e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(NEW_HOLDING_CALL, "NEW_HOLDING_CALL"); 100e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(MT_AUDIO_SPEEDUP_FOR_RINGING_CALL, "MT_AUDIO_SPEEDUP_FOR_RINGING_CALL"); 101e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(TONE_STARTED_PLAYING, "TONE_STARTED_PLAYING"); 102e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(TONE_STOPPED_PLAYING, "TONE_STOPPED_PLAYING"); 103e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu put(FOREGROUND_VOIP_MODE_CHANGE, "FOREGROUND_VOIP_MODE_CHANGE"); 104fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu 105fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu put(RUN_RUNNABLE, "RUN_RUNNABLE"); 106e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu }}; 107e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 108fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public static final String TONE_HOLD_STATE_NAME = OtherFocusState.class.getSimpleName(); 109fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public static final String UNFOCUSED_STATE_NAME = UnfocusedState.class.getSimpleName(); 110fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public static final String CALL_STATE_NAME = SimCallFocusState.class.getSimpleName(); 111fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public static final String RING_STATE_NAME = RingingFocusState.class.getSimpleName(); 112fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public static final String COMMS_STATE_NAME = VoipCallFocusState.class.getSimpleName(); 113fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu 114e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private class BaseState extends State { 115e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 116e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public boolean processMessage(Message msg) { 117e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu switch (msg.what) { 118e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case ENTER_CALL_FOCUS_FOR_TESTING: 119e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mSimCallFocusState); 120e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 121e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case ENTER_COMMS_FOCUS_FOR_TESTING: 122e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mVoipCallFocusState); 123e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 124e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case ENTER_RING_FOCUS_FOR_TESTING: 125e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mRingingFocusState); 126e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 127fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu case ENTER_TONE_OR_HOLD_FOCUS_FOR_TESTING: 128fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu transitionTo(mOtherFocusState); 129fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu return HANDLED; 130e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case ABANDON_FOCUS_FOR_TESTING: 131e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mUnfocusedState); 132e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 133e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case INITIALIZE: 134e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mIsInitialized = true; 135e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 136fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu case RUN_RUNNABLE: 137e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger java.lang.Runnable r = (java.lang.Runnable) msg.obj; 138fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu r.run(); 139fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu return HANDLED; 140e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu default: 141e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return NOT_HANDLED; 142e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 143e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 144e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 145e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 146e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private class UnfocusedState extends BaseState { 147e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 148e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public void enter() { 149e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu if (mIsInitialized) { 150e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.i(LOG_TAG, "Abandoning audio focus: now UNFOCUSED"); 151e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mAudioManager.abandonAudioFocusForCall(); 152e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mAudioManager.setMode(AudioManager.MODE_NORMAL); 153e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 154e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mMostRecentMode = AudioManager.MODE_NORMAL; 155e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.NO_FOCUS); 156e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 157e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 158e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 159e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 160e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public boolean processMessage(Message msg) { 161e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu if (super.processMessage(msg) == HANDLED) { 162e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 163e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 164e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu MessageArgs args = (MessageArgs) msg.obj; 165e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu switch (msg.what) { 166e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_ACTIVE_OR_DIALING_CALLS: 167e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Do nothing. 168e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 169e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_RINGING_CALLS: 170e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Do nothing. 171e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 172e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_HOLDING_CALLS: 173e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Do nothing. 174e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 175e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_ACTIVE_OR_DIALING_CALL: 176e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(args.foregroundCallIsVoip 177e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu ? mVoipCallFocusState : mSimCallFocusState); 178e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 179e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_RINGING_CALL: 180e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mRingingFocusState); 181e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 182e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_HOLDING_CALL: 183e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // This really shouldn't happen, but transition to the focused state anyway. 184e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.w(LOG_TAG, "Call was surprisingly put into hold from an unknown state." + 185e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu " Args are: \n" + args.toString()); 186e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mOtherFocusState); 187e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 188e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case TONE_STARTED_PLAYING: 189e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // This shouldn't happen either, but perform the action anyway. 190e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.w(LOG_TAG, "Tone started playing unexpectedly. Args are: \n" 191e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu + args.toString()); 192e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 193e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu default: 194e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // The forced focus switch commands are handled by BaseState. 195e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return NOT_HANDLED; 196e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 197e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 198e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 199e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 200e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private class RingingFocusState extends BaseState { 201e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 202e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public void enter() { 203e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.i(LOG_TAG, "Audio focus entering RINGING state"); 204e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_RING, 205e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 206e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu if (mMostRecentMode == AudioManager.MODE_IN_CALL) { 207e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Preserving behavior from the old CallAudioManager. 208e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.i(LOG_TAG, "Transition from IN_CALL -> RINGTONE." 209e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu + " Resetting to NORMAL first."); 210e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mAudioManager.setMode(AudioManager.MODE_NORMAL); 211e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 212e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mAudioManager.setMode(AudioManager.MODE_RINGTONE); 213e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 214fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu mCallAudioManager.stopCallWaiting(); 215e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager.startRinging(); 216e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS); 217e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 218e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 219e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 220e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public void exit() { 221e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Audio mode and audio stream will be set by the next state. 222e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager.stopRinging(); 223e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 224e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 225e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 226e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public boolean processMessage(Message msg) { 227e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu if (super.processMessage(msg) == HANDLED) { 228e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 229e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 230e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu MessageArgs args = (MessageArgs) msg.obj; 231e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu switch (msg.what) { 232e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_ACTIVE_OR_DIALING_CALLS: 233e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Do nothing. Loss of an active call should not impact ringer. 234e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 235e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_HOLDING_CALLS: 236e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Do nothing and keep ringing. 237e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 238e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_RINGING_CALLS: 239e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // If there are active or holding calls, switch to the appropriate focus. 240e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Otherwise abandon focus. 241fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu if (args.hasActiveOrDialingCalls) { 242e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu if (args.foregroundCallIsVoip) { 243e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mVoipCallFocusState); 244e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } else { 245e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mSimCallFocusState); 246e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 247e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } else if (args.hasHoldingCalls || args.isTonePlaying) { 248e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mOtherFocusState); 249e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } else { 250e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mUnfocusedState); 251e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 252e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 253e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_ACTIVE_OR_DIALING_CALL: 254e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // If a call becomes active suddenly, give it priority over ringing. 255e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(args.foregroundCallIsVoip 256e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu ? mVoipCallFocusState : mSimCallFocusState); 257e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 258e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_RINGING_CALL: 259e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.w(LOG_TAG, "Unexpected behavior! New ringing call appeared while in " + 260e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu "ringing state."); 261e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 262e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_HOLDING_CALL: 263e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // This really shouldn't happen, but transition to the focused state anyway. 264e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.w(LOG_TAG, "Call was surprisingly put into hold while ringing." + 265e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu " Args are: " + args.toString()); 266e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mOtherFocusState); 267e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 268e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case MT_AUDIO_SPEEDUP_FOR_RINGING_CALL: 269e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // This happens when an IMS call is answered by the in-call UI. Special case 270e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // that we have to deal with for some reason. 271e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 272e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // VOIP calls should never invoke this mechanism, so transition directly to 273e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // the sim call focus state. 274e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mSimCallFocusState); 275e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 276e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu default: 277e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // The forced focus switch commands are handled by BaseState. 278e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return NOT_HANDLED; 279e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 280e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 281e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 282e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 283e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private class SimCallFocusState extends BaseState { 284e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 285e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public void enter() { 286e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.i(LOG_TAG, "Audio focus entering SIM CALL state"); 287e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, 288e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 289e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mAudioManager.setMode(AudioManager.MODE_IN_CALL); 290e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mMostRecentMode = AudioManager.MODE_IN_CALL; 291e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS); 292e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 293e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 294e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 295e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public boolean processMessage(Message msg) { 296e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu if (super.processMessage(msg) == HANDLED) { 297e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 298e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 299e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu MessageArgs args = (MessageArgs) msg.obj; 300e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu switch (msg.what) { 301e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_ACTIVE_OR_DIALING_CALLS: 302e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Switch to either ringing, holding, or inactive 303fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu transitionTo(destinationStateAfterNoMoreActiveCalls(args)); 304e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 305e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_RINGING_CALLS: 306e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Don't transition state, but stop any call-waiting tones that may have been 307e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // playing. 308fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu if (args.isTonePlaying) { 309fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu mCallAudioManager.stopCallWaiting(); 310fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu } 311e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liu // If a MT-audio-speedup call gets disconnected by the connection service 312e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liu // concurrently with the user answering it, we may get this message 313e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liu // indicating that a ringing call has disconnected while this state machine 314e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liu // is in the SimCallFocusState. 315e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liu if (!args.hasActiveOrDialingCalls) { 316e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liu transitionTo(destinationStateAfterNoMoreActiveCalls(args)); 317e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liu } 318e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 319e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_HOLDING_CALLS: 320e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Do nothing. 321e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 322e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_ACTIVE_OR_DIALING_CALL: 323e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Do nothing. Already active. 324e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 325e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_RINGING_CALL: 326e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Don't make a call ring over an active call, but do play a call waiting tone. 327e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager.startCallWaiting(); 328e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 329e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_HOLDING_CALL: 330e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Don't do anything now. Putting an active call on hold will be handled when 331e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // NO_MORE_ACTIVE_CALLS is processed. 332e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 333e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case FOREGROUND_VOIP_MODE_CHANGE: 334e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu if (args.foregroundCallIsVoip) { 335e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mVoipCallFocusState); 336e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 337e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 338e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu default: 339e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // The forced focus switch commands are handled by BaseState. 340e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return NOT_HANDLED; 341e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 342e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 343e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 344e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 345e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private class VoipCallFocusState extends BaseState { 346e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 347e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public void enter() { 348e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.i(LOG_TAG, "Audio focus entering VOIP CALL state"); 349e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, 350e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 351e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 352e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mMostRecentMode = AudioManager.MODE_IN_COMMUNICATION; 353e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS); 354e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 355e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 356e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 357e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public boolean processMessage(Message msg) { 358e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu if (super.processMessage(msg) == HANDLED) { 359e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 360e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 361e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu MessageArgs args = (MessageArgs) msg.obj; 362e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu switch (msg.what) { 363e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_ACTIVE_OR_DIALING_CALLS: 364e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Switch to either ringing, holding, or inactive 365fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu transitionTo(destinationStateAfterNoMoreActiveCalls(args)); 366e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 367e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_RINGING_CALLS: 368e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Don't transition state, but stop any call-waiting tones that may have been 369e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // playing. 370fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu if (args.isTonePlaying) { 371fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu mCallAudioManager.stopCallWaiting(); 372fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu } 373e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 374e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_HOLDING_CALLS: 375e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Do nothing. 376e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 377e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_ACTIVE_OR_DIALING_CALL: 378e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Do nothing. Already active. 379e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 380e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_RINGING_CALL: 381e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Don't make a call ring over an active call, but do play a call waiting tone. 382e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager.startCallWaiting(); 383e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 384e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_HOLDING_CALL: 385e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Don't do anything now. Putting an active call on hold will be handled when 386e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // NO_MORE_ACTIVE_CALLS is processed. 387e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 388e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case FOREGROUND_VOIP_MODE_CHANGE: 389e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu if (!args.foregroundCallIsVoip) { 390e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mSimCallFocusState); 391e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 392e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 393e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu default: 394e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // The forced focus switch commands are handled by BaseState. 395e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return NOT_HANDLED; 396e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 397e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 398e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 399e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 400e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu /** 401e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu * This class is used for calls on hold and end-of-call tones. 402e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu */ 403e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private class OtherFocusState extends BaseState { 404e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 405e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public void enter() { 406e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.i(LOG_TAG, "Audio focus entering TONE/HOLDING state"); 407e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, 408e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 409e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mAudioManager.setMode(mMostRecentMode); 410e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS); 411e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 412e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 413e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 414e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public boolean processMessage(Message msg) { 415e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu if (super.processMessage(msg) == HANDLED) { 416e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 417e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 418e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu MessageArgs args = (MessageArgs) msg.obj; 419e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu switch (msg.what) { 420e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_HOLDING_CALLS: 421fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu if (args.hasActiveOrDialingCalls) { 422e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(args.foregroundCallIsVoip 423e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu ? mVoipCallFocusState : mSimCallFocusState); 424e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } else if (args.hasRingingCalls) { 425e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mRingingFocusState); 426e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } else if (!args.isTonePlaying) { 427e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mUnfocusedState); 428e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 429e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Do nothing if a tone is playing. 430e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 431e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_ACTIVE_OR_DIALING_CALL: 432e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(args.foregroundCallIsVoip 433e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu ? mVoipCallFocusState : mSimCallFocusState); 434e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 435e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_RINGING_CALL: 436e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Apparently this is current behavior. Should this be the case? 437e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu transitionTo(mRingingFocusState); 438e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 439e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NEW_HOLDING_CALL: 440e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // Do nothing. 441e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 442e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case NO_MORE_RINGING_CALLS: 443e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // If there are no more ringing calls in this state, then stop any call-waiting 444e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu // tones that may be playing. 445e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager.stopCallWaiting(); 446e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return HANDLED; 447e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu case TONE_STOPPED_PLAYING: 4486a11ed71899f87970ea04f9a915524be68c9680eHall Liu transitionTo(destinationStateAfterNoMoreActiveCalls(args)); 449e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu default: 450e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu return NOT_HANDLED; 451e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 452e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 453e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 454e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 455e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private static final String LOG_TAG = CallAudioModeStateMachine.class.getSimpleName(); 456e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 457fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu private final BaseState mUnfocusedState = new UnfocusedState(); 458fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu private final BaseState mRingingFocusState = new RingingFocusState(); 459fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu private final BaseState mSimCallFocusState = new SimCallFocusState(); 460fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu private final BaseState mVoipCallFocusState = new VoipCallFocusState(); 461fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu private final BaseState mOtherFocusState = new OtherFocusState(); 462e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 463e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private final AudioManager mAudioManager; 464e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private CallAudioManager mCallAudioManager; 465e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 466e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private int mMostRecentMode; 467e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private boolean mIsInitialized = false; 468e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 469fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public CallAudioModeStateMachine(AudioManager audioManager) { 470e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu super(CallAudioModeStateMachine.class.getSimpleName()); 471fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu mAudioManager = audioManager; 472e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mMostRecentMode = AudioManager.MODE_NORMAL; 473e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 474e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu addState(mUnfocusedState); 475e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu addState(mRingingFocusState); 476e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu addState(mSimCallFocusState); 477e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu addState(mVoipCallFocusState); 478e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu addState(mOtherFocusState); 479e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu setInitialState(mUnfocusedState); 480e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu start(); 48183bc41189494799f48c50a5a0c47560d2859dedaBrad Ebinger sendMessage(INITIALIZE, new MessageArgs()); 482e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 483e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 484e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public void setCallAudioManager(CallAudioManager callAudioManager) { 485e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager = callAudioManager; 486e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 487e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 488fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu public String getCurrentStateName() { 489fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu IState currentState = getCurrentState(); 490fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu return currentState == null ? "no state" : currentState.getName(); 491fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu } 492fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu 493e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liu public void sendMessageWithArgs(int messageCode, MessageArgs args) { 494e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liu sendMessage(messageCode, args); 495e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liu } 496e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liu 497e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 498e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu protected void onPreHandleMessage(Message msg) { 499e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu if (msg.obj != null && msg.obj instanceof MessageArgs) { 500e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.continueSession(((MessageArgs) msg.obj).session, "CAMSM.pM_" + msg.what); 501e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.i(LOG_TAG, "Message received: %s.", MESSAGE_CODE_TO_NAME.get(msg.what)); 502fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu } else if (msg.what == RUN_RUNNABLE && msg.obj instanceof Runnable) { 503fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu Log.i(LOG_TAG, "Running runnable for testing"); 504e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } else { 505fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu Log.w(LOG_TAG, "Message sent must be of type nonnull MessageArgs, but got " + 506fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu (msg.obj == null ? "null" : msg.obj.getClass().getSimpleName())); 507fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu Log.w(LOG_TAG, "The message was of code %d = %s", 508fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu msg.what, MESSAGE_CODE_TO_NAME.get(msg.what)); 509e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 510e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 511e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 512e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu @Override 513e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu protected void onPostHandleMessage(Message msg) { 514e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Log.endSession(); 515e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 516e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 517fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu private BaseState destinationStateAfterNoMoreActiveCalls(MessageArgs args) { 5186a11ed71899f87970ea04f9a915524be68c9680eHall Liu if (args.hasHoldingCalls) { 5196a11ed71899f87970ea04f9a915524be68c9680eHall Liu return mOtherFocusState; 5206a11ed71899f87970ea04f9a915524be68c9680eHall Liu } else if (args.hasRingingCalls) { 5216a11ed71899f87970ea04f9a915524be68c9680eHall Liu return mRingingFocusState; 5226a11ed71899f87970ea04f9a915524be68c9680eHall Liu } else if (args.isTonePlaying) { 5236a11ed71899f87970ea04f9a915524be68c9680eHall Liu return mOtherFocusState; 524fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu } else { 5256a11ed71899f87970ea04f9a915524be68c9680eHall Liu return mUnfocusedState; 526fbed016fbd4cdc744f306b13fb3a2d9042d6bd5aHall Liu } 527e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 528e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu}