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

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

Merge "[Satellite settings] Refactor part of How it work" into main

parents 2fee93b8 aa943083
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -50,7 +50,8 @@
        android:key="key_category_how_it_works"
        android:title="@string/category_name_how_it_works"
        android:clickable="false"
        android:focusable="false">
        android:focusable="false"
        settings:controller="com.android.settings.network.telephony.satellite.SatelliteSettingIndicatorController">

        <Preference
            android:key="key_satellite_connection_guide"
+1 −47
Original line number Diff line number Diff line
@@ -16,33 +16,23 @@

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

import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT;
import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_INFORMATION_REDIRECT_URL_STRING;

import static com.android.settings.network.telephony.satellite.SatelliteCarrierSettingUtils.isSatelliteAccountEligible;
import static com.android.settings.network.telephony.satellite.SatelliteCarrierSettingUtils.isSatelliteDataRestricted;

import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserManager;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.satellite.SatelliteManager;
import android.util.Log;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;

import com.android.settings.R;
import com.android.settings.dashboard.RestrictedDashboardFragment;
@@ -50,10 +40,6 @@ import com.android.settings.dashboard.RestrictedDashboardFragment;
/** Handle Satellite Setting Preference Layout. */
public class SatelliteSetting extends RestrictedDashboardFragment {
    private static final String TAG = "SatelliteSetting";
    private static final String PREF_KEY_CATEGORY_HOW_IT_WORKS = "key_category_how_it_works";
    private static final String KEY_SATELLITE_CONNECTION_GUIDE = "key_satellite_connection_guide";
    private static final String KEY_SUPPORTED_SERVICE = "key_supported_service";


    static final String SUB_ID = "sub_id";
    static final String EXTRA_IS_SERVICE_DATA_TYPE = "is_service_data_type";
@@ -63,7 +49,6 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
    private SatelliteManager mSatelliteManager;
    private PersistableBundle mConfigBundle;
    private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    private boolean mIsServiceDataType = false;
    private boolean mIsSmsAvailableForManualType = false;

    public SatelliteSetting() {
@@ -93,7 +78,6 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
                    + "do nothing.");
            finish();
        }
        mIsServiceDataType = getIntent().getBooleanExtra(EXTRA_IS_SERVICE_DATA_TYPE, false);
        mIsSmsAvailableForManualType = getIntent().getBooleanExtra(
                EXTRA_IS_SMS_AVAILABLE_FOR_MANUAL_TYPE, false);
        boolean isDataAvailableAndNotRestricted = isDataAvailableAndNotRestricted();
@@ -103,13 +87,7 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
        use(SatelliteSettingAccountInfoController.class).init(mSubId, mConfigBundle,
                mIsSmsAvailableForManualType, isDataAvailableAndNotRestricted);
        use(SatelliteSettingFooterController.class).init(mSubId, mConfigBundle);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        boolean isSatelliteEligible = isSatelliteAccountEligible(getContext(), mSubId);
        updateHowItWorksContent(isSatelliteEligible);
        use(SatelliteSettingIndicatorController.class).init(mSubId, mConfigBundle);
    }

    @Override
