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

Commit 3df2f1b3 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Supports Android APIs for the Carrier NB-Satellite Provisioning" into main

parents 9d1ee9be 0408751d
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -424,4 +424,11 @@
    <bool name="config_dropboxmanager_persistent_logging_enabled">false</bool>
    <java-symbol type="bool" name="config_dropboxmanager_persistent_logging_enabled" />

    <!-- Telephony satellite gateway class name for handling carrier roaming to satellite is using ESOS messaging. -->
    <string name="config_satellite_carrier_roaming_esos_provisioned_class" translatable="false"></string>
    <java-symbol type="string" name="config_satellite_carrier_roaming_esos_provisioned_class" />

    <!-- Telephony satellite gateway intent for handling carrier roaming to satellite is using ESOS messaging. -->
    <string name="config_satellite_carrier_roaming_esos_provisioned_intent_action" translatable="false"></string>
    <java-symbol type="string" name="config_satellite_carrier_roaming_esos_provisioned_intent_action" />
</resources>
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024, 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.telephony.satellite;

parcelable ProvisionSubscriberId;
+141 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.telephony.satellite;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;

import com.android.internal.telephony.flags.Flags;

import java.util.Objects;

/**
 * ProvisionSubscriberId
 *
 * Satellite Gateway client will use these subscriber ids to register with satellite gateway service
 * which identify user subscription with unique subscriber ids. These subscriber ids can be any
 * unique value like iccid, imsi or msisdn which is decided based upon carrier requirements.
 *
 * @hide
 */
@FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
public final class ProvisionSubscriberId implements Parcelable {
    /** provision subscriberId */
    @NonNull
    private String mSubscriberId;

    /** carrier id */
    private int mCarrierId;

    /**
     * @hide
     */
    public ProvisionSubscriberId(@NonNull String subscriberId, @NonNull int carrierId) {
        this.mCarrierId = carrierId;
        this.mSubscriberId = subscriberId;
    }

    private ProvisionSubscriberId(Parcel in) {
        readFromParcel(in);
    }

    /**
     * @hide
     */
    @Override
    @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    public void writeToParcel(@NonNull Parcel out, int flags) {
        out.writeString(mSubscriberId);
        out.writeInt(mCarrierId);
    }

    @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    public static final @android.annotation.NonNull Creator<ProvisionSubscriberId> CREATOR =
            new Creator<ProvisionSubscriberId>() {
                @Override
                public ProvisionSubscriberId createFromParcel(Parcel in) {
                    return new ProvisionSubscriberId(in);
                }

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

    /**
     * @hide
     */
    @Override
    @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    public int describeContents() {
        return 0;
    }

    /**
     * @return token.
     * @hide
     */
    @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    public String getSubscriberId() {
        return mSubscriberId;
    }

    /**
     * @return carrierId.
     * @hide
     */
    @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    public int getCarrierId() {
        return mCarrierId;
    }

    @NonNull
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();

        sb.append("SubscriberId:");
        sb.append(mSubscriberId);
        sb.append(",");

        sb.append("CarrierId:");
        sb.append(mCarrierId);
        return sb.toString();
    }

    @Override
    public int hashCode() {
        return Objects.hash(mSubscriberId, mCarrierId);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ProvisionSubscriberId that = (ProvisionSubscriberId) o;
        return mSubscriberId.equals(that.mSubscriberId) && mCarrierId
                == that.mCarrierId;
    }

