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

Commit cc1097cc authored by Thomas Nguyen's avatar Thomas Nguyen Committed by Android (Google) Code Review
Browse files

Merge "Add deprovisionSatellite" into main

parents 937f7e25 63fb3ac4
Loading
Loading
Loading
Loading
+132 −29
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -200,7 +201,8 @@ public class SatelliteController extends Handler {
    public static final int TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS = 2;
    /** This is used by CTS to override demo pointing not aligned duration. */
    public static final int TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS = 3;

    /** This is used by CTS to override evaluate esos profiles prioritization duration. */
    public static final int TIMEOUT_TYPE_EVALUATE_ESOS_PROFILES_PRIORITIZATION_DURATION_MILLIS = 4;
    /** Key used to read/write OEM-enabled satellite provision status in shared preferences. */
    private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY =
            "oem_enabled_satellite_provision_status_key";
@@ -521,7 +523,10 @@ public class SatelliteController extends Handler {
    // key : priority, low value is high, value : List<SubscriptionInfo>
    @GuardedBy("mSatelliteTokenProvisionedLock")
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    protected Map<Integer, List<SubscriptionInfo>> mSubsInfoListPerPriority = new HashMap<>();
    protected TreeMap<Integer, List<SubscriptionInfo>> mSubsInfoListPerPriority = new TreeMap<>();
    // The ID of the satellite subscription that has highest priority and is provisioned.
    @GuardedBy("mSatelliteTokenProvisionedLock")
    private int mSelectedSatelliteSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    // The last ICC ID that framework configured to modem.
    @GuardedBy("mSatelliteTokenProvisionedLock")
    private String mLastConfiguredIccId;
@@ -530,6 +535,7 @@ public class SatelliteController extends Handler {
    private long mWaitTimeForSatelliteEnablingResponse;
    private long mDemoPointingAlignedDurationMillis;
    private long mDemoPointingNotAlignedDurationMillis;
    private long mEvaluateEsosProfilesPrioritizationDurationMillis;
    private final Object mLock = new Object();
    @GuardedBy("mLock")
    private long mLastEmergencyCallTime;
@@ -720,8 +726,10 @@ public class SatelliteController extends Handler {
                getDemoPointingNotAlignedDurationMillisFromResources();
        mSatelliteEmergencyModeDurationMillis =
                getSatelliteEmergencyModeDurationFromOverlayConfig(context);
        mEvaluateEsosProfilesPrioritizationDurationMillis =
                getEvaluateEsosProfilesPrioritizationDurationMillis();
        sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
                /* delayMillis= */ TimeUnit.MINUTES.toMillis(1));
                mEvaluateEsosProfilesPrioritizationDurationMillis);

        SubscriptionManager subscriptionManager = mContext.getSystemService(
                SubscriptionManager.class);
@@ -1718,13 +1726,9 @@ public class SatelliteController extends Handler {
                RequestProvisionSatelliteArgument argument =
                        (RequestProvisionSatelliteArgument) request.argument;
                onCompleted = obtainMessage(EVENT_UPDATE_PROVISION_SATELLITE_TOKEN_DONE, request);
                // only pass to index 0.
                // TODO: Select the subscription with highest priority and set it to mSatelliteSubId
                int subId = -1;
                synchronized (mSatelliteTokenProvisionedLock) {
                    subId = mSubscriberIdPerSub.getOrDefault(
                            argument.mSatelliteSubscriberInfoList.get(0).getSubscriberId(), -1);
                }
                boolean provisionChanged = updateSatelliteSubscriptionProvisionState(
                        argument.mSatelliteSubscriberInfoList, argument.mProvisioned);
                int subId = getSelectedSatelliteSubId();
                setSatellitePhone(subId);
                String iccId = mSubscriptionManagerService.getSubscriptionInfo(subId).getIccId();
                argument.setIccId(iccId);
@@ -1738,13 +1742,16 @@ public class SatelliteController extends Handler {
                        sendResponse = true;
                    }
                }
                handleEventSatelliteSubscriptionProvisionStateChanged(
                        argument.mSatelliteSubscriberInfoList, true);
                if (provisionChanged) {
                    handleEventSatelliteSubscriptionProvisionStateChanged();
                }
                if (sendResponse) {
                    // The response is sent immediately because the ICCID has already been
                    // delivered to the modem.
                    Bundle bundle = new Bundle();
                    bundle.putBoolean(SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS, true);
                    bundle.putBoolean(
                            argument.mProvisioned ? SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS
                                    : SatelliteManager.KEY_DEPROVISION_SATELLITE_TOKENS, true);
                    argument.mResult.send(SATELLITE_RESULT_SUCCESS, bundle);
                }
                break;
@@ -1764,7 +1771,9 @@ public class SatelliteController extends Handler {
                }
                logd("updateSatelliteSubscription result=" + error);
                Bundle bundle = new Bundle();
                bundle.putBoolean(SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS,
                bundle.putBoolean(
                        argument.mProvisioned ? SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS :
                                SatelliteManager.KEY_DEPROVISION_SATELLITE_TOKENS,
                        error == SATELLITE_RESULT_SUCCESS);
                argument.mResult.send(error, bundle);
                break;
@@ -1829,11 +1838,13 @@ public class SatelliteController extends Handler {
        public ResultReceiver mResult;
        public long mRequestId;
        public String mIccId;
        public boolean mProvisioned;

        RequestProvisionSatelliteArgument(List<SatelliteSubscriberInfo> satelliteSubscriberInfoList,
                ResultReceiver result) {
                ResultReceiver result, boolean provisioned) {
            this.mSatelliteSubscriberInfoList = satelliteSubscriberInfoList;
            this.mResult = result;
            this.mProvisioned = provisioned;
            this.mRequestId = sNextSatelliteEnableRequestId.getAndUpdate(
                    n -> ((n + 1) % Long.MAX_VALUE));
        }
@@ -3037,6 +3048,14 @@ public class SatelliteController extends Handler {
            } else {
                mDemoPointingNotAlignedDurationMillis = timeoutMillis;
            }
        } else if (timeoutType
                == TIMEOUT_TYPE_EVALUATE_ESOS_PROFILES_PRIORITIZATION_DURATION_MILLIS) {
            if (reset) {
                mEvaluateEsosProfilesPrioritizationDurationMillis =
                        getEvaluateEsosProfilesPrioritizationDurationMillis();
            } else {
                mEvaluateEsosProfilesPrioritizationDurationMillis = timeoutMillis;
            }
        } else {
            plogw("Invalid timeoutType=" + timeoutType);
            return false;
@@ -3968,6 +3987,7 @@ public class SatelliteController extends Handler {
                    });
        }
        registerForSatelliteSupportedStateChanged();
        selectBindingSatelliteSubscription();
    }

    private void updateSatelliteEnabledState(boolean enabled, String caller) {
@@ -4077,10 +4097,10 @@ public class SatelliteController extends Handler {
        });
    }

    private void handleEventSatelliteSubscriptionProvisionStateChanged(
            List<SatelliteSubscriberInfo> newList, boolean provisioned) {
        logd("handleEventSatelliteSubscriptionProvisionStateChanged: newList=" + newList
                + " , provisioned=" + provisioned);
    private boolean updateSatelliteSubscriptionProvisionState(List<SatelliteSubscriberInfo> newList,
            boolean provisioned) {
        logd("updateSatelliteSubscriptionProvisionState: List=" + newList + " , provisioned="
                + provisioned);
        boolean provisionChanged = false;
        synchronized (mSatelliteTokenProvisionedLock) {
            for (SatelliteSubscriberInfo subscriberInfo : newList) {
@@ -4095,19 +4115,18 @@ public class SatelliteController extends Handler {
                try {
                    mSubscriptionManagerService.setIsSatelliteProvisionedForNonIpDatagram(subId,
                            provisioned);
                    plogd("handleEventSatelliteSubscriptionProvisionStateChanged: set Provision "
                            + "state to db subId=" + subId);
                    plogd("updateSatelliteSubscriptionProvisionState: set Provision state to db "
                            + "subId=" + subId);
                } catch (IllegalArgumentException | SecurityException ex) {
                    ploge("setIsSatelliteProvisionedForNonIpDatagram: subId=" + subId + ", ex="
                            + ex);
                }
            }
        }
        if (!provisionChanged) {
            logd("handleEventSatelliteSubscriptionProvisionStateChanged: provision state nothing "
                    + "changed.");
            return;
        return provisionChanged;
    }

    private void handleEventSatelliteSubscriptionProvisionStateChanged() {
        List<SatelliteSubscriberProvisionStatus> informList =
                getPrioritizedSatelliteSubscriberProvisionStatusList();
        plogd("handleEventSatelliteSubscriptionProvisionStateChanged: " + informList);
@@ -4118,6 +4137,7 @@ public class SatelliteController extends Handler {
                    && mProvisionedSubscriberId.containsValue(Boolean.TRUE);
            mControllerMetricsStats.setIsProvisioned(isProvisioned);
        }
        selectBindingSatelliteSubscription();
        handleStateChangedForCarrierRoamingNtnEligibility();
    }

@@ -4480,6 +4500,7 @@ public class SatelliteController extends Handler {
            updateSatelliteEnabledState(
                    false, "moveSatelliteToOffStateAndCleanUpResources");
        }
        selectBindingSatelliteSubscription();
    }

    private void setDemoModeEnabled(boolean enabled) {
@@ -6180,6 +6201,10 @@ public class SatelliteController extends Handler {
        return TimeUnit.SECONDS.toMillis(duration);
    }

    private long getEvaluateEsosProfilesPrioritizationDurationMillis() {
        return TimeUnit.MINUTES.toMillis(1);
    }

    /**
     * Calculate priority
     * 1. Active eSOS profiles are higher priority than inactive eSOS profiles.
@@ -6197,7 +6222,7 @@ public class SatelliteController extends Handler {
        List<SubscriptionInfo> allSubInfos = mSubscriptionManagerService.getAllSubInfoList(
                mContext.getOpPackageName(), mContext.getAttributionTag());
        // Key : priority - lower value has higher priority; Value : List<SubscriptionInfo>
        Map<Integer, List<SubscriptionInfo>> newSubsInfoListPerPriority = new HashMap<>();
        TreeMap<Integer, List<SubscriptionInfo>> newSubsInfoListPerPriority = new TreeMap<>();
        synchronized (mSatelliteTokenProvisionedLock) {
            for (SubscriptionInfo info : allSubInfos) {
                int subId = info.getSubscriptionId();
@@ -6249,6 +6274,7 @@ public class SatelliteController extends Handler {
                mSubsInfoListPerPriority = newSubsInfoListPerPriority;
                sendBroadCastForProvisionedESOSSubs();
                mHasSentBroadcast = true;
                selectBindingSatelliteSubscription();
            }
        }
    }
@@ -6408,6 +6434,57 @@ public class SatelliteController extends Handler {
        return list;
    }

    private int getSelectedSatelliteSubId() {
        synchronized (mSatelliteTokenProvisionedLock) {
            return mSelectedSatelliteSubId;
        }
    }

    private void selectBindingSatelliteSubscription() {
        if (isSatelliteEnabled() || isSatelliteBeingEnabled()) {
            plogd("selectBindingSatelliteSubscription: satellite subscription will be selected "
                    + "once the satellite session ends");
            return;
        }

        int selectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        List<SatelliteSubscriberProvisionStatus> satelliteSubscribers =
                getPrioritizedSatelliteSubscriberProvisionStatusList();
        for (SatelliteSubscriberProvisionStatus status : satelliteSubscribers) {
            // TODO: need to check if satellite is allowed at current location for the subscription
            int subId = getSubIdFromSubscriberId(
                    status.getSatelliteSubscriberInfo().getSubscriberId());
            if (status.getProvisionStatus() && isActiveSubId(subId)) {
                selectedSubId = subId;
                break;
            }
        }

        synchronized (mSatelliteTokenProvisionedLock) {
            if (selectedSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
                    && isSatelliteSupportedViaOem()) {
                mSelectedSatelliteSubId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
            }
            if (selectedSubId != mSelectedSatelliteSubId) {
                mSelectedSatelliteSubId = selectedSubId;
                setSatellitePhone(selectedSubId);
            }
        }
        plogd("selectBindingSatelliteSubscription: SelectedSatelliteSubId="
                + mSelectedSatelliteSubId);
    }

    private int getSubIdFromSubscriberId(String subscriberId) {
        synchronized (mSatelliteTokenProvisionedLock) {
            return mSubscriberIdPerSub.getOrDefault(subscriberId,
                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
        }
    }

    private boolean isActiveSubId(int subId) {
        return mSubscriptionManagerService.getSubscriptionInfo(subId).isActive();
    }

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    protected boolean isSubscriptionProvisioned(int subId) {
        plogd("isSubscriptionProvisioned: subId=" + subId);
@@ -6438,19 +6515,45 @@ public class SatelliteController extends Handler {
            @NonNull ResultReceiver result) {
        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
            result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
            logd("provisionSatellite: carrierRoamingNbIotNtn not support");
            return;
        }
        if (list.size() == 0) {
        if (list.isEmpty()) {
            result.send(SATELLITE_RESULT_INVALID_ARGUMENTS, null);
            logd("provisionSatellite: SatelliteSubscriberInfo list is empty");
            return;
        }

        logd("provisionSatellite:" + list);
        RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list,
                result);
                result, true);
        sendRequestAsync(CMD_UPDATE_PROVISION_SATELLITE_TOKEN, request, null);
    }

    /**
     * Deliver the list of deprovisioned satellite subscriber ids.
     *
     * @param list List of deprovisioned satellite subscriber ids.
     * @param result The result receiver that returns whether deliver success or fail.
     */
    public void deprovisionSatellite(@NonNull List<SatelliteSubscriberInfo> list,
            @NonNull ResultReceiver result) {
        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
            result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
            logd("deprovisionSatellite: carrierRoamingNbIotNtn not support");
            return;
        }
        if (list.isEmpty()) {
            result.send(SATELLITE_RESULT_INVALID_ARGUMENTS, null);
            logd("deprovisionSatellite: SatelliteSubscriberInfo list is empty");
            return;
        }

        logd("deprovisionSatellite:" + list);
        RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list,
                result, false);
        sendRequestAsync(CMD_UPDATE_PROVISION_SATELLITE_TOKEN, request, null);
    }

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    protected void setSatellitePhone(int subId) {
+85 −5
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_POOR;
import static android.telephony.satellite.SatelliteManager.KEY_DEMO_MODE_ENABLED;
import static android.telephony.satellite.SatelliteManager.KEY_DEPROVISION_SATELLITE_TOKENS;
import static android.telephony.satellite.SatelliteManager.KEY_EMERGENCY_MODE_ENABLED;
import static android.telephony.satellite.SatelliteManager.KEY_NTN_SIGNAL_STRENGTH;
import static android.telephony.satellite.SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS;
@@ -4346,7 +4347,6 @@ public class SatelliteControllerTest extends TelephonyTest {
        assertTrue(mProvisionState);
    }


    @Test
    public void testRegisterForSatelliteSubscriptionProvisionStateChanged() throws Exception {
        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
@@ -4405,8 +4405,6 @@ public class SatelliteControllerTest extends TelephonyTest {
        inputList.add(list.get(1));
        verifyProvisionSatellite(inputList);

        verify(mMockSatelliteModemInterface, times(2)).updateSatelliteSubscription(anyString(),
                any());
        assertTrue(waitForForEvents(
                semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
        assertTrue(resultArray[1].getProvisionStatus());
@@ -4416,10 +4414,92 @@ public class SatelliteControllerTest extends TelephonyTest {
        // requested, and verify that onSatelliteSubscriptionProvisionStateChanged is not called.
        verifyProvisionSatellite(inputList);

        verify(mMockSatelliteModemInterface, times(2)).updateSatelliteSubscription(anyString(),
                any());
        assertFalse(waitForForEvents(
                semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));

        // Request deprovision for subscriberID 2, verify that subscriberID 2 is set to
        // deprovision and that subscriberID 1 is set to provision.
        verifyDeprovisionSatellite(inputList);
        assertTrue(waitForForEvents(
                semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
        assertFalse(resultArray[1].getProvisionStatus());
        assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
        assertTrue(resultArray[0].getProvisionStatus());
        assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());

        // Request deprovision for subscriberID 1, verify that subscriberID 1 is set to deprovision.
        inputList = new ArrayList<>();
        inputList.add(list.get(0));
        verifyDeprovisionSatellite(inputList);
        assertTrue(waitForForEvents(
                semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
        assertFalse(resultArray[1].getProvisionStatus());
        assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
        assertFalse(resultArray[0].getProvisionStatus());
        assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());

        // Request provision for subscriberID 2, verify that subscriberID 2 is set to provision.
        inputList = new ArrayList<>();
        inputList.add(list.get(1));
        verifyProvisionSatellite(inputList);

        assertTrue(waitForForEvents(
                semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
        assertTrue(resultArray[1].getProvisionStatus());
        assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
        assertFalse(resultArray[0].getProvisionStatus());
        assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
    }

    private boolean mDeprovisionDone = false;
    private int mDeprovisionSateResultCode = -1;
    private Semaphore mDeprovisionSateSemaphore = new Semaphore(0);
    private ResultReceiver mDeprovisionSatelliteReceiver = new ResultReceiver(null) {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            mDeprovisionSateResultCode = resultCode;
            logd("DeprovisionSatelliteReceiver: resultCode=" + resultCode);
            if (resultCode == SATELLITE_RESULT_SUCCESS) {
                if (resultData.containsKey(KEY_DEPROVISION_SATELLITE_TOKENS)) {
                    mDeprovisionDone = resultData.getBoolean(KEY_DEPROVISION_SATELLITE_TOKENS);
                    logd("DeprovisionSatelliteReceiver: deprovision=" + mDeprovisionDone);
                } else {
                    loge("KEY_DEPROVISION_SATELLITE_TOKENS does not exist.");
                    mDeprovisionDone = false;
                }
            } else {
                mDeprovisionDone = false;
            }
            try {
                mDeprovisionSateSemaphore.release();
            } catch (Exception ex) {
                loge("DeprovisionSatelliteReceiver: Got exception in releasing semaphore " + ex);
            }
        }
    };

    @Test
    public void testDeprovisionSatellite() throws Exception {
        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
        verifyRequestSatelliteSubscriberProvisionStatus();
        List<SatelliteSubscriberInfo> inputList = getExpectedSatelliteSubscriberInfoList();
        verifyProvisionSatellite(inputList);
        verifyDeprovisionSatellite(inputList);
    }

    private void verifyDeprovisionSatellite(List<SatelliteSubscriberInfo> inputList) {
        doAnswer(invocation -> {
            Message message = (Message) invocation.getArguments()[1];
            AsyncResult.forMessage(message, null, new SatelliteException(SATELLITE_RESULT_SUCCESS));
            message.sendToTarget();
            return null;
        }).when(mMockSatelliteModemInterface).updateSatelliteSubscription(anyString(), any());

        mSatelliteControllerUT.deprovisionSatellite(inputList, mDeprovisionSatelliteReceiver);
        processAllMessages();
        assertEquals(SATELLITE_RESULT_SUCCESS, mDeprovisionSateResultCode);
        assertTrue(mDeprovisionDone);
    }

    private void setSatelliteSubscriberTesting() throws Exception {