Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d02731ff authored by Jeff Davidson's avatar Jeff Davidson
Browse files

Define APIs for listing embedded subscriptions.

Two new APIs will list all embedded subscriptions along with any
active ones. One API requires the ability to read phone state and
returns all subscriptions. The other requires no special permissions
but will only return those subscriptions which the caller may manage
according to their metadata.

A list result from the LPA includes whether the current eUICC is
removable. If true, subscriptions in the list are considered
transient and always removed upon the next list update (i.e. SIM card
state change) unless that update includes the subscription. Otherwise,
they will be retained across future list operations for which the
current eUICC is removable. This allows callers to retain knowledge
about available embedded subscriptions on an inactive but still
accessible eUICC, as long as that eUICC is permanent.

The LPA may request a refresh of the list at any time; this is
intended to be used of the list or metadata is updated through a
non-API operation, e.g. a server-initiated metadata update. For
operations driven through a platform API, the list will be refreshed
automatically.

Bug: 33075886
Test: TreeHugger
Change-Id: I1887cbca835c304b9eb285fd972c7c8eaffa6e1d
parent 316a22bd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -287,6 +287,7 @@ LOCAL_SRC_FILES += \
	core/java/android/service/euicc/IEuiccService.aidl \
	core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl \
	core/java/android/service/euicc/IGetEidCallback.aidl \
	core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl \
	core/java/android/service/gatekeeper/IGateKeeperService.aidl \
	core/java/android/service/notification/INotificationListener.aidl \
	core/java/android/service/notification/IStatusBarNotificationHolder.aidl \
@@ -754,6 +755,7 @@ aidl_files := \
	frameworks/base/core/java/android/service/carrier/MessagePdu.aidl \
	frameworks/base/core/java/android/service/euicc/DownloadResult.aidl \
	frameworks/base/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.aidl \
	frameworks/base/core/java/android/service/euicc/GetEuiccProfileInfoListResult.aidl \
	frameworks/base/core/java/android/service/notification/Adjustment.aidl \
	frameworks/base/core/java/android/service/notification/Condition.aidl \
	frameworks/base/core/java/android/service/notification/SnoozeCriterion.aidl \
+84 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.service.euicc;

import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.UiccAccessRule;
import android.text.TextUtils;

/**
 * Information about an embedded profile (subscription) on an eUICC.
 *
 * @hide
 *
 * TODO(b/35851809): Make this a SystemApi.
 */
public final class EuiccProfileInfo implements Parcelable {

    /** The iccid of the subscription. */
    public final String iccid;

    /**
     * Optional access rules defining which apps can manage this subscription. If unset, only the
     * platform can manage it.
     */
    public final @Nullable UiccAccessRule[] accessRules;

    /** An optional nickname for the subscription. */
    public final @Nullable String nickname;

    public static final Creator<EuiccProfileInfo> CREATOR = new Creator<EuiccProfileInfo>() {
        @Override
        public EuiccProfileInfo createFromParcel(Parcel in) {
            return new EuiccProfileInfo(in);
        }

        @Override
        public EuiccProfileInfo[] newArray(int size) {
            return new EuiccProfileInfo[size];
        }
    };

    public EuiccProfileInfo(String iccid, @Nullable UiccAccessRule[] accessRules,
            @Nullable String nickname) {
        if (!TextUtils.isDigitsOnly(iccid)) {
            throw new IllegalArgumentException("iccid contains invalid characters: " + iccid);
        }
        this.iccid = iccid;
        this.accessRules = accessRules;
        this.nickname = nickname;
    }

    private EuiccProfileInfo(Parcel in) {
        iccid = in.readString();
        accessRules = in.createTypedArray(UiccAccessRule.CREATOR);
        nickname = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(iccid);
        dest.writeTypedArray(accessRules, flags);
        dest.writeString(nickname);
    }

    @Override
    public int describeContents() {
        return 0;
    }
}
+22 −0
Original line number Diff line number Diff line
@@ -164,6 +164,17 @@ public abstract class EuiccService extends Service {
            DownloadableSubscription subscription, boolean switchAfterDownload,
            boolean forceDeactivateSim);

    /**
     * Return a list of all @link EuiccProfileInfo}s.
     *
     * @param slotId ID of the SIM slot to use when starting the download. This is currently not
     *     populated but is here to future-proof the APIs.
     * @return The result of the operation.
     * @see android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList
     * @see android.telephony.SubscriptionManager#getAccessibleSubscriptionInfoList
     */
    public abstract GetEuiccProfileInfoListResult onGetEuiccProfileInfoList(int slotId);

    /**
     * Wrapper around IEuiccService that forwards calls to implementations of {@link EuiccService}.
     */
