Loading api/current.xml +2 −2 Original line number Diff line number Diff line Loading @@ -65947,7 +65947,7 @@ synchronized="false" static="false" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > <parameter name="mode" type="int"> Loading Loading @@ -66158,7 +66158,7 @@ synchronized="false" static="false" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > <parameter name="mode" type="int"> media/java/android/media/AudioManager.java +50 −27 Original line number Diff line number Diff line Loading @@ -642,7 +642,9 @@ public class AudioManager { * <var>false</var> to turn it off */ public void setSpeakerphoneOn(boolean on){ setRouting(MODE_IN_CALL, on ? ROUTE_SPEAKER : ROUTE_EARPIECE, ROUTE_ALL); // Temporary fix for issue #1713090 until audio routing is refactored in eclair release. // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager setRoutingP(MODE_INVALID, on ? ROUTE_SPEAKER: 0, ROUTE_SPEAKER); } /** Loading @@ -651,7 +653,7 @@ public class AudioManager { * @return true if speakerphone is on, false if it's off */ public boolean isSpeakerphoneOn() { return (getRouting(MODE_IN_CALL) & ROUTE_SPEAKER) == 0 ? false : true; return (getRoutingP(MODE_IN_CALL) & ROUTE_SPEAKER) == 0 ? false : true; } /** Loading @@ -661,14 +663,9 @@ public class AudioManager { * headset; <var>false</var> to route audio to/from phone earpiece */ public void setBluetoothScoOn(boolean on){ // Don't disable A2DP when turning off SCO. // A2DP does not affect in-call routing. setRouting(MODE_RINGTONE, on ? ROUTE_BLUETOOTH_SCO: ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP); setRouting(MODE_NORMAL, on ? ROUTE_BLUETOOTH_SCO: ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP); setRouting(MODE_IN_CALL, on ? ROUTE_BLUETOOTH_SCO: ROUTE_EARPIECE, ROUTE_ALL); // Temporary fix for issue #1713090 until audio routing is refactored in eclair release. // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager setRoutingP(MODE_INVALID, on ? ROUTE_BLUETOOTH_SCO: 0, ROUTE_BLUETOOTH_SCO); } /** Loading @@ -678,7 +675,7 @@ public class AudioManager { * false if otherwise */ public boolean isBluetoothScoOn() { return (getRouting(MODE_IN_CALL) & ROUTE_BLUETOOTH_SCO) == 0 ? false : true; return (getRoutingP(MODE_IN_CALL) & ROUTE_BLUETOOTH_SCO) == 0 ? false : true; } /** Loading @@ -688,12 +685,9 @@ public class AudioManager { * headset; <var>false</var> disable A2DP audio */ public void setBluetoothA2dpOn(boolean on){ // the audio flinger chooses A2DP as a higher priority, // so there is no need to disable other routes. setRouting(MODE_RINGTONE, on ? ROUTE_BLUETOOTH_A2DP: 0, ROUTE_BLUETOOTH_A2DP); setRouting(MODE_NORMAL, on ? ROUTE_BLUETOOTH_A2DP: 0, ROUTE_BLUETOOTH_A2DP); // Temporary fix for issue #1713090 until audio routing is refactored in eclair release. // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager setRoutingP(MODE_INVALID, on ? ROUTE_BLUETOOTH_A2DP: 0, ROUTE_BLUETOOTH_A2DP); } /** Loading @@ -703,7 +697,7 @@ public class AudioManager { * false if otherwise */ public boolean isBluetoothA2dpOn() { return (getRouting(MODE_NORMAL) & ROUTE_BLUETOOTH_A2DP) == 0 ? false : true; return (getRoutingP(MODE_NORMAL) & ROUTE_BLUETOOTH_A2DP) == 0 ? false : true; } /** Loading @@ -714,14 +708,9 @@ public class AudioManager { * @hide */ public void setWiredHeadsetOn(boolean on){ // A2DP has higher priority than wired headset, so headset connect/disconnect events // should not affect A2DP routing setRouting(MODE_NORMAL, on ? ROUTE_HEADSET : ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP); setRouting(MODE_RINGTONE, on ? ROUTE_HEADSET | ROUTE_SPEAKER : ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP); setRouting(MODE_IN_CALL, on ? ROUTE_HEADSET : ROUTE_EARPIECE, ROUTE_ALL); // Temporary fix for issue #1713090 until audio routing is refactored in eclair release. // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager setRoutingP(MODE_INVALID, on ? ROUTE_HEADSET: 0, ROUTE_HEADSET); } /** Loading @@ -732,7 +721,7 @@ public class AudioManager { * @hide */ public boolean isWiredHeadsetOn() { return (getRouting(MODE_NORMAL) & ROUTE_HEADSET) == 0 ? false : true; return (getRoutingP(MODE_NORMAL) & ROUTE_HEADSET) == 0 ? false : true; } /** Loading Loading @@ -860,7 +849,11 @@ public class AudioManager { * more of ROUTE_xxx types. Set bits indicate that route should be on * @param mask bit vector of routes to change, created from one or more of * ROUTE_xxx types. Unset bits indicate the route should be left unchanged * * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), * setBluetoothScoOn(), setBluetoothA2dpOn() and setWiredHeadsetOn() methods instead. */ public void setRouting(int mode, int routes, int mask) { IAudioService service = getService(); try { Loading @@ -876,7 +869,10 @@ public class AudioManager { * @param mode audio mode to get route (e.g., MODE_RINGTONE) * @return an audio route bit vector that can be compared with ROUTE_xxx * bits * @deprecated Do not query audio routing directly, use isSpeakerphoneOn(), * isBluetoothScoOn(), isBluetoothA2dpOn() and isWiredHeadsetOn() methods instead. */ @Deprecated public int getRouting(int mode) { IAudioService service = getService(); try { Loading Loading @@ -1076,4 +1072,31 @@ public class AudioManager { * {@hide} */ private IBinder mICallBack = new Binder(); /** * {@hide} */ private void setRoutingP(int mode, int routes, int mask) { IAudioService service = getService(); try { service.setRouting(mode, routes, mask); } catch (RemoteException e) { Log.e(TAG, "Dead object in setRouting", e); } } /** * {@hide} */ private int getRoutingP(int mode) { IAudioService service = getService(); try { return service.getRouting(mode); } catch (RemoteException e) { Log.e(TAG, "Dead object in getRouting", e); return -1; } } } media/java/android/media/AudioService.java +167 −9 Original line number Diff line number Diff line Loading @@ -100,6 +100,10 @@ public class AudioService extends IAudioService.Stub { private int[] mRoutes = new int[AudioSystem.NUM_MODES]; private Object mSettingsLock = new Object(); private boolean mMediaServerOk; private boolean mSpeakerIsOn; private boolean mBluetoothScoIsConnected; private boolean mHeadsetIsConnected; private boolean mBluetoothA2dpIsConnected; private SoundPool mSoundPool; private Object mSoundEffectsLock = new Object(); Loading Loading @@ -189,6 +193,10 @@ public class AudioService extends IAudioService.Stub { mMediaServerOk = true; AudioSystem.setErrorCallback(mAudioSystemCallback); loadSoundEffects(); mSpeakerIsOn = false; mBluetoothScoIsConnected = false; mHeadsetIsConnected = false; mBluetoothA2dpIsConnected = false; } private void createAudioSystemThread() { Loading Loading @@ -606,9 +614,10 @@ public class AudioService extends IAudioService.Stub { } synchronized (mSettingsLock) { if (mode != mMode) { AudioSystem.setMode(mode); if (AudioSystem.setMode(mode) == AudioSystem.AUDIO_STATUS_OK) { mMode = mode; } } int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); int index = mStreamStates[streamType].mIndex; syncRingerAndNotificationStreamVolume(streamType, index, true); Loading @@ -623,20 +632,169 @@ public class AudioService extends IAudioService.Stub { /** @see AudioManager#setRouting(int, int, int) */ public void setRouting(int mode, int routes, int mask) { int incallMask = 0; int ringtoneMask = 0; int normalMask = 0; if (!checkAudioSettingsPermission("setRouting()")) { return; } synchronized (mSettingsLock) { if ((mRoutes[mode] & mask) != (routes & mask)) { AudioSystem.setRouting(mode, routes, mask); mRoutes[mode] = (mRoutes[mode] & ~mask) | (routes & mask); // Temporary fix for issue #1713090 until audio routing is refactored in eclair release. // mode AudioSystem.MODE_INVALID is used only by the following AudioManager methods: // setWiredHeadsetOn(), setBluetoothA2dpOn(), setBluetoothScoOn() and setSpeakerphoneOn(). // If applications are using AudioManager.setRouting() that is now deprecated, the routing // command will be ignored. if (mode == AudioSystem.MODE_INVALID) { switch (mask) { case AudioSystem.ROUTE_SPEAKER: // handle setSpeakerphoneOn() if (routes != 0 && !mSpeakerIsOn) { mSpeakerIsOn = true; mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_SPEAKER; incallMask = AudioSystem.ROUTE_ALL; } else if (mSpeakerIsOn) { mSpeakerIsOn = false; if (mBluetoothScoIsConnected) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_BLUETOOTH_SCO; } else if (mHeadsetIsConnected) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_HEADSET; } else { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_EARPIECE; } incallMask = AudioSystem.ROUTE_ALL; } break; case AudioSystem.ROUTE_BLUETOOTH_SCO: // handle setBluetoothScoOn() if (routes != 0 && !mBluetoothScoIsConnected) { mBluetoothScoIsConnected = true; mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_BLUETOOTH_SCO; mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_BLUETOOTH_SCO; mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_BLUETOOTH_SCO; incallMask = AudioSystem.ROUTE_ALL; // A2DP has higher priority than SCO headset, so headset connect/disconnect events // should not affect A2DP routing ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; } else if (mBluetoothScoIsConnected) { mBluetoothScoIsConnected = false; if (mHeadsetIsConnected) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_HEADSET; mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | (AudioSystem.ROUTE_HEADSET|AudioSystem.ROUTE_SPEAKER); mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_HEADSET; } else { if (mSpeakerIsOn) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_SPEAKER; } else { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_EARPIECE; } mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_SPEAKER; mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_SPEAKER; } incallMask = AudioSystem.ROUTE_ALL; // A2DP has higher priority than SCO headset, so headset connect/disconnect events // should not affect A2DP routing ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; } break; case AudioSystem.ROUTE_HEADSET: // handle setWiredHeadsetOn() if (routes != 0 && !mHeadsetIsConnected) { mHeadsetIsConnected = true; // do not act upon headset connection if bluetooth SCO is connected to match phone app behavior if (!mBluetoothScoIsConnected) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_HEADSET; mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | (AudioSystem.ROUTE_HEADSET|AudioSystem.ROUTE_SPEAKER); mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_HEADSET; incallMask = AudioSystem.ROUTE_ALL; // A2DP has higher priority than wired headset, so headset connect/disconnect events // should not affect A2DP routing ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; } } else if (mHeadsetIsConnected) { mHeadsetIsConnected = false; // do not act upon headset disconnection if bluetooth SCO is connected to match phone app behavior if (!mBluetoothScoIsConnected) { if (mSpeakerIsOn) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_SPEAKER; } else { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_EARPIECE; } mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_SPEAKER; mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_SPEAKER; incallMask = AudioSystem.ROUTE_ALL; // A2DP has higher priority than wired headset, so headset connect/disconnect events // should not affect A2DP routing ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; } } break; case AudioSystem.ROUTE_BLUETOOTH_A2DP: // handle setBluetoothA2dpOn() if (routes != 0 && !mBluetoothA2dpIsConnected) { mBluetoothA2dpIsConnected = true; mRoutes[AudioSystem.MODE_RINGTONE] |= AudioSystem.ROUTE_BLUETOOTH_A2DP; mRoutes[AudioSystem.MODE_NORMAL] |= AudioSystem.ROUTE_BLUETOOTH_A2DP; // the audio flinger chooses A2DP as a higher priority, // so there is no need to disable other routes. ringtoneMask = AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_BLUETOOTH_A2DP; } else if (mBluetoothA2dpIsConnected) { mBluetoothA2dpIsConnected = false; mRoutes[AudioSystem.MODE_RINGTONE] &= ~AudioSystem.ROUTE_BLUETOOTH_A2DP; mRoutes[AudioSystem.MODE_NORMAL] &= ~AudioSystem.ROUTE_BLUETOOTH_A2DP; // the audio flinger chooses A2DP as a higher priority, // so there is no need to disable other routes. ringtoneMask = AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_BLUETOOTH_A2DP; } break; } // incallMask is != 0 means we must apply ne routing to MODE_IN_CALL mode if (incallMask != 0) { AudioSystem.setRouting(AudioSystem.MODE_IN_CALL, mRoutes[AudioSystem.MODE_IN_CALL], incallMask); } // ringtoneMask is != 0 means we must apply ne routing to MODE_RINGTONE mode if (ringtoneMask != 0) { AudioSystem.setRouting(AudioSystem.MODE_RINGTONE, mRoutes[AudioSystem.MODE_RINGTONE], ringtoneMask); } // normalMask is != 0 means we must apply ne routing to MODE_NORMAL mode if (normalMask != 0) { AudioSystem.setRouting(AudioSystem.MODE_NORMAL, mRoutes[AudioSystem.MODE_NORMAL], normalMask); } int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); int index = mStreamStates[streamType].mIndex; syncRingerAndNotificationStreamVolume(streamType, index, true); setStreamVolumeInt(streamType, index, true); } } } /** @see AudioManager#getRouting(int) */ public int getRouting(int mode) { Loading Loading
api/current.xml +2 −2 Original line number Diff line number Diff line Loading @@ -65947,7 +65947,7 @@ synchronized="false" static="false" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > <parameter name="mode" type="int"> Loading Loading @@ -66158,7 +66158,7 @@ synchronized="false" static="false" final="false" deprecated="not deprecated" deprecated="deprecated" visibility="public" > <parameter name="mode" type="int">
media/java/android/media/AudioManager.java +50 −27 Original line number Diff line number Diff line Loading @@ -642,7 +642,9 @@ public class AudioManager { * <var>false</var> to turn it off */ public void setSpeakerphoneOn(boolean on){ setRouting(MODE_IN_CALL, on ? ROUTE_SPEAKER : ROUTE_EARPIECE, ROUTE_ALL); // Temporary fix for issue #1713090 until audio routing is refactored in eclair release. // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager setRoutingP(MODE_INVALID, on ? ROUTE_SPEAKER: 0, ROUTE_SPEAKER); } /** Loading @@ -651,7 +653,7 @@ public class AudioManager { * @return true if speakerphone is on, false if it's off */ public boolean isSpeakerphoneOn() { return (getRouting(MODE_IN_CALL) & ROUTE_SPEAKER) == 0 ? false : true; return (getRoutingP(MODE_IN_CALL) & ROUTE_SPEAKER) == 0 ? false : true; } /** Loading @@ -661,14 +663,9 @@ public class AudioManager { * headset; <var>false</var> to route audio to/from phone earpiece */ public void setBluetoothScoOn(boolean on){ // Don't disable A2DP when turning off SCO. // A2DP does not affect in-call routing. setRouting(MODE_RINGTONE, on ? ROUTE_BLUETOOTH_SCO: ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP); setRouting(MODE_NORMAL, on ? ROUTE_BLUETOOTH_SCO: ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP); setRouting(MODE_IN_CALL, on ? ROUTE_BLUETOOTH_SCO: ROUTE_EARPIECE, ROUTE_ALL); // Temporary fix for issue #1713090 until audio routing is refactored in eclair release. // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager setRoutingP(MODE_INVALID, on ? ROUTE_BLUETOOTH_SCO: 0, ROUTE_BLUETOOTH_SCO); } /** Loading @@ -678,7 +675,7 @@ public class AudioManager { * false if otherwise */ public boolean isBluetoothScoOn() { return (getRouting(MODE_IN_CALL) & ROUTE_BLUETOOTH_SCO) == 0 ? false : true; return (getRoutingP(MODE_IN_CALL) & ROUTE_BLUETOOTH_SCO) == 0 ? false : true; } /** Loading @@ -688,12 +685,9 @@ public class AudioManager { * headset; <var>false</var> disable A2DP audio */ public void setBluetoothA2dpOn(boolean on){ // the audio flinger chooses A2DP as a higher priority, // so there is no need to disable other routes. setRouting(MODE_RINGTONE, on ? ROUTE_BLUETOOTH_A2DP: 0, ROUTE_BLUETOOTH_A2DP); setRouting(MODE_NORMAL, on ? ROUTE_BLUETOOTH_A2DP: 0, ROUTE_BLUETOOTH_A2DP); // Temporary fix for issue #1713090 until audio routing is refactored in eclair release. // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager setRoutingP(MODE_INVALID, on ? ROUTE_BLUETOOTH_A2DP: 0, ROUTE_BLUETOOTH_A2DP); } /** Loading @@ -703,7 +697,7 @@ public class AudioManager { * false if otherwise */ public boolean isBluetoothA2dpOn() { return (getRouting(MODE_NORMAL) & ROUTE_BLUETOOTH_A2DP) == 0 ? false : true; return (getRoutingP(MODE_NORMAL) & ROUTE_BLUETOOTH_A2DP) == 0 ? false : true; } /** Loading @@ -714,14 +708,9 @@ public class AudioManager { * @hide */ public void setWiredHeadsetOn(boolean on){ // A2DP has higher priority than wired headset, so headset connect/disconnect events // should not affect A2DP routing setRouting(MODE_NORMAL, on ? ROUTE_HEADSET : ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP); setRouting(MODE_RINGTONE, on ? ROUTE_HEADSET | ROUTE_SPEAKER : ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP); setRouting(MODE_IN_CALL, on ? ROUTE_HEADSET : ROUTE_EARPIECE, ROUTE_ALL); // Temporary fix for issue #1713090 until audio routing is refactored in eclair release. // MODE_INVALID indicates to AudioService that setRouting() was initiated by AudioManager setRoutingP(MODE_INVALID, on ? ROUTE_HEADSET: 0, ROUTE_HEADSET); } /** Loading @@ -732,7 +721,7 @@ public class AudioManager { * @hide */ public boolean isWiredHeadsetOn() { return (getRouting(MODE_NORMAL) & ROUTE_HEADSET) == 0 ? false : true; return (getRoutingP(MODE_NORMAL) & ROUTE_HEADSET) == 0 ? false : true; } /** Loading Loading @@ -860,7 +849,11 @@ public class AudioManager { * more of ROUTE_xxx types. Set bits indicate that route should be on * @param mask bit vector of routes to change, created from one or more of * ROUTE_xxx types. Unset bits indicate the route should be left unchanged * * @deprecated Do not set audio routing directly, use setSpeakerphoneOn(), * setBluetoothScoOn(), setBluetoothA2dpOn() and setWiredHeadsetOn() methods instead. */ public void setRouting(int mode, int routes, int mask) { IAudioService service = getService(); try { Loading @@ -876,7 +869,10 @@ public class AudioManager { * @param mode audio mode to get route (e.g., MODE_RINGTONE) * @return an audio route bit vector that can be compared with ROUTE_xxx * bits * @deprecated Do not query audio routing directly, use isSpeakerphoneOn(), * isBluetoothScoOn(), isBluetoothA2dpOn() and isWiredHeadsetOn() methods instead. */ @Deprecated public int getRouting(int mode) { IAudioService service = getService(); try { Loading Loading @@ -1076,4 +1072,31 @@ public class AudioManager { * {@hide} */ private IBinder mICallBack = new Binder(); /** * {@hide} */ private void setRoutingP(int mode, int routes, int mask) { IAudioService service = getService(); try { service.setRouting(mode, routes, mask); } catch (RemoteException e) { Log.e(TAG, "Dead object in setRouting", e); } } /** * {@hide} */ private int getRoutingP(int mode) { IAudioService service = getService(); try { return service.getRouting(mode); } catch (RemoteException e) { Log.e(TAG, "Dead object in getRouting", e); return -1; } } }
media/java/android/media/AudioService.java +167 −9 Original line number Diff line number Diff line Loading @@ -100,6 +100,10 @@ public class AudioService extends IAudioService.Stub { private int[] mRoutes = new int[AudioSystem.NUM_MODES]; private Object mSettingsLock = new Object(); private boolean mMediaServerOk; private boolean mSpeakerIsOn; private boolean mBluetoothScoIsConnected; private boolean mHeadsetIsConnected; private boolean mBluetoothA2dpIsConnected; private SoundPool mSoundPool; private Object mSoundEffectsLock = new Object(); Loading Loading @@ -189,6 +193,10 @@ public class AudioService extends IAudioService.Stub { mMediaServerOk = true; AudioSystem.setErrorCallback(mAudioSystemCallback); loadSoundEffects(); mSpeakerIsOn = false; mBluetoothScoIsConnected = false; mHeadsetIsConnected = false; mBluetoothA2dpIsConnected = false; } private void createAudioSystemThread() { Loading Loading @@ -606,9 +614,10 @@ public class AudioService extends IAudioService.Stub { } synchronized (mSettingsLock) { if (mode != mMode) { AudioSystem.setMode(mode); if (AudioSystem.setMode(mode) == AudioSystem.AUDIO_STATUS_OK) { mMode = mode; } } int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); int index = mStreamStates[streamType].mIndex; syncRingerAndNotificationStreamVolume(streamType, index, true); Loading @@ -623,20 +632,169 @@ public class AudioService extends IAudioService.Stub { /** @see AudioManager#setRouting(int, int, int) */ public void setRouting(int mode, int routes, int mask) { int incallMask = 0; int ringtoneMask = 0; int normalMask = 0; if (!checkAudioSettingsPermission("setRouting()")) { return; } synchronized (mSettingsLock) { if ((mRoutes[mode] & mask) != (routes & mask)) { AudioSystem.setRouting(mode, routes, mask); mRoutes[mode] = (mRoutes[mode] & ~mask) | (routes & mask); // Temporary fix for issue #1713090 until audio routing is refactored in eclair release. // mode AudioSystem.MODE_INVALID is used only by the following AudioManager methods: // setWiredHeadsetOn(), setBluetoothA2dpOn(), setBluetoothScoOn() and setSpeakerphoneOn(). // If applications are using AudioManager.setRouting() that is now deprecated, the routing // command will be ignored. if (mode == AudioSystem.MODE_INVALID) { switch (mask) { case AudioSystem.ROUTE_SPEAKER: // handle setSpeakerphoneOn() if (routes != 0 && !mSpeakerIsOn) { mSpeakerIsOn = true; mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_SPEAKER; incallMask = AudioSystem.ROUTE_ALL; } else if (mSpeakerIsOn) { mSpeakerIsOn = false; if (mBluetoothScoIsConnected) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_BLUETOOTH_SCO; } else if (mHeadsetIsConnected) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_HEADSET; } else { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_EARPIECE; } incallMask = AudioSystem.ROUTE_ALL; } break; case AudioSystem.ROUTE_BLUETOOTH_SCO: // handle setBluetoothScoOn() if (routes != 0 && !mBluetoothScoIsConnected) { mBluetoothScoIsConnected = true; mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_BLUETOOTH_SCO; mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_BLUETOOTH_SCO; mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_BLUETOOTH_SCO; incallMask = AudioSystem.ROUTE_ALL; // A2DP has higher priority than SCO headset, so headset connect/disconnect events // should not affect A2DP routing ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; } else if (mBluetoothScoIsConnected) { mBluetoothScoIsConnected = false; if (mHeadsetIsConnected) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_HEADSET; mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | (AudioSystem.ROUTE_HEADSET|AudioSystem.ROUTE_SPEAKER); mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_HEADSET; } else { if (mSpeakerIsOn) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_SPEAKER; } else { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_EARPIECE; } mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_SPEAKER; mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_SPEAKER; } incallMask = AudioSystem.ROUTE_ALL; // A2DP has higher priority than SCO headset, so headset connect/disconnect events // should not affect A2DP routing ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; } break; case AudioSystem.ROUTE_HEADSET: // handle setWiredHeadsetOn() if (routes != 0 && !mHeadsetIsConnected) { mHeadsetIsConnected = true; // do not act upon headset connection if bluetooth SCO is connected to match phone app behavior if (!mBluetoothScoIsConnected) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_HEADSET; mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | (AudioSystem.ROUTE_HEADSET|AudioSystem.ROUTE_SPEAKER); mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_HEADSET; incallMask = AudioSystem.ROUTE_ALL; // A2DP has higher priority than wired headset, so headset connect/disconnect events // should not affect A2DP routing ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; } } else if (mHeadsetIsConnected) { mHeadsetIsConnected = false; // do not act upon headset disconnection if bluetooth SCO is connected to match phone app behavior if (!mBluetoothScoIsConnected) { if (mSpeakerIsOn) { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_SPEAKER; } else { mRoutes[AudioSystem.MODE_IN_CALL] = AudioSystem.ROUTE_EARPIECE; } mRoutes[AudioSystem.MODE_RINGTONE] = (mRoutes[AudioSystem.MODE_RINGTONE] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_SPEAKER; mRoutes[AudioSystem.MODE_NORMAL] = (mRoutes[AudioSystem.MODE_NORMAL] & AudioSystem.ROUTE_BLUETOOTH_A2DP) | AudioSystem.ROUTE_SPEAKER; incallMask = AudioSystem.ROUTE_ALL; // A2DP has higher priority than wired headset, so headset connect/disconnect events // should not affect A2DP routing ringtoneMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_ALL & ~AudioSystem.ROUTE_BLUETOOTH_A2DP; } } break; case AudioSystem.ROUTE_BLUETOOTH_A2DP: // handle setBluetoothA2dpOn() if (routes != 0 && !mBluetoothA2dpIsConnected) { mBluetoothA2dpIsConnected = true; mRoutes[AudioSystem.MODE_RINGTONE] |= AudioSystem.ROUTE_BLUETOOTH_A2DP; mRoutes[AudioSystem.MODE_NORMAL] |= AudioSystem.ROUTE_BLUETOOTH_A2DP; // the audio flinger chooses A2DP as a higher priority, // so there is no need to disable other routes. ringtoneMask = AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_BLUETOOTH_A2DP; } else if (mBluetoothA2dpIsConnected) { mBluetoothA2dpIsConnected = false; mRoutes[AudioSystem.MODE_RINGTONE] &= ~AudioSystem.ROUTE_BLUETOOTH_A2DP; mRoutes[AudioSystem.MODE_NORMAL] &= ~AudioSystem.ROUTE_BLUETOOTH_A2DP; // the audio flinger chooses A2DP as a higher priority, // so there is no need to disable other routes. ringtoneMask = AudioSystem.ROUTE_BLUETOOTH_A2DP; normalMask = AudioSystem.ROUTE_BLUETOOTH_A2DP; } break; } // incallMask is != 0 means we must apply ne routing to MODE_IN_CALL mode if (incallMask != 0) { AudioSystem.setRouting(AudioSystem.MODE_IN_CALL, mRoutes[AudioSystem.MODE_IN_CALL], incallMask); } // ringtoneMask is != 0 means we must apply ne routing to MODE_RINGTONE mode if (ringtoneMask != 0) { AudioSystem.setRouting(AudioSystem.MODE_RINGTONE, mRoutes[AudioSystem.MODE_RINGTONE], ringtoneMask); } // normalMask is != 0 means we must apply ne routing to MODE_NORMAL mode if (normalMask != 0) { AudioSystem.setRouting(AudioSystem.MODE_NORMAL, mRoutes[AudioSystem.MODE_NORMAL], normalMask); } int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); int index = mStreamStates[streamType].mIndex; syncRingerAndNotificationStreamVolume(streamType, index, true); setStreamVolumeInt(streamType, index, true); } } } /** @see AudioManager#getRouting(int) */ public int getRouting(int mode) { Loading