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