diff --git a/api/system-current.txt b/api/system-current.txt index 00676c815f357..d3d9c220f12ad 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3609,7 +3609,7 @@ package android.media.session { public abstract static class ControllerLink.ControllerStub { ctor public ControllerLink.ControllerStub(); - method public void adjustVolume(@NonNull String, @NonNull String, @NonNull android.media.session.ControllerCallbackLink, boolean, int, int); + method public void adjustVolume(@NonNull String, @NonNull String, @NonNull android.media.session.ControllerCallbackLink, int, int); method public void fastForward(@NonNull String, @NonNull android.media.session.ControllerCallbackLink); method @Nullable public android.os.Bundle getExtras(); method public long getFlags(); @@ -3639,7 +3639,7 @@ package android.media.session { method public void seekTo(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, long); method public void sendCommand(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle, @Nullable android.os.ResultReceiver); method public void sendCustomAction(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull String, @Nullable android.os.Bundle); - method public boolean sendMediaButton(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, boolean, @NonNull android.view.KeyEvent); + method public boolean sendMediaButton(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, @NonNull android.view.KeyEvent); method public void setVolumeTo(@NonNull String, @NonNull String, @NonNull android.media.session.ControllerCallbackLink, int, int); method public void skipToQueueItem(@NonNull String, @NonNull android.media.session.ControllerCallbackLink, long); method public void stop(@NonNull String, @NonNull android.media.session.ControllerCallbackLink); diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index d8ee643e27f01..69efb2b10af06 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -41,7 +41,6 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Configuration; -import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.graphics.Color; @@ -1885,7 +1884,8 @@ 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) { - mMediaController.dispatchVolumeButtonEventAsSystemService(event); + getMediaSessionManager().dispatchVolumeKeyEventAsSystemService( + mMediaController.getSessionToken(), event); } else { getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(event, mVolumeControlStreamType); @@ -1906,7 +1906,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { case KeyEvent.KEYCODE_MEDIA_RECORD: case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { if (mMediaController != null) { - if (mMediaController.dispatchMediaButtonEventAsSystemService(event)) { + if (getMediaSessionManager().dispatchMediaKeyEventAsSystemService( + mMediaController.getSessionToken(), event)) { return true; } } @@ -1977,7 +1978,8 @@ 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) { - mMediaController.dispatchVolumeButtonEventAsSystemService(event); + getMediaSessionManager().dispatchVolumeKeyEventAsSystemService( + mMediaController.getSessionToken(), event); } else { getMediaSessionManager().dispatchVolumeKeyEventAsSystemService( event, mVolumeControlStreamType); @@ -2007,7 +2009,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { case KeyEvent.KEYCODE_MEDIA_RECORD: case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { if (mMediaController != null) { - if (mMediaController.dispatchMediaButtonEventAsSystemService(event)) { + if (getMediaSessionManager().dispatchMediaKeyEventAsSystemService( + mMediaController.getSessionToken(), event)) { return true; } } diff --git a/media/apex/java/android/media/session/ControllerLink.java b/media/apex/java/android/media/session/ControllerLink.java index 937df20949f08..f60ec000f2d2d 100644 --- a/media/apex/java/android/media/session/ControllerLink.java +++ b/media/apex/java/android/media/session/ControllerLink.java @@ -34,6 +34,7 @@ import android.os.ResultReceiver; import android.view.KeyEvent; import java.util.List; +import java.util.Objects; /** * Handles incoming commands from {@link MediaController}. @@ -96,15 +97,12 @@ public final class ControllerLink implements Parcelable { * * @param packageName the package name of the controller * @param caller the {@link ControllerCallbackLink} of the controller - * @param asSystemService whether this event should be considered as from system service * @param mediaButton the media button key event */ boolean sendMediaButton(@NonNull String packageName, - @NonNull ControllerCallbackLink caller, boolean asSystemService, - @NonNull KeyEvent mediaButton) { + @NonNull ControllerCallbackLink caller, @NonNull KeyEvent mediaButton) { try { - return mISessionController.sendMediaButton(packageName, caller, asSystemService, - mediaButton); + return mISessionController.sendMediaButton(packageName, caller, mediaButton); } catch (RemoteException e) { throw new RuntimeException(e); } @@ -202,16 +200,14 @@ public final class ControllerLink implements Parcelable { * @param packageName the package name of the controller * @param opPackageName the op package name of this request * @param caller the {@link ControllerCallbackLink} of the controller - * @param asSystemService whether this event should be considered as from system service * @param direction the direction to adjust the volume in * @param flags the flags with this volume change request */ void adjustVolume(@NonNull String packageName, @NonNull String opPackageName, - @NonNull ControllerCallbackLink caller, boolean asSystemService, int direction, + @NonNull ControllerCallbackLink caller, int direction, int flags) { try { - mISessionController.adjustVolume(packageName, opPackageName, caller, asSystemService, - direction, flags); + mISessionController.adjustVolume(packageName, opPackageName, caller, direction, flags); } catch (RemoteException e) { throw new RuntimeException(e); } @@ -603,6 +599,23 @@ public final class ControllerLink implements Parcelable { dest.writeStrongBinder(mISessionController.asBinder()); } + @Override + public int hashCode() { + return mISessionController.asBinder().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof ControllerLink)) { + return false; + } + ControllerLink other = (ControllerLink) obj; + return Objects.equals(getBinder(), other.getBinder()); + } + /** * Class for Stub implementation */ @@ -614,8 +627,7 @@ public final class ControllerLink implements Parcelable { /** Stub method for ISessionController.sendMediaButton */ public boolean sendMediaButton(@NonNull String packageName, - @NonNull ControllerCallbackLink caller, boolean asSystemService, - @NonNull KeyEvent mediaButton) { + @NonNull ControllerCallbackLink caller, @NonNull KeyEvent mediaButton) { return false; } @@ -659,8 +671,7 @@ public final class ControllerLink implements Parcelable { /** Stub method for ISessionController.adjustVolume */ public void adjustVolume(@NonNull String packageName, @NonNull String opPackageName, - @NonNull ControllerCallbackLink caller, boolean asSystemService, int direction, - int flags) { + @NonNull ControllerCallbackLink caller, int direction, int flags) { } /** Stub method for ISessionController.setVolumeTo */ @@ -801,9 +812,8 @@ public final class ControllerLink implements Parcelable { @Override public boolean sendMediaButton(String packageName, ControllerCallbackLink caller, - boolean asSystemService, KeyEvent mediaButton) { - return mControllerStub.sendMediaButton(packageName, caller, asSystemService, - mediaButton); + KeyEvent mediaButton) { + return mControllerStub.sendMediaButton(packageName, caller, mediaButton); } @Override @@ -843,10 +853,8 @@ public final class ControllerLink implements Parcelable { @Override public void adjustVolume(String packageName, String opPackageName, - ControllerCallbackLink caller, boolean asSystemService, int direction, - int flags) { - mControllerStub.adjustVolume(packageName, opPackageName, caller, asSystemService, - direction, flags); + ControllerCallbackLink caller, int direction, int flags) { + mControllerStub.adjustVolume(packageName, opPackageName, caller, direction, flags); } @Override diff --git a/media/apex/java/android/media/session/ISessionController.aidl b/media/apex/java/android/media/session/ISessionController.aidl index a3439a1a8deb6..e697c65e11c0d 100644 --- a/media/apex/java/android/media/session/ISessionController.aidl +++ b/media/apex/java/android/media/session/ISessionController.aidl @@ -39,7 +39,7 @@ interface ISessionController { void sendCommand(String packageName, in ControllerCallbackLink caller, String command, in Bundle args, in ResultReceiver cb); boolean sendMediaButton(String packageName, in ControllerCallbackLink caller, - boolean asSystemService, in KeyEvent mediaButton); + in KeyEvent mediaButton); void registerCallback(String packageName, in ControllerCallbackLink cb); void unregisterCallback(in ControllerCallbackLink cb); String getPackageName(); @@ -48,8 +48,7 @@ interface ISessionController { long getFlags(); MediaController.PlaybackInfo getVolumeAttributes(); void adjustVolume(String packageName, String opPackageName, - in ControllerCallbackLink caller, boolean asSystemService, int direction, - int flags); + in ControllerCallbackLink caller, int direction, int flags); void setVolumeTo(String packageName, String opPackageName, in ControllerCallbackLink caller, int value, int flags); diff --git a/media/apex/java/android/media/session/MediaController.java b/media/apex/java/android/media/session/MediaController.java index 79389a8b529c0..1333ab097219a 100644 --- a/media/apex/java/android/media/session/MediaController.java +++ b/media/apex/java/android/media/session/MediaController.java @@ -123,25 +123,6 @@ public final class MediaController { * @return true if the event was sent to the session, false otherwise. */ public boolean dispatchMediaButtonEvent(@NonNull KeyEvent keyEvent) { - return dispatchMediaButtonEventInternal(false, keyEvent); - } - - /** - * Dispatches the media button event as system service to the session. - *
- * 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 dispatchMediaButtonEventInternal(true, keyEvent); - } - - private boolean dispatchMediaButtonEventInternal(boolean asSystemService, - @NonNull KeyEvent keyEvent) { if (keyEvent == null) { throw new IllegalArgumentException("KeyEvent may not be null"); } @@ -149,67 +130,13 @@ public final class MediaController { return false; } try { - return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub, - asSystemService, keyEvent); + return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub, keyEvent); } catch (RuntimeException e) { // System is dead. =( } return false; } - /** - * Dispatches the volume button event as system service to the session. - *
- * 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 {
- // Note: Need both package name and OP package name. Package name is used for
- // RemoteUserInfo, and OP package name is used for AudioService's internal
- // AppOpsManager usages.
- mSessionBinder.adjustVolume(mContext.getPackageName(),
- mContext.getOpPackageName(), mCbStub, true, direction,
- AudioManager.FLAG_SHOW_UI);
- } catch (RuntimeException e) {
- Log.wtf(TAG, "Error calling adjustVolumeBy", e);
- }
- break;
- }
-
- case KeyEvent.ACTION_UP: {
- final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
- | AudioManager.FLAG_FROM_KEY;
- try {
- // Note: Need both package name and OP package name. Package name is used for
- // RemoteUserInfo, and OP package name is used for AudioService's internal
- // AppOpsManager usages.
- mSessionBinder.adjustVolume(mContext.getPackageName(),
- mContext.getOpPackageName(), mCbStub, true, 0, flags);
- } catch (RuntimeException e) {
- Log.wtf(TAG, "Error calling adjustVolumeBy", e);
- }
- }
- }
- }
-
/**
* Get the current playback state for this session.
*
@@ -394,7 +321,7 @@ public final class MediaController {
// RemoteUserInfo, and OP package name is used for AudioService's internal
// AppOpsManager usages.
mSessionBinder.adjustVolume(mContext.getPackageName(), mContext.getOpPackageName(),
- mCbStub, false, direction, flags);
+ mCbStub, direction, flags);
} catch (RuntimeException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
}
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index e3608086395ea..edaa55dad0e56 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -42,8 +42,12 @@ interface ISessionManager {
List
+ * 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 sessionToken session token
+ * @param keyEvent media key event
+ * @return {@code true} if the event was sent to the session, {@code false} otherwise
+ * @hide
+ */
+ public boolean dispatchMediaKeyEventAsSystemService(@NonNull MediaSession.Token sessionToken,
+ @NonNull KeyEvent keyEvent) {
+ if (sessionToken == null) {
+ throw new IllegalArgumentException("sessionToken shouldn't be null");
+ }
+ if (keyEvent == null) {
+ throw new IllegalArgumentException("keyEvent shouldn't be null");
+ }
+ if (!KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())) {
+ return false;
+ }
+ try {
+ return mService.dispatchMediaKeyEventToSessionAsSystemService(mContext.getPackageName(),
+ sessionToken, keyEvent);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send key event.", e);
+ }
+ return false;
+ }
+
/**
* Send a volume key event. The receiver will be selected automatically.
*
@@ -543,6 +574,32 @@ public final class MediaSessionManager {
}
}
+ /**
+ * Dispatches the volume key event as system service to the session.
+ *
+ * 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 sessionToken sessionToken
+ * @param keyEvent volume key event
+ * @hide
+ */
+ public void dispatchVolumeKeyEventAsSystemService(@NonNull MediaSession.Token sessionToken,
+ @NonNull KeyEvent keyEvent) {
+ if (sessionToken == null) {
+ throw new IllegalArgumentException("sessionToken shouldn't be null");
+ }
+ if (keyEvent == null) {
+ throw new IllegalArgumentException("keyEvent shouldn't be null");
+ }
+ try {
+ mService.dispatchVolumeKeyEventToSessionAsSystemService(mContext.getPackageName(),
+ mContext.getOpPackageName(), sessionToken, keyEvent);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling dispatchVolumeKeyEventAsSystemService", e);
+ }
+ }
+
/**
* Dispatch an adjust volume request to the system. It will be sent to the
* most relevant audio stream or media session. The direction must be one of
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index af790f25564c5..b6ef180f4b597 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -283,6 +283,10 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
Log.w(TAG, "Muting remote playback is not supported");
return;
}
+ if (DEBUG) {
+ Log.w(TAG, "adjusting volume, pkg=" + packageName + ", asSystemService="
+ + asSystemService + ", dir=" + direction);
+ }
mSessionCb.adjustVolume(packageName, pid, uid, caller, asSystemService, direction);
int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
@@ -456,9 +460,25 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
return mSessionCb.mCb;
}
- public void sendMediaButton(String packageName, int pid, int uid, boolean asSystemService,
+ /**
+ * Sends media button.
+ *
+ * @param packageName caller package name
+ * @param pid caller pid
+ * @param uid caller uid
+ * @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.
+ * @param ke key events
+ * @param sequenceId (optional) sequence id. Use this only when a wake lock is needed.
+ * @param cb (optional) result receiver to receive callback. Use this only when a wake lock is
+ * needed.
+ * @return {@code true} if the attempt to send media button was successfuly.
+ * {@code false} otherwise.
+ */
+ public boolean sendMediaButton(String packageName, int pid, int uid, boolean asSystemService,
KeyEvent ke, int sequenceId, ResultReceiver cb) {
- mSessionCb.sendMediaButton(packageName, pid, uid, asSystemService, ke, sequenceId, cb);
+ return mSessionCb.sendMediaButton(packageName, pid, uid, asSystemService, ke, sequenceId,
+ cb);
}
public void dump(PrintWriter pw, String prefix) {
@@ -492,6 +512,10 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
final String callingOpPackageName, final int callingPid, final int callingUid,
final boolean asSystemService, final boolean useSuggested,
final int previousFlagPlaySound) {
+ if (DEBUG) {
+ Log.w(TAG, "adjusting local volume, stream=" + stream + ", dir=" + direction
+ + ", asSystemService=" + asSystemService + ", useSuggested=" + useSuggested);
+ }
// Must use opPackageName for adjusting volumes with UID.
final String opPackageName;
final int uid;
@@ -1223,9 +1247,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
@Override
public boolean sendMediaButton(String packageName, ControllerCallbackLink cb,
- boolean asSystemService, KeyEvent keyEvent) {
+ KeyEvent keyEvent) {
return mSessionCb.sendMediaButton(packageName, Binder.getCallingPid(),
- Binder.getCallingUid(), cb, asSystemService, keyEvent);
+ Binder.getCallingUid(), cb, false, keyEvent);
}
@Override
@@ -1292,14 +1316,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
@Override
public void adjustVolume(String packageName, String opPackageName,
- ControllerCallbackLink caller, boolean asSystemService, int direction,
- int flags) {
+ ControllerCallbackLink caller, int direction, int flags) {
int pid = Binder.getCallingPid();
int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
MediaSessionRecord.this.adjustVolume(packageName, opPackageName, pid, uid, caller,
- asSystemService, direction, flags, false /* useSuggested */);
+ false, direction, flags, false /* useSuggested */);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
index 94de49e729378..409060e348417 100644
--- a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
@@ -707,6 +707,14 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
return mUserRecords.get(fullUserId);
}
+ private MediaSessionRecord getMediaSessionRecordLocked(MediaSession.Token sessionToken) {
+ FullUserRecord user = getFullUserRecordLocked(UserHandle.getUserId(sessionToken.getUid()));
+ if (user != null) {
+ return user.mPriorityStack.getMediaSessionRecord(sessionToken);
+ }
+ return null;
+ }
+
/**
* Information about a full user and its corresponding managed profiles.
*
@@ -1271,6 +1279,34 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
}
}
+ @Override
+ public boolean dispatchMediaKeyEventToSessionAsSystemService(String packageName,
+ MediaSession.Token sessionToken, KeyEvent keyEvent) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
+ if (record == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Failed to find session to dispatch key event.");
+ }
+ return false;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "dispatchMediaKeyEventToSessionAsSystemService, pkg="
+ + packageName + ", pid=" + pid + ", uid=" + uid + ", sessionToken="
+ + sessionToken + ", event=" + keyEvent + ", session=" + record);
+ }
+ return record.sendMediaButton(packageName, pid, uid, true /* asSystemService */,
+ keyEvent, 0, null);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@Override
public void setCallback(ICallback callback) {
final int pid = Binder.getCallingPid();
@@ -1576,6 +1612,62 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
}
}
+ @Override
+ public void dispatchVolumeKeyEventToSessionAsSystemService(String packageName,
+ String opPackageName, MediaSession.Token sessionToken, KeyEvent keyEvent) {
+ int pid = Binder.getCallingPid();
+ int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
+ if (record == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Failed to find session to dispatch key event.");
+ }
+ return;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "dispatchVolumeKeyEventToSessionAsSystemService, pkg="
+ + packageName + ", opPkg=" + opPackageName + ", pid=" + pid
+ + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event="
+ + keyEvent + ", session=" + record);
+ }
+ 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;
+ }
+ record.adjustVolume(packageName, opPackageName, pid, uid,
+ null /* caller */, true /* asSystemService */, direction,
+ AudioManager.FLAG_SHOW_UI, false /* useSuggested */);
+ break;
+ }
+
+ case KeyEvent.ACTION_UP: {
+ final int flags =
+ AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
+ | AudioManager.FLAG_FROM_KEY;
+ record.adjustVolume(packageName, opPackageName, pid, uid,
+ null /* caller */, true /* asSystemService */, 0,
+ flags, false /* useSuggested */);
+ }
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@Override
public void dispatchAdjustVolume(String packageName, String opPackageName,
int suggestedStream, int delta, int flags) {
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index 719ec362e6e8c..9ba50ee25cb63 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -28,6 +28,7 @@ import android.util.SparseArray;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Keeps track of media sessions and their priority for notifications, media
@@ -135,6 +136,21 @@ class MediaSessionStack {
return mSessions.contains(record);
}
+ /**
+ * Gets the {@link MediaSessionRecord} with the {@link MediaSession.Token}.
+ *
+ * @param sessionToken session token
+ * @return the MediaSessionRecord. Can be {@code null} if the session is gone meanwhile.
+ */
+ public MediaSessionRecord getMediaSessionRecord(MediaSession.Token sessionToken) {
+ for (MediaSessionRecord record : mSessions) {
+ if (Objects.equals(record.getControllerLink(), sessionToken.getControllerLink())) {
+ return record;
+ }
+ }
+ return null;
+ }
+
/**
* Notify the priority tracker that a session's playback state changed.
*