Merge "Verify URI permissions in MediaMetadata" into rvc-dev am: 02a632ff37
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23174295 Change-Id: I03386569dcf349e1ce15b05cbac7d32e82b70125 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -18,6 +18,8 @@ package com.android.server.media;
|
|||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
import android.content.ContentProvider;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ParceledListSlice;
|
import android.content.pm.ParceledListSlice;
|
||||||
@@ -49,11 +51,13 @@ import android.os.Process;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
|
import com.android.server.uri.UriGrantsManagerInternal;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -67,6 +71,10 @@ import java.util.List;
|
|||||||
// TODO(jaewan): Do not call service method directly -- introduce listener instead.
|
// TODO(jaewan): Do not call service method directly -- introduce listener instead.
|
||||||
public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionRecordImpl {
|
public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionRecordImpl {
|
||||||
private static final String TAG = "MediaSessionRecord";
|
private static final String TAG = "MediaSessionRecord";
|
||||||
|
private static final String[] ART_URIS = new String[] {
|
||||||
|
MediaMetadata.METADATA_KEY_ALBUM_ART_URI,
|
||||||
|
MediaMetadata.METADATA_KEY_ART_URI,
|
||||||
|
MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI};
|
||||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,6 +128,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
|
|||||||
private final SessionStub mSession;
|
private final SessionStub mSession;
|
||||||
private final SessionCb mSessionCb;
|
private final SessionCb mSessionCb;
|
||||||
private final MediaSessionService mService;
|
private final MediaSessionService mService;
|
||||||
|
private final UriGrantsManagerInternal mUgmInternal;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
@@ -182,6 +191,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
|
|||||||
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
|
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
|
||||||
mAudioAttrs = DEFAULT_ATTRIBUTES;
|
mAudioAttrs = DEFAULT_ATTRIBUTES;
|
||||||
mPolicies = policies;
|
mPolicies = policies;
|
||||||
|
mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
|
||||||
|
|
||||||
// May throw RemoteException if the session app is killed.
|
// May throw RemoteException if the session app is killed.
|
||||||
mSessionCb.mCb.asBinder().linkToDeath(this, 0);
|
mSessionCb.mCb.asBinder().linkToDeath(this, 0);
|
||||||
@@ -859,21 +869,45 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
|
|||||||
public void setMetadata(MediaMetadata metadata, long duration, String metadataDescription)
|
public void setMetadata(MediaMetadata metadata, long duration, String metadataDescription)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
MediaMetadata temp = metadata == null ? null : new MediaMetadata.Builder(metadata)
|
|
||||||
.build();
|
|
||||||
// This is to guarantee that the underlying bundle is unparceled
|
|
||||||
// before we set it to prevent concurrent reads from throwing an
|
|
||||||
// exception
|
|
||||||
if (temp != null) {
|
|
||||||
temp.size();
|
|
||||||
}
|
|
||||||
mMetadata = temp;
|
|
||||||
mDuration = duration;
|
mDuration = duration;
|
||||||
mMetadataDescription = metadataDescription;
|
mMetadataDescription = metadataDescription;
|
||||||
|
mMetadata = sanitizeMediaMetadata(metadata);
|
||||||
}
|
}
|
||||||
mHandler.post(MessageHandler.MSG_UPDATE_METADATA);
|
mHandler.post(MessageHandler.MSG_UPDATE_METADATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MediaMetadata sanitizeMediaMetadata(MediaMetadata metadata) {
|
||||||
|
if (metadata == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder(metadata);
|
||||||
|
for (String key: ART_URIS) {
|
||||||
|
String uriString = metadata.getString(key);
|
||||||
|
if (TextUtils.isEmpty(uriString)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Uri uri = Uri.parse(uriString);
|
||||||
|
if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mUgmInternal.checkGrantUriPermission(getUid(),
|
||||||
|
getPackageName(),
|
||||||
|
ContentProvider.getUriWithoutUserId(uri),
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION,
|
||||||
|
ContentProvider.getUserIdFromUri(uri, getUserId()));
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
metadataBuilder.putString(key, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MediaMetadata sanitizedMetadata = metadataBuilder.build();
|
||||||
|
// sanitizedMetadata.size() guarantees that the underlying bundle is unparceled
|
||||||
|
// before we set it to prevent concurrent reads from throwing an
|
||||||
|
// exception
|
||||||
|
sanitizedMetadata.size();
|
||||||
|
return sanitizedMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPlaybackState(PlaybackState state) throws RemoteException {
|
public void setPlaybackState(PlaybackState state) throws RemoteException {
|
||||||
int oldState = mPlaybackState == null
|
int oldState = mPlaybackState == null
|
||||||
|
|||||||
Reference in New Issue
Block a user