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

Commit 465b2143 authored by Andrei Onea's avatar Andrei Onea
Browse files

Enforce overriding methods for IPlatformCompat

Restrict the ability of callers to IPlatformCompat.setOverrides and
IPlatformCompat.clearOverride, depending on the type of build and/or
whether the app is debuggable.

Bug: 144552011
Test: atest PlatformCompatTest
Test: atest CompatConfigTest
Change-Id: Ibff7db73d7867735853aa2ddde7c14a12625b3dc
parent 591e1fcf
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 com.android.internal.compat;

import android.os.Build;

/**
 * Platform private class for determining the type of Android build installed.
 *
 */
public class AndroidBuildClassifier {

    public boolean isDebuggableBuild() {
        return Build.IS_DEBUGGABLE;
    }

    public boolean isFinalBuild() {
        return "REL".equals(Build.VERSION.CODENAME);
    }
}
+38 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 com.android.internal.compat;

import android.content.pm.ApplicationInfo;

import com.android.internal.compat.OverrideAllowedState;

/**
 * Platform private API for determining whether a changeId can be overridden.
 *
 * {@hide}
 */
interface IOverrideValidator
{
    /**
     * Validation function.
     * @param changeId    id of the change to be toggled on or off.
     * @param packageName package of the app for which the change should be overridden.
     * @return {@link OverrideAllowedState} specifying whether the change can be overridden for
     * the given package or a reason why not.
     */
    OverrideAllowedState getOverrideAllowedState(long changeId, String packageName);
}
+6 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.compat;

import android.content.pm.ApplicationInfo;
import com.android.internal.compat.IOverrideValidator;
import java.util.Map;

parcelable CompatibilityChangeConfig;
@@ -195,4 +196,9 @@ interface IPlatformCompat
     * @return An array of {@link CompatChangeInfo} known to the service.
     */
    CompatibilityChangeInfo[] listAllChanges();

    /**
     * Get an instance that can determine whether a changeid can be overridden for a package name.
     */
    IOverrideValidator getOverrideValidator();
}
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 com.android.internal.compat;

parcelable OverrideAllowedState;
 No newline at end of file
+136 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 com.android.internal.compat;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * This class contains all the possible override allowed states.
 */
public final class OverrideAllowedState implements Parcelable {
    @IntDef({
            ALLOWED,
            DISABLED_NOT_DEBUGGABLE,
            DISABLED_NON_TARGET_SDK,
            DISABLED_TARGET_SDK_TOO_HIGH,
            PACKAGE_DOES_NOT_EXIST
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface State {
    }

    /**
     * Change can be overridden.
     */
    public static final int ALLOWED = 0;
    /**
     * Change cannot be overridden, due to the app not being debuggable.
     */
    public static final int DISABLED_NOT_DEBUGGABLE = 1;
    /**
     * Change cannot be overridden, due to the build being non-debuggable and the change being
     * non-targetSdk.
     */
    public static final int DISABLED_NON_TARGET_SDK = 2;
    /**
     * Change cannot be overridden, due to the app's targetSdk being above the change's targetSdk.
     */
    public static final int DISABLED_TARGET_SDK_TOO_HIGH = 3;
    /**
     * Package does not exist.
     */
    public static final int PACKAGE_DOES_NOT_EXIST = 4;

    @State
    public final int state;
    public final int appTargetSdk;
    public final int changeIdTargetSdk;

    private OverrideAllowedState(Parcel parcel) {
        state = parcel.readInt();
        appTargetSdk = parcel.readInt();
        changeIdTargetSdk = parcel.readInt();
    }

    public OverrideAllowedState(@State int state, int appTargetSdk, int changeIdTargetSdk) {
        this.state = state;
        this.appTargetSdk = appTargetSdk;
        this.changeIdTargetSdk = changeIdTargetSdk;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(state);
        out.writeInt(appTargetSdk);
        out.writeInt(changeIdTargetSdk);
    }

    /**
     * Enforces the policy for overriding compat changes.
     *
     * @param changeId    the change id that was attempted to be overridden.
     * @param packageName the package for which the attempt was made.
     * @throws SecurityException if the policy forbids this operation.
     */
    public void enforce(long changeId, String packageName)
            throws SecurityException {
        switch (state) {
            case ALLOWED:
                return;
            case DISABLED_NOT_DEBUGGABLE:
                throw new SecurityException(
                        "Cannot override a change on a non-debuggable app and user build.");
            case DISABLED_NON_TARGET_SDK:
                throw new SecurityException(
                        "Cannot override a default enabled/disabled change on a user build.");
            case DISABLED_TARGET_SDK_TOO_HIGH:
                throw new SecurityException(String.format(
                        "Cannot override %1$d for %2$s because the app's targetSdk (%3$d) is "
                                + "above the change's targetSdk threshold (%4$d)",
                        changeId, packageName, appTargetSdk, changeIdTargetSdk));
            case PACKAGE_DOES_NOT_EXIST:
                throw new SecurityException(String.format(
                        "Cannot override %1$d for %2$s because the package does not exist, and "
                                + "the change is targetSdk gated.",
                        changeId, packageName));
        }
    }

    public static final @NonNull
            Parcelable.Creator<OverrideAllowedState> CREATOR =
                new Parcelable.Creator<OverrideAllowedState>() {
                public OverrideAllowedState createFromParcel(Parcel parcel) {
                    OverrideAllowedState info = new OverrideAllowedState(parcel);
                    return info;
                }

                public OverrideAllowedState[] newArray(int size) {
                    return new OverrideAllowedState[size];
                }
            };
}
Loading