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

Commit d5669202 authored by Gil Cukierman's avatar Gil Cukierman Committed by Android (Google) Code Review
Browse files

Merge "Handle de-activated and new subscription Ids" into main

parents f567fef6 5313e940
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -3679,6 +3679,7 @@ public class GsmCdmaPhone extends Phone {
            case EVENT_SUBSCRIPTIONS_CHANGED:
                logd("EVENT_SUBSCRIPTIONS_CHANGED");
                updateUsageSetting();
                updateNullCipherNotifier();
                break;
            case EVENT_SET_NULL_CIPHER_AND_INTEGRITY_DONE:
                logd("EVENT_SET_NULL_CIPHER_AND_INTEGRITY_DONE");
@@ -3779,7 +3780,8 @@ public class GsmCdmaPhone extends Phone {
                        && mNullCipherNotifier != null) {
                    ar = (AsyncResult) msg.obj;
                    SecurityAlgorithmUpdate update = (SecurityAlgorithmUpdate) ar.result;
                    mNullCipherNotifier.onSecurityAlgorithmUpdate(mContext, getSubId(), update);
                    mNullCipherNotifier.onSecurityAlgorithmUpdate(mContext, getPhoneId(),
                            getSubId(), update);
                }
                break;

@@ -5454,6 +5456,25 @@ public class GsmCdmaPhone extends Phone {
                obtainMessage(EVENT_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED_DONE));
    }

    /**
     * Update the phoneId -> subId mapping of the null cipher notifier.
     */
    @VisibleForTesting
    public void updateNullCipherNotifier() {
        if (!mFeatureFlags.enableModemCipherTransparencyUnsolEvents()) {
            return;
        }

        SubscriptionInfoInternal subInfo = mSubscriptionManagerService
                .getSubscriptionInfoInternal(getSubId());
        boolean active = false;
        if (subInfo != null) {
            active = subInfo.isActive();
        }
        mNullCipherNotifier.setSubscriptionMapping(mContext, getPhoneId(),
                active ? subInfo.getSubscriptionId() : -1);
    }

    @Override
    public boolean isNullCipherAndIntegritySupported() {
        return mIsNullCipherAndIntegritySupported;
+7 −0
Original line number Diff line number Diff line
@@ -122,6 +122,13 @@ public class CellularNetworkSecuritySafetySource {
        updateSafetyCenter(context);
    }

    /**
     * Clears issue state for the identified subscription
     */
    public synchronized  void clearNullCipherState(Context context, int subId) {
        mNullCipherStates.remove(subId);
        updateSafetyCenter(context);
    }
    /**
     * Enables or disables the identifier disclosure issue and clears any current issues if the
     * enable state is changed.
+58 −10
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ public class NullCipherNotifier {

    private final CellularNetworkSecuritySafetySource mSafetySource;
    private final HashMap<Integer, SubscriptionState> mSubscriptionState = new HashMap<>();
    private final HashMap<Integer, Integer> mActiveSubscriptions = new HashMap<>();

    private final Object mEnabledLock = new Object();
    @GuardedBy("mEnabledLock")
@@ -90,15 +91,22 @@ public class NullCipherNotifier {
     * Adds a security algorithm update. If appropriate, this will trigger a user notification.
     */
    public void onSecurityAlgorithmUpdate(
            Context context, int subId, SecurityAlgorithmUpdate update) {
            Context context, int phoneId, int subId, SecurityAlgorithmUpdate update) {
        Rlog.d(TAG, "Security algorithm update: subId = " + subId + " " + update);

        if (shouldIgnoreUpdate(update)) {
            return;
        }

        if (!isEnabled()) {
            Rlog.i(TAG, "Ignoring onSecurityAlgorithmUpdate. Notifier is disabled.");
            return;
        }

        try {
            mSerializedWorkQueue.execute(() -> {
                try {
                    maybeUpdateSubscriptionMapping(context, phoneId, subId);
                    SubscriptionState subState = mSubscriptionState.get(subId);
                    if (subState == null) {
                        subState = new SubscriptionState();
@@ -108,12 +116,52 @@ public class NullCipherNotifier {
                    @CellularNetworkSecuritySafetySource.NullCipherState int nullCipherState =
                            subState.update(update);
                    mSafetySource.setNullCipherState(context, subId, nullCipherState);
                } catch (Throwable t) {
                    Rlog.e(TAG, "Failed to execute onSecurityAlgorithmUpdate " + t.getMessage());
                }
            });
        } catch (RejectedExecutionException e) {
            Rlog.e(TAG, "Failed to schedule onEnableNotifier: " + e.getMessage());
            Rlog.e(TAG, "Failed to schedule onSecurityAlgorithmUpdate: " + e.getMessage());
        }
    }

    /**
     * Set or update the current phoneId to subId mapping. When a new subId is mapped to a phoneId,
     * we update the safety source to clear state of the old subId.
     */
    public void setSubscriptionMapping(Context context, int phoneId, int subId) {

        if (!isEnabled()) {
            Rlog.i(TAG, "Ignoring setSubscriptionMapping. Notifier is disabled.");
        }

        try {
            mSerializedWorkQueue.execute(() -> {
                try {
                    maybeUpdateSubscriptionMapping(context, phoneId, subId);
                } catch (Throwable t) {
                    Rlog.e(TAG, "Failed to update subId mapping. phoneId: " + phoneId + " subId: "
                            + subId + ". " + t.getMessage());
                }
            });

        } catch (RejectedExecutionException e) {
            Rlog.e(TAG, "Failed to schedule setSubscriptionMapping: " + e.getMessage());
        }
    }

    private void maybeUpdateSubscriptionMapping(Context context, int phoneId, int subId) {
        final Integer oldSubId = mActiveSubscriptions.put(phoneId, subId);
        if (oldSubId == null || oldSubId == subId) {
            return;
        }

        // Our subId was updated for this phone, we should clear this subId's state.
        mSubscriptionState.remove(oldSubId);
        mSafetySource.clearNullCipherState(context, oldSubId);
    }


    /**
     * Enables null cipher notification; {@code onSecurityAlgorithmUpdate} will start handling
     * security algorithm updates and send notifications to the user when required.
+57 −1
Original line number Diff line number Diff line
@@ -3019,7 +3019,63 @@ public class GsmCdmaPhoneTest extends TelephonyTest {
        processAllMessages();

        verify(mNullCipherNotifier, times(1))
                .onSecurityAlgorithmUpdate(eq(mContext), eq(0), eq(update));
                .onSecurityAlgorithmUpdate(eq(mContext), eq(0), eq(0), eq(update));
    }

    @Test
    public void testUpdateNullCipherNotifier_flagDisabled() {
        when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(false);
        Phone phoneUT = makeNewPhoneUT();
        phoneUT.sendMessage(
                mPhoneUT.obtainMessage(
                        Phone.EVENT_SUBSCRIPTIONS_CHANGED,
                        new AsyncResult(null, null, null)));
        processAllMessages();

        verify(mNullCipherNotifier, never()).setSubscriptionMapping(any(), anyInt(), anyInt());
    }

    @Test
    public void testUpdateNullCipherNotifier_activeSubscription() {
        when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);

        int subId = 10;
        SubscriptionInfoInternal subInfo = new SubscriptionInfoInternal.Builder().setSimSlotIndex(
                0).setId(subId).build();
        when(mSubscriptionManagerService.getSubscriptionInfoInternal(subId)).thenReturn(
                subInfo);
        doReturn(subId).when(mSubscriptionManagerService)
                .getSubId(anyInt());
        Phone phoneUT = makeNewPhoneUT();

        phoneUT.sendMessage(
                mPhoneUT.obtainMessage(
                        Phone.EVENT_SUBSCRIPTIONS_CHANGED,
                        new AsyncResult(null, null, null)));
        processAllMessages();

        verify(mNullCipherNotifier, times(1)).setSubscriptionMapping(eq(mContext), eq(0), eq(10));
    }

    @Test
    public void testUpdateNullCipherNotifier_inactiveSubscription() {
        when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
        int subId = 1;
        SubscriptionInfoInternal subInfo = new SubscriptionInfoInternal.Builder().setSimSlotIndex(
                -1).setId(subId).build();
        when(mSubscriptionManagerService.getSubscriptionInfoInternal(subId)).thenReturn(
                subInfo);
        doReturn(subId).when(mSubscriptionManagerService)
                .getSubId(anyInt());
        Phone phoneUT = makeNewPhoneUT();

        phoneUT.sendMessage(
                mPhoneUT.obtainMessage(
                        Phone.EVENT_SUBSCRIPTIONS_CHANGED,
                        new AsyncResult(null, null, null)));
        processAllMessages();

        verify(mNullCipherNotifier, times(1)).setSubscriptionMapping(eq(mContext), eq(0), eq(-1));
    }

    @Test
+20 −0
Original line number Diff line number Diff line
@@ -171,6 +171,26 @@ public final class CellularNetworkSecuritySafetySourceTest extends TelephonyTest
        assertThat(data.getAllValues().get(2).getIssues()).hasSize(2);
    }

    @Test
    public void clearNullCipherState() {
        ArgumentCaptor<SafetySourceData> data = ArgumentCaptor.forClass(SafetySourceData.class);

        mSafetySource.setNullCipherIssueEnabled(mContext, true);
        mSafetySource.setNullCipherState(mContext, 0, NULL_CIPHER_STATE_NOTIFY_ENCRYPTED);
        mSafetySource.clearNullCipherState(mContext, 0);

        // Once for enable, once for encrypted state, and once for clearing state
        verify(mSafetyCenterManagerWrapper, times(3)).setSafetySourceData(data.capture());

        // initial check that our encrypted state update created an issue
        assertThat(data.getAllValues().get(1).getStatus()).isNotNull();
        assertThat(data.getAllValues().get(1).getIssues()).hasSize(1);

        // assert that our last call to clear state results in no issues sent to SC
        assertThat(data.getAllValues().get(2).getStatus()).isNotNull();
        assertThat(data.getAllValues().get(2).getIssues()).isEmpty();
    }

    @Test
    public void disableIdentifierDisclosueIssue_nullData() {
        // We must first enable before disabling, since a standalone call to disable may result in
Loading