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

Commit ae004d8b authored by tonihei's avatar tonihei
Browse files

Add WIU/BFSL allowlisting to MediaButtonReceiverHolder.send

This will replace the existing capability propagation via
BroadcastOptions. Specifically, it avoids accidentally propagating
BAL abilities to the receiver.

Bug: 385736540
Flag: com.android.media.mediasession.flags.add_wiu_allowlisting_to_media_button_receiver_holder_send
Test: Verified exploit in b/385736540 is no longer possible
Change-Id: I753fb3d484fb32120eec6423bf865d5f4d1d2d4b
parent 58510fe4
Loading
Loading
Loading
Loading
+72 −18
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.media;

import static com.android.media.mediasession.flags.Flags.addWiuAllowlistingToMediaButtonReceiverHolderSend;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -173,44 +175,89 @@ final class MediaButtonReceiverHolder {

    /**
     * Sends the media key event to the media button receiver.
     * <p>
     * This prioritizes using use pending intent for sending media key event.
     *
     * <p>This prioritizes using use pending intent for sending media key event.
     *
     * @param context context to be used to call PendingIntent#send
     * @param keyEvent keyEvent to send
     * @param resultCode result code to be used to call PendingIntent#send
     *                   Ignored if there's no valid pending intent.
     * @param onFinishedListener callback to be used to get result of PendingIntent#send.
     *                           Ignored if there's no valid pending intent.
     * @param handler handler to be used to call onFinishedListener
     *                Ignored if there's no valid pending intent.
     * @param fgsAllowlistDurationMs duration for which the media button receiver will be
     *                               allowed to start FGS from BG.
     * @param resultCode result code to be used to call PendingIntent#send. Ignored if there's no
     *     valid pending intent.
     * @param mediaSessionService {@link MediaSessionService} triggering the event
     * @param callingPackageName package name of the caller
     * @param callingPid PID of the caller
     * @param callingUid UID of the caller
     * @param reportedPackageName package name that is reported to the receiver using {@link
     *     Intent#EXTRA_PACKAGE_NAME}
     * @param onFinishedListener callback to be used to get result of PendingIntent#send. Ignored if
     *     there's no valid pending intent.
     * @param handler handler to be used to call onFinishedListener. Ignored if there's no valid
     *     pending intent.
     * @param fgsAllowlistDurationMs duration for which the media button receiver will be allowed to
     *     start FGS from BG.
     * @see PendingIntent#send(Context, int, Intent, PendingIntent.OnFinished, Handler)
     */
    public boolean send(Context context, KeyEvent keyEvent, String callingPackageName,
            int resultCode, PendingIntent.OnFinished onFinishedListener, Handler handler,
    public boolean send(
            Context context,
            KeyEvent keyEvent,
            MediaSessionService mediaSessionService,
            String callingPackageName,
            int callingPid,
            int callingUid,
            String reportedPackageName,
            int resultCode,
            PendingIntent.OnFinished onFinishedListener,
            Handler handler,
            long fgsAllowlistDurationMs) {
        Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
        mediaButtonIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
        // TODO: Find a way to also send PID/UID in secure way.
        mediaButtonIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, callingPackageName);
        mediaButtonIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, reportedPackageName);

        // TODO: b/385736540 - Remove options and timeout constants for fgsAllowlistDurationMs once
        //  flag add_wiu_allowlisting_to_media_button_receiver_holder_send is rolled out.
        final BroadcastOptions options = BroadcastOptions.makeBasic();
        options.setTemporaryAppAllowlist(fgsAllowlistDurationMs,
                PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                PowerWhitelistManager.REASON_MEDIA_BUTTON, "");
        options.setBackgroundActivityStartsAllowed(true);
        if (addWiuAllowlistingToMediaButtonReceiverHolderSend()) {
            PackageManager packageManager = context.getPackageManager();
            try {
                int targetUid = packageManager.getPackageUidAsUser(mPackageName, mUserId);
                mediaSessionService.tempAllowlistTargetPkgIfPossible(
                        targetUid,
                        /* targetPackage= */ mPackageName,
                        callingPid,
                        callingUid,
                        callingPackageName,
                        /* reason= */ TAG);
            } catch (PackageManager.NameNotFoundException e) {
                // Package name doesn't exist.
                if (DEBUG_KEY_EVENT) {
                    Log.d(TAG, "Can't allowlist, package " + mPackageName + "doesn't exist");
                }
            }
        }
        if (mPendingIntent != null) {
            if (DEBUG_KEY_EVENT) {
                Log.d(TAG, "Sending " + keyEvent + " to the last known PendingIntent "
                        + mPendingIntent);
            }
            try {
                if (addWiuAllowlistingToMediaButtonReceiverHolderSend()) {
                    mPendingIntent.send(
                            context, resultCode, mediaButtonIntent, onFinishedListener, handler);
                } else {
                    mPendingIntent.send(
                        context, resultCode, mediaButtonIntent, onFinishedListener, handler,
                        /* requiredPermission= */ null, options.toBundle());
                            context,
                            resultCode,
                            mediaButtonIntent,
                            onFinishedListener,
                            handler,
                            /* requiredPermission= */ null,
                            options.toBundle());
                }
            } catch (PendingIntent.CanceledException e) {
                Log.w(TAG, "Error sending key event to media button receiver " + mPendingIntent, e);
                return false;
@@ -233,8 +280,15 @@ final class MediaButtonReceiverHolder {
                        break;
                    default:
                        // Legacy behavior for other cases.
                        context.sendBroadcastAsUser(mediaButtonIntent, userHandle,
                                /* receiverPermission= */ null, options.toBundle());
                        if (addWiuAllowlistingToMediaButtonReceiverHolderSend()) {
                            context.sendBroadcastAsUser(mediaButtonIntent, userHandle);
                        } else {
                            context.sendBroadcastAsUser(
                                    mediaButtonIntent,
                                    userHandle,
                                    /* receiverPermission= */ null,
                                    options.toBundle());
                        }
                }
            } catch (Exception e) {
                Log.w(TAG, "Error sending media button to the restored intent "
+15 −6
Original line number Diff line number Diff line
@@ -2682,13 +2682,22 @@ public class MediaSessionService extends SystemService implements Monitor {
                if (needWakeLock) {
                    mKeyEventReceiver.acquireWakeLockLocked();
                }
                String callingPackageName =
                String reportedPackageName =
                        (asSystemService) ? mContext.getPackageName() : packageName;
                boolean sent = mediaButtonReceiverHolder.send(
                        mContext, keyEvent, callingPackageName,
                        needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1, mKeyEventReceiver,
                boolean sent =
                        mediaButtonReceiverHolder.send(
                                mContext,
                                keyEvent,
                                MediaSessionService.this,
                                packageName,
                                pid,
                                uid,
                                reportedPackageName,
                                needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
                                mKeyEventReceiver,
                                mHandler,
                        MediaSessionDeviceConfig.getMediaButtonReceiverFgsAllowlistDurationMs());
                                MediaSessionDeviceConfig
                                        .getMediaButtonReceiverFgsAllowlistDurationMs());
                if (sent) {
                    String pkgName = mediaButtonReceiverHolder.getPackageName();
                    for (FullUserRecord.OnMediaKeyEventDispatchedListenerRecord cr