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

Commit 1e85ca80 authored by Evan Severson's avatar Evan Severson
Browse files

Let AppOpsService evaluate access for soundtrigger

Since the introduction of a background mode for record audio permission
the app ops check the soundtrigger service does was broken. This is
because the existence of the background permission now allows for the
audio app op to be in the MODE_FOREGROUND state.

Before the background mode, the soundtrigger service checked the AppOp's
raw state because it knew that the client apps needed access to the app
even if it was in the background. Now that the background mode exists
the AppOpsService can use the app's permissions + proc state +
capabilities to correctly evaluate whether the app should have access.

Apps with the foreground-only permission are still going to work because
the service binds to them with the include_capabilities flag. Later on
we can remove this binding flag and mandate that soundtrigger clients
add the background permission to their manifest.

Bug: 172632101
Test: 1P app is able to work
Change-Id: Ic5134ea0bcabdb289315d87bbc5405a0f0128c61
parent fded2b6d
Loading
Loading
Loading
Loading
+0 −53
Original line number Diff line number Diff line
@@ -17,10 +17,8 @@
package android.media.permission;

import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.PermissionChecker;
import android.content.pm.PackageManager;
import android.os.Binder;

import java.util.Objects;
@@ -179,57 +177,6 @@ public class PermissionUtil {
                reason);
    }

    /**
     * Checks whether the given identity has the given permission to receive data.
     *
     * This variant ignores the proc-state for the sake of the check, i.e. overrides any
     * restrictions that apply specifically to apps running in the background.
     *
     * TODO(ytai): This is a temporary hack until we have permissions that are specifically intended
     *  for background microphone access.
     *
     * @param context    A {@link Context}, used for permission checks.
     * @param identity   The identity to check.
     * @param permission The identifier of the permission we want to check.
     * @param reason     The reason why we're requesting the permission, for auditing purposes.
     * @return The permission check result which is either
     * {@link PermissionChecker#PERMISSION_GRANTED}
     * or {@link PermissionChecker#PERMISSION_SOFT_DENIED} or
     * {@link PermissionChecker#PERMISSION_HARD_DENIED}.
     */
    public static int checkPermissionForDataDeliveryIgnoreProcState(@NonNull Context context,
            @NonNull Identity identity,
            @NonNull String permission,
            @NonNull String reason) {
        if (context.checkPermission(permission, identity.pid, identity.uid)
                != PackageManager.PERMISSION_GRANTED) {
            return PermissionChecker.PERMISSION_HARD_DENIED;
        }

        String appOpOfPermission = AppOpsManager.permissionToOp(permission);
        if (appOpOfPermission == null) {
            // not platform defined
            return PermissionChecker.PERMISSION_GRANTED;
        }

        String packageName = identity.packageName;
        if (packageName == null) {
            String[] packageNames = context.getPackageManager().getPackagesForUid(identity.uid);
            if (packageNames != null && packageNames.length > 0) {
                packageName = packageNames[0];
            }
        }

        final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);

        int appOpMode = appOpsManager.unsafeCheckOpRawNoThrow(appOpOfPermission, identity.uid,
                packageName);
        if (appOpMode == AppOpsManager.MODE_ALLOWED) {
            return PermissionChecker.PERMISSION_GRANTED;
        }
        return PermissionChecker.PERMISSION_SOFT_DENIED;
    }

    /**
     * Checks whether the given identity has the given permission.
     *
+2 −5
Original line number Diff line number Diff line
@@ -149,11 +149,8 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware
    private static void enforcePermissionForDataDelivery(@NonNull Context context,
            @NonNull Identity identity,
            @NonNull String permission, @NonNull String reason) {
        // TODO(ytai): We're temporarily ignoring proc state until we have a proper permission that
        //  represents being able to use the microphone in the background. Otherwise, some of our
        //  existing use-cases would break.
        final int status = PermissionUtil.checkPermissionForDataDeliveryIgnoreProcState(context,
                identity, permission, reason);
        final int status = PermissionUtil.checkPermissionForDataDelivery(context, identity,
                permission, reason);
        if (status != PermissionChecker.PERMISSION_GRANTED) {
            throw new SecurityException(
                    String.format("Failed to obtain permission %s for identity %s", permission,