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

Commit d3b6cc2d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Privileged permission for 'interactive' broadcasts"

parents 3e579752 c31b9658
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -226,6 +226,12 @@ public abstract class ActivityManagerInternal {
     */
    public abstract boolean isModernQueueEnabled();

    /**
     * Enforce capability restrictions on use of the given BroadcastOptions
     */
    public abstract void enforceBroadcastOptionsPermissions(@Nullable Bundle options,
            int callingUid);

    /**
     * Returns package name given pid.
     *
@@ -300,7 +306,7 @@ public abstract class ActivityManagerInternal {
    public abstract int handleIncomingUser(int callingPid, int callingUid, @UserIdInt int userId,
            boolean allowAll, int allowMode, String name, String callerPackage);

    /** Checks if the calling binder pid as the permission. */
    /** Checks if the calling binder pid/uid has the given permission. */
    @PermissionMethod
    public abstract void enforceCallingPermission(@PermissionName String permission, String func);

+1 −0
Original line number Diff line number Diff line
@@ -636,6 +636,7 @@ public class BroadcastOptions extends ComponentOptions {
     * @param broadcastIsInteractive
     * @see #isInteractiveBroadcast()
     */
    @RequiresPermission(android.Manifest.permission.BROADCAST_OPTION_INTERACTIVE)
    public void setInteractiveBroadcast(boolean broadcastIsInteractive) {
        mIsInteractiveBroadcast = broadcastIsInteractive;
    }
+6 −0
Original line number Diff line number Diff line
@@ -3152,6 +3152,12 @@
    <permission android:name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"
                android:protectionLevel="signature|privileged|vendorPrivileged|oem|verifier|role"/>

    <!-- Allows an application to hint that a broadcast is associated with an
         "interactive" usage scenario
         @hide -->
    <permission android:name="android.permission.BROADCAST_OPTION_INTERACTIVE"
                android:protectionLevel="signature|privileged" />

    <!-- @SystemApi Must be required by activities that handle the intent action
         {@link Intent#ACTION_SEND_SHOW_SUSPENDED_APP_DETAILS}. This is for use by apps that
         hold {@link Manifest.permission#SUSPEND_APPS} to interact with the system.
+38 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package android.app.activity;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -536,4 +538,40 @@ public class BroadcastTest extends ActivityTestsBase {
            Log.i("foo", "Unregister exception", e);
        }
    }

    public void testBroadcastOption_interactive() throws Exception {
        final BroadcastOptions options = BroadcastOptions.makeBasic();
        options.setInteractiveBroadcast(true);
        final Intent intent = makeBroadcastIntent(BROADCAST_REGISTERED);

        try {
            getContext().sendBroadcast(intent, null, options.toBundle());
            fail("No exception thrown with BroadcastOptions.setInteractiveBroadcast(true)");
        } catch (SecurityException se) {
            // Expected, correct behavior - this case intentionally empty
        } catch (Exception e) {
            fail("Unexpected exception " + e.getMessage()
                    + " thrown with BroadcastOptions.setInteractiveBroadcast(true)");
        }
    }

    public void testBroadcastOption_interactive_PendingIntent() throws Exception {
        final BroadcastOptions options = BroadcastOptions.makeBasic();
        options.setInteractiveBroadcast(true);
        final Intent intent = makeBroadcastIntent(BROADCAST_REGISTERED);
        PendingIntent brPending = PendingIntent.getBroadcast(getContext(),
                1, intent, PendingIntent.FLAG_IMMUTABLE);

        try {
            brPending.send(getContext(), 1, null, null, null, null, options.toBundle());
            fail("No exception thrown with BroadcastOptions.setInteractiveBroadcast(true)");
        } catch (SecurityException se) {
            // Expected, correct behavior - this case intentionally empty
        } catch (Exception e) {
            fail("Unexpected exception " + e.getMessage()
                    + " thrown with BroadcastOptions.setInteractiveBroadcast(true)");
        } finally {
            brPending.cancel();
        }
    }
}
+26 −13
Original line number Diff line number Diff line
@@ -13828,6 +13828,25 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    // Apply permission policy around the use of specific broadcast options
    void enforceBroadcastOptionPermissionsInternal(@Nullable Bundle options, int callingUid) {
        if (options != null && callingUid != Process.SYSTEM_UID) {
            if (options.containsKey(BroadcastOptions.KEY_ALARM_BROADCAST)) {
                if (DEBUG_BROADCAST_LIGHT) {
                    Slog.w(TAG, "Non-system caller " + callingUid
                            + " may not flag broadcast as alarm");
                }
                throw new SecurityException(
                        "Non-system callers may not flag broadcasts as alarm");
            }
            if (options.containsKey(BroadcastOptions.KEY_INTERACTIVE_BROADCAST)) {
                enforceCallingPermission(
                        android.Manifest.permission.BROADCAST_OPTION_INTERACTIVE,
                        "setInteractiveBroadcast");
            }
        }
    }
    @GuardedBy("this")
    final int broadcastIntentLocked(ProcessRecord callerApp,
            String callerPackage, String callerFeatureId, Intent intent, String resolvedType,
@@ -14695,19 +14714,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            // We're delivering the result to the caller
            final ProcessRecord resultToApp = callerApp;
            // Non-system callers can't declare that a broadcast is alarm-related.
            // The PendingIntent invocation case is handled in PendingIntentRecord.
            if (bOptions != null && callingUid != SYSTEM_UID) {
                if (bOptions.containsKey(BroadcastOptions.KEY_ALARM_BROADCAST)
                        || bOptions.containsKey(BroadcastOptions.KEY_INTERACTIVE_BROADCAST)) {
                    if (DEBUG_BROADCAST) {
                        Slog.w(TAG, "Non-system caller " + callingUid
                                + " may not flag broadcast as alarm or interactive");
                    }
                    throw new SecurityException(
                            "Non-system callers may not flag broadcasts as alarm or interactive");
                }
            }
            // Permission regimes around sender-supplied broadcast options.
            enforceBroadcastOptionPermissionsInternal(bOptions, callingUid);
            final long origId = Binder.clearCallingIdentity();
            try {
@@ -16901,6 +16909,11 @@ public class ActivityManagerService extends IActivityManager.Stub
            return mEnableModernQueue;
        }
        @Override
        public void enforceBroadcastOptionsPermissions(Bundle options, int callingUid) {
            enforceBroadcastOptionPermissionsInternal(options, callingUid);
        }
        /**
         * Returns package name by pid.
         */
Loading