Loading telephony/java/android/telephony/euicc/EuiccNotification.java 0 → 100644 +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]; } }; } telephony/java/android/telephony/euicc/EuiccRat.java 0 → 100644 +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]; } }; } Loading
telephony/java/android/telephony/euicc/EuiccNotification.java 0 → 100644 +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]; } }; }
telephony/java/android/telephony/euicc/EuiccRat.java 0 → 100644 +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]; } }; }