Loading core/java/android/content/Intent.java +35 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Rect; import android.media.RemoteControlClient; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; Loading Loading @@ -2151,6 +2152,19 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_USB_AUDIO_DEVICE_PLUG = "android.intent.action.USB_AUDIO_DEVICE_PLUG"; /** * @hide (to be un-hidden) * Broadcast Action: the volume handled by the receiver should be updated based on the * mutually exclusive extras, {@link #EXTRA_VOLUME_UPDATE_DIRECTION} * and {@link #EXTRA_VOLUME_UPDATE_VALUE}. * * @see #EXTRA_VOLUME_UPDATE_DIRECTION * @see #EXTRA_VOLUME_UPDATE_VALUE * @see android.media.RemoteControlClient */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_VOLUME_UPDATE = "android.intent.action.VOLUME_UPDATE"; /** * <p>Broadcast Action: The user has switched on advanced settings in the settings app:</p> * <ul> Loading Loading @@ -2839,6 +2853,27 @@ public class Intent implements Parcelable, Cloneable { */ public static final String EXTRA_USERID = "android.intent.extra.user_id"; /** * @hide (to be un-hidden) * An integer indicating whether the volume is to be increased (positive value) or decreased * (negative value). For bundled changes, the absolute value indicates the number of changes * in the same direction, e.g. +3 corresponds to three "volume up" changes. * @see #ACTION_VOLUME_UPDATE */ public static final String EXTRA_VOLUME_UPDATE_DIRECTION = "android.intent.extra.VOLUME_UPDATE_DIRECTION"; /** * @hide (to be un-hidden) * An integer indicating the new volume value, always between 0 and the value set for * {@link RemoteControlClient#PLAYBACKINFO_VOLUME_MAX} with * {@link RemoteControlClient#setPlaybackInformation(int, int)} * @see #ACTION_VOLUME_UPDATE */ public static final String EXTRA_VOLUME_UPDATE_VALUE = "android.intent.extra.VOLUME_UPDATE_VALUE"; // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Intent flags (see mFlags variable). Loading core/java/android/view/VolumePanel.java +162 −10 Original line number Diff line number Diff line Loading @@ -34,10 +34,7 @@ import android.media.ToneGenerator; import android.net.Uri; import android.os.Handler; import android.os.Message; import android.os.RemoteException; import android.os.Vibrator; import android.provider.Settings; import android.provider.Settings.System; import android.util.Log; import android.view.WindowManager.LayoutParams; import android.widget.ImageView; Loading Loading @@ -92,9 +89,13 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private static final int MSG_TIMEOUT = 5; private static final int MSG_RINGER_MODE_CHANGED = 6; private static final int MSG_MUTE_CHANGED = 7; private static final int MSG_REMOTE_VOLUME_CHANGED = 8; private static final int MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN = 9; private static final int MSG_SLIDER_VISIBILITY_CHANGED = 10; // Pseudo stream type for master volume private static final int STREAM_MASTER = -100; // Pseudo stream type for remote volume is defined in AudioService.STREAM_REMOTE_MUSIC protected Context mContext; private AudioManager mAudioManager; Loading Loading @@ -155,10 +156,15 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie true), // for now, use media resources for master volume MasterStream(STREAM_MASTER, R.string.volume_icon_description_media, R.string.volume_icon_description_media, //FIXME should have its own description R.drawable.ic_audio_vol, R.drawable.ic_audio_vol_mute, false); false), RemoteStream(AudioService.STREAM_REMOTE_MUSIC, R.string.volume_icon_description_media, //FIXME should have its own description R.drawable.ic_media_route_on_holo_dark, R.drawable.ic_media_route_disabled_holo_dark, false);// will be dynamically updated int streamType; int descRes; Loading @@ -184,7 +190,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie StreamResources.MediaStream, StreamResources.NotificationStream, StreamResources.AlarmStream, StreamResources.MasterStream StreamResources.MasterStream, StreamResources.RemoteStream }; /** Object that contains data for each slider */ Loading Loading @@ -297,6 +304,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private boolean isMuted(int streamType) { if (streamType == STREAM_MASTER) { return mAudioManager.isMasterMute(); } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { return (mAudioService.getRemoteStreamVolume() <= 0); } else { return mAudioManager.isStreamMute(streamType); } Loading @@ -305,6 +314,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private int getStreamMaxVolume(int streamType) { if (streamType == STREAM_MASTER) { return mAudioManager.getMasterMaxVolume(); } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { return mAudioService.getRemoteStreamMaxVolume(); } else { return mAudioManager.getStreamMaxVolume(streamType); } Loading @@ -313,6 +324,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private int getStreamVolume(int streamType) { if (streamType == STREAM_MASTER) { return mAudioManager.getMasterVolume(); } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { return mAudioService.getRemoteStreamVolume(); } else { return mAudioManager.getStreamVolume(streamType); } Loading @@ -321,6 +334,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private void setStreamVolume(int streamType, int index, int flags) { if (streamType == STREAM_MASTER) { mAudioManager.setMasterVolume(index, flags); } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { mAudioService.setRemoteStreamVolume(index); } else { mAudioManager.setStreamVolume(streamType, index, flags); } Loading Loading @@ -398,7 +413,11 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) { sc.icon.setImageResource(R.drawable.ic_audio_ring_notif_vibrate); } if (sc.streamType != mAudioManager.getMasterStreamType() && muted) { if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) { // never disable touch interactions for remote playback, the muting is not tied to // the state of the phone. sc.seekbarView.setEnabled(true); } else if (sc.streamType != mAudioManager.getMasterStreamType() && muted) { sc.seekbarView.setEnabled(false); } else { sc.seekbarView.setEnabled(true); Loading Loading @@ -446,6 +465,40 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget(); } public void postRemoteVolumeChanged(int streamType, int flags) { if (hasMessages(MSG_REMOTE_VOLUME_CHANGED)) return; synchronized (this) { if (mStreamControls == null) { createSliders(); } } removeMessages(MSG_FREE_RESOURCES); obtainMessage(MSG_REMOTE_VOLUME_CHANGED, streamType, flags).sendToTarget(); } public void postRemoteSliderVisibility(boolean visible) { obtainMessage(MSG_SLIDER_VISIBILITY_CHANGED, AudioService.STREAM_REMOTE_MUSIC, visible ? 1 : 0).sendToTarget(); } /** * Called by AudioService when it has received new remote playback information that * would affect the VolumePanel display (mainly volumes). The difference with * {@link #postRemoteVolumeChanged(int, int)} is that the handling of the posted message * (MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN) will only update the volume slider if it is being * displayed. * This special code path is due to the fact that remote volume updates arrive to AudioService * asynchronously. So after AudioService has sent the volume update (which should be treated * as a request to update the volume), the application will likely set a new volume. If the UI * is still up, we need to refresh the display to show this new value. */ public void postHasNewRemotePlaybackInfo() { if (hasMessages(MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN)) return; // don't create or prevent resources to be freed, if they disappear, this update came too // late and shouldn't warrant the panel to be displayed longer obtainMessage(MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN).sendToTarget(); } public void postMasterVolumeChanged(int flags) { postVolumeChanged(STREAM_MASTER, flags); } Loading Loading @@ -585,6 +638,11 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie max++; break; } case AudioService.STREAM_REMOTE_MUSIC: { if (LOGD) { Log.d(TAG, "showing remote volume "+index+" over "+ max); } break; } } StreamControl sc = mStreamControls.get(streamType); Loading @@ -593,7 +651,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie sc.seekbarView.setMax(max); } sc.seekbarView.setProgress(index); if (streamType != mAudioManager.getMasterStreamType() && isMuted(streamType)) { if (streamType != mAudioManager.getMasterStreamType() && streamType != AudioService.STREAM_REMOTE_MUSIC && isMuted(streamType)) { sc.seekbarView.setEnabled(false); } else { sc.seekbarView.setEnabled(true); Loading @@ -601,7 +660,9 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } if (!mDialog.isShowing()) { mAudioManager.forceVolumeControlStream(streamType); int stream = (streamType == AudioService.STREAM_REMOTE_MUSIC) ? -1 : streamType; // when the stream is for remote playback, use -1 to reset the stream type evaluation mAudioManager.forceVolumeControlStream(stream); mDialog.setContentView(mView); // Showing dialog - use collapsed state if (mShowCombinedVolumes) { Loading @@ -611,7 +672,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } // Do a little vibrate if applicable (only when going into vibrate mode) if ((flags & AudioManager.FLAG_VIBRATE) != 0 && if ((streamType != AudioService.STREAM_REMOTE_MUSIC) && ((flags & AudioManager.FLAG_VIBRATE) != 0) && mAudioService.isStreamAffectedByRingerMode(streamType) && mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) { sendMessageDelayed(obtainMessage(MSG_VIBRATE), VIBRATE_DELAY); Loading Loading @@ -658,6 +720,72 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie mVibrator.vibrate(VIBRATE_DURATION); } protected void onRemoteVolumeChanged(int streamType, int flags) { // streamType is the real stream type being affected, but for the UI sliders, we // refer to AudioService.STREAM_REMOTE_MUSIC. We still play the beeps on the real // stream type. if (LOGD) Log.d(TAG, "onRemoteVolumeChanged(stream:"+streamType+", flags: " + flags + ")"); if (((flags & AudioManager.FLAG_SHOW_UI) != 0) || mDialog.isShowing()) { synchronized (this) { if (mActiveStreamType != AudioService.STREAM_REMOTE_MUSIC) { reorderSliders(AudioService.STREAM_REMOTE_MUSIC); } onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, flags); } } else { if (LOGD) Log.d(TAG, "not calling onShowVolumeChanged(), no FLAG_SHOW_UI or no UI"); } if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && ! mRingIsSilent) { removeMessages(MSG_PLAY_SOUND); sendMessageDelayed(obtainMessage(MSG_PLAY_SOUND, streamType, flags), PLAY_SOUND_DELAY); } if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) { removeMessages(MSG_PLAY_SOUND); removeMessages(MSG_VIBRATE); onStopSounds(); } removeMessages(MSG_FREE_RESOURCES); sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY); resetTimeout(); } protected void onRemoteVolumeUpdateIfShown() { if (LOGD) Log.d(TAG, "onRemoteVolumeUpdateIfShown()"); if (mDialog.isShowing() && (mActiveStreamType == AudioService.STREAM_REMOTE_MUSIC) && (mStreamControls != null)) { onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, 0); } } /** * Handler for MSG_SLIDER_VISIBILITY_CHANGED * Hide or show a slider * @param streamType can be a valid stream type value, or VolumePanel.STREAM_MASTER, * or AudioService.STREAM_REMOTE_MUSIC * @param visible */ synchronized protected void onSliderVisibilityChanged(int streamType, int visible) { if (LOGD) Log.d(TAG, "onSliderVisibilityChanged(stream="+streamType+", visi="+visible+")"); boolean isVisible = (visible == 1); for (int i = STREAMS.length - 1 ; i >= 0 ; i--) { StreamResources streamRes = STREAMS[i]; if (streamRes.streamType == streamType) { streamRes.show = isVisible; if (!isVisible && (mActiveStreamType == streamType)) { mActiveStreamType = -1; } break; } } } /** * Lock on this VolumePanel instance as long as you use the returned ToneGenerator. */ Loading Loading @@ -750,6 +878,19 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } break; } case MSG_REMOTE_VOLUME_CHANGED: { onRemoteVolumeChanged(msg.arg1, msg.arg2); break; } case MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN: onRemoteVolumeUpdateIfShown(); break; case MSG_SLIDER_VISIBILITY_CHANGED: onSliderVisibilityChanged(msg.arg1, msg.arg2); break; } } Loading Loading @@ -779,6 +920,17 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } public void onStopTrackingTouch(SeekBar seekBar) { final Object tag = seekBar.getTag(); if (tag instanceof StreamControl) { StreamControl sc = (StreamControl) tag; // because remote volume updates are asynchronous, AudioService might have received // a new remote volume value since the finger adjusted the slider. So when the // progress of the slider isn't being tracked anymore, adjust the slider to the last // "published" remote volume value, so the UI reflects the actual volume. if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) { seekBar.setProgress(getStreamVolume(AudioService.STREAM_REMOTE_MUSIC)); } } } public void onClick(View v) { Loading core/res/res/values/public.xml +2 −0 Original line number Diff line number Diff line Loading @@ -1024,6 +1024,8 @@ <java-symbol type="drawable" name="notification_template_icon_bg" /> <java-symbol type="drawable" name="notification_template_icon_low_bg" /> <java-symbol type="drawable" name="ic_lockscreen_unlock_phantom" /> <java-symbol type="drawable" name="ic_media_route_on_holo_dark" /> <java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" /> <java-symbol type="layout" name="action_bar_home" /> <java-symbol type="layout" name="action_bar_title_item" /> Loading media/java/android/media/AudioManager.java +27 −4 Original line number Diff line number Diff line Loading @@ -98,7 +98,10 @@ public class AudioManager { /** * @hide Broadcast intent when the volume for a particular stream type changes. * Includes the stream, the new volume and previous volumes * Includes the stream, the new volume and previous volumes. * Notes: * - for internal platform use only, do not make public, * - never used for "remote" volume changes * * @see #EXTRA_VOLUME_STREAM_TYPE * @see #EXTRA_VOLUME_STREAM_VALUE Loading Loading @@ -1498,6 +1501,24 @@ public class AudioManager { return AudioSystem.isStreamActive(STREAM_MUSIC, 0); } /** * @hide * If the stream is active locally or remotely, adjust its volume according to the enforced * priority rules. * Note: only AudioManager.STREAM_MUSIC is supported at the moment */ public void adjustLocalOrRemoteStreamVolume(int streamType, int direction) { if (streamType != STREAM_MUSIC) { Log.w(TAG, "adjustLocalOrRemoteStreamVolume() doesn't support stream " + streamType); } IAudioService service = getService(); try { service.adjustLocalOrRemoteStreamVolume(streamType, direction); } catch (RemoteException e) { Log.e(TAG, "Dead object in adjustLocalOrRemoteStreamVolume", e); } } /* * Sets a generic audio configuration parameter. The use of these parameters * are platform dependant, see libaudio Loading Loading @@ -2074,10 +2095,12 @@ public class AudioManager { } IAudioService service = getService(); try { service.registerRemoteControlClient(rcClient.getRcMediaIntent(), /* mediaIntent */ int rcseId = service.registerRemoteControlClient( rcClient.getRcMediaIntent(), /* mediaIntent */ rcClient.getIRemoteControlClient(),/* rcClient */ // used to match media button event receiver and audio focus mContext.getPackageName()); /* packageName */ rcClient.setRcseId(rcseId); } catch (RemoteException e) { Log.e(TAG, "Dead object in registerRemoteControlClient"+e); } Loading media/java/android/media/AudioService.java +436 −28 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/content/Intent.java +35 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Rect; import android.media.RemoteControlClient; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; Loading Loading @@ -2151,6 +2152,19 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_USB_AUDIO_DEVICE_PLUG = "android.intent.action.USB_AUDIO_DEVICE_PLUG"; /** * @hide (to be un-hidden) * Broadcast Action: the volume handled by the receiver should be updated based on the * mutually exclusive extras, {@link #EXTRA_VOLUME_UPDATE_DIRECTION} * and {@link #EXTRA_VOLUME_UPDATE_VALUE}. * * @see #EXTRA_VOLUME_UPDATE_DIRECTION * @see #EXTRA_VOLUME_UPDATE_VALUE * @see android.media.RemoteControlClient */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_VOLUME_UPDATE = "android.intent.action.VOLUME_UPDATE"; /** * <p>Broadcast Action: The user has switched on advanced settings in the settings app:</p> * <ul> Loading Loading @@ -2839,6 +2853,27 @@ public class Intent implements Parcelable, Cloneable { */ public static final String EXTRA_USERID = "android.intent.extra.user_id"; /** * @hide (to be un-hidden) * An integer indicating whether the volume is to be increased (positive value) or decreased * (negative value). For bundled changes, the absolute value indicates the number of changes * in the same direction, e.g. +3 corresponds to three "volume up" changes. * @see #ACTION_VOLUME_UPDATE */ public static final String EXTRA_VOLUME_UPDATE_DIRECTION = "android.intent.extra.VOLUME_UPDATE_DIRECTION"; /** * @hide (to be un-hidden) * An integer indicating the new volume value, always between 0 and the value set for * {@link RemoteControlClient#PLAYBACKINFO_VOLUME_MAX} with * {@link RemoteControlClient#setPlaybackInformation(int, int)} * @see #ACTION_VOLUME_UPDATE */ public static final String EXTRA_VOLUME_UPDATE_VALUE = "android.intent.extra.VOLUME_UPDATE_VALUE"; // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Intent flags (see mFlags variable). Loading
core/java/android/view/VolumePanel.java +162 −10 Original line number Diff line number Diff line Loading @@ -34,10 +34,7 @@ import android.media.ToneGenerator; import android.net.Uri; import android.os.Handler; import android.os.Message; import android.os.RemoteException; import android.os.Vibrator; import android.provider.Settings; import android.provider.Settings.System; import android.util.Log; import android.view.WindowManager.LayoutParams; import android.widget.ImageView; Loading Loading @@ -92,9 +89,13 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private static final int MSG_TIMEOUT = 5; private static final int MSG_RINGER_MODE_CHANGED = 6; private static final int MSG_MUTE_CHANGED = 7; private static final int MSG_REMOTE_VOLUME_CHANGED = 8; private static final int MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN = 9; private static final int MSG_SLIDER_VISIBILITY_CHANGED = 10; // Pseudo stream type for master volume private static final int STREAM_MASTER = -100; // Pseudo stream type for remote volume is defined in AudioService.STREAM_REMOTE_MUSIC protected Context mContext; private AudioManager mAudioManager; Loading Loading @@ -155,10 +156,15 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie true), // for now, use media resources for master volume MasterStream(STREAM_MASTER, R.string.volume_icon_description_media, R.string.volume_icon_description_media, //FIXME should have its own description R.drawable.ic_audio_vol, R.drawable.ic_audio_vol_mute, false); false), RemoteStream(AudioService.STREAM_REMOTE_MUSIC, R.string.volume_icon_description_media, //FIXME should have its own description R.drawable.ic_media_route_on_holo_dark, R.drawable.ic_media_route_disabled_holo_dark, false);// will be dynamically updated int streamType; int descRes; Loading @@ -184,7 +190,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie StreamResources.MediaStream, StreamResources.NotificationStream, StreamResources.AlarmStream, StreamResources.MasterStream StreamResources.MasterStream, StreamResources.RemoteStream }; /** Object that contains data for each slider */ Loading Loading @@ -297,6 +304,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private boolean isMuted(int streamType) { if (streamType == STREAM_MASTER) { return mAudioManager.isMasterMute(); } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { return (mAudioService.getRemoteStreamVolume() <= 0); } else { return mAudioManager.isStreamMute(streamType); } Loading @@ -305,6 +314,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private int getStreamMaxVolume(int streamType) { if (streamType == STREAM_MASTER) { return mAudioManager.getMasterMaxVolume(); } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { return mAudioService.getRemoteStreamMaxVolume(); } else { return mAudioManager.getStreamMaxVolume(streamType); } Loading @@ -313,6 +324,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private int getStreamVolume(int streamType) { if (streamType == STREAM_MASTER) { return mAudioManager.getMasterVolume(); } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { return mAudioService.getRemoteStreamVolume(); } else { return mAudioManager.getStreamVolume(streamType); } Loading @@ -321,6 +334,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie private void setStreamVolume(int streamType, int index, int flags) { if (streamType == STREAM_MASTER) { mAudioManager.setMasterVolume(index, flags); } else if (streamType == AudioService.STREAM_REMOTE_MUSIC) { mAudioService.setRemoteStreamVolume(index); } else { mAudioManager.setStreamVolume(streamType, index, flags); } Loading Loading @@ -398,7 +413,11 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) { sc.icon.setImageResource(R.drawable.ic_audio_ring_notif_vibrate); } if (sc.streamType != mAudioManager.getMasterStreamType() && muted) { if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) { // never disable touch interactions for remote playback, the muting is not tied to // the state of the phone. sc.seekbarView.setEnabled(true); } else if (sc.streamType != mAudioManager.getMasterStreamType() && muted) { sc.seekbarView.setEnabled(false); } else { sc.seekbarView.setEnabled(true); Loading Loading @@ -446,6 +465,40 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget(); } public void postRemoteVolumeChanged(int streamType, int flags) { if (hasMessages(MSG_REMOTE_VOLUME_CHANGED)) return; synchronized (this) { if (mStreamControls == null) { createSliders(); } } removeMessages(MSG_FREE_RESOURCES); obtainMessage(MSG_REMOTE_VOLUME_CHANGED, streamType, flags).sendToTarget(); } public void postRemoteSliderVisibility(boolean visible) { obtainMessage(MSG_SLIDER_VISIBILITY_CHANGED, AudioService.STREAM_REMOTE_MUSIC, visible ? 1 : 0).sendToTarget(); } /** * Called by AudioService when it has received new remote playback information that * would affect the VolumePanel display (mainly volumes). The difference with * {@link #postRemoteVolumeChanged(int, int)} is that the handling of the posted message * (MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN) will only update the volume slider if it is being * displayed. * This special code path is due to the fact that remote volume updates arrive to AudioService * asynchronously. So after AudioService has sent the volume update (which should be treated * as a request to update the volume), the application will likely set a new volume. If the UI * is still up, we need to refresh the display to show this new value. */ public void postHasNewRemotePlaybackInfo() { if (hasMessages(MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN)) return; // don't create or prevent resources to be freed, if they disappear, this update came too // late and shouldn't warrant the panel to be displayed longer obtainMessage(MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN).sendToTarget(); } public void postMasterVolumeChanged(int flags) { postVolumeChanged(STREAM_MASTER, flags); } Loading Loading @@ -585,6 +638,11 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie max++; break; } case AudioService.STREAM_REMOTE_MUSIC: { if (LOGD) { Log.d(TAG, "showing remote volume "+index+" over "+ max); } break; } } StreamControl sc = mStreamControls.get(streamType); Loading @@ -593,7 +651,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie sc.seekbarView.setMax(max); } sc.seekbarView.setProgress(index); if (streamType != mAudioManager.getMasterStreamType() && isMuted(streamType)) { if (streamType != mAudioManager.getMasterStreamType() && streamType != AudioService.STREAM_REMOTE_MUSIC && isMuted(streamType)) { sc.seekbarView.setEnabled(false); } else { sc.seekbarView.setEnabled(true); Loading @@ -601,7 +660,9 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } if (!mDialog.isShowing()) { mAudioManager.forceVolumeControlStream(streamType); int stream = (streamType == AudioService.STREAM_REMOTE_MUSIC) ? -1 : streamType; // when the stream is for remote playback, use -1 to reset the stream type evaluation mAudioManager.forceVolumeControlStream(stream); mDialog.setContentView(mView); // Showing dialog - use collapsed state if (mShowCombinedVolumes) { Loading @@ -611,7 +672,8 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } // Do a little vibrate if applicable (only when going into vibrate mode) if ((flags & AudioManager.FLAG_VIBRATE) != 0 && if ((streamType != AudioService.STREAM_REMOTE_MUSIC) && ((flags & AudioManager.FLAG_VIBRATE) != 0) && mAudioService.isStreamAffectedByRingerMode(streamType) && mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) { sendMessageDelayed(obtainMessage(MSG_VIBRATE), VIBRATE_DELAY); Loading Loading @@ -658,6 +720,72 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie mVibrator.vibrate(VIBRATE_DURATION); } protected void onRemoteVolumeChanged(int streamType, int flags) { // streamType is the real stream type being affected, but for the UI sliders, we // refer to AudioService.STREAM_REMOTE_MUSIC. We still play the beeps on the real // stream type. if (LOGD) Log.d(TAG, "onRemoteVolumeChanged(stream:"+streamType+", flags: " + flags + ")"); if (((flags & AudioManager.FLAG_SHOW_UI) != 0) || mDialog.isShowing()) { synchronized (this) { if (mActiveStreamType != AudioService.STREAM_REMOTE_MUSIC) { reorderSliders(AudioService.STREAM_REMOTE_MUSIC); } onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, flags); } } else { if (LOGD) Log.d(TAG, "not calling onShowVolumeChanged(), no FLAG_SHOW_UI or no UI"); } if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && ! mRingIsSilent) { removeMessages(MSG_PLAY_SOUND); sendMessageDelayed(obtainMessage(MSG_PLAY_SOUND, streamType, flags), PLAY_SOUND_DELAY); } if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) { removeMessages(MSG_PLAY_SOUND); removeMessages(MSG_VIBRATE); onStopSounds(); } removeMessages(MSG_FREE_RESOURCES); sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY); resetTimeout(); } protected void onRemoteVolumeUpdateIfShown() { if (LOGD) Log.d(TAG, "onRemoteVolumeUpdateIfShown()"); if (mDialog.isShowing() && (mActiveStreamType == AudioService.STREAM_REMOTE_MUSIC) && (mStreamControls != null)) { onShowVolumeChanged(AudioService.STREAM_REMOTE_MUSIC, 0); } } /** * Handler for MSG_SLIDER_VISIBILITY_CHANGED * Hide or show a slider * @param streamType can be a valid stream type value, or VolumePanel.STREAM_MASTER, * or AudioService.STREAM_REMOTE_MUSIC * @param visible */ synchronized protected void onSliderVisibilityChanged(int streamType, int visible) { if (LOGD) Log.d(TAG, "onSliderVisibilityChanged(stream="+streamType+", visi="+visible+")"); boolean isVisible = (visible == 1); for (int i = STREAMS.length - 1 ; i >= 0 ; i--) { StreamResources streamRes = STREAMS[i]; if (streamRes.streamType == streamType) { streamRes.show = isVisible; if (!isVisible && (mActiveStreamType == streamType)) { mActiveStreamType = -1; } break; } } } /** * Lock on this VolumePanel instance as long as you use the returned ToneGenerator. */ Loading Loading @@ -750,6 +878,19 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } break; } case MSG_REMOTE_VOLUME_CHANGED: { onRemoteVolumeChanged(msg.arg1, msg.arg2); break; } case MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN: onRemoteVolumeUpdateIfShown(); break; case MSG_SLIDER_VISIBILITY_CHANGED: onSliderVisibilityChanged(msg.arg1, msg.arg2); break; } } Loading Loading @@ -779,6 +920,17 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie } public void onStopTrackingTouch(SeekBar seekBar) { final Object tag = seekBar.getTag(); if (tag instanceof StreamControl) { StreamControl sc = (StreamControl) tag; // because remote volume updates are asynchronous, AudioService might have received // a new remote volume value since the finger adjusted the slider. So when the // progress of the slider isn't being tracked anymore, adjust the slider to the last // "published" remote volume value, so the UI reflects the actual volume. if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) { seekBar.setProgress(getStreamVolume(AudioService.STREAM_REMOTE_MUSIC)); } } } public void onClick(View v) { Loading
core/res/res/values/public.xml +2 −0 Original line number Diff line number Diff line Loading @@ -1024,6 +1024,8 @@ <java-symbol type="drawable" name="notification_template_icon_bg" /> <java-symbol type="drawable" name="notification_template_icon_low_bg" /> <java-symbol type="drawable" name="ic_lockscreen_unlock_phantom" /> <java-symbol type="drawable" name="ic_media_route_on_holo_dark" /> <java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" /> <java-symbol type="layout" name="action_bar_home" /> <java-symbol type="layout" name="action_bar_title_item" /> Loading
media/java/android/media/AudioManager.java +27 −4 Original line number Diff line number Diff line Loading @@ -98,7 +98,10 @@ public class AudioManager { /** * @hide Broadcast intent when the volume for a particular stream type changes. * Includes the stream, the new volume and previous volumes * Includes the stream, the new volume and previous volumes. * Notes: * - for internal platform use only, do not make public, * - never used for "remote" volume changes * * @see #EXTRA_VOLUME_STREAM_TYPE * @see #EXTRA_VOLUME_STREAM_VALUE Loading Loading @@ -1498,6 +1501,24 @@ public class AudioManager { return AudioSystem.isStreamActive(STREAM_MUSIC, 0); } /** * @hide * If the stream is active locally or remotely, adjust its volume according to the enforced * priority rules. * Note: only AudioManager.STREAM_MUSIC is supported at the moment */ public void adjustLocalOrRemoteStreamVolume(int streamType, int direction) { if (streamType != STREAM_MUSIC) { Log.w(TAG, "adjustLocalOrRemoteStreamVolume() doesn't support stream " + streamType); } IAudioService service = getService(); try { service.adjustLocalOrRemoteStreamVolume(streamType, direction); } catch (RemoteException e) { Log.e(TAG, "Dead object in adjustLocalOrRemoteStreamVolume", e); } } /* * Sets a generic audio configuration parameter. The use of these parameters * are platform dependant, see libaudio Loading Loading @@ -2074,10 +2095,12 @@ public class AudioManager { } IAudioService service = getService(); try { service.registerRemoteControlClient(rcClient.getRcMediaIntent(), /* mediaIntent */ int rcseId = service.registerRemoteControlClient( rcClient.getRcMediaIntent(), /* mediaIntent */ rcClient.getIRemoteControlClient(),/* rcClient */ // used to match media button event receiver and audio focus mContext.getPackageName()); /* packageName */ rcClient.setRcseId(rcseId); } catch (RemoteException e) { Log.e(TAG, "Dead object in registerRemoteControlClient"+e); } Loading
media/java/android/media/AudioService.java +436 −28 File changed.Preview size limit exceeded, changes collapsed. Show changes