diff options
author | Jean-Michel Trivi <jmtrivi@google.com> | 2010-04-20 14:56:34 -0700 |
---|---|---|
committer | Jean-Michel Trivi <jmtrivi@google.com> | 2010-04-20 15:23:39 -0700 |
commit | b4bccb6d8df16a2c5235cead187156bc721cf074 (patch) | |
tree | 2c7e7e25191ce89f2e570cf802869018700d29fd /media/java | |
parent | 25dc5f30b2a8276c5790c7152a801fcd905c7281 (diff) | |
download | frameworks_base-b4bccb6d8df16a2c5235cead187156bc721cf074.zip frameworks_base-b4bccb6d8df16a2c5235cead187156bc721cf074.tar.gz frameworks_base-b4bccb6d8df16a2c5235cead187156bc721cf074.tar.bz2 |
Update AudioService to reflect phone state changes with AudioFocus.
Phone calls and rings are treated as a new client, with a dedicated
client ID that identifies it in the audio focus stack. When it is
present in the stack, others clients cannot request audio focus
(request is denied).
Because the phone state is now mostly handled like a new client,
there is no need monitor mode changes and to keep track of
undispatched focus changes, as those will delayed focus gains
will now automatically happen at the end of the call when the
phone client is removed from the focus stack.
Change-Id: I11ff73b015ab93f07040755fd8ee75c8d675e025
Diffstat (limited to 'media/java')
-rw-r--r-- | media/java/android/media/AudioService.java | 81 |
1 files changed, 52 insertions, 29 deletions
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index df07059..97b96bc 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -41,6 +41,8 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; import android.provider.Settings.System; +import android.telephony.PhoneStateListener; +import android.telephony.TelephonyManager; import android.util.Log; import android.view.KeyEvent; import android.view.VolumePanel; @@ -305,6 +307,11 @@ public class AudioService extends IAudioService.Stub { intentFilter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON); intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); context.registerReceiver(mMediaButtonReceiver, intentFilter); + + // Register for phone state monitoring + TelephonyManager tmgr = (TelephonyManager) + context.getSystemService(Context.TELEPHONY_SERVICE); + tmgr.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); } private void createAudioSystemThread() { @@ -707,7 +714,6 @@ public class AudioService extends IAudioService.Stub { } if (mode != mMode) { if (AudioSystem.setPhoneState(mode) == AudioSystem.AUDIO_STATUS_OK) { - checkForUndispatchedAudioFocusChange(mMode, mode); mMode = mode; synchronized(mSetModeDeathHandlers) { @@ -1903,21 +1909,36 @@ public class AudioService extends IAudioService.Stub { //========================================================================================== // AudioFocus //========================================================================================== - /** - * Flag to indicate that the top of the audio focus stack needs to recover focus - * but hasn't been signaled yet. + + /* constant to identify focus stack entry that is used to hold the focus while the phone + * is ringing or during a call */ - private boolean mHasUndispatchedAudioFocus = false; + private final static String IN_VOICE_COMM_FOCUS_ID = "AudioFocus_For_Phone_Ring_And_Calls"; - private void checkForUndispatchedAudioFocusChange(int prevMode, int newMode) { - // when exiting a call - if ((prevMode == AudioSystem.MODE_IN_CALL) && (newMode != AudioSystem.MODE_IN_CALL)) { - // check for undispatched remote control focus gain - if (mHasUndispatchedAudioFocus) { - notifyTopOfAudioFocusStack(); + private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { + @Override + public void onCallStateChanged(int state, String incomingNumber) { + if (state == TelephonyManager.CALL_STATE_RINGING) { + //Log.v(TAG, " CALL_STATE_RINGING"); + int ringVolume = AudioService.this.getStreamVolume(AudioManager.STREAM_RING); + if (ringVolume > 0) { + requestAudioFocus(AudioManager.STREAM_RING, + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, + null, null /* both allowed to be null only for this clientId */, + IN_VOICE_COMM_FOCUS_ID /*clientId*/); + } + } else if (state == TelephonyManager.CALL_STATE_OFFHOOK) { + //Log.v(TAG, " CALL_STATE_OFFHOOK"); + requestAudioFocus(AudioManager.STREAM_RING, + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, + null, null /* both allowed to be null only for this clientId */, + IN_VOICE_COMM_FOCUS_ID /*clientId*/); + } else if (state == TelephonyManager.CALL_STATE_IDLE) { + //Log.v(TAG, " CALL_STATE_IDLE"); + abandonAudioFocus(null, IN_VOICE_COMM_FOCUS_ID); } } - } + }; private void notifyTopOfAudioFocusStack() { // notify the top of the stack it gained focus @@ -1926,13 +1947,10 @@ public class AudioService extends IAudioService.Stub { try { mFocusStack.peek().mFocusDispatcher.dispatchAudioFocusChange( AudioManager.AUDIOFOCUS_GAIN, mFocusStack.peek().mClientId); - mHasUndispatchedAudioFocus = false; } catch (RemoteException e) { Log.e(TAG, "Failure to signal gain of audio control focus due to "+ e); e.printStackTrace(); } - } else { - mHasUndispatchedAudioFocus = true; } } } @@ -1966,7 +1984,7 @@ public class AudioService extends IAudioService.Stub { * Display in the log the current entries in the audio focus stack */ private void dumpFocusStack(PrintWriter pw) { - pw.println("Audio Focus stack entries:"); + pw.println("\nAudio Focus stack entries:"); synchronized(mFocusStack) { Iterator<FocusStackEntry> stackIterator = mFocusStack.iterator(); while(stackIterator.hasNext()) { @@ -2038,9 +2056,9 @@ public class AudioService extends IAudioService.Stub { * Returns true if the system is in a state where the focus can be reevaluated, false otherwise. */ private boolean canReassignAudioFocus() { - // focus requests are rejected during a phone call - if (getMode() == AudioSystem.MODE_IN_CALL) { - Log.i(TAG, " AudioFocus can't be reassigned during a call, exiting"); + // focus requests are rejected during a phone call or when the phone is ringing + // this is equivalent to IN_VOICE_COMM_FOCUS_ID having the focus + if (!mFocusStack.isEmpty() && IN_VOICE_COMM_FOCUS_ID.equals(mFocusStack.peek().mClientId)) { return false; } return true; @@ -2077,7 +2095,9 @@ public class AudioService extends IAudioService.Stub { // the main stream type for the audio focus request is currently not used. It may // potentially be used to handle multiple stream type-dependent audio focuses. - if ((cb == null) || !cb.pingBinder()) { + // we need a valid binder callback for clients other than the AudioService's phone + // state listener + if (!IN_VOICE_COMM_FOCUS_ID.equals(clientId) && ((cb == null) || !cb.pingBinder())) { Log.i(TAG, " AudioFocus DOA client for requestAudioFocus(), exiting"); return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } @@ -2119,14 +2139,17 @@ public class AudioService extends IAudioService.Stub { }//synchronized(mFocusStack) // handle the potential premature death of the new holder of the focus - // (premature death == death before abandoning focus) - // Register for client death notification - AudioFocusDeathHandler afdh = new AudioFocusDeathHandler(cb); - try { - cb.linkToDeath(afdh, 0); - } catch (RemoteException e) { - // client has already died! - Log.w(TAG, " AudioFocus requestAudioFocus() could not link to "+cb+" binder death"); + // (premature death == death before abandoning focus) for a client which is not the + // AudioService's phone state listener + if (!IN_VOICE_COMM_FOCUS_ID.equals(clientId)) { + // Register for client death notification + AudioFocusDeathHandler afdh = new AudioFocusDeathHandler(cb); + try { + cb.linkToDeath(afdh, 0); + } catch (RemoteException e) { + // client has already died! + Log.w(TAG, "AudioFocus requestAudioFocus() could not link to "+cb+" binder death"); + } } return AudioManager.AUDIOFOCUS_REQUEST_GRANTED; @@ -2212,7 +2235,7 @@ public class AudioService extends IAudioService.Stub { * Display in the log the current entries in the remote control focus stack */ private void dumpRCStack(PrintWriter pw) { - pw.println("Remote Control stack entries:"); + pw.println("\nRemote Control stack entries:"); synchronized(mRCStack) { Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); while(stackIterator.hasNext()) { |