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

Commit ea6b1312 authored by Thiébaud Weksteen's avatar Thiébaud Weksteen Committed by Android (Google) Code Review
Browse files

Merge "Add PermissionEnforcer class"

parents f322caa1 db259e0e
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -173,6 +173,7 @@ import android.os.IThermalService;
import android.os.IUserManager;
import android.os.IncidentManager;
import android.os.PerformanceHintManager;
import android.os.PermissionEnforcer;
import android.os.PowerManager;
import android.os.RecoverySystem;
import android.os.ServiceManager;
@@ -1366,6 +1367,14 @@ public final class SystemServiceRegistry {
                        return new PermissionCheckerManager(ctx.getOuterContext());
                    }});

        registerService(Context.PERMISSION_ENFORCER_SERVICE, PermissionEnforcer.class,
                new CachedServiceFetcher<PermissionEnforcer>() {
                    @Override
                    public PermissionEnforcer createService(ContextImpl ctx)
                            throws ServiceNotFoundException {
                        return new PermissionEnforcer(ctx.getOuterContext());
                    }});

        registerService(Context.DYNAMIC_SYSTEM_SERVICE, DynamicSystemManager.class,
                new CachedServiceFetcher<DynamicSystemManager>() {
                    @Override
+8 −0
Original line number Diff line number Diff line
@@ -5141,6 +5141,14 @@ public abstract class Context {
     */
    public static final String PERMISSION_CHECKER_SERVICE = "permission_checker";

    /**
     * Official published name of the (internal) permission enforcer service.
     *
     * @see #getSystemService(String)
     * @hide
     */
    public static final String PERMISSION_ENFORCER_SERVICE = "permission_enforcer";

    /**
     * Use with {@link #getSystemService(String) to retrieve an
     * {@link android.apphibernation.AppHibernationManager}} for
+101 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;

import android.annotation.NonNull;
import android.annotation.SystemService;
import android.content.AttributionSource;
import android.content.Context;
import android.content.PermissionChecker;
import android.permission.PermissionCheckerManager;

/**
 * PermissionEnforcer check permissions for AIDL-generated services which use
 * the @EnforcePermission annotation.
 *
 * <p>AIDL services may be annotated with @EnforcePermission which will trigger
 * the generation of permission check code. This generated code relies on
 * PermissionEnforcer to validate the permissions. The methods available are
 * purposely similar to the AIDL annotation syntax.
 *
 * @see android.permission.PermissionManager
 *
 * @hide
 */
@SystemService(Context.PERMISSION_ENFORCER_SERVICE)
public class PermissionEnforcer {

    private final Context mContext;

    /** Protected constructor. Allows subclasses to instantiate an object
     *  without using a Context.
     */
    protected PermissionEnforcer() {
        mContext = null;
    }

    /** Constructor, prefer using the fromContext static method when possible */
    public PermissionEnforcer(@NonNull Context context) {
        mContext = context;
    }

    @PermissionCheckerManager.PermissionResult
    protected int checkPermission(@NonNull String permission, @NonNull AttributionSource source) {
        return PermissionChecker.checkPermissionForDataDelivery(
            mContext, permission, PermissionChecker.PID_UNKNOWN, source, "" /* message */);
    }

    public void enforcePermission(@NonNull String permission, @NonNull
            AttributionSource source) throws SecurityException {
        int result = checkPermission(permission, source);
        if (result != PermissionCheckerManager.PERMISSION_GRANTED) {
            throw new SecurityException("Access denied, requires: " + permission);
        }
    }

    public void enforcePermissionAllOf(@NonNull String[] permissions,
            @NonNull AttributionSource source) throws SecurityException {
        for (String permission : permissions) {
            int result = checkPermission(permission, source);
            if (result != PermissionCheckerManager.PERMISSION_GRANTED) {
                throw new SecurityException("Access denied, requires: allOf={"
                        + String.join(", ", permissions) + "}");
            }
        }
    }

    public void enforcePermissionAnyOf(@NonNull String[] permissions,
            @NonNull AttributionSource source) throws SecurityException {
        for (String permission : permissions) {
            int result = checkPermission(permission, source);
            if (result == PermissionCheckerManager.PERMISSION_GRANTED) {
                return;
            }
        }
        throw new SecurityException("Access denied, requires: anyOf={"
                + String.join(", ", permissions) + "}");
    }

    /**
     * Returns a new PermissionEnforcer based on a Context.
     *
     * @hide
     */
    public static PermissionEnforcer fromContext(@NonNull Context context) {
        return context.getSystemService(PermissionEnforcer.class);
    }
}