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

Commit 4f2bc9a7 authored by Thiébaud Weksteen's avatar Thiébaud Weksteen Committed by Gerrit Code Review
Browse files

Merge changes I72f810a7,I2bd23f62

* changes:
  Add OWNER entry for android.os.PermissionEnforcer
  Add PermissionEnforcer class
parents f74a4b31 0e318f19
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -171,6 +171,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;
@@ -1351,6 +1352,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
@@ -5134,6 +5134,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
+4 −0
Original line number Diff line number Diff line
@@ -70,3 +70,7 @@ per-file Vintf* = file:/platform/system/libvintf:/OWNERS

# Tracing
per-file Trace.java = file:/TRACE_OWNERS

# PermissionEnforcer
per-file PermissionEnforcer.java = tweek@google.com, brufino@google.com
per-file PermissionEnforcer.java = file:/core/java/android/permission/OWNERS
+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);
    }
}