Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad697c41 authored by Michael Mikhail's avatar Michael Mikhail Committed by Android (Google) Code Review
Browse files

Merge "DO NOT MERGE Verify URI permissions in MediaMetadata" into tm-dev

parents be93a420 277e7e05
Loading
Loading
Loading
Loading
+44 −9
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -63,6 +65,9 @@ import android.util.EventLog;
import android.util.Log;
import android.view.KeyEvent;

import com.android.server.LocalServices;
import com.android.server.uri.UriGrantsManagerInternal;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -78,6 +83,10 @@ import java.util.concurrent.CopyOnWriteArrayList;
// TODO(jaewan): Do not call service method directly -- introduce listener instead.
public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionRecordImpl {
    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);

    /**
@@ -131,6 +140,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
    private final SessionStub mSession;
    private final SessionCb mSessionCb;
    private final MediaSessionService mService;
    private final UriGrantsManagerInternal mUgmInternal;
    private final Context mContext;
    private final boolean mVolumeAdjustmentForRemoteGroupSessions;

@@ -192,6 +202,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        mAudioAttrs = DEFAULT_ATTRIBUTES;
        mPolicies = policies;
        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
        mVolumeAdjustmentForRemoteGroupSessions = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions);

@@ -1018,21 +1029,45 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
        public void setMetadata(MediaMetadata metadata, long duration, String metadataDescription)
                throws RemoteException {
            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;
                mMetadataDescription = metadataDescription;
                mMetadata = sanitizeMediaMetadata(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
        public void setPlaybackState(PlaybackState state) throws RemoteException {
            int oldState = mPlaybackState == null