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

Commit eb171a35 authored by Holly Jiuyu Sun's avatar Holly Jiuyu Sun Committed by android-build-merger
Browse files

Merge "Add dependencies of EuiccCard." am: 90b4e47d am: 4f217d74

am: e03f92da

Change-Id: Ibc22bc94851e4faf6066f44baebaf2da8eec586e
parents f2ffcd64 e03f92da
Loading
Loading
Loading
Loading
+179 −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.telephony.euicc;

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

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Objects;

/**
 * This represents a signed notification which is defined in SGP.22. It can be either a profile
 * installation result or a notification generated for profile operations (e.g., enabling,
 * disabling, or deleting).
 *
 * @hide
 *
 * TODO(b/35851809): Make this a @SystemApi.
 */
public class EuiccNotification implements Parcelable {
    /** Event */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, prefix = { "EVENT_" }, value = {
            EVENT_INSTALL,
            EVENT_ENABLE,
            EVENT_DISABLE,
            EVENT_DELETE
    })
    public @interface Event {}

    /** A profile is downloaded and installed. */
    public static final int EVENT_INSTALL = 1;

    /** A profile is enabled. */
    public static final int EVENT_ENABLE = 1 << 1;

    /** A profile is disabled. */
    public static final int EVENT_DISABLE = 1 << 2;

    /** A profile is deleted. */
    public static final int EVENT_DELETE = 1 << 3;

    /** Value of the bits of all above events */
    @Event
    public static final int ALL_EVENTS =
            EVENT_INSTALL | EVENT_ENABLE | EVENT_DISABLE | EVENT_DELETE;

    private final int mSeq;
    private final String mTargetAddr;
    @Event private final int mEvent;
    @Nullable private final byte[] mData;

    /**
     * Creates an instance.
     *
     * @param seq The sequence number of this notification.
     * @param targetAddr The target server where to send this notification.
     * @param event The event which causes this notification.
     * @param data The data which needs to be sent to the target server. This can be null for
     *     building a list of notification metadata without data.
     */
    public EuiccNotification(int seq, String targetAddr, @Event int event, @Nullable byte[] data) {
        mSeq = seq;
        mTargetAddr = targetAddr;
        mEvent = event;
        mData = data;
    }

    /** @return The sequence number of this notification. */
    public int getSeq() {
        return mSeq;
    }

    /** @return The target server address where this notification should be sent to. */
    public String getTargetAddr() {
        return mTargetAddr;
    }

    /** @return The event of this notification. */
    @Event
    public int getEvent() {
        return mEvent;
    }

    /** @return The notification data which needs to be sent to the target server. */
    @Nullable
    public byte[] getData() {
        return mData;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }

        EuiccNotification that = (EuiccNotification) obj;
        return mSeq == that.mSeq
                && Objects.equals(mTargetAddr, that.mTargetAddr)
                && mEvent == that.mEvent
                && Arrays.equals(mData, that.mData);
    }

    @Override
    public int hashCode() {
        int result = 1;
        result = 31 * result + mSeq;
        result = 31 * result + Objects.hashCode(mTargetAddr);
        result = 31 * result + mEvent;
        result = 31 * result + Arrays.hashCode(mData);
        return result;
    }

    @Override
    public String toString() {
        return "EuiccNotification (seq="
                + mSeq
                + ", targetAddr="
                + mTargetAddr
                + ", event="
                + mEvent
                + ", data="
                + (mData == null ? "null" : "byte[" + mData.length + "]")
                + ")";
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mSeq);
        dest.writeString(mTargetAddr);
        dest.writeInt(mEvent);
        dest.writeByteArray(mData);
    }

    private EuiccNotification(Parcel source) {
        mSeq = source.readInt();
        mTargetAddr = source.readString();
        mEvent = source.readInt();
        mData = source.createByteArray();
    }

    public static final Creator<EuiccNotification> CREATOR =
            new Creator<EuiccNotification>() {
                @Override
                public EuiccNotification createFromParcel(Parcel source) {
                    return new EuiccNotification(source);
                }

                @Override
                public EuiccNotification[] newArray(int size) {
                    return new EuiccNotification[size];
                }
            };
}
+259 −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.telephony.euicc;

