diff options
author | Eric Laurent <elaurent@google.com> | 2011-11-18 16:43:31 -0800 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2012-01-17 15:15:04 -0800 |
commit | 9bc8358ddaa01c3490f9709991989633a6a3dd42 (patch) | |
tree | 12568959bb7bfd308ff2ef98c2e1ce0902ebdcd3 /media | |
parent | cc767191cfb675f744e0165608b0a4196aba2b37 (diff) | |
download | frameworks_base-9bc8358ddaa01c3490f9709991989633a6a3dd42.zip frameworks_base-9bc8358ddaa01c3490f9709991989633a6a3dd42.tar.gz frameworks_base-9bc8358ddaa01c3490f9709991989633a6a3dd42.tar.bz2 |
audio framework: manage stream volume per device
Improve volume management by keeping track of volume for each type
of device independently.
Volume for each stream (MUSIC, RINGTONE, VOICE_CALL...) is now maintained
per device.
The main changes are:
- AudioService now keeps tracks of stream volumes per device:
volume indexes are kept in a HashMap < device , index>.
active device is queried from policy manager when a volume change request
is received
initalization, mute and unmute happen on all device simultaneously
- Settings: suffixes is added to volume keys to store each device
volume independently.
- AudioSystem/AudioPolicyService/AudioPolicyInterface: added a device argument
to setStreamVolumeIndex() and getStreamVolumeIndex() to address each
device independently.
- AudioPolicyManagerBase: keep track of stream volumes for each device
and apply volume according to current device selection.
Change-Id: I61ef1c45caadca04d16363bca4140e0f81901b3f
Diffstat (limited to 'media')
-rw-r--r-- | media/java/android/media/AudioService.java | 389 | ||||
-rw-r--r-- | media/java/android/media/AudioSystem.java | 70 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 12 | ||||
-rw-r--r-- | media/libmedia/IAudioPolicyService.cpp | 19 |
4 files changed, 363 insertions, 127 deletions
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 72876d7..2eafd68 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -110,7 +110,7 @@ public class AudioService extends IAudioService.Stub { private static final int SENDMSG_QUEUE = 2; // AudioHandler message.whats - private static final int MSG_SET_SYSTEM_VOLUME = 0; + private static final int MSG_SET_DEVICE_VOLUME = 0; private static final int MSG_PERSIST_VOLUME = 1; private static final int MSG_PERSIST_RINGER_MODE = 3; private static final int MSG_PERSIST_VIBRATE_SETTING = 4; @@ -124,6 +124,7 @@ public class AudioService extends IAudioService.Stub { private static final int MSG_BT_HEADSET_CNCT_FAILED = 12; private static final int MSG_RCDISPLAY_CLEAR = 13; private static final int MSG_RCDISPLAY_UPDATE = 14; + private static final int MSG_SET_ALL_VOLUMES = 15; // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be @@ -329,6 +330,7 @@ public class AudioService extends IAudioService.Stub { // Keyguard manager proxy private KeyguardManager mKeyguardManager; + /////////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////////// @@ -431,12 +433,17 @@ public class AudioService extends IAudioService.Stub { // Correct stream index values for streams with aliases for (int i = 0; i < numStreamTypes; i++) { + int device = getDeviceForStream(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); + int index = rescaleIndex(streams[i].getIndex(device, false /* lastAudible */), + STREAM_VOLUME_ALIAS[i], + i); + streams[i].mIndex.put(device, streams[i].getValidIndex(index)); + streams[i].applyDeviceVolume(device); + index = rescaleIndex(streams[i].getIndex(device, true /* lastAudible */), + STREAM_VOLUME_ALIAS[i], + i); + streams[i].mLastAudibleIndex.put(device, streams[i].getValidIndex(index)); } } } @@ -488,10 +495,6 @@ public class AudioService extends IAudioService.Stub { restoreMediaButtonReceiver(); } - private void setStreamVolumeIndex(int stream, int index) { - AudioSystem.setStreamVolumeIndex(stream, (index + 5)/10); - } - private int rescaleIndex(int index, int srcStream, int dstStream) { return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex(); } @@ -535,7 +538,11 @@ public class AudioService extends IAudioService.Stub { // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION) int streamTypeAlias = STREAM_VOLUME_ALIAS[streamType]; VolumeStreamState streamState = mStreamStates[streamTypeAlias]; - final int oldIndex = (streamState.muteCount() != 0) ? streamState.mLastAudibleIndex : streamState.mIndex; + + final int device = getDeviceForStream(streamTypeAlias); + // get last audible index if stream is muted, current index otherwise + final int oldIndex = streamState.getIndex(device, + (streamState.muteCount() != 0) /* lastAudible */); boolean adjustVolume = true; // If either the client forces allowing ringer modes for this adjustment, @@ -564,32 +571,32 @@ public class AudioService extends IAudioService.Stub { if (STREAM_VOLUME_ALIAS[i] == streamTypeAlias) { VolumeStreamState s = mStreamStates[i]; - s.adjustLastAudibleIndex(direction); + s.adjustLastAudibleIndex(direction, device); // Post a persist volume msg sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, SENDMSG_REPLACE, PERSIST_LAST_AUDIBLE, - 0, + device, s, PERSIST_DELAY); } } } - index = streamState.mLastAudibleIndex; + index = streamState.getIndex(device, true /* lastAudible */); } else { - if (adjustVolume && streamState.adjustIndex(direction)) { + if (adjustVolume && streamState.adjustIndex(direction, device)) { // Post message to set system volume (it in turn will post a message // to persist). Do not change volume if stream is muted. sendMsg(mAudioHandler, - MSG_SET_SYSTEM_VOLUME, + MSG_SET_DEVICE_VOLUME, SENDMSG_NOOP, - 0, + device, 0, streamState, 0); } - index = streamState.mIndex; + index = streamState.getIndex(device, false /* lastAudible */); } sendVolumeUpdate(streamType, oldIndex, index, flags); @@ -600,7 +607,10 @@ public class AudioService extends IAudioService.Stub { ensureValidStreamType(streamType); VolumeStreamState streamState = mStreamStates[STREAM_VOLUME_ALIAS[streamType]]; - final int oldIndex = (streamState.muteCount() != 0) ? streamState.mLastAudibleIndex : streamState.mIndex; + final int device = getDeviceForStream(streamType); + // get last audible index if stream is muted, current index otherwise + final int oldIndex = streamState.getIndex(device, + (streamState.muteCount() != 0) /* lastAudible */); // setting ring or notifications volume to 0 on voice capable devices enters silent mode if (mVoiceCapable && (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || @@ -610,7 +620,11 @@ public class AudioService extends IAudioService.Stub { newRingerMode = System.getInt(mContentResolver, System.VIBRATE_IN_SILENT, 1) == 1 ? AudioManager.RINGER_MODE_VIBRATE : AudioManager.RINGER_MODE_SILENT; - setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, false, true); + setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], + index, + device, + false, + true); } else { newRingerMode = AudioManager.RINGER_MODE_NORMAL; } @@ -618,9 +632,10 @@ public class AudioService extends IAudioService.Stub { } index = rescaleIndex(index * 10, streamType, STREAM_VOLUME_ALIAS[streamType]); - setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, false, true); - - index = (streamState.muteCount() != 0) ? streamState.mLastAudibleIndex : streamState.mIndex; + setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, device, false, true); + // get last audible index if stream is muted, current index otherwise + index = streamState.getIndex(device, + (streamState.muteCount() != 0) /* lastAudible */); sendVolumeUpdate(streamType, oldIndex, index, flags); } @@ -648,35 +663,40 @@ public class AudioService extends IAudioService.Stub { * * @param streamType Type of the stream * @param index Desired volume index of the stream + * @param device the device whose volume must be changed * @param force If true, set the volume even if the desired volume is same * as the current volume. * @param lastAudible If true, stores new index as last audible one */ - private void setStreamVolumeInt(int streamType, int index, boolean force, boolean lastAudible) { + private void setStreamVolumeInt(int streamType, + int index, + int device, + boolean force, + boolean lastAudible) { VolumeStreamState streamState = mStreamStates[streamType]; // If stream is muted, set last audible index only if (streamState.muteCount() != 0) { // Do not allow last audible index to be 0 if (index != 0) { - streamState.setLastAudibleIndex(index); + streamState.setLastAudibleIndex(index, device); // Post a persist volume msg sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, SENDMSG_REPLACE, PERSIST_LAST_AUDIBLE, - 0, + device, streamState, PERSIST_DELAY); } } else { - if (streamState.setIndex(index, lastAudible) || force) { + if (streamState.setIndex(index, device, lastAudible) || force) { // Post message to set system volume (it in turn will post a message // to persist). sendMsg(mAudioHandler, - MSG_SET_SYSTEM_VOLUME, + MSG_SET_DEVICE_VOLUME, SENDMSG_NOOP, - 0, + device, 0, streamState, 0); @@ -708,7 +728,8 @@ public class AudioService extends IAudioService.Stub { /** @see AudioManager#getStreamVolume(int) */ public int getStreamVolume(int streamType) { ensureValidStreamType(streamType); - return (mStreamStates[streamType].mIndex + 5) / 10; + int device = getDeviceForStream(streamType); + return (mStreamStates[streamType].getIndex(device, false /* lastAudible */) + 5) / 10; } /** @see AudioManager#getStreamMaxVolume(int) */ @@ -721,7 +742,8 @@ public class AudioService extends IAudioService.Stub { /** Get last audible volume before stream was muted. */ public int getLastAudibleStreamVolume(int streamType) { ensureValidStreamType(streamType); - return (mStreamStates[streamType].mLastAudibleIndex + 5) / 10; + int device = getDeviceForStream(streamType); + return (mStreamStates[streamType].getIndex(device, true /* lastAudible */) + 5) / 10; } /** @see AudioManager#getRingerMode() */ @@ -764,9 +786,16 @@ public class AudioService extends IAudioService.Stub { // ring and notifications volume should never be 0 when not silenced // on voice capable devices if (mVoiceCapable && - STREAM_VOLUME_ALIAS[streamType] == AudioSystem.STREAM_RING && - mStreamStates[streamType].mLastAudibleIndex == 0) { - mStreamStates[streamType].mLastAudibleIndex = 10; + STREAM_VOLUME_ALIAS[streamType] == AudioSystem.STREAM_RING) { + + Set set = mStreamStates[streamType].mLastAudibleIndex.entrySet(); + Iterator i = set.iterator(); + while (i.hasNext()) { + Map.Entry entry = (Map.Entry)i.next(); + if ((Integer)entry.getValue() == 0) { + entry.setValue(10); + } + } } mStreamStates[streamType].mute(null, false); mRingerModeMutedStreams &= ~(1 << streamType); @@ -988,8 +1017,9 @@ public class AudioService extends IAudioService.Stub { } } int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); - int index = mStreamStates[STREAM_VOLUME_ALIAS[streamType]].mIndex; - setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, true, false); + int device = getDeviceForStream(streamType); + int index = mStreamStates[STREAM_VOLUME_ALIAS[streamType]].getIndex(device, false); + setStreamVolumeInt(STREAM_VOLUME_ALIAS[streamType], index, device, true, false); } return newModeOwnerPid; } @@ -1253,28 +1283,7 @@ public class AudioService extends IAudioService.Stub { for (int streamType = 0; streamType < numStreamTypes; streamType++) { VolumeStreamState streamState = mStreamStates[streamType]; - String settingName = System.VOLUME_SETTINGS[STREAM_VOLUME_ALIAS[streamType]]; - String lastAudibleSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE; - 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); + streamState.readSettings(); // unmute stream that was muted but is not affect by mute anymore if (streamState.muteCount() != 0 && !isStreamAffectedByMute(streamType)) { @@ -1286,7 +1295,7 @@ public class AudioService extends IAudioService.Stub { } // apply stream volume if (streamState.muteCount() == 0) { - setStreamVolumeIndex(streamType, streamState.mIndex); + streamState.applyAllVolumes(); } } @@ -1877,6 +1886,22 @@ public class AudioService extends IAudioService.Stub { return false; } + private int getDeviceForStream(int stream) { + int device = AudioSystem.getDevicesForStream(stream); + if ((device & (device - 1)) != 0) { + // Multiple device selection is either: + // - speaker + one other device: give priority to speaker in this case. + // - one A2DP device + another device: happens with duplicated output. In this case + // retain the device on the A2DP output as the other must not correspond to an active + // selection if not the speaker. + if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) { + device = AudioSystem.DEVICE_OUT_SPEAKER; + } else { + device &= AudioSystem.DEVICE_OUT_ALL_A2DP; + } + } + return device; + } /////////////////////////////////////////////////////////////////////////// // Inner classes @@ -1888,54 +1913,127 @@ public class AudioService extends IAudioService.Stub { private String mVolumeIndexSettingName; private String mLastAudibleVolumeIndexSettingName; private int mIndexMax; - private int mIndex; - private int mLastAudibleIndex; - private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo requests client death + private final HashMap <Integer, Integer> mIndex = new HashMap <Integer, Integer>(); + private final HashMap <Integer, Integer> mLastAudibleIndex = + new HashMap <Integer, Integer>(); + private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death private VolumeStreamState(String settingName, int streamType) { - setVolumeIndexSettingName(settingName); + mVolumeIndexSettingName = settingName; + mLastAudibleVolumeIndexSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE; mStreamType = streamType; - - final ContentResolver cr = mContentResolver; mIndexMax = 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); + + readSettings(); + + applyAllVolumes(); + mDeathHandlers = new ArrayList<VolumeDeathHandler>(); } - public void setVolumeIndexSettingName(String settingName) { - mVolumeIndexSettingName = settingName; - mLastAudibleVolumeIndexSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE; + public String getSettingNameForDevice(boolean lastAudible, int device) { + String name = lastAudible ? + mLastAudibleVolumeIndexSettingName : + mVolumeIndexSettingName; + String suffix = AudioSystem.getDeviceName(device); + if (suffix.isEmpty()) { + return name; + } + return name + "_" + suffix; + } + + public void readSettings() { + int index = Settings.System.getInt(mContentResolver, + mVolumeIndexSettingName, + AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]); + + mIndex.clear(); + mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index); + + index = Settings.System.getInt(mContentResolver, + mLastAudibleVolumeIndexSettingName, + (index > 0) ? index : AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]); + mLastAudibleIndex.clear(); + mLastAudibleIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index); + + int remainingDevices = AudioSystem.DEVICE_OUT_ALL; + for (int i = 0; remainingDevices != 0; i++) { + int device = (1 << i); + if ((device & remainingDevices) == 0) { + continue; + } + remainingDevices &= ~device; + + // retrieve current volume for device + String name = getSettingNameForDevice(false, device); + index = Settings.System.getInt(mContentResolver, name, -1); + if (index == -1) { + continue; + } + mIndex.put(device, getValidIndex(10 * index)); + + // retrieve last audible volume for device + name = getSettingNameForDevice(true, device); + index = Settings.System.getInt(mContentResolver, name, -1); + mLastAudibleIndex.put(device, getValidIndex(10 * index)); + } } - public boolean adjustIndex(int deltaIndex) { - return setIndex(mIndex + deltaIndex * 10, true); + public void applyDeviceVolume(int device) { + AudioSystem.setStreamVolumeIndex(mStreamType, + (getIndex(device, false /* lastAudible */) + 5)/10, + device); } - public boolean setIndex(int index, boolean lastAudible) { - int oldIndex = mIndex; - mIndex = getValidIndex(index); + public void applyAllVolumes() { + // apply default volume first: by convention this will reset all + // devices volumes in audio policy manager to the supplied value + AudioSystem.setStreamVolumeIndex(mStreamType, + (getIndex(AudioSystem.DEVICE_OUT_DEFAULT, false /* lastAudible */) + 5)/10, + AudioSystem.DEVICE_OUT_DEFAULT); + // then apply device specific volumes + Set set = mIndex.entrySet(); + Iterator i = set.iterator(); + while (i.hasNext()) { + Map.Entry entry = (Map.Entry)i.next(); + int device = ((Integer)entry.getKey()).intValue(); + if (device != AudioSystem.DEVICE_OUT_DEFAULT) { + AudioSystem.setStreamVolumeIndex(mStreamType, + ((Integer)entry.getValue() + 5)/10, + device); + } + } + } + + public boolean adjustIndex(int deltaIndex, int device) { + return setIndex(getIndex(device, + false /* lastAudible */) + deltaIndex * 10, + device, + true /* lastAudible */); + } - if (oldIndex != mIndex) { + public boolean setIndex(int index, int device, boolean lastAudible) { + int oldIndex = getIndex(device, false /* lastAudible */); + index = getValidIndex(index); + mIndex.put(device, getValidIndex(index)); + + if (oldIndex != index) { if (lastAudible) { - mLastAudibleIndex = mIndex; + mLastAudibleIndex.put(device, index); } // 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); + mStreamStates[streamType].setIndex(rescaleIndex(index, + mStreamType, + streamType), + device, + lastAudible); } } return true; @@ -1944,12 +2042,29 @@ public class AudioService extends IAudioService.Stub { } } - public void setLastAudibleIndex(int index) { - mLastAudibleIndex = getValidIndex(index); + public int getIndex(int device, boolean lastAudible) { + HashMap <Integer, Integer> indexes; + if (lastAudible) { + indexes = mLastAudibleIndex; + } else { + indexes = mIndex; + } + Integer index = indexes.get(device); + if (index == null) { + // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT + index = indexes.get(AudioSystem.DEVICE_OUT_DEFAULT); + } + return index.intValue(); + } + + public void setLastAudibleIndex(int index, int device) { + mLastAudibleIndex.put(device, getValidIndex(index)); } - public void adjustLastAudibleIndex(int deltaIndex) { - setLastAudibleIndex(mLastAudibleIndex + deltaIndex * 10); + public void adjustLastAudibleIndex(int deltaIndex, int device) { + setLastAudibleIndex(getIndex(device, + true /* lastAudible */) + deltaIndex * 10, + device); } public int getMaxIndex() { @@ -1994,10 +2109,20 @@ public class AudioService extends IAudioService.Stub { mICallback.linkToDeath(this, 0); } mDeathHandlers.add(this); - // If the stream is not yet muted by any client, set lvel to 0 + // If the stream is not yet muted by any client, set level to 0 if (muteCount() == 0) { - setIndex(0, false); - sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, SENDMSG_NOOP, 0, 0, + Set set = mIndex.entrySet(); + Iterator i = set.iterator(); + while (i.hasNext()) { + Map.Entry entry = (Map.Entry)i.next(); + int device = ((Integer)entry.getKey()).intValue(); + setIndex(0, device, false /* lastAudible */); + } + sendMsg(mAudioHandler, + MSG_SET_ALL_VOLUMES, + SENDMSG_NOOP, + 0, + 0, VolumeStreamState.this, 0); } } catch (RemoteException e) { @@ -2026,9 +2151,22 @@ public class AudioService extends IAudioService.Stub { // If the stream is not muted any more, restore it's volume if // ringer mode allows it if (!isStreamAffectedByRingerMode(mStreamType) || - getRingerMode() == AudioManager.RINGER_MODE_NORMAL) { - setIndex(mLastAudibleIndex, false); - sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, SENDMSG_NOOP, 0, 0, + mRingerMode == AudioManager.RINGER_MODE_NORMAL) { + Set set = mIndex.entrySet(); + Iterator i = set.iterator(); + while (i.hasNext()) { + Map.Entry entry = (Map.Entry)i.next(); + int device = ((Integer)entry.getKey()).intValue(); + setIndex(getIndex(device, + true /* lastAudible */), + device, + false /* lastAudible */); + } + sendMsg(mAudioHandler, + MSG_SET_ALL_VOLUMES, + SENDMSG_NOOP, + 0, + 0, VolumeStreamState.this, 0); } } @@ -2107,17 +2245,17 @@ public class AudioService extends IAudioService.Stub { /** Handles internal volume messages in separate volume thread. */ private class AudioHandler extends Handler { - private void setSystemVolume(VolumeStreamState streamState) { + private void setDeviceVolume(VolumeStreamState streamState, int device) { - // Adjust volume - setStreamVolumeIndex(streamState.mStreamType, streamState.mIndex); + // Apply volume + streamState.applyDeviceVolume(device); // 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); + STREAM_VOLUME_ALIAS[streamType] == streamState.mStreamType) { + mStreamStates[streamType].applyDeviceVolume(device); } } @@ -2126,21 +2264,39 @@ public class AudioService extends IAudioService.Stub { MSG_PERSIST_VOLUME, SENDMSG_REPLACE, PERSIST_CURRENT|PERSIST_LAST_AUDIBLE, - 0, + device, streamState, PERSIST_DELAY); } + private void setAllVolumes(VolumeStreamState streamState) { + + // Apply volume + streamState.applyAllVolumes(); + + // 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) { + mStreamStates[streamType].applyAllVolumes(); + } + } + } + private void persistVolume(VolumeStreamState streamState, - int persistType) { + int persistType, + int device) { if ((persistType & PERSIST_CURRENT) != 0) { - System.putInt(mContentResolver, streamState.mVolumeIndexSettingName, - (streamState.mIndex + 5)/ 10); + System.putInt(mContentResolver, + streamState.getSettingNameForDevice(false /* lastAudible */, device), + (streamState.getIndex(device, false /* lastAudible */) + 5)/ 10); } if ((persistType & PERSIST_LAST_AUDIBLE) != 0) { - System.putInt(mContentResolver, streamState.mLastAudibleVolumeIndexSettingName, - (streamState.mLastAudibleIndex + 5) / 10); + System.putInt(mContentResolver, + streamState.getSettingNameForDevice(true /* lastAudible */, device), + (streamState.getIndex(device, true /* lastAudible */) + 5) / 10); } } @@ -2223,12 +2379,16 @@ public class AudioService extends IAudioService.Stub { switch (msg.what) { - case MSG_SET_SYSTEM_VOLUME: - setSystemVolume((VolumeStreamState) msg.obj); + case MSG_SET_DEVICE_VOLUME: + setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1); + break; + + case MSG_SET_ALL_VOLUMES: + setAllVolumes((VolumeStreamState) msg.obj); break; case MSG_PERSIST_VOLUME: - persistVolume((VolumeStreamState) msg.obj, msg.arg1); + persistVolume((VolumeStreamState) msg.obj, msg.arg1, msg.arg2); break; case MSG_PERSIST_RINGER_MODE: @@ -2264,7 +2424,7 @@ public class AudioService extends IAudioService.Stub { synchronized (mConnectedDevices) { Set set = mConnectedDevices.entrySet(); Iterator i = set.iterator(); - while(i.hasNext()){ + while (i.hasNext()) { Map.Entry device = (Map.Entry)i.next(); AudioSystem.setDeviceConnectionState( ((Integer)device.getKey()).intValue(), @@ -2282,15 +2442,10 @@ public class AudioService extends IAudioService.Stub { // Restore stream volumes int numStreamTypes = AudioSystem.getNumStreamTypes(); for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { - int index; VolumeStreamState streamState = mStreamStates[streamType]; AudioSystem.initStreamVolume(streamType, 0, (streamState.mIndexMax + 5) / 10); - if (streamState.muteCount() == 0) { - index = streamState.mIndex; - } else { - index = 0; - } - setStreamVolumeIndex(streamType, index); + + streamState.applyAllVolumes(); } // Restore ringer mode diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 474a842..81145d3 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -183,6 +183,7 @@ public class AudioSystem } } + /* * AudioPolicyService methods */ @@ -202,6 +203,23 @@ public class AudioSystem public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800; public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000; public static final int DEVICE_OUT_DEFAULT = 0x8000; + public static final int DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | + DEVICE_OUT_SPEAKER | + DEVICE_OUT_WIRED_HEADSET | + DEVICE_OUT_WIRED_HEADPHONE | + DEVICE_OUT_BLUETOOTH_SCO | + DEVICE_OUT_BLUETOOTH_SCO_HEADSET | + DEVICE_OUT_BLUETOOTH_SCO_CARKIT | + DEVICE_OUT_BLUETOOTH_A2DP | + DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | + DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | + DEVICE_OUT_AUX_DIGITAL | + DEVICE_OUT_ANLG_DOCK_HEADSET | + DEVICE_OUT_DGTL_DOCK_HEADSET | + DEVICE_OUT_DEFAULT); + public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | + DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | + DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER); // input devices public static final int DEVICE_IN_COMMUNICATION = 0x10000; public static final int DEVICE_IN_AMBIENT = 0x20000; @@ -218,6 +236,54 @@ public class AudioSystem public static final int DEVICE_STATE_AVAILABLE = 1; private static final int NUM_DEVICE_STATES = 1; + public static final String DEVICE_OUT_EARPIECE_NAME = "earpiece"; + public static final String DEVICE_OUT_SPEAKER_NAME = "speaker"; + public static final String DEVICE_OUT_WIRED_HEADSET_NAME = "headset"; + public static final String DEVICE_OUT_WIRED_HEADPHONE_NAME = "headphone"; + public static final String DEVICE_OUT_BLUETOOTH_SCO_NAME = "bt_sco"; + public static final String DEVICE_OUT_BLUETOOTH_SCO_HEADSET_NAME = "bt_sco_hs"; + public static final String DEVICE_OUT_BLUETOOTH_SCO_CARKIT_NAME = "bt_sco_carkit"; + public static final String DEVICE_OUT_BLUETOOTH_A2DP_NAME = "bt_a2dp"; + public static final String DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES_NAME = "bt_a2dp_hp"; + public static final String DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER_NAME = "bt_a2dp_spk"; + public static final String DEVICE_OUT_AUX_DIGITAL_NAME = "aux_digital"; + public static final String DEVICE_OUT_ANLG_DOCK_HEADSET_NAME = "analog_dock"; + public static final String DEVICE_OUT_DGTL_DOCK_HEADSET_NAME = "digital_dock"; + + public static String getDeviceName(int device) + { + switch(device) { + case DEVICE_OUT_EARPIECE: + return DEVICE_OUT_EARPIECE_NAME; + case DEVICE_OUT_SPEAKER: + return DEVICE_OUT_SPEAKER_NAME; + case DEVICE_OUT_WIRED_HEADSET: + return DEVICE_OUT_WIRED_HEADSET_NAME; + case DEVICE_OUT_WIRED_HEADPHONE: + return DEVICE_OUT_WIRED_HEADPHONE_NAME; + case DEVICE_OUT_BLUETOOTH_SCO: + return DEVICE_OUT_BLUETOOTH_SCO_NAME; + case DEVICE_OUT_BLUETOOTH_SCO_HEADSET: + return DEVICE_OUT_BLUETOOTH_SCO_HEADSET_NAME; + case DEVICE_OUT_BLUETOOTH_SCO_CARKIT: + return DEVICE_OUT_BLUETOOTH_SCO_CARKIT_NAME; + case DEVICE_OUT_BLUETOOTH_A2DP: + return DEVICE_OUT_BLUETOOTH_A2DP_NAME; + case DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: + return DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES_NAME; + case DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: + return DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER_NAME; + case DEVICE_OUT_AUX_DIGITAL: + return DEVICE_OUT_AUX_DIGITAL_NAME; + case DEVICE_OUT_ANLG_DOCK_HEADSET: + return DEVICE_OUT_ANLG_DOCK_HEADSET_NAME; + case DEVICE_OUT_DGTL_DOCK_HEADSET: + return DEVICE_OUT_DGTL_DOCK_HEADSET_NAME; + default: + return ""; + } + } + // phone state, match audio_mode??? public static final int PHONE_STATE_OFFCALL = 0; public static final int PHONE_STATE_RINGING = 1; @@ -251,7 +317,7 @@ public class AudioSystem 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); + public static native int setStreamVolumeIndex(int stream, int index, int device); + public static native int getStreamVolumeIndex(int stream, int device); public static native int getDevicesForStream(int stream); } diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 5193848..d52f8f8 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -668,18 +668,22 @@ status_t AudioSystem::initStreamVolume(audio_stream_type_t stream, return aps->initStreamVolume(stream, indexMin, indexMax); } -status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream, int index) +status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream, + int index, + audio_devices_t device) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; - return aps->setStreamVolumeIndex(stream, index); + return aps->setStreamVolumeIndex(stream, index, device); } -status_t AudioSystem::getStreamVolumeIndex(audio_stream_type_t stream, int *index) +status_t AudioSystem::getStreamVolumeIndex(audio_stream_type_t stream, + int *index, + audio_devices_t device) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; - return aps->getStreamVolumeIndex(stream, index); + return aps->getStreamVolumeIndex(stream, index, device); } uint32_t AudioSystem::getStrategyForStream(audio_stream_type_t stream) diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 67d9c45..952d7b2 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -240,21 +240,28 @@ public: return static_cast <status_t> (reply.readInt32()); } - virtual status_t setStreamVolumeIndex(audio_stream_type_t stream, int index) + virtual status_t setStreamVolumeIndex(audio_stream_type_t stream, + int index, + audio_devices_t device) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(static_cast <uint32_t>(stream)); data.writeInt32(index); + data.writeInt32(static_cast <uint32_t>(device)); remote()->transact(SET_STREAM_VOLUME, data, &reply); return static_cast <status_t> (reply.readInt32()); } - virtual status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index) + virtual status_t getStreamVolumeIndex(audio_stream_type_t stream, + int *index, + audio_devices_t device) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); data.writeInt32(static_cast <uint32_t>(stream)); + data.writeInt32(static_cast <uint32_t>(device)); + remote()->transact(GET_STREAM_VOLUME, data, &reply); int lIndex = reply.readInt32(); if (index) *index = lIndex; @@ -525,7 +532,10 @@ status_t BnAudioPolicyService::onTransact( audio_stream_type_t stream = static_cast <audio_stream_type_t>(data.readInt32()); int index = data.readInt32(); - reply->writeInt32(static_cast <uint32_t>(setStreamVolumeIndex(stream, index))); + audio_devices_t device = static_cast <audio_devices_t>(data.readInt32()); + reply->writeInt32(static_cast <uint32_t>(setStreamVolumeIndex(stream, + index, + device))); return NO_ERROR; } break; @@ -533,8 +543,9 @@ status_t BnAudioPolicyService::onTransact( CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_stream_type_t stream = static_cast <audio_stream_type_t>(data.readInt32()); + audio_devices_t device = static_cast <audio_devices_t>(data.readInt32()); int index; - status_t status = getStreamVolumeIndex(stream, &index); + status_t status = getStreamVolumeIndex(stream, &index, device); reply->writeInt32(index); reply->writeInt32(static_cast <uint32_t>(status)); return NO_ERROR; |