    private void readFromParcel(Parcel in) {
        mSubscriberId = in.readString();
        mCarrierId = in.readInt();
    }
}
+197 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import java.lang.annotation.RetentionPolicy;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -232,6 +233,29 @@ public final class SatelliteManager {

    public static final String KEY_NTN_SIGNAL_STRENGTH = "ntn_signal_strength";

    /**
     * Bundle key to get the response from
     * {@link #requestProvisionSubscriberIds(Executor, OutcomeReceiver)}.
     * @hide
     */
    public static final String KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN =
            "request_provision_subscriber_id";

    /**
     * Bundle key to get the response from
     * {@link #requestIsProvisioned(String, Executor, OutcomeReceiver)}.
     * @hide
     */
    public static final String KEY_IS_SATELLITE_PROVISIONED = "request_is_satellite_provisioned";

    /**
     * Bundle key to get the response from
     * {@link #provisionSatellite(List, Executor, OutcomeReceiver)}.
     * @hide
     */
    public static final String KEY_PROVISION_SATELLITE_TOKENS = "provision_satellite";


    /**
     * The request was successfully processed.
     */
@@ -2580,6 +2604,179 @@ public final class SatelliteManager {
        }
    }

    /**
     * Request to get list of prioritized satellite subscriber ids to be used for provision.
     *
     * Satellite Gateway client will use these subscriber ids to register with satellite gateway
     * service which identify user subscription with unique subscriber ids. These subscriber ids
     * can be any unique value like iccid, imsi or msisdn which is decided based upon carrier
     * requirements.
     *
     * @param executor The executor on which the callback will be called.
     * @param callback The callback object to which the result will be delivered.
     * If successful, the callback returns a list of tokens sorted in ascending priority order index
     * 0 has the highest priority. Otherwise, it returns an error with a SatelliteException.
     *
     * @throws SecurityException if the caller doesn't have required permission.
     * @hide
     */
    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
    @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    public void requestProvisionSubscriberIds(@NonNull @CallbackExecutor Executor executor,
            @NonNull OutcomeReceiver<List<ProvisionSubscriberId>, SatelliteException> callback) {
        Objects.requireNonNull(executor);
        Objects.requireNonNull(callback);

        try {
            ITelephony telephony = getITelephony();
            if (telephony != null) {
                ResultReceiver receiver = new ResultReceiver(null) {
                    @Override
                    protected void onReceiveResult(int resultCode, Bundle resultData) {
                        if (resultCode == SATELLITE_RESULT_SUCCESS) {
                            if (resultData.containsKey(KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN)) {
                                List<ProvisionSubscriberId> list =
                                        Collections.singletonList(resultData.getParcelable(
                                                KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN,
                                                ProvisionSubscriberId.class));
                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
                                        callback.onResult(list)));
                            } else {
                                loge("KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN does not exist.");
                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
                                        callback.onError(new SatelliteException(
                                                SATELLITE_RESULT_REQUEST_FAILED))));
                            }
                        } else {
                            executor.execute(() -> Binder.withCleanCallingIdentity(() ->
                                    callback.onError(new SatelliteException(resultCode))));
                        }
                    }
                };
                telephony.requestProvisionSubscriberIds(receiver);
            } else {
                loge("requestProvisionSubscriberIds() invalid telephony");
                executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError(
                        new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE))));
            }
        } catch (RemoteException ex) {
            loge("requestProvisionSubscriberIds() RemoteException: " + ex);
            executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError(
                    new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE))));
        }
    }

    /**
     * Request to get provisioned status for given a satellite subscriber id.
     *
     * @param satelliteSubscriberId Satellite subscriber id requiring provisioned status check.
     * @param executor The executor on which the callback will be called.
     * @param callback callback.
     *
     * @throws SecurityException if the caller doesn't have required permission.
     * @hide
     */
    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
    @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    public void requestIsProvisioned(@NonNull String satelliteSubscriberId,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
        Objects.requireNonNull(satelliteSubscriberId);
        Objects.requireNonNull(executor);
        Objects.requireNonNull(callback);

        try {
            ITelephony telephony = getITelephony();
            if (telephony != null) {
                ResultReceiver receiver = new ResultReceiver(null) {
                    @Override
                    protected void onReceiveResult(int resultCode, Bundle resultData) {
                        if (resultCode == SATELLITE_RESULT_SUCCESS) {
                            if (resultData.containsKey(KEY_SATELLITE_PROVISIONED)) {
                                boolean isIsProvisioned =
                                        resultData.getBoolean(KEY_SATELLITE_PROVISIONED);
                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
                                        callback.onResult(isIsProvisioned)));
                            } else {
                                loge("KEY_REQUEST_PROVISION_TOKENS does not exist.");
                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
                                        callback.onError(new SatelliteException(
                                                SATELLITE_RESULT_REQUEST_FAILED))));
                            }
                        } else {
                            executor.execute(() -> Binder.withCleanCallingIdentity(() ->
                                    callback.onError(new SatelliteException(resultCode))));
                        }
                    }
                };
                telephony.requestIsProvisioned(satelliteSubscriberId, receiver);
            } else {
                loge("requestIsSatelliteProvisioned() invalid telephony");
                executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError(
                        new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE))));
            }
        } catch (RemoteException ex) {
            loge("requestIsSatelliteProvisioned() RemoteException: " + ex);
            executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError(
                    new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE))));
        }
    }

    /**
     * Deliver the list of provisioned satellite subscriber ids.
     *
     * @param list List of ProvisionSubscriberId.
     * @param executor The executor on which the callback will be called.
     * @param callback The callback object to which the result will be delivered.
     *
     * @throws SecurityException if the caller doesn't have required permission.
     * @hide
     */
    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
    @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    public void provisionSatellite(@NonNull List<ProvisionSubscriberId> list,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
        Objects.requireNonNull(executor);
        Objects.requireNonNull(callback);

        try {
            ITelephony telephony = getITelephony();
            if (telephony != null) {
                ResultReceiver receiver = new ResultReceiver(null) {
                    @Override
                    protected void onReceiveResult(int resultCode, Bundle resultData) {
                        if (resultCode == SATELLITE_RESULT_SUCCESS) {
                            if (resultData.containsKey(KEY_PROVISION_SATELLITE_TOKENS)) {
                                boolean isUpdated =
                                        resultData.getBoolean(KEY_PROVISION_SATELLITE_TOKENS);
                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
                                        callback.onResult(isUpdated)));
                            } else {
                                loge("KEY_REQUEST_PROVISION_TOKENS does not exist.");
                                executor.execute(() -> Binder.withCleanCallingIdentity(() ->
                                        callback.onError(new SatelliteException(
                                                SATELLITE_RESULT_REQUEST_FAILED))));
                            }
                        } else {
                            executor.execute(() -> Binder.withCleanCallingIdentity(() ->
                                    callback.onError(new SatelliteException(resultCode))));
                        }
                    }
                };
                telephony.provisionSatellite(list, receiver);
            } else {
                loge("provisionSatellite() invalid telephony");
                executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError(
                        new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE))));
            }
        } catch (RemoteException ex) {
            loge("provisionSatellite() RemoteException: " + ex);
            executor.execute(() -> Binder.withCleanCallingIdentity(() -> callback.onError(
                    new SatelliteException(SATELLITE_RESULT_ILLEGAL_STATE))));
        }
    }

    @Nullable
    private static ITelephony getITelephony() {
        ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.telephony.satellite.stub;

/**
 * {@hide}
 */
parcelable ProvisionSubscriberId {
    /** provision subscriberId */
    String subscriberId;

    /** carrier id */
    int mCarrierId;
}
Loading