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

Commit e216fd42 authored by Chaohui Wang's avatar Chaohui Wang
Browse files

No show DisableSimFooterPreference when sub not found

DisableSimFooterPreferenceController.getAvailabilityStatus() used to
return AVAILABLE when the subscription is not found in selectable
subscription info list.

Return CONDITIONALLY_UNAVAILABLE in this case to fix.

Bug: 336232487
Test: manual - on Mobile Settings
Change-Id: I88642fc9853ce6603a78dfdc0e5fed1da1553adc
parent 211afbea
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 * 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.
@@ -14,49 +14,41 @@
 * limitations under the License.
 */

package com.android.settings.network.telephony;
package com.android.settings.network.telephony

import android.content.Context;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;

import com.android.settings.network.SubscriptionUtil;
import android.content.Context
import android.telephony.SubscriptionManager

/**
 * Shows information about disable a physical SIM.
 */
public class DisableSimFooterPreferenceController extends TelephonyBasePreferenceController {

    /**
     * Constructor
     */
    public DisableSimFooterPreferenceController(Context context, String preferenceKey) {
        super(context, preferenceKey);
    }
class DisableSimFooterPreferenceController @JvmOverloads constructor(
    context: Context,
    preferenceKey: String,
    private val subscriptionRepository: SubscriptionRepository = SubscriptionRepository(context),
) : TelephonyBasePreferenceController(context, preferenceKey) {

    /**
     * re-init for SIM based on given subscription ID.
     * Re-init for SIM based on given subscription ID.
     *
     * @param subId is the given subscription ID
     */
    public void init(int subId) {
        mSubId = subId;
    fun init(subId: Int) {
        mSubId = subId
    }

    @Override
    public int getAvailabilityStatus(int subId) {
        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            return CONDITIONALLY_UNAVAILABLE;
    override fun getAvailabilityStatus(subId: Int): Int {
        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID ||
            subscriptionRepository.canDisablePhysicalSubscription()
        ) {
            return CONDITIONALLY_UNAVAILABLE
        }

        SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class);
        for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) {
            if (info.getSubscriptionId() == subId) {
                if (info.isEmbedded() || SubscriptionUtil.showToggleForPhysicalSim(subManager)) {
                    return CONDITIONALLY_UNAVAILABLE;
                }
                break;
        val isAvailable =
            subscriptionRepository.getSelectableSubscriptionInfoList().any { subInfo ->
                subInfo.subscriptionId == subId && !subInfo.isEmbedded
            }
        }
        return AVAILABLE;

        return if (isAvailable) AVAILABLE else CONDITIONALLY_UNAVAILABLE
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ import kotlinx.coroutines.flow.onEach
private const val TAG = "SubscriptionRepository"

class SubscriptionRepository(private val context: Context) {
    private val subscriptionManager = context.requireSubscriptionManager()

    /**
     * Return a list of subscriptions that are available and visible to the user.
     *
@@ -55,6 +57,7 @@ class SubscriptionRepository(private val context: Context) {
        isSubscriptionEnabledFlow(subId).collectLatestWithLifecycle(lifecycleOwner, action = action)
    }

    fun canDisablePhysicalSubscription() = subscriptionManager.canDisablePhysicalSubscription()
}

val Context.subscriptionManager: SubscriptionManager?
+102 −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 com.android.settings.network.telephony

import android.content.Context
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.core.BasePreferenceController.AVAILABLE
import com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub

@RunWith(AndroidJUnit4::class)
class DisableSimFooterPreferenceControllerTest {

    private val subscriptionInfo = mock<SubscriptionInfo> {
        on { subscriptionId } doReturn SUB_ID
    }

    private var context: Context = ApplicationProvider.getApplicationContext()

    private val mockSubscriptionRepository = mock<SubscriptionRepository> {
        on { getSelectableSubscriptionInfoList() } doReturn listOf(subscriptionInfo)
    }

    private var controller = DisableSimFooterPreferenceController(
        context = context,
        preferenceKey = PREFERENCE_KEY,
        subscriptionRepository = mockSubscriptionRepository,
    ).apply { init(SUB_ID) }

    @Test
    fun getAvailabilityStatus_invalidId_notAvailable() {
        val availabilityStatus = controller.getAvailabilityStatus(INVALID_SUBSCRIPTION_ID)

        assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE)
    }

    @Test
    fun getAvailabilityStatus_eSim_notAvailable() {
        subscriptionInfo.stub {
            on { isEmbedded } doReturn true
        }

        val availabilityStatus = controller.getAvailabilityStatus(SUB_ID)

        assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE)
    }

    @Test
    fun getAvailabilityStatus_pSimAndCannotDisable_available() {
        mockSubscriptionRepository.stub {
            on { canDisablePhysicalSubscription() } doReturn false
        }
        subscriptionInfo.stub {
            on { isEmbedded } doReturn false
        }

        val availabilityStatus = controller.getAvailabilityStatus(SUB_ID)

        assertThat(availabilityStatus).isEqualTo(AVAILABLE)
    }

    @Test
    fun getAvailabilityStatus_pSimAndCanDisable_notAvailable() {
        mockSubscriptionRepository.stub {
            on { canDisablePhysicalSubscription() } doReturn true
        }
        subscriptionInfo.stub {
            on { isEmbedded } doReturn false
        }

        val availabilityStatus = controller.getAvailabilityStatus(SUB_ID)

        assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE)
    }

    private companion object {
        const val PREFERENCE_KEY = "preference_key"
        const val SUB_ID = 111
    }
}
+0 −94
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 com.android.settings.network.telephony;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.android.settings.network.SubscriptionUtil;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.Arrays;

@RunWith(AndroidJUnit4.class)
public class DisableSimFooterPreferenceControllerTest {
    private static final String PREF_KEY = "pref_key";
    private static final int SUB_ID = 111;

    @Mock
    private SubscriptionInfo mInfo;

    private Context mContext;
    @Mock
    private SubscriptionManager mSubscriptionManager;
    private DisableSimFooterPreferenceController mController;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = spy(ApplicationProvider.getApplicationContext());
        when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
        when(mSubscriptionManager.createForAllUserProfiles()).thenReturn(mSubscriptionManager);

        when(mInfo.getSubscriptionId()).thenReturn(SUB_ID);
        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mInfo));
        mController = new DisableSimFooterPreferenceController(mContext, PREF_KEY);
    }

    @Test
    public void isAvailable_noInit_notAvailable() {
        assertThat(mController.isAvailable()).isFalse();
    }

    @Test
    public void isAvailable_eSIM_notAvailable() {
        when(mInfo.isEmbedded()).thenReturn(true);
        mController.init(SUB_ID);
        assertThat(mController.isAvailable()).isFalse();
    }

    @Test
    public void isAvailable_pSIM_available_cannot_disable_pSIM() {
        when(mInfo.isEmbedded()).thenReturn(false);
        mController.init(SUB_ID);
        doReturn(false).when(mSubscriptionManager).canDisablePhysicalSubscription();
        assertThat(mController.isAvailable()).isTrue();
    }

    @Test
    public void isAvailable_pSIM_available_can_disable_pSIM() {
        when(mInfo.isEmbedded()).thenReturn(false);
        mController.init(SUB_ID);
        doReturn(true).when(mSubscriptionManager).canDisablePhysicalSubscription();
        assertThat(mController.isAvailable()).isFalse();
    }
}