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

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

Merge "Add PermissionManager exposing SPLIT_PERMISSIONS"

parents edfdc8eb 039678e1
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -950,6 +950,7 @@ package android.content {
    field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control";
    field public static final java.lang.String NETWORK_SCORE_SERVICE = "network_score";
    field public static final java.lang.String OEM_LOCK_SERVICE = "oem_lock";
    field public static final java.lang.String PERMISSION_SERVICE = "permission";
    field public static final java.lang.String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
    field public static final java.lang.String SECURE_ELEMENT_SERVICE = "secure_element";
    field public static final java.lang.String STATS_MANAGER = "stats";
@@ -4192,6 +4193,20 @@ package android.os.storage {

}

package android.permission {

  public final class PermissionManager {
    method public java.util.List<android.permission.PermissionManager.SplitPermissionInfo> getSplitPermissions();
  }

  public static final class PermissionManager.SplitPermissionInfo {
    method public java.lang.String[] getNewPermissions();
    method public java.lang.String getRootPermission();
    method public int getTargetSdk();
  }

}

package android.permissionpresenterservice {

  public abstract class RuntimePermissionPresenterService extends android.app.Service {
+8 −0
Original line number Diff line number Diff line
@@ -134,6 +134,7 @@ import android.os.UserManager;
import android.os.Vibrator;
import android.os.health.SystemHealthManager;
import android.os.storage.StorageManager;
import android.permission.PermissionManager;
import android.print.IPrintManager;
import android.print.PrintManager;
import android.service.oemlock.IOemLockService;
@@ -1064,6 +1065,13 @@ final class SystemServiceRegistry {
                            throws ServiceNotFoundException {
                        return new TimeZoneDetector();
                    }});

        registerService(Context.PERMISSION_SERVICE, PermissionManager.class,
                new CachedServiceFetcher<PermissionManager>() {
                    @Override
                    public PermissionManager createService(ContextImpl ctx) {
                        return new PermissionManager(ctx.getOuterContext());
                    }});
    }

    /**
+9 −0
Original line number Diff line number Diff line
@@ -3088,6 +3088,7 @@ public abstract class Context {
            //@hide: SYSTEM_UPDATE_SERVICE,
            //@hide: TIME_DETECTOR_SERVICE,
            //@hide: TIME_ZONE_DETECTOR_SERVICE,
            PERMISSION_SERVICE,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ServiceName {}
@@ -3860,6 +3861,14 @@ public abstract class Context {
     */
    public static final String SOUND_TRIGGER_SERVICE = "soundtrigger";

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

    /**
     * Use with {@link #getSystemService(String)} to retrieve an
+10 −49
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@ import static android.os.Build.VERSION_CODES.O;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;

import android.Manifest;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -73,6 +72,7 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.permission.PermissionManager;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.system.StructStat;
@@ -258,19 +258,6 @@ public class PackageParser {
        }
    }

    /** @hide */
    public static class SplitPermissionInfo {
        public final String rootPerm;
        public final String[] newPerms;
        public final int targetSdk;

        public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
            this.rootPerm = rootPerm;
            this.newPerms = newPerms;
            this.targetSdk = targetSdk;
        }
    }

    /**
     * List of new permissions that have been added since 1.0.
     * NOTE: These must be declared in SDK version order, with permissions
@@ -289,34 +276,6 @@ public class PackageParser {
                    android.os.Build.VERSION_CODES.DONUT, 0)
    };

    /**
     * List of permissions that have been split into more granular or dependent
     * permissions.
     * @hide
     */
    public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
        new PackageParser.SplitPermissionInfo[] {
            // READ_EXTERNAL_STORAGE is always required when an app requests
            // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
            // write access without read access.  The hack here with the target
            // target SDK version ensures that this grant is always done.
            new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
                    android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
            new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
                    new String[] { android.Manifest.permission.READ_CALL_LOG },
                    android.os.Build.VERSION_CODES.JELLY_BEAN),
            new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
                    new String[] { android.Manifest.permission.WRITE_CALL_LOG },
                    android.os.Build.VERSION_CODES.JELLY_BEAN),
            new PackageParser.SplitPermissionInfo(Manifest.permission.ACCESS_FINE_LOCATION,
                    new String[] { android.Manifest.permission.ACCESS_BACKGROUND_LOCATION },
                    android.os.Build.VERSION_CODES.P0),
            new PackageParser.SplitPermissionInfo(Manifest.permission.ACCESS_COARSE_LOCATION,
                    new String[] { android.Manifest.permission.ACCESS_BACKGROUND_LOCATION },
                    android.os.Build.VERSION_CODES.P0),
    };

    /**
     * @deprecated callers should move to explicitly passing around source path.
     */