@@ -122,25 +100,6 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
        return R.xml.satellite_setting;
    }

    private void updateHowItWorksContent(boolean isSatelliteEligible) {
        /* Composes "How it works" section, which guides how users can use satellite messaging, when
           satellite messaging is included in user's mobile plan, or it'll will be grey out. */
        if (!isSatelliteEligible) {
            PreferenceCategory category = findPreference(PREF_KEY_CATEGORY_HOW_IT_WORKS);
            category.setEnabled(false);
            category.setShouldDisableView(true);
        }
        if (!isCarrierRoamingNtnConnectedTypeManual()) {
            return;
        }
        Preference connectionGuide = findPreference(KEY_SATELLITE_CONNECTION_GUIDE);
        connectionGuide.setTitle(R.string.title_satellite_connection_guide_for_manual_type);
        connectionGuide.setSummary(R.string.summary_satellite_connection_guide_for_manual_type);
        Preference supportedService = findPreference(KEY_SUPPORTED_SERVICE);
        supportedService.setTitle(R.string.title_supported_service_for_manual_type);
        supportedService.setSummary(R.string.summary_supported_service_for_manual_type);
    }

    private PersistableBundle fetchCarrierConfigData(int subId) {
        CarrierConfigManager carrierConfigManager = mActivity.getSystemService(
                CarrierConfigManager.class);
@@ -162,11 +121,6 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
        return bundle;
    }

    private boolean isCarrierRoamingNtnConnectedTypeManual() {
        return CARRIER_ROAMING_NTN_CONNECT_MANUAL == mConfigBundle.getInt(
                KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC);
    }

    private boolean isSatelliteAttachSupported() {
        return mConfigBundle.getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false);
    }
+90 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.satellite

import android.content.Context
import android.os.PersistableBundle
import android.telephony.CarrierConfigManager
import androidx.annotation.VisibleForTesting
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceScreen
import com.android.settings.R
import com.android.settings.network.telephony.TelephonyBasePreferenceController

/** A controller to control How is work paragraph.  */
class SatelliteSettingIndicatorController(context: Context?, preferenceKey: String?) :
    TelephonyBasePreferenceController(context, preferenceKey) {
    private var mCarrierConfigs: PersistableBundle? = null

    fun init(subId: Int, carrierConfigs: PersistableBundle) {
        mSubId = subId
        mCarrierConfigs = carrierConfigs
    }

    override fun displayPreference(screen: PreferenceScreen) {
        super.displayPreference(screen)
        updateHowItWorksContent(
            screen,
            SatelliteCarrierSettingUtils.isSatelliteAccountEligible(mContext, mSubId)
        )
    }

    override fun getAvailabilityStatus(subId: Int): Int {
        return AVAILABLE
    }

    @VisibleForTesting
    fun updateHowItWorksContent(screen: PreferenceScreen, isSatelliteEligible: Boolean) {
        /* Composes "How it works" section, which guides how users can use satellite messaging, when
           satellite messaging is included in user's mobile plan, or it'll will be grey out. */
        if (!isSatelliteEligible) {
            val category =
                screen.findPreference<PreferenceCategory?>(PREF_KEY_CATEGORY_HOW_IT_WORKS)
            if (category == null) return
            category.isEnabled = false
            category.shouldDisableView = true
        }
        if (!this.isCarrierRoamingNtnConnectedTypeManual) {
            return
        }
        val connectionGuide: Preference = screen.findPreference(KEY_SATELLITE_CONNECTION_GUIDE)!!
        connectionGuide.setTitle(R.string.title_satellite_connection_guide_for_manual_type)
        connectionGuide.setSummary(R.string.summary_satellite_connection_guide_for_manual_type)

        val supportedService: Preference = screen.findPreference(KEY_SUPPORTED_SERVICE)!!
        supportedService.setTitle(R.string.title_supported_service_for_manual_type)
        supportedService.setSummary(R.string.summary_supported_service_for_manual_type)

    }

    private val isCarrierRoamingNtnConnectedTypeManual: Boolean
        get() = CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL == mCarrierConfigs!!.getInt(
            CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
            CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC
        )

    companion object {
        @VisibleForTesting
        const val PREF_KEY_CATEGORY_HOW_IT_WORKS: String = "key_category_how_it_works"

        @VisibleForTesting
        const val KEY_SATELLITE_CONNECTION_GUIDE: String = "key_satellite_connection_guide"

        @VisibleForTesting
        const val KEY_SUPPORTED_SERVICE: String = "key_supported_service"
    }
}
+123 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.satellite

import android.content.Context
import android.os.Looper
import android.os.PersistableBundle
import android.telephony.CarrierConfigManager
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceManager
import androidx.test.annotation.UiThreadTest
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers
import org.mockito.Mockito
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule

