Allow Activity/Service to get media keys across the boot

Bug: 121122701
Test: Manually tested
Change-Id: Id56f3ebfad9ed3472d28712eed3fa539c6e3e485
This commit is contained in:
Jaewan Kim
2018-12-17 19:33:09 +09:00
parent a13ea6fdc2
commit 8f47426faa

View File

@@ -27,8 +27,10 @@ import android.content.ComponentName;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.media.AudioManager; import android.media.AudioManager;
@@ -634,11 +636,16 @@ public class MediaSessionService extends SystemService implements Monitor {
* <p>The contents of this object is guarded by {@link #mLock}. * <p>The contents of this object is guarded by {@link #mLock}.
*/ */
final class FullUserRecord implements MediaSessionStack.OnMediaButtonSessionChangedListener { final class FullUserRecord implements MediaSessionStack.OnMediaButtonSessionChangedListener {
public static final int COMPONENT_TYPE_BROADCAST = 0;
public static final int COMPONENT_TYPE_ACTIVITY = 1;
public static final int COMPONENT_TYPE_SERVICE = 2;
private static final String COMPONENT_NAME_USER_ID_DELIM = ","; private static final String COMPONENT_NAME_USER_ID_DELIM = ",";
private final int mFullUserId; private final int mFullUserId;
private final MediaSessionStack mPriorityStack; private final MediaSessionStack mPriorityStack;
private PendingIntent mLastMediaButtonReceiver; private PendingIntent mLastMediaButtonReceiver;
private ComponentName mRestoredMediaButtonReceiver; private ComponentName mRestoredMediaButtonReceiver;
private int mRestoredMediaButtonReceiverComponentType;
private int mRestoredMediaButtonReceiverUserId; private int mRestoredMediaButtonReceiverUserId;
private IOnVolumeKeyLongPressListener mOnVolumeKeyLongPressListener; private IOnVolumeKeyLongPressListener mOnVolumeKeyLongPressListener;
@@ -655,17 +662,23 @@ public class MediaSessionService extends SystemService implements Monitor {
mFullUserId = fullUserId; mFullUserId = fullUserId;
mPriorityStack = new MediaSessionStack(mAudioPlayerStateMonitor, this); mPriorityStack = new MediaSessionStack(mAudioPlayerStateMonitor, this);
// Restore the remembered media button receiver before the boot. // Restore the remembered media button receiver before the boot.
String mediaButtonReceiver = Settings.Secure.getStringForUser(mContentResolver, String mediaButtonReceiverInfo = Settings.Secure.getStringForUser(mContentResolver,
Settings.System.MEDIA_BUTTON_RECEIVER, mFullUserId); Settings.System.MEDIA_BUTTON_RECEIVER, mFullUserId);
if (mediaButtonReceiver == null) { if (mediaButtonReceiverInfo == null) {
return; return;
} }
String[] tokens = mediaButtonReceiver.split(COMPONENT_NAME_USER_ID_DELIM); String[] tokens = mediaButtonReceiverInfo.split(COMPONENT_NAME_USER_ID_DELIM);
if (tokens == null || tokens.length != 2) { if (tokens == null || (tokens.length != 2 && tokens.length != 3)) {
return; return;
} }
mRestoredMediaButtonReceiver = ComponentName.unflattenFromString(tokens[0]); mRestoredMediaButtonReceiver = ComponentName.unflattenFromString(tokens[0]);
mRestoredMediaButtonReceiverUserId = Integer.parseInt(tokens[1]); mRestoredMediaButtonReceiverUserId = Integer.parseInt(tokens[1]);
if (tokens.length == 3) {
mRestoredMediaButtonReceiverComponentType = Integer.parseInt(tokens[2]);
} else {
mRestoredMediaButtonReceiverComponentType =
getComponentType(mRestoredMediaButtonReceiver);
}
} }
public void destroySessionsForUserLocked(int userId) { public void destroySessionsForUserLocked(int userId) {
@@ -696,6 +709,8 @@ public class MediaSessionService extends SystemService implements Monitor {
pw.println(indent + "Callback: " + mCallback); pw.println(indent + "Callback: " + mCallback);
pw.println(indent + "Last MediaButtonReceiver: " + mLastMediaButtonReceiver); pw.println(indent + "Last MediaButtonReceiver: " + mLastMediaButtonReceiver);
pw.println(indent + "Restored MediaButtonReceiver: " + mRestoredMediaButtonReceiver); pw.println(indent + "Restored MediaButtonReceiver: " + mRestoredMediaButtonReceiver);
pw.println(indent + "Restored MediaButtonReceiverComponentType: "
+ mRestoredMediaButtonReceiverComponentType);
mPriorityStack.dump(pw, indent); mPriorityStack.dump(pw, indent);
} }
@@ -722,17 +737,21 @@ public class MediaSessionService extends SystemService implements Monitor {
PendingIntent receiver = record.getMediaButtonReceiver(); PendingIntent receiver = record.getMediaButtonReceiver();
mLastMediaButtonReceiver = receiver; mLastMediaButtonReceiver = receiver;
mRestoredMediaButtonReceiver = null; mRestoredMediaButtonReceiver = null;
String componentName = "";
String mediaButtonReceiverInfo = "";
if (receiver != null) { if (receiver != null) {
ComponentName component = receiver.getIntent().getComponent(); ComponentName component = receiver.getIntent().getComponent();
if (component != null if (component != null
&& record.getPackageName().equals(component.getPackageName())) { && record.getPackageName().equals(component.getPackageName())) {
componentName = component.flattenToString(); String componentName = component.flattenToString();
int componentType = getComponentType(component);
mediaButtonReceiverInfo = String.join(COMPONENT_NAME_USER_ID_DELIM,
componentName, String.valueOf(record.getUserId()),
String.valueOf(componentType));
} }
} }
Settings.Secure.putStringForUser(mContentResolver, Settings.Secure.putStringForUser(mContentResolver,
Settings.System.MEDIA_BUTTON_RECEIVER, Settings.System.MEDIA_BUTTON_RECEIVER, mediaButtonReceiverInfo,
componentName + COMPONENT_NAME_USER_ID_DELIM + record.getUserId(),
mFullUserId); mFullUserId);
} }
@@ -762,6 +781,32 @@ public class MediaSessionService extends SystemService implements Monitor {
return isGlobalPriorityActiveLocked() return isGlobalPriorityActiveLocked()
? mGlobalPrioritySession : mPriorityStack.getMediaButtonSession(); ? mGlobalPrioritySession : mPriorityStack.getMediaButtonSession();
} }
private int getComponentType(ComponentName componentName) {
PackageManager pm = getContext().getPackageManager();
try {
ActivityInfo activityInfo = pm.getActivityInfo(componentName,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.GET_ACTIVITIES);
if (activityInfo != null) {
return COMPONENT_TYPE_ACTIVITY;
}
} catch (NameNotFoundException e) {
}
try {
ServiceInfo serviceInfo = pm.getServiceInfo(componentName,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.GET_SERVICES);
if (serviceInfo != null) {
return COMPONENT_TYPE_SERVICE;
}
} catch (NameNotFoundException e) {
}
// Pick legacy behavior for BroadcastReceiver or unknown.
return COMPONENT_TYPE_BROADCAST;
}
} }
final class SessionsListenerRecord implements IBinder.DeathRecipient { final class SessionsListenerRecord implements IBinder.DeathRecipient {
@@ -1580,14 +1625,32 @@ public class MediaSessionService extends SystemService implements Monitor {
} else { } else {
ComponentName receiver = ComponentName receiver =
mCurrentFullUserRecord.mRestoredMediaButtonReceiver; mCurrentFullUserRecord.mRestoredMediaButtonReceiver;
int componentType = mCurrentFullUserRecord
.mRestoredMediaButtonReceiverComponentType;
UserHandle userHandle = UserHandle.of(mCurrentFullUserRecord
.mRestoredMediaButtonReceiverUserId);
if (DEBUG_KEY_EVENT) { if (DEBUG_KEY_EVENT) {
Log.d(TAG, "Sending " + keyEvent + " to the restored intent " Log.d(TAG, "Sending " + keyEvent + " to the restored intent "
+ receiver); + receiver + ", type=" + componentType);
} }
mediaButtonIntent.setComponent(receiver); mediaButtonIntent.setComponent(receiver);
getContext().sendBroadcastAsUser(mediaButtonIntent, try {
UserHandle.of(mCurrentFullUserRecord switch (componentType) {
.mRestoredMediaButtonReceiverUserId)); case FullUserRecord.COMPONENT_TYPE_ACTIVITY:
getContext().startActivityAsUser(mediaButtonIntent, userHandle);
break;
case FullUserRecord.COMPONENT_TYPE_SERVICE:
getContext().startForegroundServiceAsUser(mediaButtonIntent,
userHandle);
break;
default:
// Legacy behavior for other cases.
getContext().sendBroadcastAsUser(mediaButtonIntent, userHandle);
}
} catch (Exception e) {
Log.w(TAG, "Error sending media button to the restored intent "
+ receiver + ", type=" + componentType, e);
}
if (mCurrentFullUserRecord.mCallback != null) { if (mCurrentFullUserRecord.mCallback != null) {
mCurrentFullUserRecord.mCallback mCurrentFullUserRecord.mCallback
.onMediaKeyEventDispatchedToMediaButtonReceiver( .onMediaKeyEventDispatchedToMediaButtonReceiver(