Merge "Route mute key events through MediaSessionService" into lmp-mr1-dev

This commit is contained in:
RoboErik
2014-12-05 23:16:40 +00:00
committed by Android (Google) Code Review
7 changed files with 136 additions and 31 deletions

View File

@@ -137,6 +137,17 @@ public class AudioManager {
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
/**
* @hide Broadcast intent when a stream mute state changes.
* Includes the stream that changed and the new mute state
*
* @see #EXTRA_VOLUME_STREAM_TYPE
* @see #EXTRA_STREAM_VOLUME_MUTED
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String STREAM_MUTE_CHANGED_ACTION =
"android.media.STREAM_MUTE_CHANGED_ACTION";
/**
* @hide Broadcast intent when the master volume changes.
* Includes the new volume
@@ -220,6 +231,13 @@ public class AudioManager {
public static final String EXTRA_MASTER_VOLUME_MUTED =
"android.media.EXTRA_MASTER_VOLUME_MUTED";
/**
* @hide The new stream volume mute state for the stream mute changed intent.
* Value is boolean
*/
public static final String EXTRA_STREAM_VOLUME_MUTED =
"android.media.EXTRA_STREAM_VOLUME_MUTED";
/**
* Broadcast Action: Wired Headset plugged in or unplugged.
*
@@ -728,11 +746,7 @@ public class AudioManager {
break;
case KeyEvent.KEYCODE_VOLUME_MUTE:
if (event.getRepeatCount() == 0) {
if (mUseMasterVolume) {
setMasterMute(!isMasterMute());
} else {
// TODO: Actually handle MUTE.
}
MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, false);
}
break;
}
@@ -763,6 +777,9 @@ public class AudioManager {
}
mVolumeKeyUpTime = SystemClock.uptimeMillis();
break;
case KeyEvent.KEYCODE_VOLUME_MUTE:
MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, false);
break;
}
}

View File

@@ -15,6 +15,8 @@
*/
package android.media;
import android.os.IBinder;
import com.android.server.LocalServices;
/**
@@ -39,6 +41,9 @@ public abstract class AudioManagerInternal {
public abstract void adjustMasterVolumeForUid(int steps, int flags, String callingPackage,
int uid);
public abstract void setMasterMuteForUid(boolean state, int flags, String callingPackage,
IBinder cb, int uid);
public abstract void setRingerModeDelegate(RingerModeDelegate delegate);
public abstract int getRingerModeInternal();

View File

@@ -1517,12 +1517,20 @@ public class AudioService extends IAudioService.Stub {
if (mUseFixedVolume) {
return;
}
if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
streamType = getActiveStreamType(streamType);
}
if (isStreamAffectedByMute(streamType)) {
if (streamType == AudioSystem.STREAM_MUSIC) {
setSystemAudioMute(state);
}
mStreamStates[streamType].mute(cb, state);
Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
sendBroadcastToAll(intent);
}
}
@@ -1544,6 +1552,9 @@ public class AudioService extends IAudioService.Stub {
/** get stream mute state. */
public boolean isStreamMute(int streamType) {
if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
streamType = getActiveStreamType(streamType);
}
synchronized (VolumeStreamState.class) {
return mStreamStates[streamType].isMuted_syncVSS();
}
@@ -1651,11 +1662,16 @@ public class AudioService extends IAudioService.Stub {
/** @see AudioManager#setMasterMute(boolean, int) */
public void setMasterMute(boolean state, int flags, String callingPackage, IBinder cb) {
setMasterMuteInternal(state, flags, callingPackage, cb, Binder.getCallingUid());
}
private void setMasterMuteInternal(boolean state, int flags, String callingPackage, IBinder cb,
int uid) {
if (mUseFixedVolume) {
return;
}
if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(),
callingPackage) != AppOpsManager.MODE_ALLOWED) {
if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
!= AppOpsManager.MODE_ALLOWED) {
return;
}
if (state != AudioSystem.getMasterMute()) {
@@ -1665,6 +1681,10 @@ public class AudioService extends IAudioService.Stub {
sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1
: 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY);
sendMasterMuteUpdate(state, flags);
Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, state);
sendBroadcastToAll(intent);
}
}
@@ -5781,6 +5801,12 @@ public class AudioService extends IAudioService.Stub {
public void setRingerModeInternal(int ringerMode, String caller) {
AudioService.this.setRingerModeInternal(ringerMode, caller);
}
@Override
public void setMasterMuteForUid(boolean state, int flags, String callingPackage, IBinder cb,
int uid) {
setMasterMuteInternal(state, flags, callingPackage, cb, uid);
}
}
//==========================================================================================

View File

@@ -190,6 +190,7 @@ public class MediaSessionLegacyHelper {
boolean down = keyEvent.getAction() == KeyEvent.ACTION_DOWN;
boolean up = keyEvent.getAction() == KeyEvent.ACTION_UP;
int direction = 0;
boolean isMute = false;
switch (keyEvent.getKeyCode()) {
case KeyEvent.KEYCODE_VOLUME_UP:
direction = AudioManager.ADJUST_RAISE;
@@ -198,15 +199,11 @@ public class MediaSessionLegacyHelper {
direction = AudioManager.ADJUST_LOWER;
break;
case KeyEvent.KEYCODE_VOLUME_MUTE:
// TODO
isMute = true;
break;
}
if ((down || up) && direction != 0) {
if (down || up) {
int flags;
// If this is action up we want to send a beep for non-music events
if (up) {
direction = 0;
}
if (musicOnly) {
// This flag is used when the screen is off to only affect
// active media
@@ -219,9 +216,23 @@ public class MediaSessionLegacyHelper {
flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE;
}
}
mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
direction, flags);
if (direction != 0) {
// If this is action up we want to send a beep for non-music events
if (up) {
direction = 0;
}
mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
direction, flags);
} else if (isMute) {
if (down) {
// We need to send two volume events on down, one to mute
// and one to show the UI
mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
MediaSessionManager.DIRECTION_MUTE, flags);
}
mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
0 /* direction, causes UI to show on down */, flags);
}
}
}