import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
import android.service.carrier.CarrierIdentifier;
import android.service.euicc.EuiccProfileInfo;
import android.text.TextUtils;

import com.android.internal.annotations.VisibleForTesting;

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

/**
 * This represents the RAT (Rules Authorisation Table) stored on eUICC.
 *
 * @hide
 *
 * TODO(b/35851809): Make this a @SystemApi.
 */
public final class EuiccRat implements Parcelable {
    /** Profile policy rule flags */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, prefix = { "POLICY_RULE_FLAG_" }, value = {
            POLICY_RULE_FLAG_CONSENT_REQUIRED
    })
    public @interface PolicyRuleFlag {}

    /** User consent is required to install the profile. */
    public static final int POLICY_RULE_FLAG_CONSENT_REQUIRED = 1;

    private final int[] mPolicyRules;
    private final CarrierIdentifier[][] mCarrierIds;
    private final int[] mPolicyRuleFlags;

    /** This is used to build new {@link EuiccRat} instance. */
    public static final class Builder {
        private int[] mPolicyRules;
        private CarrierIdentifier[][] mCarrierIds;
        private int[] mPolicyRuleFlags;
        private int mPosition;

        /**
         * Creates a new builder.
         *
         * @param ruleNum The number of authorisation rules in the table.
         */
        public Builder(int ruleNum) {
            mPolicyRules = new int[ruleNum];
            mCarrierIds = new CarrierIdentifier[ruleNum][];
            mPolicyRuleFlags = new int[ruleNum];
        }

        /**
         * Builds the RAT instance. This builder should not be used anymore after this method is
         * called, otherwise {@link NullPointerException} will be thrown.
         */
        public EuiccRat build() {
            if (mPosition != mPolicyRules.length) {
                throw new IllegalStateException(
                        "Not enough rules are added, expected: "
                                + mPolicyRules.length
                                + ", added: "
                                + mPosition);
            }
            return new EuiccRat(mPolicyRules, mCarrierIds, mPolicyRuleFlags);
        }

        /**
         * Adds an authorisation rule.
         *
         * @throws ArrayIndexOutOfBoundsException If the {@code mPosition} is larger than the size
         *     this table.
         */
        public Builder add(int policyRules, CarrierIdentifier[] carrierId, int policyRuleFlags) {
            if (mPosition >= mPolicyRules.length) {
                throw new ArrayIndexOutOfBoundsException(mPosition);
            }
            mPolicyRules[mPosition] = policyRules;
            mCarrierIds[mPosition] = carrierId;
            mPolicyRuleFlags[mPosition] = policyRuleFlags;
            mPosition++;
            return this;
        }
    }

    /**
     * @param mccRule A 2-character or 3-character string which can be either MCC or MNC. The
     *     character 'E' is used as a wild char to match any digit.
     * @param mcc A 2-character or 3-character string which can be either MCC or MNC.
     * @return Whether the {@code mccRule} matches {@code mcc}.
     *
     * @hide
     */
    @VisibleForTesting
    public static boolean match(String mccRule, String mcc) {
        if (mccRule.length() < mcc.length()) {
            return false;
        }
        for (int i = 0; i < mccRule.length(); i++) {
            // 'E' is the wild char to match any digit.
            if (mccRule.charAt(i) == 'E'
                    || (i < mcc.length() && mccRule.charAt(i) == mcc.charAt(i))) {
                continue;
            }
            return false;
        }
        return true;
    }

    private EuiccRat(int[] policyRules, CarrierIdentifier[][] carrierIds, int[] policyRuleFlags) {
        mPolicyRules = policyRules;
        mCarrierIds = carrierIds;
        mPolicyRuleFlags = policyRuleFlags;
    }

    /**
     * Finds the index of the first authorisation rule matching the given policy and carrier id. If
     * the returned index is not negative, the carrier is allowed to apply this policy to its
     * profile.
     *
     * @param policy The policy rule.
     * @param carrierId The carrier id.
     * @return The index of authorization rule. If no rule is found, -1 will be returned.
     */
    public int findIndex(@EuiccProfileInfo.PolicyRule int policy, CarrierIdentifier carrierId) {
        for (int i = 0; i < mPolicyRules.length; i++) {
            if ((mPolicyRules[i] & policy) == 0) {
                continue;
            }
            CarrierIdentifier[] carrierIds = mCarrierIds[i];
            if (carrierIds == null || carrierIds.length == 0) {
                continue;
            }
            for (int j = 0; j < carrierIds.length; j++) {
                CarrierIdentifier ruleCarrierId = carrierIds[j];
                if (!match(ruleCarrierId.getMcc(), carrierId.getMcc())
                        || !match(ruleCarrierId.getMnc(), carrierId.getMnc())) {
                    continue;
                }
                String gid = ruleCarrierId.getGid1();
                if (!TextUtils.isEmpty(gid) && !gid.equals(carrierId.getGid1())) {
                    continue;
                }
                gid = ruleCarrierId.getGid2();
                if (!TextUtils.isEmpty(gid) && !gid.equals(carrierId.getGid2())) {
                    continue;
                }
                return i;
            }
        }
        return -1;
    }

    /**
     * Tests if the entry in the table has the given policy rule flag.
     *
     * @param index The index of the entry.
     * @param flag The policy rule flag to be tested.
     * @throws ArrayIndexOutOfBoundsException If the {@code index} is negative or larger than the
     *     size of this table.
     */
    public boolean hasPolicyRuleFlag(int index, @PolicyRuleFlag int flag) {
        if (index < 0 || index >= mPolicyRules.length) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        return (mPolicyRuleFlags[index] & flag) != 0;
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeIntArray(mPolicyRules);
        for (CarrierIdentifier[] ids : mCarrierIds) {
            dest.writeTypedArray(ids, flags);
        }
        dest.writeIntArray(mPolicyRuleFlags);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }

        EuiccRat that = (EuiccRat) obj;
        if (mCarrierIds.length != that.mCarrierIds.length) {
            return false;
        }
        for (int i = 0; i < mCarrierIds.length; i++) {
            CarrierIdentifier[] carrierIds = mCarrierIds[i];
            CarrierIdentifier[] thatCarrierIds = that.mCarrierIds[i];
            if (carrierIds != null && thatCarrierIds != null) {
                if (carrierIds.length != thatCarrierIds.length) {
                    return false;
                }
                for (int j = 0; j < carrierIds.length; j++) {
                    if (!carrierIds[j].equals(thatCarrierIds[j])) {
                        return false;
                    }
                }
                continue;
            } else if (carrierIds == null && thatCarrierIds == null) {
                continue;
            }
            return false;
        }

        return Arrays.equals(mPolicyRules, that.mPolicyRules)
                && Arrays.equals(mPolicyRuleFlags, that.mPolicyRuleFlags);
    }

    private EuiccRat(Parcel source) {
        mPolicyRules = source.createIntArray();
        int len = mPolicyRules.length;
        mCarrierIds = new CarrierIdentifier[len][];
        for (int i = 0; i < len; i++) {
            mCarrierIds[i] = source.createTypedArray(CarrierIdentifier.CREATOR);
        }
        mPolicyRuleFlags = source.createIntArray();
    }

    public static final Creator<EuiccRat> CREATOR =
            new Creator<EuiccRat>() {
                @Override
                public EuiccRat createFromParcel(Parcel source) {
                    return new EuiccRat(source);
                }

                @Override
                public EuiccRat[] newArray(int size) {
                    return new EuiccRat[size];
                }
            };
}