1 /*
2  * Copyright (C) 2017 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  */
16 package android.service.euicc;
17 
18 import android.annotation.IntDef;
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.compat.annotation.UnsupportedAppUsage;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.service.carrier.CarrierIdentifier;
26 import android.telephony.UiccAccessRule;
27 import android.text.TextUtils;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 import java.util.Arrays;
32 import java.util.Collections;
33 import java.util.List;
34 import java.util.Objects;
35 
36 /**
37  * Information about an embedded profile (subscription) on an eUICC.
38  *
39  * @hide
40  */
41 @SystemApi
42 public final class EuiccProfileInfo implements Parcelable {
43 
44     /** Profile policy rules (bit mask) */
45     @Retention(RetentionPolicy.SOURCE)
46     @IntDef(flag = true, prefix = { "POLICY_RULE_" }, value = {
47             POLICY_RULE_DO_NOT_DISABLE,
48             POLICY_RULE_DO_NOT_DELETE,
49             POLICY_RULE_DELETE_AFTER_DISABLING
50     })
51     /** @hide */
52     public @interface PolicyRule {}
53     /** Once this profile is enabled, it cannot be disabled. */
54     public static final int POLICY_RULE_DO_NOT_DISABLE = 1;
55     /** This profile cannot be deleted. */
56     public static final int POLICY_RULE_DO_NOT_DELETE = 1 << 1;
57     /** This profile should be deleted after being disabled. */
58     public static final int POLICY_RULE_DELETE_AFTER_DISABLING = 1 << 2;
59 
60     /** Class of the profile */
61     @Retention(RetentionPolicy.SOURCE)
62     @IntDef(prefix = { "PROFILE_CLASS_" }, value = {
63             PROFILE_CLASS_TESTING,
64             PROFILE_CLASS_PROVISIONING,
65             PROFILE_CLASS_OPERATIONAL,
66             PROFILE_CLASS_UNSET
67     })
68     /** @hide */
69     public @interface ProfileClass {}
70     /** Testing profiles */
71     public static final int PROFILE_CLASS_TESTING = 0;
72     /** Provisioning profiles which are pre-loaded on eUICC */
73     public static final int PROFILE_CLASS_PROVISIONING = 1;
74     /** Operational profiles which can be pre-loaded or downloaded */
75     public static final int PROFILE_CLASS_OPERATIONAL = 2;
76     /**
77      * Profile class not set.
78      * @hide
79      */
80     public static final int PROFILE_CLASS_UNSET = -1;
81 
82     /** State of the profile */
83     @Retention(RetentionPolicy.SOURCE)
84     @IntDef(prefix = { "PROFILE_STATE_" }, value = {
85             PROFILE_STATE_DISABLED,
86             PROFILE_STATE_ENABLED,
87             PROFILE_STATE_UNSET
88     })
89     /** @hide */
90     public @interface ProfileState {}
91     /** Disabled profiles */
92     public static final int PROFILE_STATE_DISABLED = 0;
93     /** Enabled profile */
94     public static final int PROFILE_STATE_ENABLED = 1;
95     /**
96      * Profile state not set.
97      * @hide
98      */
99     public static final int PROFILE_STATE_UNSET = -1;
100 
101     /** The iccid of the subscription. */
102     private final String mIccid;
103 
104     /** An optional nickname for the subscription. */
105     private final @Nullable String mNickname;
106 
107     /** The service provider name for the subscription. */
108     private final String mServiceProviderName;
109 
110     /** The profile name for the subscription. */
111     private final String mProfileName;
112 
113     /** Profile class for the subscription. */
114     @ProfileClass private final int mProfileClass;
115 
116     /** The profile state of the subscription. */
117     @ProfileState private final int mState;
118 
119     /** The operator Id of the subscription. */
120     private final CarrierIdentifier mCarrierIdentifier;
121 
122     /** The policy rules of the subscription. */
123     @PolicyRule private final int mPolicyRules;
124 
125     /**
126      * Optional access rules defining which apps can manage this subscription. If unset, only the
127      * platform can manage it.
128      */
129     private final @Nullable UiccAccessRule[] mAccessRules;
130 
131     public static final @android.annotation.NonNull Creator<EuiccProfileInfo> CREATOR = new Creator<EuiccProfileInfo>() {
132         @Override
133         public EuiccProfileInfo createFromParcel(Parcel in) {
134             return new EuiccProfileInfo(in);
135         }
136 
137         @Override
138         public EuiccProfileInfo[] newArray(int size) {
139             return new EuiccProfileInfo[size];
140         }
141     };
142 
143     // TODO(b/70292228): Remove this method when LPA can be updated.
144     /**
145      * @hide
146      * @deprecated - Do not use.
147      */
148     @Deprecated
149     @UnsupportedAppUsage
EuiccProfileInfo(String iccid, @Nullable UiccAccessRule[] accessRules, @Nullable String nickname)150     public EuiccProfileInfo(String iccid, @Nullable UiccAccessRule[] accessRules,
151             @Nullable String nickname) {
152         if (!TextUtils.isDigitsOnly(iccid)) {
153             throw new IllegalArgumentException("iccid contains invalid characters: " + iccid);
154         }
155         this.mIccid = iccid;
156         this.mAccessRules = accessRules;
157         this.mNickname = nickname;
158 
159         this.mServiceProviderName = null;
160         this.mProfileName = null;
161         this.mProfileClass = PROFILE_CLASS_UNSET;
162         this.mState = PROFILE_STATE_UNSET;
163         this.mCarrierIdentifier = null;
164         this.mPolicyRules = 0;
165     }
166 
EuiccProfileInfo(Parcel in)167     private EuiccProfileInfo(Parcel in) {
168         mIccid = in.readString();
169         mNickname = in.readString();
170         mServiceProviderName = in.readString();
171         mProfileName = in.readString();
172         mProfileClass = in.readInt();
173         mState = in.readInt();
174         byte exist = in.readByte();
175         if (exist == (byte) 1) {
176             mCarrierIdentifier = CarrierIdentifier.CREATOR.createFromParcel(in);
177         } else {
178             mCarrierIdentifier = null;
179         }
180         mPolicyRules = in.readInt();
181         mAccessRules = in.createTypedArray(UiccAccessRule.CREATOR);
182     }
183 
184     @Override
writeToParcel(Parcel dest, int flags)185     public void writeToParcel(Parcel dest, int flags) {
186         dest.writeString(mIccid);
187         dest.writeString(mNickname);
188         dest.writeString(mServiceProviderName);
189         dest.writeString(mProfileName);
190         dest.writeInt(mProfileClass);
191         dest.writeInt(mState);
192         if (mCarrierIdentifier != null) {
193             dest.writeByte((byte) 1);
194             mCarrierIdentifier.writeToParcel(dest, flags);
195         } else {
196             dest.writeByte((byte) 0);
197         }
198         dest.writeInt(mPolicyRules);
199         dest.writeTypedArray(mAccessRules, flags);
200     }
201 
202     @Override
describeContents()203     public int describeContents() {
204         return 0;
205     }
206 
207     /** The builder to build a new {@link EuiccProfileInfo} instance. */
208     public static final class Builder {
209         private String mIccid;
210         private List<UiccAccessRule> mAccessRules;
211         private String mNickname;
212         private String mServiceProviderName;
213         private String mProfileName;
214         @ProfileClass private int mProfileClass;
215         @ProfileState private int mState;
216         private CarrierIdentifier mCarrierIdentifier;
217         @PolicyRule private int mPolicyRules;
218 
Builder(String value)219         public Builder(String value) {
220             if (!TextUtils.isDigitsOnly(value)) {
221                 throw new IllegalArgumentException("iccid contains invalid characters: " + value);
222             }
223             mIccid = value;
224         }
225 
Builder(EuiccProfileInfo baseProfile)226         public Builder(EuiccProfileInfo baseProfile) {
227             mIccid = baseProfile.mIccid;
228             mNickname = baseProfile.mNickname;
229             mServiceProviderName = baseProfile.mServiceProviderName;
230             mProfileName = baseProfile.mProfileName;
231             mProfileClass = baseProfile.mProfileClass;
232             mState = baseProfile.mState;
233             mCarrierIdentifier = baseProfile.mCarrierIdentifier;
234             mPolicyRules = baseProfile.mPolicyRules;
235             mAccessRules = baseProfile.mAccessRules == null
236                             ? Collections.emptyList()
237                             : Arrays.asList(baseProfile.mAccessRules);
238         }
239 
240         /** Builds the profile instance. */
build()241         public EuiccProfileInfo build() {
242             if (mIccid == null) {
243                 throw new IllegalStateException("ICCID must be set for a profile.");
244             }
245             return new EuiccProfileInfo(
246                     mIccid,
247                     mNickname,
248                     mServiceProviderName,
249                     mProfileName,
250                     mProfileClass,
251                     mState,
252                     mCarrierIdentifier,
253                     mPolicyRules,
254                     mAccessRules);
255         }
256 
257         /** Sets the iccId of the subscription. */
setIccid(String value)258         public Builder setIccid(String value) {
259             if (!TextUtils.isDigitsOnly(value)) {
260                 throw new IllegalArgumentException("iccid contains invalid characters: " + value);
261             }
262             mIccid = value;
263             return this;
264         }
265 
266         /** Sets the nickname of the subscription. */
setNickname(String value)267         public Builder setNickname(String value) {
268             mNickname = value;
269             return this;
270         }
271 
272         /** Sets the service provider name of the subscription. */
setServiceProviderName(String value)273         public Builder setServiceProviderName(String value) {
274             mServiceProviderName = value;
275             return this;
276         }
277 
278         /** Sets the profile name of the subscription. */
setProfileName(String value)279         public Builder setProfileName(String value) {
280             mProfileName = value;
281             return this;
282         }
283 
284         /** Sets the profile class of the subscription. */
setProfileClass(@rofileClass int value)285         public Builder setProfileClass(@ProfileClass int value) {
286             mProfileClass = value;
287             return this;
288         }
289 
290         /** Sets the state of the subscription. */
setState(@rofileState int value)291         public Builder setState(@ProfileState int value) {
292             mState = value;
293             return this;
294         }
295 
296         /** Sets the carrier identifier of the subscription. */
setCarrierIdentifier(CarrierIdentifier value)297         public Builder setCarrierIdentifier(CarrierIdentifier value) {
298             mCarrierIdentifier = value;
299             return this;
300         }
301 
302         /** Sets the policy rules of the subscription. */
setPolicyRules(@olicyRule int value)303         public Builder setPolicyRules(@PolicyRule int value) {
304             mPolicyRules = value;
305             return this;
306         }
307 
308         /** Sets the access rules of the subscription. */
setUiccAccessRule(@ullable List<UiccAccessRule> value)309         public Builder setUiccAccessRule(@Nullable List<UiccAccessRule> value) {
310             mAccessRules = value;
311             return this;
312         }
313     }
314 
EuiccProfileInfo( String iccid, @Nullable String nickname, String serviceProviderName, String profileName, @ProfileClass int profileClass, @ProfileState int state, CarrierIdentifier carrierIdentifier, @PolicyRule int policyRules, @Nullable List<UiccAccessRule> accessRules)315     private EuiccProfileInfo(
316             String iccid,
317             @Nullable String nickname,
318             String serviceProviderName,
319             String profileName,
320             @ProfileClass int profileClass,
321             @ProfileState int state,
322             CarrierIdentifier carrierIdentifier,
323             @PolicyRule int policyRules,
324             @Nullable List<UiccAccessRule> accessRules) {
325         this.mIccid = iccid;
326         this.mNickname = nickname;
327         this.mServiceProviderName = serviceProviderName;
328         this.mProfileName = profileName;
329         this.mProfileClass = profileClass;
330         this.mState = state;
331         this.mCarrierIdentifier = carrierIdentifier;
332         this.mPolicyRules = policyRules;
333         if (accessRules != null && accessRules.size() > 0) {
334             this.mAccessRules = accessRules.toArray(new UiccAccessRule[accessRules.size()]);
335         } else {
336             this.mAccessRules = null;
337         }
338     }
339 
340     /** Gets the ICCID string. */
getIccid()341     public String getIccid() {
342         return mIccid;
343     }
344 
345     /** Gets the access rules. */
346     @Nullable
getUiccAccessRules()347     public List<UiccAccessRule> getUiccAccessRules() {
348         if (mAccessRules == null) return null;
349         return Arrays.asList(mAccessRules);
350     }
351 
352     /** Gets the nickname. */
353     @Nullable
getNickname()354     public String getNickname() {
355         return mNickname;
356     }
357 
358     /** Gets the service provider name. */
getServiceProviderName()359     public String getServiceProviderName() {
360         return mServiceProviderName;
361     }
362 
363     /** Gets the profile name. */
getProfileName()364     public String getProfileName() {
365         return mProfileName;
366     }
367 
368     /** Gets the profile class. */
369     @ProfileClass
getProfileClass()370     public int getProfileClass() {
371         return mProfileClass;
372     }
373 
374     /** Gets the state of the subscription. */
375     @ProfileState
getState()376     public int getState() {
377         return mState;
378     }
379 
380     /** Gets the carrier identifier. */
getCarrierIdentifier()381     public CarrierIdentifier getCarrierIdentifier() {
382         return mCarrierIdentifier;
383     }
384 
385     /** Gets the policy rules. */
386     @PolicyRule
getPolicyRules()387     public int getPolicyRules() {
388         return mPolicyRules;
389     }
390 
391     /** Returns whether any policy rule exists. */
hasPolicyRules()392     public boolean hasPolicyRules() {
393         return mPolicyRules != 0;
394     }
395 
396     /** Checks whether a certain policy rule exists. */
hasPolicyRule(@olicyRule int policy)397     public boolean hasPolicyRule(@PolicyRule int policy) {
398         return (mPolicyRules & policy) != 0;
399     }
400 
401     @Override
equals(@ullable Object obj)402     public boolean equals(@Nullable Object obj) {
403         if (this == obj) {
404             return true;
405         }
406         if (obj == null || getClass() != obj.getClass()) {
407             return false;
408         }
409 
410         EuiccProfileInfo that = (EuiccProfileInfo) obj;
411         return Objects.equals(mIccid, that.mIccid)
412                 && Objects.equals(mNickname, that.mNickname)
413                 && Objects.equals(mServiceProviderName, that.mServiceProviderName)
414                 && Objects.equals(mProfileName, that.mProfileName)
415                 && mProfileClass == that.mProfileClass
416                 && mState == that.mState
417                 && Objects.equals(mCarrierIdentifier, that.mCarrierIdentifier)
418                 && mPolicyRules == that.mPolicyRules
419                 && Arrays.equals(mAccessRules, that.mAccessRules);
420     }
421 
422     @Override
hashCode()423     public int hashCode() {
424         int result = 1;
425         result = 31 * result + Objects.hashCode(mIccid);
426         result = 31 * result + Objects.hashCode(mNickname);
427         result = 31 * result + Objects.hashCode(mServiceProviderName);
428         result = 31 * result + Objects.hashCode(mProfileName);
429         result = 31 * result + mProfileClass;
430         result = 31 * result + mState;
431         result = 31 * result + Objects.hashCode(mCarrierIdentifier);
432         result = 31 * result + mPolicyRules;
433         result = 31 * result + Arrays.hashCode(mAccessRules);
434         return result;
435     }
436 
437     @NonNull
438     @Override
toString()439     public String toString() {
440         return "EuiccProfileInfo (nickname="
441                 + mNickname
442                 + ", serviceProviderName="
443                 + mServiceProviderName
444                 + ", profileName="
445                 + mProfileName
446                 + ", profileClass="
447                 + mProfileClass
448                 + ", state="
449                 + mState
450                 + ", CarrierIdentifier="
451                 + mCarrierIdentifier
452                 + ", policyRules="
453                 + mPolicyRules
454                 + ", accessRules="
455                 + Arrays.toString(mAccessRules)
456                 + ")";
457     }
458 }
459