diff options
author | Eric Laurent <elaurent@google.com> | 2009-07-17 12:17:14 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2009-07-23 06:03:39 -0700 |
commit | a553c25b33c99b345cf1c8688f8df0ed8df14e5a (patch) | |
tree | 025c461b13e66ad0ceac8d0f8d9b13fd88ae168a /media/java | |
parent | ebd7bc54028949619bbf3fa5ed6c1188f588c230 (diff) | |
download | frameworks_base-a553c25b33c99b345cf1c8688f8df0ed8df14e5a.zip frameworks_base-a553c25b33c99b345cf1c8688f8df0ed8df14e5a.tar.gz frameworks_base-a553c25b33c99b345cf1c8688f8df0ed8df14e5a.tar.bz2 |
Fix issue 1795088 Improve audio routing code
Initial commit for review.
Integrated comments after patch set 1 review.
Fixed lockup in AudioFlinger::ThreadBase::exit()
Fixed lockup when playing tone with AudioPlocyService startTone()
Diffstat (limited to 'media/java')
-rw-r--r-- | media/java/android/media/AudioFormat.java | 55 | ||||
-rw-r--r-- | media/java/android/media/AudioManager.java | 203 | ||||
-rw-r--r-- | media/java/android/media/AudioRecord.java | 36 | ||||
-rw-r--r-- | media/java/android/media/AudioService.java | 701 | ||||
-rw-r--r-- | media/java/android/media/AudioSystem.java | 157 | ||||
-rw-r--r-- | media/java/android/media/AudioTrack.java | 35 | ||||
-rw-r--r-- | media/java/android/media/IAudioService.aidl | 16 | ||||
-rw-r--r-- | media/java/android/media/JetPlayer.java | 2 | ||||
-rw-r--r-- | media/java/android/media/ToneGenerator.java | 4 |
9 files changed, 595 insertions, 614 deletions
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index 0732b61..500f6a4 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -37,15 +37,58 @@ public class AudioFormat { public static final int ENCODING_PCM_8BIT = 3; // accessed by native code /** Invalid audio channel configuration */ - public static final int CHANNEL_CONFIGURATION_INVALID = 0; + /** @deprecated use CHANNEL_INVALID instead */ + @Deprecated public static final int CHANNEL_CONFIGURATION_INVALID = 0; /** Default audio channel configuration */ - public static final int CHANNEL_CONFIGURATION_DEFAULT = 1; + /** @deprecated use CHANNEL_OUT_DEFAULT or CHANNEL_IN_DEFAULT instead */ + @Deprecated public static final int CHANNEL_CONFIGURATION_DEFAULT = 1; /** Mono audio configuration */ - public static final int CHANNEL_CONFIGURATION_MONO = 2; + /** @deprecated use CHANNEL_OUT_MONO or CHANNEL_IN_MONO instead */ + @Deprecated public static final int CHANNEL_CONFIGURATION_MONO = 2; /** Stereo (2 channel) audio configuration */ - public static final int CHANNEL_CONFIGURATION_STEREO = 3; - -} + /** @deprecated use CHANNEL_OUT_STEREO or CHANNEL_IN_STEREO instead */ + @Deprecated public static final int CHANNEL_CONFIGURATION_STEREO = 3; + /** Invalid audio channel mask */ + public static final int CHANNEL_INVALID = -1; + /** Default audio channel mask */ + // Channel mask definitions must be kept in sync with native values in include/media/AudioSystem.h + public static final int CHANNEL_OUT_DEFAULT = 0; + public static final int CHANNEL_OUT_FRONT_LEFT = 0x1; + public static final int CHANNEL_OUT_FRONT_RIGHT = 0x2; + public static final int CHANNEL_OUT_FRONT_CENTER = 0x4; + public static final int CHANNEL_OUT_LOW_FREQUENCY = 0x8; + public static final int CHANNEL_OUT_BACK_LEFT = 0x10; + public static final int CHANNEL_OUT_BACK_RIGHT = 0x20; + public static final int CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40; + public static final int CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80; + public static final int CHANNEL_OUT_BACK_CENTER = 0x100; + public static final int CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT; + public static final int CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT); + public static final int CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | + CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT); + public static final int CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | + CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER); + public static final int CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | + CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT); + public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | + CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT | + CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER); + public static final int CHANNEL_IN_DEFAULT = 0; + public static final int CHANNEL_IN_LEFT = 0x10000; + public static final int CHANNEL_IN_RIGHT = 0x20000; + public static final int CHANNEL_IN_FRONT = 0x40000; + public static final int CHANNEL_IN_BACK = 0x80000; + public static final int CHANNEL_IN_LEFT_PROCESSED = 0x100000; + public static final int CHANNEL_IN_RIGHT_PROCESSED = 0x200000; + public static final int CHANNEL_IN_FRONT_PROCESSED = 0x400000; + public static final int CHANNEL_IN_BACK_PROCESSED = 0x800000; + public static final int CHANNEL_IN_PRESSURE = 0x1000000; + public static final int CHANNEL_IN_X_AXIS = 0x2000000; + public static final int CHANNEL_IN_Y_AXIS = 0x4000000; + public static final int CHANNEL_IN_Z_AXIS = 0x8000000; + public static final int CHANNEL_IN_MONO = CHANNEL_IN_FRONT; + public static final int CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT); +} diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index a65a417..040d4bc 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -140,11 +140,17 @@ public class AudioManager { public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION; /** @hide The audio stream for phone calls when connected to bluetooth */ public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO; + /** @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */ + public static final int STREAM_SYSTEM_ENFORCED = AudioSystem.STREAM_SYSTEM_ENFORCED; + /** The audio stream for DTMF Tones */ + public static final int STREAM_DTMF = AudioSystem.STREAM_DTMF; + /** @hide The audio stream for text to speech (TTS) */ + public static final int STREAM_TTS = AudioSystem.STREAM_TTS; /** Number of audio streams */ /** * @deprecated Use AudioSystem.getNumStreamTypes() instead */ - public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS; + @Deprecated public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS; /** @hide Maximum volume index values for audio streams */ @@ -156,6 +162,9 @@ public class AudioManager { 8, // STREAM_ALARM 8, // STREAM_NOTIFICATION 16, // STREAM_BLUETOOTH_SCO + 8, // STREAM_SYSTEM_ENFORCED + 16, // STREAM_DTMF + 16 // STREAM_TTS }; /** @hide Default volume index values for audio streams */ @@ -166,7 +175,10 @@ public class AudioManager { 11, // STREAM_MUSIC 6, // STREAM_ALARM 5, // STREAM_NOTIFICATION - 7 // STREAM_BLUETOOTH_SCO + 7, // STREAM_BLUETOOTH_SCO + 5, // STREAM_SYSTEM_ENFORCED + 11, // STREAM_DTMF + 11 // STREAM_TTS }; /** @@ -637,9 +649,11 @@ public class AudioManager { * <var>false</var> to turn it off */ public void setSpeakerphoneOn(boolean on){ - // 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); + if (on) { + AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_SPEAKER); + } else { + AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE); + } } /** @@ -648,41 +662,47 @@ public class AudioManager { * @return true if speakerphone is on, false if it's off */ public boolean isSpeakerphoneOn() { - return (getRoutingP(MODE_IN_CALL) & ROUTE_SPEAKER) == 0 ? false : true; + if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) == AudioSystem.FORCE_SPEAKER) { + return true; + } else { + return false; + } } /** - * Sets audio routing to the Bluetooth headset on or off. + * Request use of Bluetooth SCO headset for communications. * - * @param on set <var>true</var> to route SCO (voice) audio to/from Bluetooth - * headset; <var>false</var> to route audio to/from phone earpiece + * @param on set <var>true</var> to use bluetooth SCO for communications; + * <var>false</var> to not use bluetooth SCO for communications */ public void setBluetoothScoOn(boolean on){ - // 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); + if (on) { + AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_BT_SCO); + } else { + AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE); + } } /** - * Checks whether audio routing to the Bluetooth headset is on or off. + * Checks whether communications use Bluetooth SCO. * - * @return true if SCO audio is being routed to/from Bluetooth headset; + * @return true if SCO is used for communications; * false if otherwise */ public boolean isBluetoothScoOn() { - return (getRoutingP(MODE_IN_CALL) & ROUTE_BLUETOOTH_SCO) == 0 ? false : true; + if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) == AudioSystem.FORCE_BT_SCO) { + return true; + } else { + return false; + } } /** - * Sets A2DP audio routing to the Bluetooth headset on or off. - * * @param on set <var>true</var> to route A2DP audio to/from Bluetooth * headset; <var>false</var> disable A2DP audio + * @deprecated Do not use. */ - public void setBluetoothA2dpOn(boolean on){ - // 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); + @Deprecated public void setBluetoothA2dpOn(boolean on){ } /** @@ -692,7 +712,12 @@ public class AudioManager { * false if otherwise */ public boolean isBluetoothA2dpOn() { - return (getRoutingP(MODE_NORMAL) & ROUTE_BLUETOOTH_A2DP) == 0 ? false : true; + if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,"") + == AudioSystem.DEVICE_STATE_UNAVAILABLE) { + return false; + } else { + return true; + } } /** @@ -700,12 +725,9 @@ public class AudioManager { * * @param on set <var>true</var> to route audio to/from wired * headset; <var>false</var> disable wired headset audio - * @hide + * @deprecated Do not use. */ - public void setWiredHeadsetOn(boolean on){ - // 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); + @Deprecated public void setWiredHeadsetOn(boolean on){ } /** @@ -713,10 +735,14 @@ public class AudioManager { * * @return true if audio is being routed to/from wired headset; * false if otherwise - * @hide */ public boolean isWiredHeadsetOn() { - return (getRoutingP(MODE_NORMAL) & ROUTE_HEADSET) == 0 ? false : true; + if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,"") + == AudioSystem.DEVICE_STATE_UNAVAILABLE) { + return false; + } else { + return true; + } } /** @@ -726,12 +752,7 @@ public class AudioManager { * <var>false</var> to turn mute off */ public void setMicrophoneMute(boolean on){ - IAudioService service = getService(); - try { - service.setMicrophoneMute(on); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in setMicrophoneMute", e); - } + AudioSystem.muteMicrophone(on); } /** @@ -740,13 +761,7 @@ public class AudioManager { * @return true if microphone is muted, false if it's not */ public boolean isMicrophoneMute() { - IAudioService service = getService(); - try { - return service.isMicrophoneMute(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in isMicrophoneMute", e); - return false; - } + return AudioSystem.isMicrophoneMuted(); } /** @@ -809,32 +824,39 @@ public class AudioManager { /* Routing bits for setRouting/getRouting API */ /** * Routing audio output to earpiece + * @deprecated */ - public static final int ROUTE_EARPIECE = AudioSystem.ROUTE_EARPIECE; + @Deprecated public static final int ROUTE_EARPIECE = AudioSystem.ROUTE_EARPIECE; /** * Routing audio output to spaker + * @deprecated */ - public static final int ROUTE_SPEAKER = AudioSystem.ROUTE_SPEAKER; + @Deprecated public static final int ROUTE_SPEAKER = AudioSystem.ROUTE_SPEAKER; /** * @deprecated use {@link #ROUTE_BLUETOOTH_SCO} + * @deprecated */ @Deprecated public static final int ROUTE_BLUETOOTH = AudioSystem.ROUTE_BLUETOOTH_SCO; /** * Routing audio output to bluetooth SCO + * @deprecated */ - public static final int ROUTE_BLUETOOTH_SCO = AudioSystem.ROUTE_BLUETOOTH_SCO; + @Deprecated public static final int ROUTE_BLUETOOTH_SCO = AudioSystem.ROUTE_BLUETOOTH_SCO; /** * Routing audio output to headset + * @deprecated */ - public static final int ROUTE_HEADSET = AudioSystem.ROUTE_HEADSET; + @Deprecated public static final int ROUTE_HEADSET = AudioSystem.ROUTE_HEADSET; /** * Routing audio output to bluetooth A2DP + * @deprecated */ - public static final int ROUTE_BLUETOOTH_A2DP = AudioSystem.ROUTE_BLUETOOTH_A2DP; + @Deprecated public static final int ROUTE_BLUETOOTH_A2DP = AudioSystem.ROUTE_BLUETOOTH_A2DP; /** * Used for mask parameter of {@link #setRouting(int,int,int)}. + * @deprecated */ - public static final int ROUTE_ALL = AudioSystem.ROUTE_ALL; + @Deprecated public static final int ROUTE_ALL = AudioSystem.ROUTE_ALL; /** * Sets the audio routing for a specified mode @@ -846,16 +868,10 @@ public class AudioManager { * 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. + * setBluetoothScoOn() methods instead. */ - + @Deprecated public void setRouting(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); - } } /** @@ -869,13 +885,7 @@ public class AudioManager { */ @Deprecated public int getRouting(int mode) { - IAudioService service = getService(); - try { - return service.getRouting(mode); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in getRouting", e); - return -1; - } + return -1; } /** @@ -884,13 +894,7 @@ public class AudioManager { * @return true if any music tracks are active. */ public boolean isMusicActive() { - IAudioService service = getService(); - try { - return service.isMusicActive(); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in isMusicActive", e); - return false; - } + return AudioSystem.isMusicActive(); } /* @@ -906,14 +910,32 @@ public class AudioManager { */ /** * @hide + * @deprecated Use {@link #setPrameters(String)} instead */ - public void setParameter(String key, String value) { - IAudioService service = getService(); - try { - service.setParameter(key, value); - } catch (RemoteException e) { - Log.e(TAG, "Dead object in setParameter", e); - } + @Deprecated public void setParameter(String key, String value) { + setParameters(key+"="+value); + } + + /** + * Sets a variable number of parameter values to audio hardware. + * + * @param keyValuePairs list of parameters key value pairs in the form: + * key1=value1;key2=value2;... + * + */ + public void setParameters(String keyValuePairs) { + AudioSystem.setParameters(keyValuePairs); + } + + /** + * Sets a varaible number of parameter values to audio hardware. + * + * @param keys list of parameters + * @return list of parameters key value pairs in the form: + * key1=value1;key2=value2;... + */ + public String getParameters(String keys) { + return AudioSystem.getParameters(keys); } /* Sound effect identifiers */ @@ -1082,31 +1104,4 @@ 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; - } - } - } diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 4d1535f..d96331f 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -86,7 +86,7 @@ public class AudioRecord public static final int ERROR_INVALID_OPERATION = -3; private static final int AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT = -16; - private static final int AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT = -17; + private static final int AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK = -17; private static final int AUDIORECORD_ERROR_SETUP_INVALIDFORMAT = -18; private static final int AUDIORECORD_ERROR_SETUP_INVALIDSOURCE = -19; private static final int AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED = -20; @@ -135,7 +135,7 @@ public class AudioRecord /** * The current audio channel configuration */ - private int mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; + private int mChannelConfiguration = AudioFormat.CHANNEL_IN_MONO; /** * The encoding of the audio samples. * @see AudioFormat#ENCODING_PCM_8BIT @@ -193,8 +193,8 @@ public class AudioRecord * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but * not limited to) 44100, 22050 and 11025. * @param channelConfig describes the configuration of the audio channels. - * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and - * {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO} + * See {@link AudioFormat#CHANNEL_IN_MONO} and + * {@link AudioFormat#CHANNEL_IN_STEREO} * @param audioFormat the format in which the audio data is represented. * See {@link AudioFormat#ENCODING_PCM_16BIT} and * {@link AudioFormat#ENCODING_PCM_8BIT} @@ -265,18 +265,18 @@ public class AudioRecord //-------------- // channel config switch (channelConfig) { - case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT: - case AudioFormat.CHANNEL_CONFIGURATION_MONO: + case AudioFormat.CHANNEL_IN_DEFAULT: + case AudioFormat.CHANNEL_IN_MONO: mChannelCount = 1; - mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; + mChannelConfiguration = AudioFormat.CHANNEL_IN_MONO; break; - case AudioFormat.CHANNEL_CONFIGURATION_STEREO: + case AudioFormat.CHANNEL_IN_STEREO: mChannelCount = 2; - mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO; + mChannelConfiguration = AudioFormat.CHANNEL_IN_STEREO; break; default: mChannelCount = 0; - mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_INVALID; + mChannelConfiguration = AudioFormat.CHANNEL_INVALID; throw (new IllegalArgumentException("Unsupported channel configuration.")); } @@ -368,8 +368,8 @@ public class AudioRecord /** * Returns the configured channel configuration. - * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} - * and {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}. + * See {@link AudioFormat#CHANNEL_IN_MONO} + * and {@link AudioFormat#CHANNEL_IN_STEREO}. */ public int getChannelConfiguration() { return mChannelConfiguration; @@ -425,8 +425,8 @@ public class AudioRecord * will be polled for new data. * @param sampleRateInHz the sample rate expressed in Hertz. * @param channelConfig describes the configuration of the audio channels. - * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and - * {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO} + * See {@link AudioFormat#CHANNEL_IN_MONO} and + * {@link AudioFormat#CHANNEL_IN_STEREO} * @param audioFormat the format in which the audio data is represented. * See {@link AudioFormat#ENCODING_PCM_16BIT}. * @return {@link #ERROR_BAD_VALUE} if the recording parameters are not supported by the @@ -438,14 +438,14 @@ public class AudioRecord static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) { int channelCount = 0; switch(channelConfig) { - case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT: - case AudioFormat.CHANNEL_CONFIGURATION_MONO: + case AudioFormat.CHANNEL_IN_DEFAULT: + case AudioFormat.CHANNEL_IN_MONO: channelCount = 1; break; - case AudioFormat.CHANNEL_CONFIGURATION_STEREO: + case AudioFormat.CHANNEL_IN_STEREO: channelCount = 2; break; - case AudioFormat.CHANNEL_CONFIGURATION_INVALID: + case AudioFormat.CHANNEL_INVALID: default: loge("getMinBufferSize(): Invalid channel configuration."); return AudioRecord.ERROR_BAD_VALUE; diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 58c04f3..177a7cf 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -20,6 +20,12 @@ import android.app.ActivityManagerNative; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; +import android.bluetooth.BluetoothIntent; +import android.content.BroadcastReceiver; +import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothA2dp; + import android.content.pm.PackageManager; import android.database.ContentObserver; import android.media.MediaPlayer.OnCompletionListener; @@ -94,16 +100,10 @@ public class AudioService extends IAudioService.Stub { /** @see VolumeStreamState */ private VolumeStreamState[] mStreamStates; private SettingsObserver mSettingsObserver; - - private boolean mMicMute; + private int mMode; - 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(); @@ -135,6 +135,23 @@ public class AudioService extends IAudioService.Stub { {4, -1} // FX_FOCUS_RETURN }; + /* STREAM_VOLUME_ALIAS[] indicates for each stream if it uses the volume settings + * of another stream: This avoids multiplying the volume settings for hidden + * stream types that follow other stream behavior for volume settings + * NOTE: do not create loops in aliases! */ + private int[] STREAM_VOLUME_ALIAS = new int[] { + AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL + AudioSystem.STREAM_SYSTEM, // STREAM_SYSTEM + AudioSystem.STREAM_RING, // STREAM_RING + AudioSystem.STREAM_MUSIC, // STREAM_MUSIC + AudioSystem.STREAM_ALARM, // STREAM_ALARM + AudioSystem.STREAM_NOTIFICATION, // STREAM_NOTIFICATION + AudioSystem.STREAM_VOICE_CALL, // STREAM_BLUETOOTH_SCO + AudioSystem.STREAM_SYSTEM, // STREAM_SYSTEM_ENFORCED + AudioSystem.STREAM_VOICE_CALL, // STREAM_DTMF + AudioSystem.STREAM_MUSIC // STREAM_TTS + }; + private AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() { public void onError(int error) { switch (error) { @@ -178,6 +195,21 @@ public class AudioService extends IAudioService.Stub { */ private int mVibrateSetting; + /** @see System#NOTIFICATIONS_USE_RING_VOLUME */ + private int mNotificationsUseRingVolume; + + // Broadcast receiver for device connections intent broadcasts + private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver(); + + //TODO: use common definitions with HeadsetObserver + private static final int BIT_HEADSET = (1 << 0); + private static final int BIT_HEADSET_NO_MIC = (1 << 1); + private static final int BIT_TTY = (1 << 2); + private static final int BIT_FM_HEADSET = (1 << 3); + private static final int BIT_FM_SPEAKER = (1 << 4); + + private int mHeadsetState; + /////////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////////// @@ -188,18 +220,20 @@ public class AudioService extends IAudioService.Stub { mContentResolver = context.getContentResolver(); mVolumePanel = new VolumePanel(context, this); mSettingsObserver = new SettingsObserver(); - + createAudioSystemThread(); - createStreamStates(); readPersistedSettings(); - readAudioSettings(); + createStreamStates(); mMediaServerOk = true; AudioSystem.setErrorCallback(mAudioSystemCallback); loadSoundEffects(); - mSpeakerIsOn = false; - mBluetoothScoIsConnected = false; - mHeadsetIsConnected = false; - mBluetoothA2dpIsConnected = false; + + // Register for device connection intent broadcasts. + IntentFilter intentFilter = + new IntentFilter(Intent.ACTION_HEADSET_PLUG); + intentFilter.addAction(BluetoothA2dp.SINK_STATE_CHANGED_ACTION); + intentFilter.addAction(BluetoothIntent.HEADSET_AUDIO_STATE_CHANGED_ACTION); + context.registerReceiver(mReceiver, intentFilter); } private void createAudioSystemThread() { @@ -223,63 +257,23 @@ public class AudioService extends IAudioService.Stub { } private void createStreamStates() { - final int[] volumeLevelsPhone = - createVolumeLevels(0, AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_VOICE_CALL]); - final int[] volumeLevelsCoarse = - createVolumeLevels(0, AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_SYSTEM]); - final int[] volumeLevelsFine = - createVolumeLevels(0, AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_MUSIC]); - final int[] volumeLevelsBtPhone = - createVolumeLevels(0, - AudioManager.MAX_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]); - int numStreamTypes = AudioSystem.getNumStreamTypes(); VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes]; for (int i = 0; i < numStreamTypes; i++) { - final int[] levels; - - switch (i) { - - case AudioSystem.STREAM_MUSIC: - levels = volumeLevelsFine; - break; - - case AudioSystem.STREAM_VOICE_CALL: - levels = volumeLevelsPhone; - break; - - case AudioSystem.STREAM_BLUETOOTH_SCO: - levels = volumeLevelsBtPhone; - break; - - default: - levels = volumeLevelsCoarse; - break; - } - - if (i == AudioSystem.STREAM_BLUETOOTH_SCO) { - streams[i] = new VolumeStreamState(AudioManager.DEFAULT_STREAM_VOLUME[i], i,levels); - } else { - streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[i], i, levels); - } + streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[STREAM_VOLUME_ALIAS[i]], i); } - } - private static int[] createVolumeLevels(int offset, int numlevels) { - double curve = 1.0f; // 1.4f - int [] volumes = new int[numlevels + offset]; - for (int i = 0; i < offset; i++) { - volumes[i] = 0; - } - - double val = 0; - double max = Math.pow(numlevels - 1, curve); - for (int i = 0; i < numlevels; i++) { - val = Math.pow(i, curve) / max; - volumes[offset + i] = (int) (val * 100.0f); + // Correct stream index values for streams with aliases + for (int i = 0; i < numStreamTypes; i++) { + if (STREAM_VOLUME_ALIAS[i] != i) { + int index = rescaleIndex(streams[i].mIndex, STREAM_VOLUME_ALIAS[i], i); + streams[i].mIndex = streams[i].getValidIndex(index); + setStreamVolumeIndex(i, index); + index = rescaleIndex(streams[i].mLastAudibleIndex, STREAM_VOLUME_ALIAS[i], i); + streams[i].mLastAudibleIndex = streams[i].getValidIndex(index); + } } - return volumes; } private void readPersistedSettings() { @@ -291,12 +285,19 @@ public class AudioService extends IAudioService.Stub { mRingerModeAffectedStreams = Settings.System.getInt(cr, Settings.System.MODE_RINGER_STREAMS_AFFECTED, - ((1 << AudioManager.STREAM_RING)|(1 << AudioManager.STREAM_NOTIFICATION)|(1 << AudioManager.STREAM_SYSTEM))); + ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)| + (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED))); mMuteAffectedStreams = System.getInt(cr, System.MUTE_STREAMS_AFFECTED, ((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM))); + mNotificationsUseRingVolume = System.getInt(cr, + Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1); + + if (mNotificationsUseRingVolume == 1) { + STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING; + } // Each stream will read its own persisted settings // Broadcast the sticky intent @@ -307,25 +308,13 @@ public class AudioService extends IAudioService.Stub { broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION); } - private void readAudioSettings() { - synchronized (mSettingsLock) { - mMicMute = AudioSystem.isMicrophoneMuted(); - mMode = AudioSystem.getMode(); - for (int mode = 0; mode < AudioSystem.NUM_MODES; mode++) { - mRoutes[mode] = AudioSystem.getRouting(mode); - } - } + private void setStreamVolumeIndex(int stream, int index) { + AudioSystem.setStreamVolumeIndex(stream, (index + 5)/10); } - private void applyAudioSettings() { - synchronized (mSettingsLock) { - AudioSystem.muteMicrophone(mMicMute); - AudioSystem.setMode(mMode); - for (int mode = 0; mode < AudioSystem.NUM_MODES; mode++) { - AudioSystem.setRouting(mode, mRoutes[mode], AudioSystem.ROUTE_ALL); - } - } - } + private int rescaleIndex(int index, int srcStream, int dstStream) { + return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex(); + } /////////////////////////////////////////////////////////////////////////// // IPC methods @@ -354,44 +343,26 @@ public class AudioService extends IAudioService.Stub { ensureValidDirection(direction); ensureValidStreamType(streamType); - boolean notificationsUseRingVolume = Settings.System.getInt(mContentResolver, - Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1) == 1; - if (notificationsUseRingVolume && streamType == AudioManager.STREAM_NOTIFICATION) { - // Redirect the volume change to the ring stream - streamType = AudioManager.STREAM_RING; - } - VolumeStreamState streamState = mStreamStates[streamType]; + VolumeStreamState streamState = mStreamStates[STREAM_VOLUME_ALIAS[streamType]]; final int oldIndex = streamState.mIndex; boolean adjustVolume = true; // If either the client forces allowing ringer modes for this adjustment, // or the stream type is one that is affected by ringer modes if ((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0 - || streamType == AudioManager.STREAM_RING) { + || streamType == AudioSystem.STREAM_RING) { // Check if the ringer mode changes with this volume adjustment. If // it does, it will handle adjusting the volume, so we won't below adjustVolume = checkForRingerModeChange(oldIndex, direction); } if (adjustVolume && streamState.adjustIndex(direction)) { - - boolean alsoUpdateNotificationVolume = notificationsUseRingVolume && - streamType == AudioManager.STREAM_RING; - if (alsoUpdateNotificationVolume) { - mStreamStates[AudioManager.STREAM_NOTIFICATION].adjustIndex(direction); - } - // Post message to set system volume (it in turn will post a message // to persist). Do not change volume if stream is muted. if (streamState.muteCount() == 0) { - sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, streamType, SENDMSG_NOOP, 0, 0, + sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, STREAM_VOLUME_ALIAS[streamType], SENDMSG_NOOP, 0, 0, streamState, 0); - - if (alsoUpdateNotificationVolume) { - sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, AudioManager.STREAM_NOTIFICATION, - SENDMSG_NOOP, 0, 0, mStreamStates[AudioManager.STREAM_NOTIFICATION], 0); - } } } @@ -404,9 +375,8 @@ public class AudioService extends IAudioService.Stub { /** @see AudioManager#setStreamVolume(int, int, int) */ public void setStreamVolume(int streamType, int index, int flags) { ensureValidStreamType(streamType); - syncRingerAndNotificationStreamVolume(streamType, index, false); - - setStreamVolumeInt(streamType, index, false, true); + index = rescaleIndex(index * 10, streamType, STREAM_VOLUME_ALIAS[streamType]); + setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, false, true); // UI, etc. mVolumePanel.postVolumeChanged(streamType, flags); @@ -420,37 +390,12 @@ public class AudioService extends IAudioService.Stub { intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, getStreamVolume(streamType)); // Currently, sending the intent only when the stream is BLUETOOTH_SCO - if (streamType == AudioManager.STREAM_BLUETOOTH_SCO) { + if (streamType == AudioSystem.STREAM_BLUETOOTH_SCO) { mContext.sendBroadcast(intent); } } /** - * Sync the STREAM_RING and STREAM_NOTIFICATION volumes if mandated by the - * value in Settings. - * - * @param streamType Type of the stream - * @param index Volume index for the stream - * @param force If true, set the volume even if the current and desired - * volume as same - */ - private void syncRingerAndNotificationStreamVolume(int streamType, int index, boolean force) { - boolean notificationsUseRingVolume = Settings.System.getInt(mContentResolver, - Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1) == 1; - if (notificationsUseRingVolume) { - if (streamType == AudioManager.STREAM_NOTIFICATION) { - // Redirect the volume change to the ring stream - streamType = AudioManager.STREAM_RING; - } - if (streamType == AudioManager.STREAM_RING) { - // One-off to sync notification volume to ringer volume - setStreamVolumeInt(AudioManager.STREAM_NOTIFICATION, index, force, true); - } - } - } - - - /** * Sets the stream state's index, and posts a message to set system volume. * This will not call out to the UI. Assumes a valid stream type. * @@ -491,13 +436,13 @@ public class AudioService extends IAudioService.Stub { /** @see AudioManager#getStreamVolume(int) */ public int getStreamVolume(int streamType) { ensureValidStreamType(streamType); - return mStreamStates[streamType].mIndex; + return (mStreamStates[streamType].mIndex + 5) / 10; } /** @see AudioManager#getStreamMaxVolume(int) */ public int getStreamMaxVolume(int streamType) { ensureValidStreamType(streamType); - return mStreamStates[streamType].getMaxIndex(); + return (mStreamStates[streamType].getMaxIndex() + 5) / 10; } /** @see AudioManager#getRingerMode() */ @@ -507,11 +452,12 @@ public class AudioService extends IAudioService.Stub { /** @see AudioManager#setRingerMode(int) */ public void setRingerMode(int ringerMode) { - if (ringerMode != mRingerMode) { - setRingerModeInt(ringerMode, true); - - // Send sticky broadcast - broadcastRingerMode(); + synchronized (mSettingsLock) { + if (ringerMode != mRingerMode) { + setRingerModeInt(ringerMode, true); + // Send sticky broadcast + broadcastRingerMode(); + } } } @@ -541,7 +487,7 @@ public class AudioService extends IAudioService.Stub { } } } - + // Post a persist ringer mode msg if (persist) { sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, SHARED_MSG, @@ -606,39 +552,28 @@ public class AudioService extends IAudioService.Stub { return existingValue; } - /** @see AudioManager#setMicrophoneMute(boolean) */ - public void setMicrophoneMute(boolean on) { - if (!checkAudioSettingsPermission("setMicrophoneMute()")) { - return; - } - synchronized (mSettingsLock) { - if (on != mMicMute) { - AudioSystem.muteMicrophone(on); - mMicMute = on; - } - } - } - - /** @see AudioManager#isMicrophoneMute() */ - public boolean isMicrophoneMute() { - return mMicMute; - } - /** @see AudioManager#setMode(int) */ public void setMode(int mode) { if (!checkAudioSettingsPermission("setMode()")) { return; } + + if (mode < AudioSystem.MODE_CURRENT || mode > AudioSystem.MODE_IN_CALL) { + return; + } + synchronized (mSettingsLock) { + if (mode == AudioSystem.MODE_CURRENT) { + mode = mMode; + } if (mode != mMode) { - if (AudioSystem.setMode(mode) == AudioSystem.AUDIO_STATUS_OK) { + if (AudioSystem.setPhoneState(mode) == AudioSystem.AUDIO_STATUS_OK) { mMode = mode; } } int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); - int index = mStreamStates[streamType].mIndex; - syncRingerAndNotificationStreamVolume(streamType, index, true); - setStreamVolumeInt(streamType, index, true, true); + int index = mStreamStates[STREAM_VOLUME_ALIAS[streamType]].mIndex; + setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, true, true); } } @@ -647,187 +582,6 @@ public class AudioService extends IAudioService.Stub { return mMode; } - /** @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) { - // 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 (routes == 0 && 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 (routes == 0 && 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 (routes == 0 && 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 (routes == 0 && 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, true); - } - } - } - - /** @see AudioManager#getRouting(int) */ - public int getRouting(int mode) { - return mRoutes[mode]; - } - - /** @see AudioManager#isMusicActive() */ - public boolean isMusicActive() { - return AudioSystem.isMusicActive(); - } - - /** @see AudioManager#setParameter(String, String) */ - public void setParameter(String key, String value) { - AudioSystem.setParameter(key, value); - } - /** @see AudioManager#playSoundEffect(int) */ public void playSoundEffect(int effectType) { sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SHARED_MSG, SENDMSG_NOOP, @@ -930,14 +684,28 @@ public class AudioService extends IAudioService.Stub { if (streamType != AudioSystem.STREAM_BLUETOOTH_SCO) { String settingName = System.VOLUME_SETTINGS[streamType]; String lastAudibleSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE; - - streamState.mIndex = streamState.getValidIndex(Settings.System.getInt(mContentResolver, - settingName, - AudioManager.DEFAULT_STREAM_VOLUME[streamType])); - streamState.mLastAudibleIndex = streamState.getValidIndex(Settings.System.getInt(mContentResolver, - lastAudibleSettingName, - streamState.mIndex > 0 ? streamState.mIndex : AudioManager.DEFAULT_STREAM_VOLUME[streamType])); + int index = Settings.System.getInt(mContentResolver, + settingName, + AudioManager.DEFAULT_STREAM_VOLUME[streamType]); + if (STREAM_VOLUME_ALIAS[streamType] != streamType) { + index = rescaleIndex(index * 10, STREAM_VOLUME_ALIAS[streamType], streamType); + } else { + index *= 10; + } + streamState.mIndex = streamState.getValidIndex(index); + + index = (index + 5) / 10; + index = Settings.System.getInt(mContentResolver, + lastAudibleSettingName, + (index > 0) ? index : AudioManager.DEFAULT_STREAM_VOLUME[streamType]); + if (STREAM_VOLUME_ALIAS[streamType] != streamType) { + index = rescaleIndex(index * 10, STREAM_VOLUME_ALIAS[streamType], streamType); + } else { + index *= 10; + } + streamState.mLastAudibleIndex = streamState.getValidIndex(index); } + // unmute stream that whas muted but is not affect by mute anymore if (streamState.muteCount() != 0 && !isStreamAffectedByMute(streamType)) { int size = streamState.mDeathHandlers.size(); @@ -948,7 +716,7 @@ public class AudioService extends IAudioService.Stub { } // apply stream volume if (streamState.muteCount() == 0) { - AudioSystem.setVolume(streamType, streamState.mVolumes[streamState.mIndex]); + setStreamVolumeIndex(streamType, streamState.mIndex); } } @@ -969,7 +737,7 @@ public class AudioService extends IAudioService.Stub { boolean adjustVolumeIndex = true; int newRingerMode = mRingerMode; - if (mRingerMode == AudioManager.RINGER_MODE_NORMAL && oldIndex == 1 + if (mRingerMode == AudioManager.RINGER_MODE_NORMAL && (oldIndex + 5) / 10 == 1 && direction == AudioManager.ADJUST_LOWER) { newRingerMode = AudioManager.RINGER_MODE_VIBRATE; } else if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) { @@ -1026,7 +794,7 @@ public class AudioService extends IAudioService.Stub { Log.w(TAG, "Couldn't connect to phone service", e); } - if ((getRouting(AudioSystem.MODE_IN_CALL) & AudioSystem.ROUTE_BLUETOOTH_SCO) != 0) { + if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) == AudioSystem.FORCE_BT_SCO) { // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO..."); return AudioSystem.STREAM_BLUETOOTH_SCO; } else if (isOffhook) { @@ -1110,47 +878,36 @@ public class AudioService extends IAudioService.Stub { private final String mLastAudibleVolumeIndexSettingName; private final int mStreamType; - private final int[] mVolumes; + private int mIndexMax; private int mIndex; private int mLastAudibleIndex; private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo requests client death - private VolumeStreamState(String settingName, int streamType, int[] volumes) { + private VolumeStreamState(String settingName, int streamType) { mVolumeIndexSettingName = settingName; mLastAudibleVolumeIndexSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE; mStreamType = streamType; - mVolumes = volumes; final ContentResolver cr = mContentResolver; - mIndex = getValidIndex(Settings.System.getInt(cr, mVolumeIndexSettingName, AudioManager.DEFAULT_STREAM_VOLUME[streamType])); - mLastAudibleIndex = getValidIndex(Settings.System.getInt(cr, - mLastAudibleVolumeIndexSettingName, mIndex > 0 ? mIndex : AudioManager.DEFAULT_STREAM_VOLUME[streamType])); - - AudioSystem.setVolume(streamType, volumes[mIndex]); - mDeathHandlers = new ArrayList<VolumeDeathHandler>(); - } - - /** - * Constructor to be used when there is no setting associated with the VolumeStreamState. - * - * @param defaultVolume Default volume of the stream to use. - * @param streamType Type of the stream. - * @param volumes Volumes levels associated with this stream. - */ - private VolumeStreamState(int defaultVolume, int streamType, int[] volumes) { - mVolumeIndexSettingName = null; - mLastAudibleVolumeIndexSettingName = null; - mIndex = mLastAudibleIndex = defaultVolume; - mStreamType = streamType; - mVolumes = volumes; - AudioSystem.setVolume(mStreamType, defaultVolume); + mIndexMax = AudioManager.MAX_STREAM_VOLUME[streamType]; + mIndex = Settings.System.getInt(cr, + mVolumeIndexSettingName, + AudioManager.DEFAULT_STREAM_VOLUME[streamType]); + mLastAudibleIndex = Settings.System.getInt(cr, + mLastAudibleVolumeIndexSettingName, + (mIndex > 0) ? mIndex : AudioManager.DEFAULT_STREAM_VOLUME[streamType]); + AudioSystem.initStreamVolume(streamType, 0, mIndexMax); + mIndexMax *= 10; + mIndex = getValidIndex(10 * mIndex); + mLastAudibleIndex = getValidIndex(10 * mLastAudibleIndex); + setStreamVolumeIndex(streamType, mIndex); mDeathHandlers = new ArrayList<VolumeDeathHandler>(); } public boolean adjustIndex(int deltaIndex) { - return setIndex(mIndex + deltaIndex, true); + return setIndex(mIndex + deltaIndex * 10, true); } public boolean setIndex(int index, boolean lastAudible) { @@ -1161,6 +918,13 @@ public class AudioService extends IAudioService.Stub { if (lastAudible) { mLastAudibleIndex = mIndex; } + // Apply change to all streams using this one as alias + int numStreamTypes = AudioSystem.getNumStreamTypes(); + for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { + if (streamType != mStreamType && STREAM_VOLUME_ALIAS[streamType] == mStreamType) { + mStreamStates[streamType].setIndex(rescaleIndex(mIndex, mStreamType, streamType), lastAudible); + } + } return true; } else { return false; @@ -1168,7 +932,7 @@ public class AudioService extends IAudioService.Stub { } public int getMaxIndex() { - return mVolumes.length - 1; + return mIndexMax; } public void mute(IBinder cb, boolean state) { @@ -1183,8 +947,8 @@ public class AudioService extends IAudioService.Stub { private int getValidIndex(int index) { if (index < 0) { return 0; - } else if (index >= mVolumes.length) { - return mVolumes.length - 1; + } else if (index > mIndexMax) { + return mIndexMax; } return index; @@ -1318,8 +1082,16 @@ public class AudioService extends IAudioService.Stub { private void setSystemVolume(VolumeStreamState streamState) { // Adjust volume - AudioSystem - .setVolume(streamState.mStreamType, streamState.mVolumes[streamState.mIndex]); + setStreamVolumeIndex(streamState.mStreamType, streamState.mIndex); + + // Apply change to all streams using this one as alias + int numStreamTypes = AudioSystem.getNumStreamTypes(); + for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { + if (streamType != streamState.mStreamType && + STREAM_VOLUME_ALIAS[streamType] == streamState.mStreamType) { + setStreamVolumeIndex(streamType, mStreamStates[streamType].mIndex); + } + } // Post a persist volume msg sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, streamState.mStreamType, @@ -1327,12 +1099,10 @@ public class AudioService extends IAudioService.Stub { } private void persistVolume(VolumeStreamState streamState) { - if (streamState.mStreamType != AudioManager.STREAM_BLUETOOTH_SCO) { - System.putInt(mContentResolver, streamState.mVolumeIndexSettingName, - streamState.mIndex); - System.putInt(mContentResolver, streamState.mLastAudibleVolumeIndexSettingName, - streamState.mLastAudibleIndex); - } + System.putInt(mContentResolver, streamState.mVolumeIndexSettingName, + (streamState.mIndex + 5)/ 10); + System.putInt(mContentResolver, streamState.mLastAudibleVolumeIndexSettingName, + (streamState.mLastAudibleIndex + 5) / 10); } private void persistRingerMode() { @@ -1426,18 +1196,17 @@ public class AudioService extends IAudioService.Stub { case MSG_MEDIA_SERVER_STARTED: Log.e(TAG, "Media server started."); - // Restore audio routing and stream volumes - applyAudioSettings(); + // Restore stream volumes int numStreamTypes = AudioSystem.getNumStreamTypes(); for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { - int volume; + int index; VolumeStreamState streamState = mStreamStates[streamType]; if (streamState.muteCount() == 0) { - volume = streamState.mVolumes[streamState.mIndex]; + index = streamState.mIndex; } else { - volume = streamState.mVolumes[0]; + index = 0; } - AudioSystem.setVolume(streamType, volume); + setStreamVolumeIndex(streamType, index); } setRingerMode(mRingerMode); mMediaServerOk = true; @@ -1451,28 +1220,144 @@ public class AudioService extends IAudioService.Stub { } private class SettingsObserver extends ContentObserver { - + SettingsObserver() { super(new Handler()); mContentResolver.registerContentObserver(Settings.System.getUriFor( Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this); + mContentResolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.NOTIFICATIONS_USE_RING_VOLUME), false, this); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); - - mRingerModeAffectedStreams = Settings.System.getInt(mContentResolver, - Settings.System.MODE_RINGER_STREAMS_AFFECTED, - 0); + synchronized (mSettingsLock) { + int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver, + Settings.System.MODE_RINGER_STREAMS_AFFECTED, + 0); + if (ringerModeAffectedStreams != mRingerModeAffectedStreams) { + /* + * Ensure all stream types that should be affected by ringer mode + * are in the proper state. + */ + mRingerModeAffectedStreams = ringerModeAffectedStreams; + setRingerModeInt(getRingerMode(), false); + } - /* - * Ensure all stream types that should be affected by ringer mode - * are in the proper state. - */ - setRingerModeInt(getRingerMode(), false); + int notificationsUseRingVolume = Settings.System.getInt(mContentResolver, + Settings.System.NOTIFICATIONS_USE_RING_VOLUME, + 1); + if (notificationsUseRingVolume != mNotificationsUseRingVolume) { + mNotificationsUseRingVolume = notificationsUseRingVolume; + if (mNotificationsUseRingVolume == 1) { + STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING; + } else { + STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_NOTIFICATION; + // Persist notification volume volume as it was not persisted while aliased to ring volume + sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, AudioSystem.STREAM_NOTIFICATION, + SENDMSG_REPLACE, 0, 0, mStreamStates[AudioSystem.STREAM_NOTIFICATION], PERSIST_DELAY); + } + } + } } - } - + + /** + * Receiver for misc intent broadcasts the Phone app cares about. + */ + private class AudioServiceBroadcastReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + + if (action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) { + int state = intent.getIntExtra(BluetoothA2dp.SINK_STATE, + BluetoothA2dp.STATE_DISCONNECTED); + String address = intent.getStringExtra(BluetoothIntent.ADDRESS); + if (state == BluetoothA2dp.STATE_DISCONNECTED) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + AudioSystem.DEVICE_STATE_UNAVAILABLE, + address); + } else if (state == BluetoothA2dp.STATE_CONNECTED){ + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + AudioSystem.DEVICE_STATE_AVAILABLE, + address); + } + } else if (action.equals(BluetoothIntent.HEADSET_AUDIO_STATE_CHANGED_ACTION)) { + int state = intent.getIntExtra(BluetoothIntent.HEADSET_AUDIO_STATE, + BluetoothHeadset.STATE_ERROR); + String address = intent.getStringExtra(BluetoothIntent.ADDRESS); + if (state == BluetoothHeadset.AUDIO_STATE_DISCONNECTED) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, + AudioSystem.DEVICE_STATE_UNAVAILABLE, + address); + } else if (state == BluetoothHeadset.AUDIO_STATE_CONNECTED) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, + AudioSystem.DEVICE_STATE_AVAILABLE, + address); + } + } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) { + int state = intent.getIntExtra("state", 0); + if ((state & BIT_HEADSET) == 0 && + (mHeadsetState & BIT_HEADSET) != 0) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET, + AudioSystem.DEVICE_STATE_UNAVAILABLE, + ""); + } else if ((state & BIT_HEADSET) != 0 && + (mHeadsetState & BIT_HEADSET) == 0) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET, + AudioSystem.DEVICE_STATE_AVAILABLE, + ""); + } + if ((state & BIT_HEADSET_NO_MIC) == 0 && + (mHeadsetState & BIT_HEADSET_NO_MIC) != 0) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, + AudioSystem.DEVICE_STATE_UNAVAILABLE, + ""); + } else if ((state & BIT_HEADSET_NO_MIC) != 0 && + (mHeadsetState & BIT_HEADSET_NO_MIC) == 0) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, + AudioSystem.DEVICE_STATE_AVAILABLE, + ""); + } + if ((state & BIT_TTY) == 0 && + (mHeadsetState & BIT_TTY) != 0) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_TTY, + AudioSystem.DEVICE_STATE_UNAVAILABLE, + ""); + } else if ((state & BIT_TTY) != 0 && + (mHeadsetState & BIT_TTY) == 0) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_TTY, + AudioSystem.DEVICE_STATE_AVAILABLE, + ""); + } + if ((state & BIT_FM_HEADSET) == 0 && + (mHeadsetState & BIT_FM_HEADSET) != 0) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_HEADPHONE, + AudioSystem.DEVICE_STATE_UNAVAILABLE, + ""); + } else if ((state & BIT_FM_HEADSET) != 0 && + (mHeadsetState & BIT_FM_HEADSET) == 0) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_HEADPHONE, + AudioSystem.DEVICE_STATE_AVAILABLE, + ""); + } + if ((state & BIT_FM_SPEAKER) == 0 && + (mHeadsetState & BIT_FM_SPEAKER) != 0) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_SPEAKER, + AudioSystem.DEVICE_STATE_UNAVAILABLE, + ""); + } else if ((state & BIT_FM_SPEAKER) != 0 && + (mHeadsetState & BIT_FM_SPEAKER) == 0) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_SPEAKER, + AudioSystem.DEVICE_STATE_AVAILABLE, + ""); + } + mHeadsetState = state; + } + } + } + + } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 5917ab9..d587f65 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -45,38 +45,21 @@ public class AudioSystem public static final int STREAM_NOTIFICATION = 5; /* @hide The audio stream for phone calls when connected on bluetooth */ public static final int STREAM_BLUETOOTH_SCO = 6; + /* @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */ + public static final int STREAM_SYSTEM_ENFORCED = 7; + /* @hide The audio stream for DTMF tones */ + public static final int STREAM_DTMF = 8; + /* @hide The audio stream for text to speech (TTS) */ + public static final int STREAM_TTS = 9; /** * @deprecated Use {@link #numStreamTypes() instead} */ public static final int NUM_STREAMS = 5; // Expose only the getter method publicly so we can change it in the future - private static final int NUM_STREAM_TYPES = 7; + private static final int NUM_STREAM_TYPES = 10; public static final int getNumStreamTypes() { return NUM_STREAM_TYPES; } - /* max and min volume levels */ - /* Maximum volume setting, for use with setVolume(int,int) */ - public static final int MAX_VOLUME = 100; - /* Minimum volume setting, for use with setVolume(int,int) */ - public static final int MIN_VOLUME = 0; - - /* - * Sets the volume of a specified audio stream. - * - * param type the stream type to set the volume of (e.g. STREAM_MUSIC) - * param volume the volume level to set (0-100) - * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR - */ - public static native int setVolume(int type, int volume); - - /* - * Returns the volume of a specified audio stream. - * - * param type the stream type to get the volume of (e.g. STREAM_MUSIC) - * return the current volume (0-100) - */ - public static native int getVolume(int type); - /* * Sets the microphone mute on or off. * @@ -101,17 +84,22 @@ public class AudioSystem * it can route the audio appropriately. * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR */ - public static native int setMode(int mode); - + /** @deprecated use {@link #setPhoneState(int)} */ + public static int setMode(int mode) { + return AUDIO_STATUS_ERROR; + } /* * Returns the current audio mode. * * return the current audio mode (NORMAL, RINGTONE, or IN_CALL). * Returns the current current audio state from the HAL. */ - public static native int getMode(); + /** @deprecated */ + public static int getMode() { + return MODE_INVALID; + } - /* modes for setMode/getMode/setRoute/getRoute */ + /* modes for setPhoneState */ public static final int MODE_INVALID = -2; public static final int MODE_CURRENT = -1; public static final int MODE_NORMAL = 0; @@ -121,15 +109,20 @@ public class AudioSystem /* Routing bits for setRouting/getRouting API */ - public static final int ROUTE_EARPIECE = (1 << 0); - public static final int ROUTE_SPEAKER = (1 << 1); - + /** @deprecated */ + @Deprecated public static final int ROUTE_EARPIECE = (1 << 0); + /** @deprecated */ + @Deprecated public static final int ROUTE_SPEAKER = (1 << 1); /** @deprecated use {@link #ROUTE_BLUETOOTH_SCO} */ @Deprecated public static final int ROUTE_BLUETOOTH = (1 << 2); - public static final int ROUTE_BLUETOOTH_SCO = (1 << 2); - public static final int ROUTE_HEADSET = (1 << 3); - public static final int ROUTE_BLUETOOTH_A2DP = (1 << 4); - public static final int ROUTE_ALL = 0xFFFFFFFF; + /** @deprecated */ + @Deprecated public static final int ROUTE_BLUETOOTH_SCO = (1 << 2); + /** @deprecated */ + @Deprecated public static final int ROUTE_HEADSET = (1 << 3); + /** @deprecated */ + @Deprecated public static final int ROUTE_BLUETOOTH_A2DP = (1 << 4); + /** @deprecated */ + @Deprecated public static final int ROUTE_ALL = 0xFFFFFFFF; /* * Sets the audio routing for a specified mode @@ -141,7 +134,10 @@ public class AudioSystem * ROUTE_xxx types. Unset bits indicate the route should be left unchanged * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR */ - public static native int setRouting(int mode, int routes, int mask); + /** @deprecated use {@link #setDeviceConnectionState(int,int,String)} */ + public static int setRouting(int mode, int routes, int mask) { + return AUDIO_STATUS_ERROR; + } /* * Returns the current audio routing bit vector for a specified mode. @@ -150,7 +146,10 @@ public class AudioSystem * return an audio route bit vector that can be compared with ROUTE_xxx * bits */ - public static native int getRouting(int mode); + /** @deprecated use {@link #getDeviceConnectionState(int,String)} */ + public static int getRouting(int mode) { + return 0; + } /* * Checks whether any music is active. @@ -160,17 +159,23 @@ public class AudioSystem public static native boolean isMusicActive(); /* - * Sets a generic audio configuration parameter. The use of these parameters + * Sets a group generic audio configuration parameters. The use of these parameters * are platform dependant, see libaudio * - * ** Temporary interface - DO NOT USE - * - * TODO: Replace with a more generic key:value get/set mechanism + * param keyValuePairs list of parameters key value pairs in the form: + * key1=value1;key2=value2;... + */ + public static native int setParameters(String keyValuePairs); + + /* + * Gets a group generic audio configuration parameters. The use of these parameters + * are platform dependant, see libaudio * - * param key name of parameter to set. Must not be null. - * param value value of parameter. Must not be null. + * param keys list of parameters + * return value: list of parameters key value pairs in the form: + * key1=value1;key2=value2;... */ - public static native void setParameter(String key, String value); + public static native String getParameters(String keys); /* private final static String TAG = "audio"; @@ -220,4 +225,68 @@ public class AudioSystem mErrorCallback.onError(error); } } + + /* + * AudioPolicyService methods + */ + + // output devices + public static final int DEVICE_OUT_EARPIECE = 0x1; + public static final int DEVICE_OUT_SPEAKER = 0x2; + public static final int DEVICE_OUT_WIRED_HEADSET = 0x4; + public static final int DEVICE_OUT_WIRED_HEADPHONE = 0x8; + public static final int DEVICE_OUT_BLUETOOTH_SCO = 0x10; + public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20; + public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40; + public static final int DEVICE_OUT_BLUETOOTH_A2DP = 0x80; + public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100; + public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200; + public static final int DEVICE_OUT_AUX_DIGITAL = 0x400; + public static final int DEVICE_OUT_FM_HEADPHONE = 0x800; + public static final int DEVICE_OUT_FM_SPEAKER = 0x1000; + public static final int DEVICE_OUT_TTY = 0x2000; + public static final int DEVICE_OUT_DEFAULT = 0x8000; + // input devices + public static final int DEVICE_IN_COMMUNICATION = 0x10000; + public static final int DEVICE_IN_AMBIENT = 0x20000; + public static final int DEVICE_IN_BUILTIN_MIC1 = 0x40000; + public static final int DEVICE_IN_BUILTIN_MIC2 = 0x80000; + public static final int DEVICE_IN_MIC_ARRAY = 0x100000; + public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x200000; + public static final int DEVICE_IN_WIRED_HEADSET = 0x400000; + public static final int DEVICE_IN_AUX_DIGITAL = 0x800000; + public static final int DEVICE_IN_DEFAULT = 0x80000000; + + // device states + public static final int DEVICE_STATE_UNAVAILABLE = 0; + public static final int DEVICE_STATE_AVAILABLE = 1; + + // phone state + public static final int PHONE_STATE_OFFCALL = 0; + public static final int PHONE_STATE_RINGING = 1; + public static final int PHONE_STATE_INCALL = 2; + + // config for setForceUse + public static final int FORCE_NONE = 0; + public static final int FORCE_SPEAKER = 1; + public static final int FORCE_HEADPHONES = 2; + public static final int FORCE_BT_SCO = 3; + public static final int FORCE_BT_A2DP = 4; + public static final int FORCE_WIRED_ACCESSORY = 5; + public static final int FORCE_DEFAULT = FORCE_NONE; + + // usage for serForceUse + public static final int FOR_COMMUNICATION = 0; + public static final int FOR_MEDIA = 1; + public static final int FOR_RECORD = 2; + + public static native int setDeviceConnectionState(int device, int state, String device_address); + public static native int getDeviceConnectionState(int device, String device_address); + public static native int setPhoneState(int state); + public static native int setRingerMode(int mode, int mask); + public static native int setForceUse(int usage, int config); + public static native int getForceUse(int usage); + public static native int initStreamVolume(int stream, int indexMin, int indexMax); + public static native int setStreamVolumeIndex(int stream, int index); + public static native int getStreamVolumeIndex(int stream); } diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 5f1be9d..7fbe965 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -120,7 +120,7 @@ public class AudioTrack public static final int ERROR_INVALID_OPERATION = -3; private static final int ERROR_NATIVESETUP_AUDIOSYSTEM = -16; - private static final int ERROR_NATIVESETUP_INVALIDCHANNELCOUNT = -17; + private static final int ERROR_NATIVESETUP_INVALIDCHANNELMASK = -17; private static final int ERROR_NATIVESETUP_INVALIDFORMAT = -18; private static final int ERROR_NATIVESETUP_INVALIDSTREAMTYPE = -19; private static final int ERROR_NATIVESETUP_NATIVEINITFAILED = -20; @@ -198,7 +198,7 @@ public class AudioTrack /** * The current audio channel configuration. */ - private int mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; + private int mChannelConfiguration = AudioFormat.CHANNEL_OUT_MONO; /** * The encoding of the audio samples. * @see AudioFormat#ENCODING_PCM_8BIT @@ -235,8 +235,8 @@ public class AudioTrack * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but * not limited to) 44100, 22050 and 11025. * @param channelConfig describes the configuration of the audio channels. - * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and - * {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO} + * See {@link AudioFormat#CHANNEL_OUT_MONO} and + * {@link AudioFormat#CHANNEL_OUT_STEREO} * @param audioFormat the format in which the audio data is represented. * See {@link AudioFormat#ENCODING_PCM_16BIT} and * {@link AudioFormat#ENCODING_PCM_8BIT} @@ -298,7 +298,8 @@ public class AudioTrack && (streamType != AudioManager.STREAM_RING) && (streamType != AudioManager.STREAM_SYSTEM) && (streamType != AudioManager.STREAM_VOICE_CALL) && (streamType != AudioManager.STREAM_NOTIFICATION) - && (streamType != AudioManager.STREAM_BLUETOOTH_SCO)) { + && (streamType != AudioManager.STREAM_BLUETOOTH_SCO) + && (streamType != AudioManager.STREAM_DTMF)) { throw (new IllegalArgumentException("Invalid stream type.")); } else { mStreamType = streamType; @@ -316,18 +317,18 @@ public class AudioTrack //-------------- // channel config switch (channelConfig) { - case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT: - case AudioFormat.CHANNEL_CONFIGURATION_MONO: + case AudioFormat.CHANNEL_OUT_DEFAULT: + case AudioFormat.CHANNEL_OUT_MONO: mChannelCount = 1; - mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO; + mChannelConfiguration = AudioFormat.CHANNEL_OUT_MONO; break; - case AudioFormat.CHANNEL_CONFIGURATION_STEREO: + case AudioFormat.CHANNEL_OUT_STEREO: mChannelCount = 2; - mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO; + mChannelConfiguration = AudioFormat.CHANNEL_OUT_STEREO; break; default: mChannelCount = 0; - mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_INVALID; + mChannelConfiguration = AudioFormat.CHANNEL_INVALID; throw(new IllegalArgumentException("Unsupported channel configuration.")); } @@ -452,8 +453,8 @@ public class AudioTrack /** * Returns the configured channel configuration. - * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} - * and {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}. + * See {@link AudioFormat#CHANNEL_OUT_MONO} + * and {@link AudioFormat#CHANNEL_OUT_STEREO}. */ public int getChannelConfiguration() { return mChannelConfiguration; @@ -531,8 +532,8 @@ public class AudioTrack * the expected frequency at which the buffer will be refilled with additional data to play. * @param sampleRateInHz the sample rate expressed in Hertz. * @param channelConfig describes the configuration of the audio channels. - * See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and - * {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO} + * See {@link AudioFormat#CHANNEL_OUT_MONO} and + * {@link AudioFormat#CHANNEL_OUT_STEREO} * @param audioFormat the format in which the audio data is represented. * See {@link AudioFormat#ENCODING_PCM_16BIT} and * {@link AudioFormat#ENCODING_PCM_8BIT} @@ -544,10 +545,10 @@ public class AudioTrack static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) { int channelCount = 0; switch(channelConfig) { - case AudioFormat.CHANNEL_CONFIGURATION_MONO: + case AudioFormat.CHANNEL_OUT_MONO: channelCount = 1; break; - case AudioFormat.CHANNEL_CONFIGURATION_STEREO: + case AudioFormat.CHANNEL_OUT_STEREO: channelCount = 2; break; default: diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 9a8264f..bb4252b 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -29,9 +29,9 @@ interface IAudioService { void setStreamVolume(int streamType, int index, int flags); - void setStreamSolo(int streamType, boolean state, IBinder cb); + void setStreamSolo(int streamType, boolean state, IBinder cb); - void setStreamMute(int streamType, boolean state, IBinder cb); + void setStreamMute(int streamType, boolean state, IBinder cb); int getStreamVolume(int streamType); @@ -46,23 +46,11 @@ interface IAudioService { int getVibrateSetting(int vibrateType); boolean shouldVibrate(int vibrateType); - - void setMicrophoneMute(boolean on); - - boolean isMicrophoneMute(); void setMode(int mode); int getMode(); - void setRouting(int mode, int routes, int mask); - - int getRouting(int mode); - - boolean isMusicActive(); - - void setParameter(String key, String value); - oneway void playSoundEffect(int effectType); oneway void playSoundEffectVolume(int effectType, float volume); diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java index 4fb0ead..2263605 100644 --- a/media/java/android/media/JetPlayer.java +++ b/media/java/android/media/JetPlayer.java @@ -89,7 +89,7 @@ public class JetPlayer // Jet rendering audio parameters private static final int JET_OUTPUT_RATE = 22050; // _SAMPLE_RATE_22050 in Android.mk private static final int JET_OUTPUT_CHANNEL_CONFIG = - AudioFormat.CHANNEL_CONFIGURATION_STEREO; // NUM_OUTPUT_CHANNELS=2 in Android.mk + AudioFormat.CHANNEL_OUT_STEREO; // NUM_OUTPUT_CHANNELS=2 in Android.mk //-------------------------------------------- diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java index e5ee9a3..c60a1ac 100644 --- a/media/java/android/media/ToneGenerator.java +++ b/media/java/android/media/ToneGenerator.java @@ -724,9 +724,9 @@ public class ToneGenerator public static final int TONE_CDMA_SIGNAL_OFF = 98; /** Maximum volume, for use with {@link #ToneGenerator(int,int)} */ - public static final int MAX_VOLUME = AudioSystem.MAX_VOLUME; + public static final int MAX_VOLUME = 100; /** Minimum volume setting, for use with {@link #ToneGenerator(int,int)} */ - public static final int MIN_VOLUME = AudioSystem.MIN_VOLUME; + public static final int MIN_VOLUME = 0; /** |