blob: 89842aefc66ed73bb6cd7e25b9e253db8add682a [file] [log] [blame]
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.telephony.euicc;
17
18import android.annotation.IntDef;
Holly Jiuyu Sun4f73b9c2017-12-12 20:17:09 -080019import android.annotation.SystemApi;
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -080020import android.os.Parcel;
21import android.os.Parcelable;
22import android.service.carrier.CarrierIdentifier;
23import android.service.euicc.EuiccProfileInfo;
24import android.text.TextUtils;
25
26import com.android.internal.annotations.VisibleForTesting;
27
28import java.lang.annotation.Retention;
29import java.lang.annotation.RetentionPolicy;
30import java.util.Arrays;
Holly Jiuyu Sun4f73b9c2017-12-12 20:17:09 -080031import java.util.ArrayList;
32import java.util.List;
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -080033
34/**
35 * This represents the RAT (Rules Authorisation Table) stored on eUICC.
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -080036 * @hide
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -080037 */
Holly Jiuyu Sun4f73b9c2017-12-12 20:17:09 -080038@SystemApi
Holly Jiuyu Sunfb1c7842017-12-21 18:44:59 -080039public final class EuiccRulesAuthTable implements Parcelable {
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -080040 /** Profile policy rule flags */
41 @Retention(RetentionPolicy.SOURCE)
42 @IntDef(flag = true, prefix = { "POLICY_RULE_FLAG_" }, value = {
43 POLICY_RULE_FLAG_CONSENT_REQUIRED
44 })
Holly Jiuyu Sun4f73b9c2017-12-12 20:17:09 -080045 /** @hide */
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -080046 public @interface PolicyRuleFlag {}
47
48 /** User consent is required to install the profile. */
49 public static final int POLICY_RULE_FLAG_CONSENT_REQUIRED = 1;
50
51 private final int[] mPolicyRules;
52 private final CarrierIdentifier[][] mCarrierIds;
53 private final int[] mPolicyRuleFlags;
54
Holly Jiuyu Sunfb1c7842017-12-21 18:44:59 -080055 /** This is used to build new {@link EuiccRulesAuthTable} instance. */
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -080056 public static final class Builder {
57 private int[] mPolicyRules;
58 private CarrierIdentifier[][] mCarrierIds;
59 private int[] mPolicyRuleFlags;
60 private int mPosition;
61
62 /**
63 * Creates a new builder.
64 *
65 * @param ruleNum The number of authorisation rules in the table.
66 */
67 public Builder(int ruleNum) {
68 mPolicyRules = new int[ruleNum];
69 mCarrierIds = new CarrierIdentifier[ruleNum][];
70 mPolicyRuleFlags = new int[ruleNum];
71 }
72
73 /**
74 * Builds the RAT instance. This builder should not be used anymore after this method is
75 * called, otherwise {@link NullPointerException} will be thrown.
76 */
Holly Jiuyu Sunfb1c7842017-12-21 18:44:59 -080077 public EuiccRulesAuthTable build() {
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -080078 if (mPosition != mPolicyRules.length) {
79 throw new IllegalStateException(
80 "Not enough rules are added, expected: "
81 + mPolicyRules.length
82 + ", added: "
83 + mPosition);
84 }
Holly Jiuyu Sunfb1c7842017-12-21 18:44:59 -080085 return new EuiccRulesAuthTable(mPolicyRules, mCarrierIds, mPolicyRuleFlags);
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -080086 }
87
88 /**
89 * Adds an authorisation rule.
90 *
91 * @throws ArrayIndexOutOfBoundsException If the {@code mPosition} is larger than the size
92 * this table.
93 */
Holly Jiuyu Sun4f73b9c2017-12-12 20:17:09 -080094 public Builder add(int policyRules, List<CarrierIdentifier> carrierId, int policyRuleFlags) {
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -080095 if (mPosition >= mPolicyRules.length) {
96 throw new ArrayIndexOutOfBoundsException(mPosition);
97 }
98 mPolicyRules[mPosition] = policyRules;
Holly Jiuyu Sun4f73b9c2017-12-12 20:17:09 -080099 if (carrierId != null && carrierId.size() > 0) {
100 mCarrierIds[mPosition] = carrierId.toArray(new CarrierIdentifier[carrierId.size()]);
101 }
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -0800102 mPolicyRuleFlags[mPosition] = policyRuleFlags;
103 mPosition++;
104 return this;
105 }
106 }
107
108 /**
109 * @param mccRule A 2-character or 3-character string which can be either MCC or MNC. The
110 * character 'E' is used as a wild char to match any digit.
111 * @param mcc A 2-character or 3-character string which can be either MCC or MNC.
112 * @return Whether the {@code mccRule} matches {@code mcc}.
113 *
114 * @hide
115 */
116 @VisibleForTesting
117 public static boolean match(String mccRule, String mcc) {
118 if (mccRule.length() < mcc.length()) {
119 return false;
120 }
121 for (int i = 0; i < mccRule.length(); i++) {
122 // 'E' is the wild char to match any digit.
123 if (mccRule.charAt(i) == 'E'
124 || (i < mcc.length() && mccRule.charAt(i) == mcc.charAt(i))) {
125 continue;
126 }
127 return false;
128 }
129 return true;
130 }
131
Holly Jiuyu Sunfb1c7842017-12-21 18:44:59 -0800132 private EuiccRulesAuthTable(int[] policyRules, CarrierIdentifier[][] carrierIds,
133 int[] policyRuleFlags) {
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -0800134 mPolicyRules = policyRules;
135 mCarrierIds = carrierIds;
136 mPolicyRuleFlags = policyRuleFlags;
137 }
138
139 /**
140 * Finds the index of the first authorisation rule matching the given policy and carrier id. If
141 * the returned index is not negative, the carrier is allowed to apply this policy to its
142 * profile.
143 *
144 * @param policy The policy rule.
145 * @param carrierId The carrier id.
146 * @return The index of authorization rule. If no rule is found, -1 will be returned.
147 */
148 public int findIndex(@EuiccProfileInfo.PolicyRule int policy, CarrierIdentifier carrierId) {
149 for (int i = 0; i < mPolicyRules.length; i++) {
150 if ((mPolicyRules[i] & policy) == 0) {
151 continue;
152 }
153 CarrierIdentifier[] carrierIds = mCarrierIds[i];
154 if (carrierIds == null || carrierIds.length == 0) {
155 continue;
156 }
157 for (int j = 0; j < carrierIds.length; j++) {
158 CarrierIdentifier ruleCarrierId = carrierIds[j];
159 if (!match(ruleCarrierId.getMcc(), carrierId.getMcc())
160 || !match(ruleCarrierId.getMnc(), carrierId.getMnc())) {
161 continue;
162 }
163 String gid = ruleCarrierId.getGid1();
164 if (!TextUtils.isEmpty(gid) && !gid.equals(carrierId.getGid1())) {
165 continue;
166 }
167 gid = ruleCarrierId.getGid2();
168 if (!TextUtils.isEmpty(gid) && !gid.equals(carrierId.getGid2())) {
169 continue;
170 }
171 return i;
172 }
173 }
174 return -1;
175 }
176
177 /**
178 * Tests if the entry in the table has the given policy rule flag.
179 *
180 * @param index The index of the entry.
181 * @param flag The policy rule flag to be tested.
182 * @throws ArrayIndexOutOfBoundsException If the {@code index} is negative or larger than the
183 * size of this table.
184 */
185 public boolean hasPolicyRuleFlag(int index, @PolicyRuleFlag int flag) {
186 if (index < 0 || index >= mPolicyRules.length) {
187 throw new ArrayIndexOutOfBoundsException(index);
188 }
189 return (mPolicyRuleFlags[index] & flag) != 0;
190 }
191
192 @Override
193 public int describeContents() {
194 return 0;
195 }
196
197 @Override
198 public void writeToParcel(Parcel dest, int flags) {
199 dest.writeIntArray(mPolicyRules);
200 for (CarrierIdentifier[] ids : mCarrierIds) {
201 dest.writeTypedArray(ids, flags);
202 }
203 dest.writeIntArray(mPolicyRuleFlags);
204 }
205
206 @Override
207 public boolean equals(Object obj) {
208 if (this == obj) {
209 return true;
210 }
211 if (obj == null || getClass() != obj.getClass()) {
212 return false;
213 }
214
Holly Jiuyu Sunfb1c7842017-12-21 18:44:59 -0800215 EuiccRulesAuthTable that = (EuiccRulesAuthTable) obj;
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -0800216 if (mCarrierIds.length != that.mCarrierIds.length) {
217 return false;
218 }
219 for (int i = 0; i < mCarrierIds.length; i++) {
220 CarrierIdentifier[] carrierIds = mCarrierIds[i];
221 CarrierIdentifier[] thatCarrierIds = that.mCarrierIds[i];
222 if (carrierIds != null && thatCarrierIds != null) {
223 if (carrierIds.length != thatCarrierIds.length) {
224 return false;
225 }
226 for (int j = 0; j < carrierIds.length; j++) {
227 if (!carrierIds[j].equals(thatCarrierIds[j])) {
228 return false;
229 }
230 }
231 continue;
232 } else if (carrierIds == null && thatCarrierIds == null) {
233 continue;
234 }
235 return false;
236 }
237
238 return Arrays.equals(mPolicyRules, that.mPolicyRules)
239 && Arrays.equals(mPolicyRuleFlags, that.mPolicyRuleFlags);
240 }
241
Holly Jiuyu Sunfb1c7842017-12-21 18:44:59 -0800242 private EuiccRulesAuthTable(Parcel source) {
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -0800243 mPolicyRules = source.createIntArray();
244 int len = mPolicyRules.length;
245 mCarrierIds = new CarrierIdentifier[len][];
246 for (int i = 0; i < len; i++) {
247 mCarrierIds[i] = source.createTypedArray(CarrierIdentifier.CREATOR);
248 }
249 mPolicyRuleFlags = source.createIntArray();
250 }
251
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700252 public static final @android.annotation.NonNull Creator<EuiccRulesAuthTable> CREATOR =
Holly Jiuyu Sunfb1c7842017-12-21 18:44:59 -0800253 new Creator<EuiccRulesAuthTable>() {
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -0800254 @Override
Holly Jiuyu Sunfb1c7842017-12-21 18:44:59 -0800255 public EuiccRulesAuthTable createFromParcel(Parcel source) {
256 return new EuiccRulesAuthTable(source);
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -0800257 }
258
259 @Override
Holly Jiuyu Sunfb1c7842017-12-21 18:44:59 -0800260 public EuiccRulesAuthTable[] newArray(int size) {
261 return new EuiccRulesAuthTable[size];
Holly Jiuyu Sun47a74262018-01-09 19:23:11 -0800262 }
263 };
264}