@@ -2474,16 +2433,18 @@ public class PackageParser {
            Slog.i(TAG, implicitPerms.toString());
        }

        final int NS = PackageParser.SPLIT_PERMISSIONS.length;

        final int NS = PermissionManager.SPLIT_PERMISSIONS.length;
        for (int is=0; is<NS; is++) {
            final PackageParser.SplitPermissionInfo spi
                    = PackageParser.SPLIT_PERMISSIONS[is];
            if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
                    || !pkg.requestedPermissions.contains(spi.rootPerm)) {
            final PermissionManager.SplitPermissionInfo spi =
                    PermissionManager.SPLIT_PERMISSIONS[is];
            if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk()
                    || !pkg.requestedPermissions.contains(spi.getRootPermission())) {
                continue;
            }
            for (int in=0; in<spi.newPerms.length; in++) {
                final String perm = spi.newPerms[in];
            final String[] newPerms = spi.getNewPermissions();
            for (int in = 0; in < newPerms.length; in++) {
                final String perm = newPerms[in];
                if (!pkg.requestedPermissions.contains(perm)) {
                    pkg.requestedPermissions.add(perm);
                }
+136 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.permission;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;

import com.android.internal.annotations.Immutable;

import java.util.Arrays;
import java.util.List;

/**
 * System level service for accessing the permission capabilities of the platform.
 *
 * @hide
 */
@SystemApi
@SystemService(Context.PERMISSION_SERVICE)
public final class PermissionManager {
    /**
     * {@link android.content.pm.PackageParser} needs access without having a {@link Context}.
     *
     * @hide
     */
    public static final SplitPermissionInfo[] SPLIT_PERMISSIONS = new SplitPermissionInfo[]{
            // READ_EXTERNAL_STORAGE is always required when an app requests
            // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
            // write access without read access.  The hack here with the target
            // target SDK version ensures that this grant is always done.
            new SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
                    android.os.Build.VERSION_CODES.CUR_DEVELOPMENT + 1),
            new SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
                    new String[]{android.Manifest.permission.READ_CALL_LOG},
                    android.os.Build.VERSION_CODES.JELLY_BEAN),
            new SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
                    new String[]{android.Manifest.permission.WRITE_CALL_LOG},
                    android.os.Build.VERSION_CODES.JELLY_BEAN),
            new SplitPermissionInfo(Manifest.permission.ACCESS_FINE_LOCATION,
                    new String[]{android.Manifest.permission.ACCESS_BACKGROUND_LOCATION},
                    android.os.Build.VERSION_CODES.P0),
            new SplitPermissionInfo(Manifest.permission.ACCESS_COARSE_LOCATION,
                    new String[]{android.Manifest.permission.ACCESS_BACKGROUND_LOCATION},
                    android.os.Build.VERSION_CODES.P0)};

    private final @NonNull Context mContext;

    /**
     * Creates a new instance.
     *
     * @param context The current context in which to operate.
     * @hide
     */
    public PermissionManager(@NonNull Context context) {
        mContext = context;
    }

    /**
     * Get list of permissions that have been split into more granular or dependent permissions.
     *
     * <p>E.g. before {@link android.os.Build.VERSION_CODES#P0} an app that was granted
     * {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access he location while it was in
     * foreground and background. On platforms after {@link android.os.Build.VERSION_CODES#P0}
     * the location permission only grants location access while the app is in foreground. This
     * would break apps that target before {@link android.os.Build.VERSION_CODES#P0}. Hence whenever
     * such an old app asks for a location permission (i.e. the
     * {@link SplitPermissionInfo#getRootPermission()}), then the
     * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside
     * {@{@link SplitPermissionInfo#getNewPermissions}) is added.
     *
     * <p>Note: Regular apps do not have to worry about this. The platform and permission controller
     * automatically add the new permissions where needed.
     *
     * @return All permissions that are split.
     */
    public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
        return Arrays.asList(SPLIT_PERMISSIONS);
    }

    /**
     * A permission that was added in a previous API level might have split into several
     * permissions. This object describes one such split.
     */
    @Immutable
    public static final class SplitPermissionInfo {
        private final @NonNull String mRootPerm;
        private final @NonNull String[] mNewPerms;
        private final int mTargetSdk;

        /**
         * Get the permission that is split.
         */
        public @NonNull String getRootPermission() {
            return mRootPerm;
        }

        /**
         * Get the permissions that are added.
         */
        public @NonNull String[] getNewPermissions() {
            return mNewPerms;
        }

        /**
         * Get the target API level when the permission was split.
         */
        public int getTargetSdk() {
            return mTargetSdk;
        }

        private SplitPermissionInfo(@NonNull String rootPerm, @NonNull String[] newPerms,
                int targetSdk) {
            mRootPerm = rootPerm;
            mNewPerms = newPerms;
            mTargetSdk = targetSdk;
        }
    }
}
Loading