diff options
Diffstat (limited to 'src/com/android/dialer/voicemail/VoicemailAudioManager.java')
-rw-r--r-- | src/com/android/dialer/voicemail/VoicemailAudioManager.java | 140 |
1 files changed, 134 insertions, 6 deletions
diff --git a/src/com/android/dialer/voicemail/VoicemailAudioManager.java b/src/com/android/dialer/voicemail/VoicemailAudioManager.java index e64e180b6..267eeca09 100644 --- a/src/com/android/dialer/voicemail/VoicemailAudioManager.java +++ b/src/com/android/dialer/voicemail/VoicemailAudioManager.java @@ -19,25 +19,36 @@ package com.android.dialer.voicemail; import android.content.Context; import android.media.AudioManager; import android.media.AudioManager.OnAudioFocusChangeListener; +import android.telecom.CallAudioState; import android.util.Log; +import java.util.Objects; import java.util.concurrent.RejectedExecutionException; /** * This class manages all audio changes for voicemail playback. */ -final class VoicemailAudioManager implements OnAudioFocusChangeListener { +final class VoicemailAudioManager implements OnAudioFocusChangeListener, + WiredHeadsetManager.Listener { private static final String TAG = VoicemailAudioManager.class.getSimpleName(); public static final int PLAYBACK_STREAM = AudioManager.STREAM_VOICE_CALL; private AudioManager mAudioManager; private VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; + private WiredHeadsetManager mWiredHeadsetManager; + private boolean mWasSpeakerOn; + private CallAudioState mCallAudioState; public VoicemailAudioManager(Context context, VoicemailPlaybackPresenter voicemailPlaybackPresenter) { mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mVoicemailPlaybackPresenter = voicemailPlaybackPresenter; + mWiredHeadsetManager = new WiredHeadsetManager(context); + mWiredHeadsetManager.setListener(this); + + mCallAudioState = getInitialAudioState(); + Log.i(TAG, "Initial audioState = " + mCallAudioState); } public void requestAudioFocus() { @@ -60,14 +71,131 @@ final class VoicemailAudioManager implements OnAudioFocusChangeListener { mVoicemailPlaybackPresenter.onAudioFocusChange(focusChange == AudioManager.AUDIOFOCUS_GAIN); } - public void turnOnSpeaker(boolean on) { + @Override + public void onWiredHeadsetPluggedInChanged(boolean oldIsPluggedIn, boolean newIsPluggedIn) { + Log.i(TAG, "wired headset was plugged in changed: " + oldIsPluggedIn + + " -> "+ newIsPluggedIn); + + if (oldIsPluggedIn == newIsPluggedIn) { + return; + } + + int newRoute = mCallAudioState.getRoute(); // start out with existing route + if (newIsPluggedIn) { + newRoute = CallAudioState.ROUTE_WIRED_HEADSET; + } else { + if (mWasSpeakerOn) { + newRoute = CallAudioState.ROUTE_SPEAKER; + } else { + newRoute = CallAudioState.ROUTE_EARPIECE; + } + } + + mVoicemailPlaybackPresenter.setSpeakerphoneOn(newRoute == CallAudioState.ROUTE_SPEAKER); + + // We need to call this every time even if we do not change the route because the supported + // routes changed either to include or not include WIRED_HEADSET. + setSystemAudioState( + new CallAudioState(false /* muted */, newRoute, calculateSupportedRoutes())); + } + + public void setSpeakerphoneOn(boolean on) { + setAudioRoute(on ? CallAudioState.ROUTE_SPEAKER : CallAudioState.ROUTE_WIRED_OR_EARPIECE); + } + + public boolean isWiredHeadsetPluggedIn() { + return mWiredHeadsetManager.isPluggedIn(); + } + + public void registerReceivers() { + // Receivers is plural because we expect to add bluetooth support. + mWiredHeadsetManager.registerReceiver(); + } + + public void unregisterReceivers() { + mWiredHeadsetManager.unregisterReceiver(); + } + + /** + * Change the audio route, for example from earpiece to speakerphone. + * + * @param route The new audio route to use. See {@link CallAudioState}. + */ + void setAudioRoute(int route) { + Log.v(TAG, "setAudioRoute, route: " + CallAudioState.audioRouteToString(route)); + + // Change ROUTE_WIRED_OR_EARPIECE to a single entry. + int newRoute = selectWiredOrEarpiece(route, mCallAudioState.getSupportedRouteMask()); + + // If route is unsupported, do nothing. + if ((mCallAudioState.getSupportedRouteMask() | newRoute) == 0) { + Log.w(TAG, "Asking to set to a route that is unsupported: " + newRoute); + return; + } + + if (mCallAudioState.getRoute() != newRoute) { + // Remember the new speaker state so it can be restored when the user plugs and unplugs + // a headset. + mWasSpeakerOn = newRoute == CallAudioState.ROUTE_SPEAKER; + setSystemAudioState(new CallAudioState(false /* muted */, newRoute, + mCallAudioState.getSupportedRouteMask())); + } + } + + private CallAudioState getInitialAudioState() { + int supportedRouteMask = calculateSupportedRoutes(); + int route = selectWiredOrEarpiece(CallAudioState.ROUTE_WIRED_OR_EARPIECE, + supportedRouteMask); + return new CallAudioState(false /* muted */, route, supportedRouteMask); + } + + private int calculateSupportedRoutes() { + int routeMask = CallAudioState.ROUTE_SPEAKER; + if (mWiredHeadsetManager.isPluggedIn()) { + routeMask |= CallAudioState.ROUTE_WIRED_HEADSET; + } else { + routeMask |= CallAudioState.ROUTE_EARPIECE; + } + return routeMask; + } + + private int selectWiredOrEarpiece(int route, int supportedRouteMask) { + // Since they are mutually exclusive and one is ALWAYS valid, we allow a special input of + // ROUTE_WIRED_OR_EARPIECE so that callers don't have to make a call to check which is + // supported before calling setAudioRoute. + if (route == CallAudioState.ROUTE_WIRED_OR_EARPIECE) { + route = CallAudioState.ROUTE_WIRED_OR_EARPIECE & supportedRouteMask; + if (route == 0) { + Log.wtf(TAG, "One of wired headset or earpiece should always be valid."); + // assume earpiece in this case. + route = CallAudioState.ROUTE_EARPIECE; + } + } + return route; + } + + private void setSystemAudioState(CallAudioState callAudioState) { + CallAudioState oldAudioState = mCallAudioState; + mCallAudioState = callAudioState; + + Log.i(TAG, "setSystemAudioState: changing from " + oldAudioState + " to " + + mCallAudioState); + + // Audio route. + if (mCallAudioState.getRoute() == CallAudioState.ROUTE_SPEAKER) { + turnOnSpeaker(true); + } else if (mCallAudioState.getRoute() == CallAudioState.ROUTE_EARPIECE || + mCallAudioState.getRoute() == CallAudioState.ROUTE_WIRED_HEADSET) { + // Just handle turning off the speaker, the system will handle switching between wired + // headset and earpiece. + turnOnSpeaker(false); + } + } + + private void turnOnSpeaker(boolean on) { if (mAudioManager.isSpeakerphoneOn() != on) { Log.i(TAG, "turning speaker phone on: " + on); mAudioManager.setSpeakerphoneOn(on); } } - - public boolean isSpeakerphoneOn() { - return mAudioManager.isSpeakerphoneOn(); - } }
\ No newline at end of file |