Persist safe MediaSession intents across reboots
Persist a MediaSession's PendingIntent across reboots so long as it
is for the same package as the MediaSession that created it.
bug:15575138
Change-Id: I34144a90d1f9c320e7509cb9c64281b48dac9140
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 77a1fa9..667d02a 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -117,7 +117,6 @@
public void onStart() {
publishBinderService(Context.MEDIA_SESSION_SERVICE, mSessionManagerImpl);
Watchdog.getInstance().addMonitor(this);
- updateUser();
mKeyguardManager =
(KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
mAudioService = getAudioService();
@@ -125,6 +124,8 @@
mContentResolver = getContext().getContentResolver();
mSettingsObserver = new SettingsObserver();
mSettingsObserver.observe();
+
+ updateUser();
}
private IAudioService getAudioService() {
@@ -501,6 +502,12 @@
UserRecord user = mUserRecords.get(record.getUserId());
if (receiver != null && user != null) {
user.mLastMediaButtonReceiver = receiver;
+ ComponentName component = receiver.getIntent().getComponent();
+ if (component != null && record.getPackageName().equals(component.getPackageName())) {
+ Settings.Secure.putStringForUser(mContentResolver,
+ Settings.System.MEDIA_BUTTON_RECEIVER, component.flattenToString(),
+ record.getUserId());
+ }
}
}
@@ -511,14 +518,17 @@
final class UserRecord {
private final int mUserId;
private final ArrayList<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>();
+ private final Context mContext;
private PendingIntent mLastMediaButtonReceiver;
+ private ComponentName mRestoredMediaButtonReceiver;
public UserRecord(Context context, int userId) {
+ mContext = context;
mUserId = userId;
+ restoreMediaButtonReceiver();
}
public void startLocked() {
- // nothing for now
}
public void stopLocked() {
@@ -548,6 +558,7 @@
pw.println(prefix + "Record for user " + mUserId);
String indent = prefix + " ";
pw.println(indent + "MediaButtonReceiver:" + mLastMediaButtonReceiver);
+ pw.println(indent + "Restored ButtonReceiver:" + mRestoredMediaButtonReceiver);
int size = mSessions.size();
pw.println(indent + size + " Sessions:");
for (int i = 0; i < size; i++) {
@@ -556,6 +567,19 @@
pw.println(indent + mSessions.get(i).toString());
}
}
+
+ private void restoreMediaButtonReceiver() {
+ String receiverName = Settings.Secure.getStringForUser(mContentResolver,
+ Settings.System.MEDIA_BUTTON_RECEIVER, UserHandle.USER_CURRENT);
+ if (!TextUtils.isEmpty(receiverName)) {
+ ComponentName eventReceiver = ComponentName.unflattenFromString(receiverName);
+ if (eventReceiver == null) {
+ // an invalid name was persisted
+ return;
+ }
+ mRestoredMediaButtonReceiver = eventReceiver;
+ }
+ }
}
final class SessionsListenerRecord implements IBinder.DeathRecipient {
@@ -723,8 +747,9 @@
synchronized (mLock) {
// If we don't have a media button receiver to fall back on
// include non-playing sessions for dispatching
- boolean useNotPlayingSessions = mUserRecords.get(
- ActivityManager.getCurrentUser()).mLastMediaButtonReceiver == null;
+ UserRecord ur = mUserRecords.get(ActivityManager.getCurrentUser());
+ boolean useNotPlayingSessions = ur.mLastMediaButtonReceiver == null
+ && ur.mRestoredMediaButtonReceiver == null;
MediaSessionRecord session = mPriorityStack
.getDefaultMediaButtonSession(mCurrentUserId, useNotPlayingSessions);
if (isVoiceKey(keyEvent.getKeyCode())) {
@@ -929,9 +954,12 @@
// Launch the last PendingIntent we had with priority
int userId = ActivityManager.getCurrentUser();
UserRecord user = mUserRecords.get(userId);
- if (user.mLastMediaButtonReceiver != null) {
+ if (user.mLastMediaButtonReceiver != null
+ || user.mRestoredMediaButtonReceiver != null) {
if (DEBUG) {
- Log.d(TAG, "Sending media key to last known PendingIntent");
+ Log.d(TAG, "Sending media key to last known PendingIntent "
+ + user.mLastMediaButtonReceiver + " or restored Intent "
+ + user.mRestoredMediaButtonReceiver);
}
if (needWakeLock) {
mKeyEventReceiver.aquireWakeLockLocked();
@@ -939,9 +967,15 @@
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
try {
- user.mLastMediaButtonReceiver.send(getContext(),
- needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
- mediaButtonIntent, mKeyEventReceiver, null);
+ if (user.mLastMediaButtonReceiver != null) {
+ user.mLastMediaButtonReceiver.send(getContext(),
+ needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
+ mediaButtonIntent, mKeyEventReceiver, null);
+ } else {
+ mediaButtonIntent.setComponent(user.mRestoredMediaButtonReceiver);
+ getContext().sendBroadcastAsUser(mediaButtonIntent,
+ new UserHandle(userId));
+ }
} catch (CanceledException e) {
Log.i(TAG, "Error sending key event to media button receiver "
+ user.mLastMediaButtonReceiver, e);