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

Commit 5f2bc22d authored by Jay Thomas Sullivan's avatar Jay Thomas Sullivan
Browse files

Combine AppOpsManager arrays into one

AppOpsManager currently has multiple arrays which are all related:

- sOpToSwitch
- sOpToString
- sOpNames
- sOpPerms
- sOpRestrictions
- sOpAllowSystemRestrictionBypass
- sOpDefaultMode
- sOpDisableReset
- sOpRestrictRead

Despite being different arrays, they're essentially a single list of
objects with each field sliced into a different array.

As the entries in these arrays grows, they are are difficult to keep
track of. To simplify things, we can simply join them all into a single
list of objects. Because there are so many fields, we use the builder
pattern to prevent the array from becoming unreadable.

Test: presubmit
Bug: 242097113
No-Typo-Check: typo EMERGECY is preexisting and non-trivial to fix
Change-Id: I1c54a18fc8ca2de6c5ab4a2ae62d1943fcbaea62
parent 2a1fdce4
Loading
Loading
Loading
Loading
+198 −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.app;

import static android.app.AppOpsManager.OP_NONE;

import android.annotation.NonNull;

import java.util.Objects;

/**
 * Information about a particular app op.
 */
class AppOpInfo {
    /**
     * A unique constant identifying this app op.
     */
    public final int code;

    /**
     * This maps each operation to the operation that serves as the
     * switch to determine whether it is allowed.  Generally this is
     * a 1:1 mapping, but for some things (like location) that have
     * multiple low-level operations being tracked that should be
     * presented to the user as one switch then this can be used to
     * make them all controlled by the same single operation.
     */
    public final int switchCode;

    /**
     * This maps each operation to the public string constant for it.
     */
    public final String name;

    /**
     * This provides a simple name for each operation to be used
     * in debug output.
     */
    public final String simpleName;

    /**
     * This optionally maps a permission to an operation.  If there
     * is no permission associated with an operation, it is null.
     */
    public final String permission;

    /**
     * Specifies whether an Op should be restricted by a user restriction.
     * Each Op should be filled with a restriction string from UserManager or
     * null to specify it is not affected by any user restriction.
     */
    public final String restriction;

    /**
     * In which cases should an app be allowed to bypass the
     * {@link AppOpsManager#setUserRestriction user restriction} for a certain app-op.
     */
    public final AppOpsManager.RestrictionBypass allowSystemRestrictionBypass;

    /**
     * This specifies the default mode for each operation.
     */
    public final int defaultMode;

    /**
     * This specifies whether each option is allowed to be reset
     * when resetting all app preferences.  Disable reset for
     * app ops that are under strong control of some part of the
     * system (such as OP_WRITE_SMS, which should be allowed only
     * for whichever app is selected as the current SMS app).
     */
    public final boolean disableReset;

    /**
     * This specifies whether each option is only allowed to be read
     * by apps with manage appops permission.
     */
    public final boolean restrictRead;

    AppOpInfo(int code,
            int switchCode,
            @NonNull String name,
            @NonNull String simpleName,
            String permission,
            String restriction,
            AppOpsManager.RestrictionBypass allowSystemRestrictionBypass,
            int defaultMode,
            boolean disableReset,
            boolean restrictRead) {
        if (code < OP_NONE) throw new IllegalArgumentException();
        if (switchCode < OP_NONE) throw new IllegalArgumentException();
        Objects.requireNonNull(name);
        Objects.requireNonNull(simpleName);
        this.code = code;
        this.switchCode = switchCode;
        this.name = name;
        this.simpleName = simpleName;
        this.permission = permission;
        this.restriction = restriction;
        this.allowSystemRestrictionBypass = allowSystemRestrictionBypass;
        this.defaultMode = defaultMode;
        this.disableReset = disableReset;
        this.restrictRead = restrictRead;
    }

    static class Builder {
        private int mCode;
        private int mSwitchCode;
        private String mName;
        private String mSimpleName;
        private String mPermission = null;
        private String mRestriction = null;
        private AppOpsManager.RestrictionBypass mAllowSystemRestrictionBypass = null;
        private int mDefaultMode = AppOpsManager.MODE_DEFAULT;
        private boolean mDisableReset = false;
        private boolean mRestrictRead = false;

        Builder(int code, @NonNull String name, @NonNull String simpleName) {
            if (code < OP_NONE) throw new IllegalArgumentException();
            Objects.requireNonNull(name);
            Objects.requireNonNull(simpleName);
            this.mCode = code;
            this.mSwitchCode = code;
            this.mName = name;
            this.mSimpleName = simpleName;
        }

        public Builder setCode(int value) {
            this.mCode = value;
            return this;
        }

        public Builder setSwitchCode(int value) {
            this.mSwitchCode = value;
            return this;
        }

        public Builder setName(String value) {
            this.mName = value;
            return this;
        }

        public Builder setSimpleName(String value) {
            this.mSimpleName = value;
            return this;
        }

        public Builder setPermission(String value) {
            this.mPermission = value;
            return this;
        }

        public Builder setRestriction(String value) {
            this.mRestriction = value;
            return this;
        }

        public Builder setAllowSystemRestrictionBypass(
                AppOpsManager.RestrictionBypass value) {
            this.mAllowSystemRestrictionBypass = value;
            return this;
        }

        public Builder setDefaultMode(int value) {
            this.mDefaultMode = value;
            return this;
        }

        public Builder setDisableReset(boolean value) {
            this.mDisableReset = value;
            return this;
        }

        public Builder setRestrictRead(boolean value) {
            this.mRestrictRead = value;
            return this;
        }

        public AppOpInfo build() {
            return new AppOpInfo(mCode, mSwitchCode, mName, mSimpleName, mPermission, mRestriction,
                mAllowSystemRestrictionBypass, mDefaultMode, mDisableReset, mRestrictRead);
        }
    }
}
+407 −1216

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -354,7 +354,7 @@ public final class PermissionPolicyService extends SystemService {
     * Get op that controls the access related to the permission.
     *
     * <p>Usually the permission-op relationship is 1:1 but some permissions (e.g. fine location)
     * {@link AppOpsManager#sOpToSwitch share an op} to control the access.
     * {@link AppOpsManager#opToSwitch(int)}  share an op} to control the access.
     *
     * @param permission The permission
     * @return The op that controls the access of the permission