Merge "MediaSessionService: Provide caller information for media key events" into pi-dev
am: 183a63474f
Change-Id: I6ad5053137c2ae7d123940c7f5239060d70ce68f
This commit is contained in:
@@ -46,6 +46,8 @@ import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
|
||||
public class Media extends BaseCommand {
|
||||
// This doesn't belongs to any package. Setting the package name to empty string.
|
||||
private static final String PACKAGE_NAME = "";
|
||||
private ISessionManager mSessionService;
|
||||
|
||||
/**
|
||||
@@ -104,7 +106,7 @@ public class Media extends BaseCommand {
|
||||
|
||||
private void sendMediaKey(KeyEvent event) {
|
||||
try {
|
||||
mSessionService.dispatchMediaKeyEvent(event, false);
|
||||
mSessionService.dispatchMediaKeyEvent(PACKAGE_NAME, false, event, false);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
@@ -264,13 +266,13 @@ public class Media extends BaseCommand {
|
||||
} else if ("q".equals(line) || "quit".equals(line)) {
|
||||
break;
|
||||
} else if ("play".equals(line)) {
|
||||
mController.play("");
|
||||
mController.play(PACKAGE_NAME);
|
||||
} else if ("pause".equals(line)) {
|
||||
mController.pause("");
|
||||
mController.pause(PACKAGE_NAME);
|
||||
} else if ("next".equals(line)) {
|
||||
mController.next("");
|
||||
mController.next(PACKAGE_NAME);
|
||||
} else if ("previous".equals(line)) {
|
||||
mController.previous("");
|
||||
mController.previous(PACKAGE_NAME);
|
||||
} else {
|
||||
System.out.println("Invalid command: " + line);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.media.AudioManager;
|
||||
import android.media.session.MediaSessionLegacyHelper;
|
||||
import android.media.session.MediaSessionManager;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
@@ -48,6 +48,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
|
||||
KeyguardManager mKeyguardManager;
|
||||
SearchManager mSearchManager;
|
||||
TelephonyManager mTelephonyManager;
|
||||
MediaSessionManager mMediaSessionManager;
|
||||
|
||||
public PhoneFallbackEventHandler(Context context) {
|
||||
mContext = context;
|
||||
@@ -84,8 +85,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
|
||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||
case KeyEvent.KEYCODE_VOLUME_MUTE: {
|
||||
MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
|
||||
event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
|
||||
handleVolumeKeyEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -216,8 +216,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||
case KeyEvent.KEYCODE_VOLUME_MUTE: {
|
||||
if (!event.isCanceled()) {
|
||||
MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
|
||||
event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
|
||||
handleVolumeKeyEvent(event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -306,12 +305,25 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler {
|
||||
return mAudioManager;
|
||||
}
|
||||
|
||||
MediaSessionManager getMediaSessionManager() {
|
||||
if (mMediaSessionManager == null) {
|
||||
mMediaSessionManager =
|
||||
(MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
|
||||
}
|
||||
return mMediaSessionManager;
|
||||
}
|
||||
|
||||
void sendCloseSystemWindows() {
|
||||
PhoneWindow.sendCloseSystemWindows(mContext, null);
|
||||
}
|
||||
|
||||
private void handleVolumeKeyEvent(KeyEvent keyEvent) {
|
||||
getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(keyEvent,
|
||||
AudioManager.USE_DEFAULT_STREAM_TYPE);
|
||||
}
|
||||
|
||||
private void handleMediaKeyEvent(KeyEvent keyEvent) {
|
||||
MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(keyEvent, false);
|
||||
getMediaSessionManager().dispatchMediaKeyEventAsSystemService(keyEvent);
|
||||
}
|
||||
|
||||
private boolean isUserSetupComplete() {
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.view.WindowManager.LayoutParams.*;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.SearchManager;
|
||||
import android.media.session.MediaSessionManager;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import android.text.TextUtils;
|
||||
@@ -74,7 +75,6 @@ import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.AudioManager;
|
||||
import android.media.session.MediaController;
|
||||
import android.media.session.MediaSessionLegacyHelper;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -252,6 +252,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
|
||||
private AudioManager mAudioManager;
|
||||
private KeyguardManager mKeyguardManager;
|
||||
private MediaSessionManager mMediaSessionManager;
|
||||
|
||||
private int mUiOptions = 0;
|
||||
|
||||
@@ -1873,22 +1874,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
// If we have a session send it the volume command, otherwise
|
||||
// use the suggested stream.
|
||||
if (mMediaController != null) {
|
||||
int direction = 0;
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||
direction = AudioManager.ADJUST_RAISE;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||
direction = AudioManager.ADJUST_LOWER;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_VOLUME_MUTE:
|
||||
direction = AudioManager.ADJUST_TOGGLE_MUTE;
|
||||
break;
|
||||
}
|
||||
mMediaController.adjustVolume(direction, AudioManager.FLAG_SHOW_UI);
|
||||
mMediaController.dispatchVolumeButtonEventAsSystemService(event);
|
||||
} else {
|
||||
MediaSessionLegacyHelper.getHelper(getContext()).sendVolumeKeyEvent(
|
||||
event, mVolumeControlStreamType, false);
|
||||
getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(event,
|
||||
mVolumeControlStreamType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1906,7 +1895,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
case KeyEvent.KEYCODE_MEDIA_RECORD:
|
||||
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
|
||||
if (mMediaController != null) {
|
||||
if (mMediaController.dispatchMediaButtonEvent(event)) {
|
||||
if (mMediaController.dispatchMediaButtonEventAsSystemService(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1948,6 +1937,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
return mAudioManager;
|
||||
}
|
||||
|
||||
private MediaSessionManager getMediaSessionManager() {
|
||||
if (mMediaSessionManager == null) {
|
||||
mMediaSessionManager = (MediaSessionManager) getContext().getSystemService(
|
||||
Context.MEDIA_SESSION_SERVICE);
|
||||
}
|
||||
return mMediaSessionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* A key was released and not handled by anything else in the window.
|
||||
*
|
||||
@@ -1969,12 +1966,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
// If we have a session send it the volume command, otherwise
|
||||
// use the suggested stream.
|
||||
if (mMediaController != null) {
|
||||
final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
|
||||
| AudioManager.FLAG_FROM_KEY;
|
||||
mMediaController.adjustVolume(0, flags);
|
||||
mMediaController.dispatchVolumeButtonEventAsSystemService(event);
|
||||
} else {
|
||||
MediaSessionLegacyHelper.getHelper(getContext()).sendVolumeKeyEvent(
|
||||
event, mVolumeControlStreamType, false);
|
||||
getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(
|
||||
event, mVolumeControlStreamType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1983,8 +1978,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
// doesn't have one of these. In this case, we execute it here and
|
||||
// eat the event instead, because we have mVolumeControlStreamType
|
||||
// and they don't.
|
||||
MediaSessionLegacyHelper.getHelper(getContext()).sendVolumeKeyEvent(
|
||||
event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
|
||||
getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(
|
||||
event, AudioManager.USE_DEFAULT_STREAM_TYPE);
|
||||
return true;
|
||||
}
|
||||
// These are all the recognized media key codes in
|
||||
@@ -2001,7 +1996,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
case KeyEvent.KEYCODE_MEDIA_RECORD:
|
||||
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
|
||||
if (mMediaController != null) {
|
||||
if (mMediaController.dispatchMediaButtonEvent(event)) {
|
||||
if (mMediaController.dispatchMediaButtonEventAsSystemService(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import java.util.List;
|
||||
*/
|
||||
interface ISessionController {
|
||||
void sendCommand(String packageName, String command, in Bundle args, in ResultReceiver cb);
|
||||
boolean sendMediaButton(String packageName, in KeyEvent mediaButton);
|
||||
boolean sendMediaButton(String packageName, boolean asSystemService, in KeyEvent mediaButton);
|
||||
void registerCallbackListener(in ISessionControllerCallback cb);
|
||||
void unregisterCallbackListener(in ISessionControllerCallback cb);
|
||||
boolean isTransportControlEnabled();
|
||||
@@ -46,7 +46,7 @@ interface ISessionController {
|
||||
PendingIntent getLaunchPendingIntent();
|
||||
long getFlags();
|
||||
ParcelableVolumeInfo getVolumeAttributes();
|
||||
void adjustVolume(String packageName, int direction, int flags);
|
||||
void adjustVolume(String packageName, boolean asSystemService, int direction, int flags);
|
||||
void setVolumeTo(String packageName, int value, int flags);
|
||||
|
||||
// These commands are for the TransportControls
|
||||
|
||||
@@ -34,9 +34,11 @@ import android.view.KeyEvent;
|
||||
interface ISessionManager {
|
||||
ISession createSession(String packageName, in ISessionCallback cb, String tag, int userId);
|
||||
List<IBinder> getSessions(in ComponentName compName, int userId);
|
||||
void dispatchMediaKeyEvent(in KeyEvent keyEvent, boolean needWakeLock);
|
||||
void dispatchVolumeKeyEvent(in KeyEvent keyEvent, int stream, boolean musicOnly);
|
||||
void dispatchAdjustVolume(int suggestedStream, int delta, int flags);
|
||||
void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
|
||||
boolean needWakeLock);
|
||||
void dispatchVolumeKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
|
||||
int stream, boolean musicOnly);
|
||||
void dispatchAdjustVolume(String packageName, int suggestedStream, int delta, int flags);
|
||||
void addSessionsListener(in IActiveSessionsListener listener, in ComponentName compName,
|
||||
int userId);
|
||||
void removeSessionsListener(in IActiveSessionsListener listener);
|
||||
|
||||
@@ -126,6 +126,27 @@ public final class MediaController {
|
||||
* @return true if the event was sent to the session, false otherwise.
|
||||
*/
|
||||
public boolean dispatchMediaButtonEvent(@NonNull KeyEvent keyEvent) {
|
||||
return dispatchMediButtonEventInternal(false, keyEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the media button event as system service to the session. This only effects the
|
||||
* {@link MediaSession.Callback#getCurrentControllerInfo()} and doesn't bypass any permission
|
||||
* check done by the system service.
|
||||
* <p>
|
||||
* Should be only called by the {@link com.android.internal.policy.PhoneWindow} when the
|
||||
* foreground activity didn't consume the key from the hardware devices.
|
||||
*
|
||||
* @param keyEvent media key event
|
||||
* @return {@code true} if the event was sent to the session, {@code false} otherwise
|
||||
* @hide
|
||||
*/
|
||||
public boolean dispatchMediaButtonEventAsSystemService(@NonNull KeyEvent keyEvent) {
|
||||
return dispatchMediButtonEventInternal(true, keyEvent);
|
||||
}
|
||||
|
||||
private boolean dispatchMediButtonEventInternal(boolean asSystemService,
|
||||
@NonNull KeyEvent keyEvent) {
|
||||
if (keyEvent == null) {
|
||||
throw new IllegalArgumentException("KeyEvent may not be null");
|
||||
}
|
||||
@@ -133,13 +154,60 @@ public final class MediaController {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return mSessionBinder.sendMediaButton(mContext.getPackageName(), keyEvent);
|
||||
return mSessionBinder.sendMediaButton(mContext.getPackageName(), asSystemService,
|
||||
keyEvent);
|
||||
} catch (RemoteException e) {
|
||||
// System is dead. =(
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the volume button event as system service to the session. This only effects the
|
||||
* {@link MediaSession.Callback#getCurrentControllerInfo()} and doesn't bypass any permission
|
||||
* check done by the system service.
|
||||
* <p>
|
||||
* Should be only called by the {@link com.android.internal.policy.PhoneWindow} when the
|
||||
* foreground activity didn't consume the key from the hardware devices.
|
||||
*
|
||||
* @param keyEvent volume key event
|
||||
* @hide
|
||||
*/
|
||||
public void dispatchVolumeButtonEventAsSystemService(@NonNull KeyEvent keyEvent) {
|
||||
switch (keyEvent.getAction()) {
|
||||
case KeyEvent.ACTION_DOWN: {
|
||||
int direction = 0;
|
||||
switch (keyEvent.getKeyCode()) {
|
||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||
direction = AudioManager.ADJUST_RAISE;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||
direction = AudioManager.ADJUST_LOWER;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_VOLUME_MUTE:
|
||||
direction = AudioManager.ADJUST_TOGGLE_MUTE;
|
||||
break;
|
||||
}
|
||||
try {
|
||||
mSessionBinder.adjustVolume(mContext.getPackageName(), true, direction,
|
||||
AudioManager.FLAG_SHOW_UI);
|
||||
} catch (RemoteException e) {
|
||||
Log.wtf(TAG, "Error calling adjustVolumeBy", e);
|
||||
}
|
||||
}
|
||||
|
||||
case KeyEvent.ACTION_UP: {
|
||||
final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
|
||||
| AudioManager.FLAG_FROM_KEY;
|
||||
try {
|
||||
mSessionBinder.adjustVolume(mContext.getPackageName(), true, 0, flags);
|
||||
} catch (RemoteException e) {
|
||||
Log.wtf(TAG, "Error calling adjustVolumeBy", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current playback state for this session.
|
||||
*
|
||||
@@ -322,7 +390,7 @@ public final class MediaController {
|
||||
*/
|
||||
public void adjustVolume(int direction, int flags) {
|
||||
try {
|
||||
mSessionBinder.adjustVolume(mContext.getPackageName(), direction, flags);
|
||||
mSessionBinder.adjustVolume(mContext.getPackageName(), false, direction, flags);
|
||||
} catch (RemoteException e) {
|
||||
Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
|
||||
}
|
||||
|
||||
@@ -122,6 +122,15 @@ public final class MediaSession {
|
||||
FLAG_EXCLUSIVE_GLOBAL_PRIORITY })
|
||||
public @interface SessionFlags { }
|
||||
|
||||
private static final String EXTRA_KEY_CALLING_PACKAGE =
|
||||
"android.media.session.extra.CALLING_PACKAGE";
|
||||
private static final String EXTRA_KEY_CALLING_PID =
|
||||
"android.media.session.extra.CALLING_PID";
|
||||
private static final String EXTRA_KEY_CALLING_UID =
|
||||
"android.media.session.extra.CALLING_UID";
|
||||
private static final String EXTRA_KEY_ORIGINAL_BUNDLE =
|
||||
"android.media.session.extra.ORIGINAL_BUNDLE";
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private final int mMaxBitmapSize;
|
||||
|
||||
@@ -520,11 +529,15 @@ public final class MediaSession {
|
||||
* @see MediaSessionManager#isTrustedForMediaControl(RemoteUserInfo)
|
||||
*/
|
||||
public final @NonNull RemoteUserInfo getCurrentControllerInfo() {
|
||||
if (mCallback == null || mCallback.mCurrentControllerInfo == null) {
|
||||
return createRemoteUserInfo(getCurrentData());
|
||||
}
|
||||
|
||||
private @NonNull Bundle getCurrentData() {
|
||||
if (mCallback == null || mCallback.mCurrentData == null) {
|
||||
throw new IllegalStateException(
|
||||
"This should be called inside of MediaSession.Callback methods");
|
||||
}
|
||||
return mCallback.mCurrentControllerInfo;
|
||||
return mCallback.mCurrentData;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -556,7 +569,7 @@ public final class MediaSession {
|
||||
*/
|
||||
public String getCallingPackage() {
|
||||
if (mCallback != null) {
|
||||
return mCallback.mCurrentControllerInfo.getPackageName();
|
||||
return createRemoteUserInfo(mCallback.mCurrentData).getPackageName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -658,6 +671,57 @@ public final class MediaSession {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the extra bundle that includes the caller information.
|
||||
*
|
||||
* @return An extraBundle that contains caller information
|
||||
*/
|
||||
private static Bundle createExtraBundle(String packageName, int pid, int uid) {
|
||||
return createExtraBundle(packageName, pid, uid, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the extra bundle that includes the caller information.
|
||||
*
|
||||
* @param originalBundle bundle
|
||||
* @return An extraBundle that contains caller information
|
||||
*/
|
||||
private static Bundle createExtraBundle(String packageName, int pid, int uid,
|
||||
Bundle originalBundle) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EXTRA_KEY_CALLING_PACKAGE, packageName);
|
||||
bundle.putInt(EXTRA_KEY_CALLING_PID, pid);
|
||||
bundle.putInt(EXTRA_KEY_CALLING_UID, uid);
|
||||
if (originalBundle != null) {
|
||||
bundle.putBundle(EXTRA_KEY_ORIGINAL_BUNDLE, originalBundle);
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link RemoteUserInfo} from the extra bundle created by
|
||||
* {@link #createExtraBundle}.
|
||||
*
|
||||
* @param extraBundle that previously created by createExtraBundle()
|
||||
* @return a RemoteUserInfo
|
||||
*/
|
||||
private static RemoteUserInfo createRemoteUserInfo(Bundle extraBundle) {
|
||||
return new RemoteUserInfo(
|
||||
extraBundle.getString(EXTRA_KEY_CALLING_PACKAGE),
|
||||
extraBundle.getInt(EXTRA_KEY_CALLING_PID, INVALID_PID),
|
||||
extraBundle.getInt(EXTRA_KEY_CALLING_UID, INVALID_UID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the original bundle from the extra bundle created by {@link #createExtraBundle}.
|
||||
*
|
||||
* @param extraBundle that previously created by createExtraBundle()
|
||||
* @return a Bundle
|
||||
*/
|
||||
private static Bundle getOriginalBundle(Bundle extraBundle) {
|
||||
return extraBundle.getBundle(EXTRA_KEY_ORIGINAL_BUNDLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is considered an active playback state.
|
||||
*
|
||||
@@ -755,9 +819,6 @@ public final class MediaSession {
|
||||
private MediaSession mSession;
|
||||
private CallbackMessageHandler mHandler;
|
||||
private boolean mMediaPlayPauseKeyPending;
|
||||
private String mCallingPackage;
|
||||
private int mCallingPid;
|
||||
private int mCallingUid;
|
||||
|
||||
public Callback() {
|
||||
}
|
||||
@@ -811,8 +872,9 @@ public final class MediaSession {
|
||||
}
|
||||
} else {
|
||||
mMediaPlayPauseKeyPending = true;
|
||||
mHandler.sendEmptyMessageDelayed(CallbackMessageHandler
|
||||
.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT,
|
||||
mHandler.postDelayed(CallbackMessageHandler
|
||||
.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT,
|
||||
mSession.getCurrentData(),
|
||||
ViewConfiguration.getDoubleTapTimeout());
|
||||
}
|
||||
return true;
|
||||
@@ -1242,22 +1304,6 @@ public final class MediaSession {
|
||||
session.dispatchSetVolumeTo(value, createExtraBundle(packageName, pid, uid));
|
||||
}
|
||||
}
|
||||
|
||||
private Bundle createExtraBundle(String packageName, int pid, int uid) {
|
||||
return createExtraBundle(packageName, pid, uid, null);
|
||||
}
|
||||
|
||||
private Bundle createExtraBundle(String packageName, int pid, int uid,
|
||||
Bundle originalBundle) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(CallbackMessageHandler.EXTRA_KEY_CALLING_PACKAGE, packageName);
|
||||
bundle.putInt(CallbackMessageHandler.EXTRA_KEY_CALLING_PID, pid);
|
||||
bundle.putInt(CallbackMessageHandler.EXTRA_KEY_CALLING_UID, uid);
|
||||
if (originalBundle != null) {
|
||||
bundle.putBundle(CallbackMessageHandler.EXTRA_KEY_ORIGINAL_BUNDLE, originalBundle);
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1379,15 +1425,6 @@ public final class MediaSession {
|
||||
|
||||
private class CallbackMessageHandler extends Handler {
|
||||
|
||||
private static final String EXTRA_KEY_CALLING_PACKAGE =
|
||||
"android.media.session.extra.CALLING_PACKAGE";
|
||||
private static final String EXTRA_KEY_CALLING_PID =
|
||||
"android.media.session.extra.CALLING_PID";
|
||||
private static final String EXTRA_KEY_CALLING_UID =
|
||||
"android.media.session.extra.CALLING_UID";
|
||||
private static final String EXTRA_KEY_ORIGINAL_BUNDLE =
|
||||
"android.media.session.extra.ORIGINAL_BUNDLE";
|
||||
|
||||
private static final int MSG_COMMAND = 1;
|
||||
private static final int MSG_MEDIA_BUTTON = 2;
|
||||
private static final int MSG_PREPARE = 3;
|
||||
@@ -1413,8 +1450,7 @@ public final class MediaSession {
|
||||
private static final int MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT = 23;
|
||||
|
||||
private MediaSession.Callback mCallback;
|
||||
|
||||
private RemoteUserInfo mCurrentControllerInfo;
|
||||
private Bundle mCurrentData;
|
||||
|
||||
public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) {
|
||||
super(looper, null, true);
|
||||
@@ -1422,22 +1458,25 @@ public final class MediaSession {
|
||||
mCallback.mHandler = this;
|
||||
}
|
||||
|
||||
public void post(int what, Object obj, Bundle bundle) {
|
||||
public void post(int what, Object obj, Bundle data) {
|
||||
Message msg = obtainMessage(what, obj);
|
||||
msg.setData(bundle);
|
||||
msg.setData(data);
|
||||
msg.sendToTarget();
|
||||
}
|
||||
|
||||
public void postDelayed(int what, Bundle data, long delayMs) {
|
||||
Message msg = obtainMessage(what);
|
||||
msg.setData(data);
|
||||
sendMessageDelayed(msg, delayMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
VolumeProvider vp;
|
||||
Bundle bundle = msg.getData();
|
||||
Bundle originalBundle = bundle.getBundle(EXTRA_KEY_ORIGINAL_BUNDLE);
|
||||
Bundle data = msg.getData();
|
||||
Bundle originalBundle = getOriginalBundle(data);
|
||||
|
||||
mCurrentControllerInfo = new RemoteUserInfo(
|
||||
bundle.getString(EXTRA_KEY_CALLING_PACKAGE),
|
||||
bundle.getInt(EXTRA_KEY_CALLING_PID, INVALID_PID),
|
||||
bundle.getInt(EXTRA_KEY_CALLING_UID, INVALID_UID));
|
||||
mCurrentData = data;
|
||||
|
||||
switch (msg.what) {
|
||||
case MSG_COMMAND:
|
||||
@@ -1521,7 +1560,7 @@ public final class MediaSession {
|
||||
mCallback.handleMediaPlayPauseKeySingleTapIfPending();
|
||||
break;
|
||||
}
|
||||
mCurrentControllerInfo = null;
|
||||
mCurrentData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,8 +300,28 @@ public final class MediaSessionManager {
|
||||
* @hide
|
||||
*/
|
||||
public void dispatchMediaKeyEvent(@NonNull KeyEvent keyEvent, boolean needWakeLock) {
|
||||
dispatchMediaKeyEventInternal(false, keyEvent, needWakeLock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a media key event as system component. The receiver will be selected automatically.
|
||||
* <p>
|
||||
* Should be only called by the {@link com.android.internal.policy.PhoneWindow} or
|
||||
* {@link android.view.FallbackEventHandler} when the foreground activity didn't consume the key
|
||||
* from the hardware devices.
|
||||
*
|
||||
* @param keyEvent The KeyEvent to send.
|
||||
* @hide
|
||||
*/
|
||||
public void dispatchMediaKeyEventAsSystemService(KeyEvent keyEvent) {
|
||||
dispatchMediaKeyEventInternal(true, keyEvent, false);
|
||||
}
|
||||
|
||||
private void dispatchMediaKeyEventInternal(boolean asSystemService, @NonNull KeyEvent keyEvent,
|
||||
boolean needWakeLock) {
|
||||
try {
|
||||
mService.dispatchMediaKeyEvent(keyEvent, needWakeLock);
|
||||
mService.dispatchMediaKeyEvent(mContext.getPackageName(), asSystemService, keyEvent,
|
||||
needWakeLock);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to send key event.", e);
|
||||
}
|
||||
@@ -311,12 +331,33 @@ public final class MediaSessionManager {
|
||||
* Send a volume key event. The receiver will be selected automatically.
|
||||
*
|
||||
* @param keyEvent The volume KeyEvent to send.
|
||||
* @param needWakeLock True if a wake lock should be held while sending the key.
|
||||
* @hide
|
||||
*/
|
||||
public void dispatchVolumeKeyEvent(@NonNull KeyEvent keyEvent, int stream, boolean musicOnly) {
|
||||
dispatchVolumeKeyEventInternal(false, keyEvent, stream, musicOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the volume button event as system service to the session. This only effects the
|
||||
* {@link MediaSession.Callback#getCurrentControllerInfo()} and doesn't bypass any permission
|
||||
* check done by the system service.
|
||||
* <p>
|
||||
* Should be only called by the {@link com.android.internal.policy.PhoneWindow} or
|
||||
* {@link android.view.FallbackEventHandler} when the foreground activity didn't consume the key
|
||||
* from the hardware devices.
|
||||
*
|
||||
* @param keyEvent The KeyEvent to send.
|
||||
* @hide
|
||||
*/
|
||||
public void dispatchVolumeKeyEventAsSystemService(@NonNull KeyEvent keyEvent, int streamType) {
|
||||
dispatchVolumeKeyEventInternal(true, keyEvent, streamType, false);
|
||||
}
|
||||
|
||||
private void dispatchVolumeKeyEventInternal(boolean asSystemService, @NonNull KeyEvent keyEvent,
|
||||
int stream, boolean musicOnly) {
|
||||
try {
|
||||
mService.dispatchVolumeKeyEvent(keyEvent, stream, musicOnly);
|
||||
mService.dispatchVolumeKeyEvent(mContext.getPackageName(), asSystemService, keyEvent,
|
||||
stream, musicOnly);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to send volume key event.", e);
|
||||
}
|
||||
@@ -336,7 +377,8 @@ public final class MediaSessionManager {
|
||||
*/
|
||||
public void dispatchAdjustVolume(int suggestedStream, int direction, int flags) {
|
||||
try {
|
||||
mService.dispatchAdjustVolume(suggestedStream, direction, flags);
|
||||
mService.dispatchAdjustVolume(mContext.getPackageName(), suggestedStream, direction,
|
||||
flags);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to send adjust volume.", e);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.SystemClock;
|
||||
@@ -82,6 +83,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
|
||||
private final SessionStub mSession;
|
||||
private final SessionCb mSessionCb;
|
||||
private final MediaSessionService mService;
|
||||
private final Context mContext;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private final ArrayList<ISessionControllerCallbackHolder> mControllerCallbackHolders =
|
||||
@@ -126,8 +128,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
|
||||
mSession = new SessionStub();
|
||||
mSessionCb = new SessionCb(cb);
|
||||
mService = service;
|
||||
mContext = mService.getContext();
|
||||
mHandler = new MessageHandler(handlerLooper);
|
||||
mAudioManager = (AudioManager) service.getContext().getSystemService(Context.AUDIO_SERVICE);
|
||||
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
|
||||
mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
|
||||
}
|
||||
@@ -232,12 +235,17 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
|
||||
* @param packageName The package that made the original volume request.
|
||||
* @param pid The pid that made the original volume request.
|
||||
* @param uid The uid that made the original volume request.
|
||||
* @param asSystemService {@code true} if the event sent to the session as if it was come from
|
||||
* the system service instead of the app process. This helps sessions to distinguish
|
||||
* between the key injection by the app and key events from the hardware devices.
|
||||
* Should be used only when the volume key events aren't handled by foreground
|
||||
* activity. {@code false} otherwise to tell session about the real caller.
|
||||
* @param direction The direction to adjust volume in.
|
||||
* @param flags Any of the flags from {@link AudioManager}.
|
||||
* @param useSuggested True to use adjustSuggestedStreamVolume instead of
|
||||
*/
|
||||
public void adjustVolume(String packageName, int pid, int uid, int direction, int flags,
|
||||
boolean useSuggested) {
|
||||
public void adjustVolume(String packageName, int pid, int uid, boolean asSystemService,
|
||||
int direction, int flags, boolean useSuggested) {
|
||||
int previousFlagPlaySound = flags & AudioManager.FLAG_PLAY_SOUND;
|
||||
if (isPlaybackActive() || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) {
|
||||
flags &= ~AudioManager.FLAG_PLAY_SOUND;
|
||||
@@ -258,7 +266,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
|
||||
Log.w(TAG, "Muting remote playback is not supported");
|
||||
return;
|
||||
}
|
||||
mSessionCb.adjustVolume(packageName, pid, uid, direction);
|
||||
mSessionCb.adjustVolume(packageName, pid, uid, asSystemService, direction);
|
||||
|
||||
int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
|
||||
mOptimisticVolume = volumeBefore + direction;
|
||||
@@ -418,9 +426,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
|
||||
return mSessionCb.mCb;
|
||||
}
|
||||
|
||||
public void sendMediaButton(String packageName, int pid, int uid, KeyEvent ke, int sequenceId,
|
||||
ResultReceiver cb) {
|
||||
mSessionCb.sendMediaButton(packageName, pid, uid, ke, sequenceId, cb);
|
||||
public void sendMediaButton(String packageName, int pid, int uid, boolean asSystemService,
|
||||
KeyEvent ke, int sequenceId, ResultReceiver cb) {
|
||||
mSessionCb.sendMediaButton(packageName, pid, uid, asSystemService, ke, sequenceId, cb);
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw, String prefix) {
|
||||
@@ -698,11 +706,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
|
||||
}
|
||||
|
||||
private String getPackageName(int uid) {
|
||||
Context context = mService.getContext();
|
||||
if (context == null) {
|
||||
return null;
|
||||
}
|
||||
String[] packages = context.getPackageManager().getPackagesForUid(uid);
|
||||
String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
|
||||
if (packages != null && packages.length > 0) {
|
||||
return packages[0];
|
||||
}
|
||||
@@ -907,12 +911,17 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
|
||||
mCb = cb;
|
||||
}
|
||||
|
||||
public boolean sendMediaButton(String packageName, int pid, int uid, KeyEvent keyEvent,
|
||||
int sequenceId, ResultReceiver cb) {
|
||||
public boolean sendMediaButton(String packageName, int pid, int uid,
|
||||
boolean asSystemService, KeyEvent keyEvent, int sequenceId, ResultReceiver cb) {
|
||||
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
|
||||
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
|
||||
try {
|
||||
mCb.onMediaButton(packageName, pid, uid, mediaButtonIntent, sequenceId, cb);
|
||||
if (asSystemService) {
|
||||
mCb.onMediaButton(mContext.getPackageName(), Process.myPid(),
|
||||
Process.SYSTEM_UID, mediaButtonIntent, sequenceId, cb);
|
||||
} else {
|
||||
mCb.onMediaButton(packageName, pid, uid, mediaButtonIntent, sequenceId, cb);
|
||||
}
|
||||
return true;
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote failure in sendMediaRequest.", e);
|
||||
@@ -1079,9 +1088,15 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
|
||||
}
|
||||
}
|
||||
|
||||
public void adjustVolume(String packageName, int pid, int uid, int direction) {
|
||||
public void adjustVolume(String packageName, int pid, int uid, boolean asSystemService,
|
||||
int direction) {
|
||||
try {
|
||||
mCb.onAdjustVolume(packageName, pid, uid, direction);
|
||||
if (asSystemService) {
|
||||
mCb.onAdjustVolume(mContext.getPackageName(), Process.myPid(),
|
||||
Process.SYSTEM_UID, direction);
|
||||
} else {
|
||||
mCb.onAdjustVolume(packageName, pid, uid, direction);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote failure in adjustVolume.", e);
|
||||
}
|
||||
@@ -1105,9 +1120,10 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendMediaButton(String packageName, KeyEvent mediaButtonIntent) {
|
||||
public boolean sendMediaButton(String packageName, boolean asSystemService,
|
||||
KeyEvent mediaButtonIntent) {
|
||||
return mSessionCb.sendMediaButton(packageName, Binder.getCallingPid(),
|
||||
Binder.getCallingUid(), mediaButtonIntent, 0, null);
|
||||
Binder.getCallingUid(), asSystemService, mediaButtonIntent, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1188,13 +1204,14 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustVolume(String packageName, int direction, int flags) {
|
||||
public void adjustVolume(String packageName, boolean asSystemService, int direction,
|
||||
int flags) {
|
||||
int pid = Binder.getCallingPid();
|
||||
int uid = Binder.getCallingUid();
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
MediaSessionRecord.this.adjustVolume(packageName, pid, uid, direction, flags,
|
||||
false /* useSuggested */);
|
||||
MediaSessionRecord.this.adjustVolume(packageName, pid, uid, asSystemService,
|
||||
direction, flags, false /* useSuggested */);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
|
||||
@@ -1093,13 +1093,21 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
* registered listeners, or if there was none, broadcast an
|
||||
* ACTION_MEDIA_BUTTON intent to the rest of the system.
|
||||
*
|
||||
* @param packageName The caller package
|
||||
* @param asSystemService {@code true} if the event sent to the session as if it was come
|
||||
* from the system service instead of the app process. This helps sessions to
|
||||
* distinguish between the key injection by the app and key events from the
|
||||
* hardware devices. Should be used only when the volume key events aren't handled
|
||||
* by foreground activity. {@code false} otherwise to tell session about the real
|
||||
* caller.
|
||||
* @param keyEvent a non-null KeyEvent whose key code is one of the
|
||||
* supported media buttons
|
||||
* @param needWakeLock true if a PARTIAL_WAKE_LOCK needs to be held
|
||||
* while this key event is dispatched.
|
||||
*/
|
||||
@Override
|
||||
public void dispatchMediaKeyEvent(KeyEvent keyEvent, boolean needWakeLock) {
|
||||
public void dispatchMediaKeyEvent(String packageName, boolean asSystemService,
|
||||
KeyEvent keyEvent, boolean needWakeLock) {
|
||||
if (keyEvent == null || !KeyEvent.isMediaKey(keyEvent.getKeyCode())) {
|
||||
Log.w(TAG, "Attempted to dispatch null or non-media key event.");
|
||||
return;
|
||||
@@ -1110,7 +1118,8 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "dispatchMediaKeyEvent, pid=" + pid + ", uid=" + uid + ", event="
|
||||
Log.d(TAG, "dispatchMediaKeyEvent, pkg=" + packageName + " pid=" + pid
|
||||
+ ", uid=" + uid + ", asSystem=" + asSystemService + ", event="
|
||||
+ keyEvent);
|
||||
}
|
||||
if (!isUserSetupComplete()) {
|
||||
@@ -1137,7 +1146,8 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
}
|
||||
try {
|
||||
mCurrentFullUserRecord.mOnMediaKeyListener.onMediaKey(keyEvent,
|
||||
new MediaKeyListenerResultReceiver(keyEvent, needWakeLock));
|
||||
new MediaKeyListenerResultReceiver(packageName, pid, uid,
|
||||
asSystemService, keyEvent, needWakeLock));
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to send " + keyEvent
|
||||
@@ -1146,9 +1156,11 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
}
|
||||
}
|
||||
if (!isGlobalPriorityActive && isVoiceKey(keyEvent.getKeyCode())) {
|
||||
handleVoiceKeyEventLocked(keyEvent, needWakeLock);
|
||||
handleVoiceKeyEventLocked(packageName, pid, uid, asSystemService, keyEvent,
|
||||
needWakeLock);
|
||||
} else {
|
||||
dispatchMediaKeyEventLocked(keyEvent, needWakeLock);
|
||||
dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
|
||||
keyEvent, needWakeLock);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@@ -1324,6 +1336,13 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
* there's no active global priority session, long-pressess will be sent to the
|
||||
* long-press listener instead of adjusting volume.
|
||||
*
|
||||
* @param packageName The caller package.
|
||||
* @param asSystemService {@code true} if the event sent to the session as if it was come
|
||||
* from the system service instead of the app process. This helps sessions to
|
||||
* distinguish between the key injection by the app and key events from the
|
||||
* hardware devices. Should be used only when the volume key events aren't handled
|
||||
* by foreground activity. {@code false} otherwise to tell session about the real
|
||||
* caller.
|
||||
* @param keyEvent a non-null KeyEvent whose key code is one of the
|
||||
* {@link KeyEvent#KEYCODE_VOLUME_UP},
|
||||
* {@link KeyEvent#KEYCODE_VOLUME_DOWN},
|
||||
@@ -1332,7 +1351,8 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
* @param musicOnly true if both UI nor haptic feedback aren't needed when adjust volume.
|
||||
*/
|
||||
@Override
|
||||
public void dispatchVolumeKeyEvent(KeyEvent keyEvent, int stream, boolean musicOnly) {
|
||||
public void dispatchVolumeKeyEvent(String packageName, boolean asSystemService,
|
||||
KeyEvent keyEvent, int stream, boolean musicOnly) {
|
||||
if (keyEvent == null ||
|
||||
(keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_UP
|
||||
&& keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_DOWN
|
||||
@@ -1346,15 +1366,16 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
|
||||
if (DEBUG_KEY_EVENT) {
|
||||
Log.d(TAG, "dispatchVolumeKeyEvent, pid=" + pid + ", uid=" + uid + ", event="
|
||||
+ keyEvent);
|
||||
Log.d(TAG, "dispatchVolumeKeyEvent, pkg=" + packageName + ", pid=" + pid + ", uid="
|
||||
+ uid + ", asSystem=" + asSystemService + ", event=" + keyEvent);
|
||||
}
|
||||
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
if (isGlobalPriorityActiveLocked()
|
||||
|| mCurrentFullUserRecord.mOnVolumeKeyLongPressListener == null) {
|
||||
dispatchVolumeKeyEventLocked(keyEvent, stream, musicOnly);
|
||||
dispatchVolumeKeyEventLocked(packageName, pid, uid, asSystemService,
|
||||
keyEvent, stream, musicOnly);
|
||||
} else {
|
||||
// TODO: Consider the case when both volume up and down keys are pressed
|
||||
// at the same time.
|
||||
@@ -1387,11 +1408,12 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
&& mCurrentFullUserRecord.mInitialDownVolumeKeyEvent
|
||||
.getDownTime() == keyEvent.getDownTime()) {
|
||||
// Short-press. Should change volume.
|
||||
dispatchVolumeKeyEventLocked(
|
||||
dispatchVolumeKeyEventLocked(packageName, pid, uid, asSystemService,
|
||||
mCurrentFullUserRecord.mInitialDownVolumeKeyEvent,
|
||||
mCurrentFullUserRecord.mInitialDownVolumeStream,
|
||||
mCurrentFullUserRecord.mInitialDownMusicOnly);
|
||||
dispatchVolumeKeyEventLocked(keyEvent, stream, musicOnly);
|
||||
dispatchVolumeKeyEventLocked(packageName, pid, uid, asSystemService,
|
||||
keyEvent, stream, musicOnly);
|
||||
} else {
|
||||
dispatchVolumeKeyLongPressLocked(keyEvent);
|
||||
}
|
||||
@@ -1403,8 +1425,8 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchVolumeKeyEventLocked(
|
||||
KeyEvent keyEvent, int stream, boolean musicOnly) {
|
||||
private void dispatchVolumeKeyEventLocked(String packageName, int pid, int uid,
|
||||
boolean asSystemService, KeyEvent keyEvent, int stream, boolean musicOnly) {
|
||||
boolean down = keyEvent.getAction() == KeyEvent.ACTION_DOWN;
|
||||
boolean up = keyEvent.getAction() == KeyEvent.ACTION_UP;
|
||||
int direction = 0;
|
||||
@@ -1438,21 +1460,27 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
if (up) {
|
||||
direction = 0;
|
||||
}
|
||||
dispatchAdjustVolumeLocked(stream, direction, flags);
|
||||
dispatchAdjustVolumeLocked(packageName, pid, uid, asSystemService, stream,
|
||||
direction, flags);
|
||||
} else if (isMute) {
|
||||
if (down && keyEvent.getRepeatCount() == 0) {
|
||||
dispatchAdjustVolumeLocked(stream, AudioManager.ADJUST_TOGGLE_MUTE, flags);
|
||||
dispatchAdjustVolumeLocked(packageName, pid, uid, asSystemService, stream,
|
||||
AudioManager.ADJUST_TOGGLE_MUTE, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchAdjustVolume(int suggestedStream, int delta, int flags) {
|
||||
public void dispatchAdjustVolume(String packageName, int suggestedStream, int delta,
|
||||
int flags) {
|
||||
final int pid = Binder.getCallingPid();
|
||||
final int uid = Binder.getCallingUid();
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
dispatchAdjustVolumeLocked(suggestedStream, delta, flags);
|
||||
dispatchAdjustVolumeLocked(packageName, pid, uid, false,
|
||||
suggestedStream, delta, flags);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
@@ -1777,7 +1805,8 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void dispatchAdjustVolumeLocked(int suggestedStream, int direction, int flags) {
|
||||
private void dispatchAdjustVolumeLocked(String packageName, int pid, int uid,
|
||||
boolean asSystemService, int suggestedStream, int direction, int flags) {
|
||||
MediaSessionRecord session = isGlobalPriorityActiveLocked() ? mGlobalPrioritySession
|
||||
: mCurrentFullUserRecord.mPriorityStack.getDefaultVolumeSession();
|
||||
|
||||
@@ -1822,12 +1851,13 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
session.adjustVolume(getContext().getPackageName(), Process.myPid(),
|
||||
Process.SYSTEM_UID, direction, flags, true);
|
||||
session.adjustVolume(packageName, pid, uid, asSystemService,
|
||||
direction, flags, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleVoiceKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock) {
|
||||
private void handleVoiceKeyEventLocked(String packageName, int pid, int uid,
|
||||
boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
|
||||
int action = keyEvent.getAction();
|
||||
boolean isLongPress = (keyEvent.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0;
|
||||
if (action == KeyEvent.ACTION_DOWN) {
|
||||
@@ -1844,14 +1874,17 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
if (!mVoiceButtonHandled && !keyEvent.isCanceled()) {
|
||||
// Resend the down then send this event through
|
||||
KeyEvent downEvent = KeyEvent.changeAction(keyEvent, KeyEvent.ACTION_DOWN);
|
||||
dispatchMediaKeyEventLocked(downEvent, needWakeLock);
|
||||
dispatchMediaKeyEventLocked(keyEvent, needWakeLock);
|
||||
dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
|
||||
downEvent, needWakeLock);
|
||||
dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
|
||||
keyEvent, needWakeLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchMediaKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock) {
|
||||
private void dispatchMediaKeyEventLocked(String packageName, int pid, int uid,
|
||||
boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
|
||||
MediaSessionRecord session = mCurrentFullUserRecord.getMediaButtonSessionLocked();
|
||||
if (session != null) {
|
||||
if (DEBUG_KEY_EVENT) {
|
||||
@@ -1861,17 +1894,13 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
mKeyEventReceiver.aquireWakeLockLocked();
|
||||
}
|
||||
// If we don't need a wakelock use -1 as the id so we won't release it later.
|
||||
session.sendMediaButton(getContext().getPackageName(),
|
||||
Process.myPid(),
|
||||
Process.SYSTEM_UID,
|
||||
keyEvent,
|
||||
session.sendMediaButton(packageName, pid, uid, asSystemService, keyEvent,
|
||||
needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
|
||||
mKeyEventReceiver);
|
||||
if (mCurrentFullUserRecord.mCallback != null) {
|
||||
try {
|
||||
mCurrentFullUserRecord.mCallback.onMediaKeyEventDispatchedToMediaSession(
|
||||
keyEvent,
|
||||
new MediaSession.Token(session.getControllerBinder()));
|
||||
keyEvent, new MediaSession.Token(session.getControllerBinder()));
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to send callback", e);
|
||||
}
|
||||
@@ -1884,6 +1913,10 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
|
||||
mediaButtonIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
|
||||
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
|
||||
// TODO: Find a way to also send PID/UID in secure way.
|
||||
String callerPackageName =
|
||||
(asSystemService) ? getContext().getPackageName() : packageName;
|
||||
mediaButtonIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, callerPackageName);
|
||||
try {
|
||||
if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
|
||||
PendingIntent receiver = mCurrentFullUserRecord.mLastMediaButtonReceiver;
|
||||
@@ -1984,13 +2017,22 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
}
|
||||
|
||||
private class MediaKeyListenerResultReceiver extends ResultReceiver implements Runnable {
|
||||
private KeyEvent mKeyEvent;
|
||||
private boolean mNeedWakeLock;
|
||||
private final String mPackageName;
|
||||
private final int mPid;
|
||||
private final int mUid;
|
||||
private final boolean mAsSystemService;
|
||||
private final KeyEvent mKeyEvent;
|
||||
private final boolean mNeedWakeLock;
|
||||
private boolean mHandled;
|
||||
|
||||
private MediaKeyListenerResultReceiver(KeyEvent keyEvent, boolean needWakeLock) {
|
||||
private MediaKeyListenerResultReceiver(String packageName, int pid, int uid,
|
||||
boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
|
||||
super(mHandler);
|
||||
mHandler.postDelayed(this, MEDIA_KEY_LISTENER_TIMEOUT);
|
||||
mPackageName = packageName;
|
||||
mPid = pid;
|
||||
mUid = uid;
|
||||
mAsSystemService = asSystemService;
|
||||
mKeyEvent = keyEvent;
|
||||
mNeedWakeLock = needWakeLock;
|
||||
}
|
||||
@@ -2020,9 +2062,11 @@ public class MediaSessionService extends SystemService implements Monitor {
|
||||
synchronized (mLock) {
|
||||
if (!isGlobalPriorityActiveLocked()
|
||||
&& isVoiceKey(mKeyEvent.getKeyCode())) {
|
||||
handleVoiceKeyEventLocked(mKeyEvent, mNeedWakeLock);
|
||||
handleVoiceKeyEventLocked(mPackageName, mPid, mUid, mAsSystemService,
|
||||
mKeyEvent, mNeedWakeLock);
|
||||
} else {
|
||||
dispatchMediaKeyEventLocked(mKeyEvent, mNeedWakeLock);
|
||||
dispatchMediaKeyEventLocked(mPackageName, mPid, mUid, mAsSystemService,
|
||||
mKeyEvent, mNeedWakeLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user