From 22370a8a4aa7c80ef5338f8ba41508c7b2c6e2cc Mon Sep 17 00:00:00 2001 From: tomhsu Date: Mon, 25 Nov 2024 15:09:56 +0000 Subject: [PATCH] Make Satellite messageing dynamically change wording by network type Flag: com.android.settings.flags.satellite_oem_settings_ux_migration Fix: b/378410271 Test: atest pass Change-Id: I6d2d2ba656a6e2eb26ae103f8af84a1ce5fd49c8 --- res/values/strings.xml | 17 +- res/xml/satellite_setting.xml | 8 +- .../network/telephony/SatelliteSetting.java | 109 ++++++++--- .../SatelliteSettingPreferenceController.java | 82 +++++++- ...eSettingsPreferenceCategoryController.java | 11 +- ...tingsPreferenceCategoryControllerTest.java | 2 +- ...lliteSettingsPreferenceControllerTest.java | 179 ++++++++++++++++++ 7 files changed, 364 insertions(+), 44 deletions(-) create mode 100644 tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 6ba28533355..aec0fa669ef 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12275,13 +12275,13 @@ Satellite messaging - About satellite messaging + About %1$s You can send and receive text messages by satellite as part of an eligible %1$s account Your %1$s plan - Satellite messaging is included with your account + Messaging is included with your account Satellite messaging isn\u2019t included with your account @@ -12297,9 +12297,9 @@ You can text anyone, including emergency services. Your phone will reconnect to a mobile network when available. - Satellite messaging may take longer and is available only in some areas. Weather and certain structures may affect your satellite connection. Calling by satellite isn\u2019t available. Emergency calls may still connect.\n\nIt may take some time for account changes to show in Settings. Contact your carrier for details. + %1$s may take longer and is available only in some areas. Weather and certain structures may affect your satellite connection. Calling by satellite isn\u2019t available. Emergency calls may still connect.\n\nIt may take some time for account changes to show in Settings. Contact %1$s for details. - More about satellite messaging + More about %1$s Can’t turn on %1$s @@ -12307,7 +12307,14 @@ Satellite connectivity - Satellite connectivity + Satellite connectivity + + satellite connectivity + + satellite messaging + + Use of data is included with your account + diff --git a/res/xml/satellite_setting.xml b/res/xml/satellite_setting.xml index 09fbbd66171..60fe5bfb335 100644 --- a/res/xml/satellite_setting.xml +++ b/res/xml/satellite_setting.xml @@ -22,7 +22,7 @@ settings:keywords="@string/keywords_satellite_setting"> + android:key="key_category_about_satellite"> @@ -35,6 +35,12 @@ + + + { + messagingPreference.setOnPreferenceClickListener(pref -> { String url = readSatelliteMoreInfoString(mSubId); if (!url.isEmpty()) { Uri uri = Uri.parse(url); @@ -173,11 +199,13 @@ public class SatelliteSetting extends RestrictedDashboardFragment { } return true; }); - icon = getResources().getDrawable(R.drawable.ic_block_24px); + icon = getResources().getDrawable(R.drawable.ic_block_24px, null); } icon.setTintList(Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary)); - preference.setIcon(icon); + messagingPreference.setIcon(icon); + } + 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) { @@ -185,13 +213,15 @@ public class SatelliteSetting extends RestrictedDashboardFragment { category.setEnabled(false); category.setShouldDisableView(true); } + } + private void updateFooterContent() { // More about satellite messaging FooterPreference footerPreference = findPreference(KEY_FOOTER_PREFERENCE); if (footerPreference != null) { footerPreference.setSummary( getResources().getString(R.string.satellite_setting_summary_more_information, - operatorName)); + getSubjectString(), mSimOperatorName)); final String[] link = new String[1]; link[0] = readSatelliteMoreInfoString(mSubId); @@ -205,8 +235,9 @@ public class SatelliteSetting extends RestrictedDashboardFragment { } } }); + footerPreference.setLearnMoreText( - getResources().getString(R.string.more_about_satellite_messaging)); + getString(R.string.more_about_satellite_messaging, getDescriptionString())); } } } @@ -245,6 +276,32 @@ public class SatelliteSetting extends RestrictedDashboardFragment { return bundle.getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false); } + // This is for a word which first letter is uppercase. e.g. Satellite messaging. + private String getSubjectString() { + int result; + if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) { + result = mIsServiceDataType + ? R.string.title_satellite_setting_connectivity + : R.string.satellite_setting_title; + } else { + result = R.string.satellite_setting_title; + } + return getString(result); + } + + // This is for a word without uppercase letter. e.g. satellite messaging. + private String getDescriptionString() { + int result; + if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) { + result = mIsServiceDataType + ? R.string.description_satellite_setting_connectivity + : R.string.description_satellite_setting_messaging; + } else { + result = R.string.satellite_setting_title; + } + return getString(result); + } + private static void loge(String message) { Log.e(TAG, message); } diff --git a/src/com/android/settings/network/telephony/SatelliteSettingPreferenceController.java b/src/com/android/settings/network/telephony/SatelliteSettingPreferenceController.java index efdd9cb9ca5..f13ea354ff5 100644 --- a/src/com/android/settings/network/telephony/SatelliteSettingPreferenceController.java +++ b/src/com/android/settings/network/telephony/SatelliteSettingPreferenceController.java @@ -16,16 +16,25 @@ package com.android.settings.network.telephony; +import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA; +import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS; + import android.content.Context; import android.content.Intent; import android.os.PersistableBundle; import android.provider.Settings; import android.telephony.CarrierConfigManager; +import android.telephony.TelephonyCallback; +import android.telephony.TelephonyManager; +import android.telephony.satellite.NtnSignalStrength; import android.telephony.satellite.SatelliteManager; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import androidx.lifecycle.DefaultLifecycleObserver; +import androidx.lifecycle.LifecycleOwner; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; @@ -33,28 +42,33 @@ import com.android.internal.telephony.flags.Flags; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.network.CarrierConfigCache; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnStart; -import com.android.settingslib.core.lifecycle.events.OnStop; +import java.util.List; import java.util.Set; /** * Preference controller for "Satellite Setting" */ public class SatelliteSettingPreferenceController extends - TelephonyBasePreferenceController implements LifecycleObserver, OnStart, OnStop { - + TelephonyBasePreferenceController implements DefaultLifecycleObserver { private static final String TAG = "SatelliteSettingPreferenceController"; CarrierConfigCache mCarrierConfigCache; SatelliteManager mSatelliteManager; - @Nullable private Boolean mIsSatelliteEligible = null; + private TelephonyManager mTelephonyManager = null; + @VisibleForTesting + final CarrierRoamingNtnModeCallback mCarrierRoamingNtnModeCallback = + new CarrierRoamingNtnModeCallback(); + + @Nullable + private Boolean mIsSatelliteEligible = null; + private boolean mIsServiceDataType = false; public SatelliteSettingPreferenceController(@NonNull Context context, @NonNull String key) { super(context, key); mCarrierConfigCache = CarrierConfigCache.getInstance(context); mSatelliteManager = context.getSystemService(SatelliteManager.class); + mTelephonyManager = context.getSystemService(TelephonyManager.class); } @Override @@ -76,11 +90,18 @@ public class SatelliteSettingPreferenceController extends } @Override - public void onStart() { + public void onResume(@NonNull LifecycleOwner owner) { + if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) { + mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(), + mCarrierRoamingNtnModeCallback); + } } @Override - public void onStop() { + public void onPause(@NonNull LifecycleOwner owner) { + if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) { + mTelephonyManager.unregisterTelephonyCallback(mCarrierRoamingNtnModeCallback); + } } @Override @@ -93,6 +114,7 @@ public class SatelliteSettingPreferenceController extends public void updateState(@Nullable Preference preference) { super.updateState(preference); if (preference != null) { + mCarrierRoamingNtnModeCallback.mPref = preference; updateSummary(preference); } } @@ -106,6 +128,7 @@ public class SatelliteSettingPreferenceController extends // This will setup the Home and Search affordance intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, true); intent.putExtra(SatelliteSetting.SUB_ID, mSubId); + intent.putExtra(SatelliteSetting.EXTRA_IS_SERVICE_DATA_TYPE, mIsServiceDataType); mContext.startActivity(intent); return true; } @@ -115,11 +138,13 @@ public class SatelliteSettingPreferenceController extends /** * Set subId for Satellite Settings page. + * * @param subId subscription ID. */ public void init(int subId) { logd("init(), subId=" + subId); mSubId = subId; + mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId); } private void updateSummary(Preference preference) { @@ -148,4 +173,45 @@ public class SatelliteSettingPreferenceController extends private static void loge(String message) { Log.e(TAG, message); } + + @VisibleForTesting + class CarrierRoamingNtnModeCallback extends TelephonyCallback implements + TelephonyCallback.CarrierRoamingNtnModeListener { + Preference mPref = null; + + @Override + public void onCarrierRoamingNtnAvailableServicesChanged(List availableServices) { + CarrierRoamingNtnModeListener.super.onCarrierRoamingNtnAvailableServicesChanged( + availableServices); + boolean isSmsAvailable = availableServices.contains(SERVICE_TYPE_SMS); + boolean isDataAvailable = availableServices.contains(SERVICE_TYPE_DATA); + logd("isSmsAvailable : " + isSmsAvailable + + " / isDataAvailable " + isDataAvailable); + if (mPref == null) { + logd("Satellite preference is not initialized yet"); + return; + } + if (isDataAvailable) { + mIsServiceDataType = true; + mPref.setTitle(R.string.title_satellite_setting_connectivity); + } else if (isSmsAvailable) { + mPref.setTitle(R.string.satellite_setting_title); + } + } + + @Override + public void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) { + // Do nothing + } + + @Override + public void onCarrierRoamingNtnModeChanged(boolean active) { + // Do nothing + } + + @Override + public void onCarrierRoamingNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) { + // Do nothing + } + } } diff --git a/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java b/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java index ae3262f78ab..c1820595219 100644 --- a/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java +++ b/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java @@ -33,6 +33,7 @@ import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceScreen; import com.android.settings.R; +import com.android.settings.flags.Flags; import java.util.Arrays; import java.util.List; @@ -87,13 +88,17 @@ public class SatelliteSettingsPreferenceCategoryController @Override public void onResume(@NonNull LifecycleOwner owner) { - mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(), - mCarrierRoamingNtnModeCallback); + if (Flags.satelliteOemSettingsUxMigration()) { + mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(), + mCarrierRoamingNtnModeCallback); + } } @Override public void onPause(@NonNull LifecycleOwner owner) { - mTelephonyManager.unregisterTelephonyCallback(mCarrierRoamingNtnModeCallback); + if (Flags.satelliteOemSettingsUxMigration()) { + mTelephonyManager.unregisterTelephonyCallback(mCarrierRoamingNtnModeCallback); + } } @VisibleForTesting diff --git a/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java index bd06a646137..299ea133536 100644 --- a/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java @@ -114,7 +114,7 @@ public class SatelliteSettingsPreferenceCategoryControllerTest { new int[]{SERVICE_TYPE_DATA}); assertThat(preferenceCategory.getTitle()).isEqualTo( - mContext.getString(R.string.satellite_setting_connectivity)); + mContext.getString(R.string.title_satellite_setting_connectivity)); } diff --git a/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceControllerTest.java new file mode 100644 index 00000000000..b15c6608080 --- /dev/null +++ b/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceControllerTest.java @@ -0,0 +1,179 @@ +/* + * 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 static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA; +import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; +import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.Looper; +import android.os.PersistableBundle; +import android.platform.test.annotations.EnableFlags; +import android.telephony.CarrierConfigManager; +import android.telephony.TelephonyManager; +import android.telephony.satellite.SatelliteManager; + +import androidx.preference.Preference; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.internal.telephony.flags.Flags; +import com.android.settings.R; +import com.android.settings.network.CarrierConfigCache; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.List; + +@RunWith(AndroidJUnit4.class) +public class SatelliteSettingsPreferenceControllerTest { + private static final String KEY = "key"; + private static final int TEST_SUB_ID = 0; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + + @Mock + private CarrierConfigCache mCarrierConfigCache; + @Mock + private TelephonyManager mTelephonyManager; + + private Context mContext = null; + private SatelliteManager mSatelliteManager; + private SatelliteSettingPreferenceController mController = null; + private PersistableBundle mCarrierConfig = new PersistableBundle(); + + @Before + public void setUp() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + mContext = spy(ApplicationProvider.getApplicationContext()); + mSatelliteManager = new SatelliteManager(mContext); + CarrierConfigCache.setTestInstance(mContext, mCarrierConfigCache); + when(mContext.getSystemService(SatelliteManager.class)).thenReturn(mSatelliteManager); + when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); + when(mTelephonyManager.createForSubscriptionId(TEST_SUB_ID)).thenReturn(mTelephonyManager); + mController = spy(new SatelliteSettingPreferenceController(mContext, KEY)); + } + + @Test + @EnableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) + public void getAvailabilityStatus_noSatellite_returnUnsupport() { + when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null); + mController = new SatelliteSettingPreferenceController(mContext, KEY); + + int result = mController.getAvailabilityStatus(TEST_SUB_ID); + + assertThat(result).isEqualTo(UNSUPPORTED_ON_DEVICE); + } + + @Test + @EnableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) + public void getAvailabilityStatus_carrierIsNotSupport_returnUnavailable() { + when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null); + mCarrierConfig.putBoolean( + CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, + false); + when(mCarrierConfigCache.getConfigForSubId(TEST_SUB_ID)).thenReturn(mCarrierConfig); + + int result = mController.getAvailabilityStatus(TEST_SUB_ID); + + assertThat(result).isEqualTo(CONDITIONALLY_UNAVAILABLE); + } + + @Test + @EnableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) + public void getAvailabilityStatus_carrierIsSupport_returnAvailable() { + when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null); + mCarrierConfig.putBoolean( + CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, + true); + when(mCarrierConfigCache.getConfigForSubId(TEST_SUB_ID)).thenReturn(mCarrierConfig); + + int result = mController.getAvailabilityStatus(TEST_SUB_ID); + + assertThat(result).isEqualTo(AVAILABLE); + } + + @Test + @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION) + public void getAvailabilityStatus_registerTelephonyCallback_success() { + mController.init(TEST_SUB_ID); + mController.onResume(null); + + verify(mTelephonyManager).registerTelephonyCallback(any(), any()); + } + + @Test + @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION) + public void getAvailabilityStatus_unregisterTelephonyCallback_success() { + mController.init(TEST_SUB_ID); + mController.onPause(null); + + verify(mTelephonyManager).unregisterTelephonyCallback(any()); + } + + @Test + @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION) + public void getAvailabilityStatus_hasServiceDataType_showDataUi() { + mController.init(TEST_SUB_ID); + Preference preference = new Preference(mContext); + preference.setKey(KEY); + preference.setTitle("test title"); + mController.updateState(preference); + + mController.mCarrierRoamingNtnModeCallback.onCarrierRoamingNtnAvailableServicesChanged( + List.of(SERVICE_TYPE_SMS, SERVICE_TYPE_DATA)); + + assertThat(preference.getTitle()).isEqualTo( + mContext.getString(R.string.title_satellite_setting_connectivity)); + } + + @Test + @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION) + public void getAvailabilityStatus_hasServiceDataType_showSmsUi() { + mController.init(TEST_SUB_ID); + Preference preference = new Preference(mContext); + preference.setKey(KEY); + preference.setTitle("test title"); + mController.updateState(preference); + + mController.mCarrierRoamingNtnModeCallback.onCarrierRoamingNtnAvailableServicesChanged( + List.of(SERVICE_TYPE_SMS)); + + assertThat(preference.getTitle()).isEqualTo( + mContext.getString(R.string.satellite_setting_title)); + } +}