@@ -205,5 +216,16 @@ public abstract class EuiccService extends Service {
                // Can't communicate with the phone process; ignore.
            }
        }

        @Override
        public void getEuiccProfileInfoList(int slotId, IGetEuiccProfileInfoListCallback callback) {
            GetEuiccProfileInfoListResult result =
                    EuiccService.this.onGetEuiccProfileInfoList(slotId);
            try {
                callback.onComplete(result);
            } catch (RemoteException e) {
                // Can't communicate with the phone process; ignore.
            }
        }
    }
}
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.service.euicc;

parcelable GetEuiccProfileInfoListResult;
+128 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.service.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;

/**
 * Result of a {@link EuiccService#onGetEuiccProfileInfoList} operation.
 * @hide
 *
 * TODO(b/35851809): Make this a SystemApi.
 */
public final class GetEuiccProfileInfoListResult implements Parcelable {

    public static final Creator<GetEuiccProfileInfoListResult> CREATOR =
            new Creator<GetEuiccProfileInfoListResult>() {
        @Override
        public GetEuiccProfileInfoListResult createFromParcel(Parcel in) {
            return new GetEuiccProfileInfoListResult(in);
        }

        @Override
        public GetEuiccProfileInfoListResult[] newArray(int size) {
            return new GetEuiccProfileInfoListResult[size];
        }
    };

    /** @hide */
    @IntDef({
            RESULT_OK,
            RESULT_GENERIC_ERROR,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ResultCode {}

    public static final int RESULT_OK = 0;
    public static final int RESULT_GENERIC_ERROR = 1;

    /** Result of the operation - one of the RESULT_* constants. */
    public final @ResultCode int result;

    /** Implementation-defined detailed error code in case of a failure not covered here. */
    public final int detailedCode;

    /** The profile list (only upon success). */
    @Nullable
    public final EuiccProfileInfo[] profiles;

    /** Whether the eUICC is removable. */
    public final boolean isRemovable;

    private GetEuiccProfileInfoListResult(int result, int detailedCode, EuiccProfileInfo[] profiles,
            boolean isRemovable) {
        this.result = result;
        this.detailedCode = detailedCode;
        this.profiles = profiles;
        this.isRemovable = isRemovable;
    }

    private GetEuiccProfileInfoListResult(Parcel in) {
        this.result = in.readInt();
        this.detailedCode = in.readInt();
        this.profiles = in.createTypedArray(EuiccProfileInfo.CREATOR);
        this.isRemovable = in.readBoolean();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(result);
        dest.writeInt(detailedCode);
        dest.writeTypedArray(profiles, flags);
        dest.writeBoolean(isRemovable);
    }

    /**
     * Return a result indicating that the listing was successful.
     *
     * @param profiles the list of profiles
     * @param isRemovable whether the eUICC in this slot is removable. If true, the profiles
     *     returned here will only be considered accessible as long as this eUICC is present.
     *     Otherwise, they will remain accessible until the next time a response with isRemovable
     *     set to false is returned.
     */
    public static GetEuiccProfileInfoListResult success(
            EuiccProfileInfo[] profiles, boolean isRemovable) {
        return new GetEuiccProfileInfoListResult(
                RESULT_OK, 0 /* detailedCode */, profiles, isRemovable);
    }

    /**
     * Return a result indicating that an error occurred for which no other more specific error
     * code has been defined.
     *
     * @param detailedCode an implementation-defined detailed error code for debugging purposes.
     * @param isRemovable whether the eUICC in this slot is removable. If true, only removable
     *     profiles will be made inaccessible. Otherwise, all embedded profiles will be
     *     considered inaccessible.
     */
    public static GetEuiccProfileInfoListResult genericError(
            int detailedCode, boolean isRemovable) {
        return new GetEuiccProfileInfoListResult(
                RESULT_GENERIC_ERROR, detailedCode, null /* profiles */, isRemovable);
    }

    @Override
    public int describeContents() {
        return 0;
    }
}
Loading