@UiThreadTest
class SatelliteSettingIndicatorControllerTest {
    private var mContext: Context? = null
    private var mController: SatelliteSettingIndicatorController? = null
    private val mCarrierConfig = PersistableBundle()

    @Before
    fun setUp() {
        mContext = Mockito.spy<Context>(ApplicationProvider.getApplicationContext<Context?>())
        mController = SatelliteSettingIndicatorController(mContext, KEY)
    }

    @Test
    fun updateHowItWorksContent_accountNotEligible_categoryIsDisabled() {
        mCarrierConfig.putInt(
            CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
            CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC
        )
        mController?.init(TEST_SUB_ID, mCarrierConfig)
        val preferenceManager = PreferenceManager(mContext!!)
        val preferenceScreen = preferenceManager.createPreferenceScreen(mContext!!)
        val category = Mockito.spy<PreferenceCategory>(PreferenceCategory(mContext!!))
        category.setKey(SatelliteSettingIndicatorController.Companion.PREF_KEY_CATEGORY_HOW_IT_WORKS)
        category.title = "test title"
        category.isEnabled = true
        preferenceScreen.addPreference(category)

        mController?.updateHowItWorksContent(preferenceScreen, false)

        Mockito.verify(category, Mockito.times(1)).isEnabled = false
        Mockito.verify(category, Mockito.times(1)).shouldDisableView = true
    }

    @Test
    fun updateHowItWorksContent_accountEligible_categoryIsEnabled() {
        mCarrierConfig.putInt(
            CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
            CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC
        )
        mController?.init(TEST_SUB_ID, mCarrierConfig)
        val preferenceManager = PreferenceManager(mContext!!)
        val preferenceScreen = preferenceManager.createPreferenceScreen(mContext!!)
        val category = Mockito.spy<PreferenceCategory>(PreferenceCategory(mContext!!))
        category.setKey(SatelliteSettingIndicatorController.Companion.PREF_KEY_CATEGORY_HOW_IT_WORKS)
        category.title = "test title"
        category.isEnabled = true
        preferenceScreen.addPreference(category)

        mController!!.updateHowItWorksContent(preferenceScreen, true)

        Mockito.verify(category, Mockito.times(0)).isEnabled = false
        Mockito.verify(category, Mockito.times(0)).shouldDisableView = true
    }

    @Test
    fun updateHowItWorksContent_ntnConnectIsManual_summaryChanged() {
        mCarrierConfig.putInt(
            CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
            CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL
        )
        mController?.init(TEST_SUB_ID, mCarrierConfig)
        val preferenceManager = PreferenceManager(mContext!!)
        val preferenceScreen = preferenceManager.createPreferenceScreen(mContext!!)
        val category = Mockito.spy<PreferenceCategory>(PreferenceCategory(mContext!!))
        category.setKey(SatelliteSettingIndicatorController.Companion.PREF_KEY_CATEGORY_HOW_IT_WORKS)
        category.title = "test title"
        val preference1 = Mockito.spy<Preference>(Preference(mContext!!))
        preference1.setKey(SatelliteSettingIndicatorController.Companion.KEY_SATELLITE_CONNECTION_GUIDE)
        preference1.title = "preference1"
        val preference2 = Mockito.spy<Preference>(Preference(mContext!!))
        preference2.setKey(SatelliteSettingIndicatorController.Companion.KEY_SUPPORTED_SERVICE)
        preference2.title = "preference2"
        preferenceScreen.addPreference(category)
        preferenceScreen.addPreference(preference1)
        preferenceScreen.addPreference(preference2)

        mController?.updateHowItWorksContent(preferenceScreen, false)

        Mockito.verify(preference1).setSummary(ArgumentMatchers.any<CharSequence?>())
        Mockito.verify(preference2).setSummary(ArgumentMatchers.any<CharSequence?>())
    }

    companion object {
        private const val KEY = "SatelliteSettingIndicatorControllerTest"
        private const val TEST_SUB_ID = 5
    }
}