View File

@@ -58,6 +58,14 @@ public final class MediaSessionManager {
private Context mContext;
/**
* Special flag for sending the mute key to dispatchAdjustVolume used by the
* system.
*
* @hide
*/
public static final int DIRECTION_MUTE = -99;
/**
* @hide
*/

View File

@@ -35,6 +35,7 @@ import android.media.session.ISessionControllerCallback;
import android.media.session.MediaController;
import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.ParcelableVolumeInfo;
import android.media.session.PlaybackState;
import android.media.AudioAttributes;
@@ -92,6 +93,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private final MediaSessionService mService;
private final boolean mUseMasterVolume;
private final IBinder mICallback = new Binder();
private final Object mLock = new Object();
private final ArrayList<ISessionControllerCallback> mControllerCallbacks =
new ArrayList<ISessionControllerCallback>();
@@ -245,6 +247,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
if (isPlaybackActive(false) || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) {
flags &= ~AudioManager.FLAG_PLAY_SOUND;
}
boolean isMute = direction == MediaSessionManager.DIRECTION_MUTE;
if (direction > 1) {
direction = 1;
} else if (direction < -1) {
@@ -254,29 +257,52 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
if (mUseMasterVolume) {
// If this device only uses master volume and playback is local
// just adjust the master volume and return.
mAudioManagerInternal.adjustMasterVolumeForUid(direction, flags, packageName, uid);
if (isMute) {
mAudioManagerInternal.setMasterMuteForUid(!mAudioManager.isMasterMute(),
flags, packageName, mICallback, uid);
} else {
mAudioManagerInternal.adjustMasterVolumeForUid(direction, flags, packageName,
uid);
}
return;
}
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
if (useSuggested) {
if (AudioSystem.isStreamActive(stream, 0)) {
mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, direction,
flags, packageName, uid);
if (isMute) {
mAudioManager.setStreamMute(stream, !mAudioManager.isStreamMute(stream));
} else {
mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, direction,
flags, packageName, uid);
}
} else {
flags |= previousFlagPlaySound;
mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(
AudioManager.USE_DEFAULT_STREAM_TYPE, direction, flags, packageName,
uid);
if (isMute) {
mAudioManager.setStreamMute(AudioManager.USE_DEFAULT_STREAM_TYPE,
!mAudioManager.isStreamMute(AudioManager.USE_DEFAULT_STREAM_TYPE));
} else {
mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(
AudioManager.USE_DEFAULT_STREAM_TYPE, direction, flags, packageName,
uid);
}
}
} else {
mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
packageName, uid);
if (isMute) {
mAudioManager.setStreamMute(stream, !mAudioManager.isStreamMute(stream));
} else {
mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
packageName, uid);
}
}
} else {
if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
// Nothing to do, the volume cannot be changed
return;
}
if (isMute) {
Log.w(TAG, "Muting remote playback is not supported");
return;
}
mSessionCb.adjustVolume(direction);
int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);

View File

@@ -40,6 +40,7 @@ import android.media.session.ISessionCallback;
import android.media.session.ISessionManager;
import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -588,6 +589,8 @@ public class MediaSessionService extends SystemService implements Monitor {
"android.media.AudioService.WAKELOCK_ACQUIRED";
private static final int WAKELOCK_RELEASE_ON_FINISHED = 1980; // magic number
private final IBinder mICallback = new Binder();
private boolean mVoiceButtonDown = false;
private boolean mVoiceButtonHandled = false;
@@ -720,8 +723,7 @@ public class MediaSessionService extends SystemService implements Monitor {
}
@Override
public void dispatchAdjustVolume(int suggestedStream, int delta, int flags)
throws RemoteException {
public void dispatchAdjustVolume(int suggestedStream, int delta, int flags) {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
@@ -828,11 +830,21 @@ public class MediaSessionService extends SystemService implements Monitor {
}
try {
if (mUseMasterVolume) {
mAudioService.adjustMasterVolume(direction, flags,
getContext().getOpPackageName());
if (direction == MediaSessionManager.DIRECTION_MUTE) {
mAudioService.setMasterMute(!mAudioService.isMasterMute(), flags,
getContext().getOpPackageName(), mICallback);
} else {
mAudioService.adjustMasterVolume(direction, flags,
getContext().getOpPackageName());
}
} else {
mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream, flags,
getContext().getOpPackageName());
if (direction == MediaSessionManager.DIRECTION_MUTE) {
mAudioService.setStreamMute(suggestedStream,
!mAudioService.isStreamMute(suggestedStream), mICallback);
} else {
mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
flags, getContext().getOpPackageName());
}
}
} catch (RemoteException e) {
Log.e(TAG, "Error adjusting default volume.", e);
@@ -841,7 +853,7 @@ public class MediaSessionService extends SystemService implements Monitor {
session.adjustVolume(direction, flags, getContext().getPackageName(),
UserHandle.myUserId(), true);
if (session.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE
&& mRvc != null) {
&& mRvc != null && direction != MediaSessionManager.DIRECTION_MUTE) {
try {
mRvc.remoteVolumeChanged(session.getControllerBinder(), flags);
} catch (Exception e) {