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