[Settings] Apply the SettingsDataService to the SIM page, roaming

controller

Implement it in 0RoamingPreferenceController
Launch MobileNetworkSettings in SettingsApp by SubSettingLauncher
Launch MobileNetworkSettings by intent

Bug: 257197354
Test: atest RoamingPreferenceControllerTest
Change-Id: Ia2df51ad3a9b2b72bdada05de480e0b05d2d4f43
This commit is contained in:
Zoey Chen
2022-11-03 08:19:00 +00:00
parent 469b708a2a
commit 7dfd3be886
4 changed files with 296 additions and 122 deletions

View File

@@ -39,6 +39,7 @@ import android.util.Log;
import com.android.settings.network.telephony.MobileNetworkUtils; import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.mobile.dataservice.DataServiceUtils;
import com.android.settingslib.mobile.dataservice.MobileNetworkDatabase; import com.android.settingslib.mobile.dataservice.MobileNetworkDatabase;
import com.android.settingslib.mobile.dataservice.MobileNetworkInfoDao; import com.android.settingslib.mobile.dataservice.MobileNetworkInfoDao;
import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity; import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
@@ -49,6 +50,7 @@ import com.android.settingslib.mobile.dataservice.UiccInfoEntity;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@@ -98,21 +100,29 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
public static MobileNetworkRepository create(Context context, public static MobileNetworkRepository create(Context context,
MobileNetworkCallback mobileNetworkCallback) { MobileNetworkCallback mobileNetworkCallback) {
return new MobileNetworkRepository(context, mobileNetworkCallback); return new MobileNetworkRepository(context, mobileNetworkCallback,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
} }
private MobileNetworkRepository(Context context, MobileNetworkCallback mobileNetworkCallback) { public static MobileNetworkRepository createBySubId(Context context,
MobileNetworkCallback mobileNetworkCallback, int subId) {
return new MobileNetworkRepository(context, mobileNetworkCallback, subId);
}
private MobileNetworkRepository(Context context, MobileNetworkCallback mobileNetworkCallback,
int subId) {
mSubId = subId;
mContext = context; mContext = context;
mCallback = mobileNetworkCallback;
mMobileNetworkDatabase = MobileNetworkDatabase.getInstance(context); mMobileNetworkDatabase = MobileNetworkDatabase.getInstance(context);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_MOBILE_NETWORK_DB_CREATED);
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mCallback = mobileNetworkCallback;
mSubscriptionInfoDao = mMobileNetworkDatabase.mSubscriptionInfoDao(); mSubscriptionInfoDao = mMobileNetworkDatabase.mSubscriptionInfoDao();
mUiccInfoDao = mMobileNetworkDatabase.mUiccInfoDao(); mUiccInfoDao = mMobileNetworkDatabase.mUiccInfoDao();
mMobileNetworkInfoDao = mMobileNetworkDatabase.mMobileNetworkInfoDao(); mMobileNetworkInfoDao = mMobileNetworkDatabase.mMobileNetworkInfoDao();
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mAirplaneModeObserver = new AirplaneModeObserver(new Handler(Looper.getMainLooper())); mAirplaneModeObserver = new AirplaneModeObserver(new Handler(Looper.getMainLooper()));
mAirplaneModeSettingUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON); mAirplaneModeSettingUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_MOBILE_NETWORK_DB_CREATED);
mFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); mFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
mFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED); mFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED);
} }
@@ -205,6 +215,10 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
return mSubscriptionInfoDao.querySubInfoById(subId); return mSubscriptionInfoDao.querySubInfoById(subId);
} }
public MobileNetworkInfoEntity queryMobileNetworkInfoBySubId(String subId) {
return mMobileNetworkInfoDao.queryMobileNetworkInfoBySubId(subId);
}
public int getSubInfosCount() { public int getSubInfosCount() {
return mSubscriptionInfoDao.count(); return mSubscriptionInfoDao.count();
} }
@@ -222,26 +236,26 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
for (int i = 0; i < uiccSlotInfos.length; i++) { for (int i = 0; i < uiccSlotInfos.length; i++) {
UiccSlotInfo curSlotInfo = uiccSlotInfos[i]; UiccSlotInfo curSlotInfo = uiccSlotInfos[i];
if (curSlotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT) { if (curSlotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT) {
final int index = i;
mIsEuicc = curSlotInfo.getIsEuicc(); mIsEuicc = curSlotInfo.getIsEuicc();
mCardState = curSlotInfo.getCardStateInfo(); mCardState = curSlotInfo.getCardStateInfo();
mIsRemovable = curSlotInfo.isRemovable(); mIsRemovable = curSlotInfo.isRemovable();
mCardId = subInfo.getCardId(); mCardId = subInfo.getCardId();
Collection<UiccPortInfo> uiccPortInfos = curSlotInfo.getPorts(); Collection<UiccPortInfo> uiccPortInfos = curSlotInfo.getPorts();
for (UiccPortInfo portInfo : uiccPortInfos) { uiccPortInfos.forEach(portInfo -> {
if (portInfo.getPortIndex() == subInfo.getPortIndex() if (portInfo.getPortIndex() == subInfo.getPortIndex()
&& portInfo.getLogicalSlotIndex() == subInfo.getSimSlotIndex()) { && portInfo.getLogicalSlotIndex() == subInfo.getSimSlotIndex()) {
mPhysicalSlotIndex = i; mPhysicalSlotIndex = index;
mLogicalSlotIndex = portInfo.getLogicalSlotIndex(); mLogicalSlotIndex = portInfo.getLogicalSlotIndex();
mIsActive = portInfo.isActive(); mIsActive = portInfo.isActive();
mPortIndex = portInfo.getPortIndex(); mPortIndex = portInfo.getPortIndex();
break;
} else if (DEBUG) { } else if (DEBUG) {
Log.d(TAG, Log.d(TAG,
"Can not get port index and physicalSlotIndex for subId " "Can not get port index and physicalSlotIndex for subId "
+ mSubId); + mSubId);
} }
} });
if (mPhysicalSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) { if (mPhysicalSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
break; break;
} }
@@ -398,7 +412,8 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
MobileNetworkUtils.shouldDisplayNetworkSelectOptions(context, mSubId), MobileNetworkUtils.shouldDisplayNetworkSelectOptions(context, mSubId),
MobileNetworkUtils.isTdscdmaSupported(context, mSubId), MobileNetworkUtils.isTdscdmaSupported(context, mSubId),
MobileNetworkUtils.activeNetworkIsCellular(context), MobileNetworkUtils.activeNetworkIsCellular(context),
SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager) SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager),
mTelephonyManager.isDataRoamingEnabled()
); );
} }
@@ -446,9 +461,10 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
} }
if (!mSubscriptionInfoMap.isEmpty()) { if (!mSubscriptionInfoMap.isEmpty()) {
mSubscriptionInfoMap.forEach((key, value) -> { Iterator<Integer> iterator = mSubscriptionInfoMap.keySet().iterator();
deleteAllInfoBySubId(String.valueOf(key)); while (iterator.hasNext()) {
}); deleteAllInfoBySubId(String.valueOf(iterator.next()));
}
} }
} }
} }

View File

@@ -23,7 +23,6 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings; import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.text.TextUtils; import android.text.TextUtils;
@@ -40,8 +39,8 @@ import com.android.settings.Settings.MobileNetworkActivity;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.datausage.BillingCyclePreferenceController; import com.android.settings.datausage.BillingCyclePreferenceController;
import com.android.settings.datausage.DataUsageSummaryPreferenceController; import com.android.settings.datausage.DataUsageSummaryPreferenceController;
import com.android.settings.network.ActiveSubscriptionsListener;
import com.android.settings.network.CarrierWifiTogglePreferenceController; import com.android.settings.network.CarrierWifiTogglePreferenceController;
import com.android.settings.network.MobileNetworkRepository;
import com.android.settings.network.SubscriptionUtil; import com.android.settings.network.SubscriptionUtil;
import com.android.settings.network.telephony.cdma.CdmaSubscriptionPreferenceController; import com.android.settings.network.telephony.cdma.CdmaSubscriptionPreferenceController;
import com.android.settings.network.telephony.cdma.CdmaSystemSelectPreferenceController; import com.android.settings.network.telephony.cdma.CdmaSystemSelectPreferenceController;
@@ -50,15 +49,26 @@ import com.android.settings.network.telephony.gsm.OpenNetworkSelectPagePreferenc
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.wifi.WifiPickerTrackerHelper; import com.android.settings.wifi.WifiPickerTrackerHelper;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.mobile.dataservice.DataServiceUtils;
import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
import com.android.settingslib.mobile.dataservice.UiccInfoEntity;
import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer; import java.util.function.Consumer;
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class MobileNetworkSettings extends AbstractMobileNetworkSettings { public class MobileNetworkSettings extends AbstractMobileNetworkSettings implements
MobileNetworkRepository.MobileNetworkCallback {
private static final String LOG_TAG = "NetworkSettings"; private static final String LOG_TAG = "NetworkSettings";
public static final int REQUEST_CODE_EXIT_ECM = 17; public static final int REQUEST_CODE_EXIT_ECM = 17;
@@ -66,10 +76,14 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
@VisibleForTesting @VisibleForTesting
static final String KEY_CLICKED_PREF = "key_clicked_pref"; static final String KEY_CLICKED_PREF = "key_clicked_pref";
private static final String KEY_ROAMING_PREF = "button_roaming_key";
//String keys for preference lookup //String keys for preference lookup
private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key"; private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key";
private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key"; private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key";
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
private TelephonyManager mTelephonyManager; private TelephonyManager mTelephonyManager;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -79,9 +93,11 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
private UserManager mUserManager; private UserManager mUserManager;
private String mClickedPrefKey; private String mClickedPrefKey;
private ActiveSubscriptionsListener mActiveSubscriptionsListener; private MobileNetworkRepository mMobileNetworkRepository;
private boolean mDropFirstSubscriptionChangeNotify; private List<SubscriptionInfoEntity> mSubInfoEntityList = new ArrayList<>();
private int mActiveSubscriptionsListenerCount; private Map<Integer, SubscriptionInfoEntity> mSubscriptionInfoMap = new HashMap<>();
private SubscriptionInfoEntity mSubscriptionInfoEntity;
private MobileNetworkInfoEntity mMobileNetworkInfoEntity;
public MobileNetworkSettings() { public MobileNetworkSettings() {
super(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS); super(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
@@ -138,12 +154,21 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
MobileNetworkUtils.getSearchableSubscriptionId(context)); MobileNetworkUtils.getSearchableSubscriptionId(context));
Log.d(LOG_TAG, "display subId from getArguments(): " + mSubId); Log.d(LOG_TAG, "display subId from getArguments(): " + mSubId);
} }
mMobileNetworkRepository = MobileNetworkRepository.create(context, this);
if (!SubscriptionManager.isValidSubscriptionId(mSubId)) { mExecutor.execute(() -> {
mSubscriptionInfoEntity = mMobileNetworkRepository.getSubInfoById(
String.valueOf(mSubId));
mMobileNetworkInfoEntity =
mMobileNetworkRepository.queryMobileNetworkInfoBySubId(
String.valueOf(mSubId));
});
if (mSubId <= SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
return Arrays.asList(); return Arrays.asList();
} }
return Arrays.asList( return Arrays.asList(
new DataUsageSummaryPreferenceController(getActivity(), getSettingsLifecycle(), new DataUsageSummaryPreferenceController(getActivity(), getSettingsLifecycle(),
this, mSubId),
new RoamingPreferenceController(context, KEY_ROAMING_PREF, getSettingsLifecycle(),
this, mSubId)); this, mSubId));
} }
@@ -151,28 +176,38 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
Intent intent = getIntent(); if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
SubscriptionInfo info = SubscriptionUtil.getSubscriptionOrDefault(context, mSubId);
if (info == null) {
Log.d(LOG_TAG, "Invalid subId request " + mSubId); Log.d(LOG_TAG, "Invalid subId request " + mSubId);
return; return;
} }
int oldSubId = mSubId; Intent intent = getIntent();
updateSubscriptions(info); if (intent != null) {
// If the subscription has changed or the new intent does not contain the opt in action, int updateSubscriptionIndex = intent.getIntExtra(Settings.EXTRA_SUB_ID,
// remove the old discovery dialog. If the activity is being recreated, we will see SubscriptionManager.INVALID_SUBSCRIPTION_ID);
// onCreate -> onNewIntent, so the dialog will first be recreated for the old subscription
// and then removed. if (updateSubscriptionIndex != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
if (!MobileNetworkActivity.doesIntentContainOptInAction(intent)) { int oldSubId = mSubId;
removeContactDiscoveryDialog(oldSubId); mSubId = updateSubscriptionIndex;
} // If the subscription has changed or the new intent does not contain the opt in
// action,
// remove the old discovery dialog. If the activity is being recreated, we will see
// onCreate -> onNewIntent, so the dialog will first be recreated for the old
// subscription
// and then removed.
if (updateSubscriptionIndex != oldSubId
|| !MobileNetworkActivity.doesIntentContainOptInAction(intent)) {
removeContactDiscoveryDialog(oldSubId);
}
// evaluate showing the new discovery dialog if this intent contains an action to
// show the
// opt-in.
if (MobileNetworkActivity.doesIntentContainOptInAction(intent)) {
showContactDiscoveryDialog();
}
}
// evaluate showing the new discovery dialog if this intent contains an action to show the
// opt-in.
if (MobileNetworkActivity.doesIntentContainOptInAction(intent)) {
showContactDiscoveryDialog(
SubscriptionUtil.getSubscriptionOrDefault(context, mSubId));
} }
final DataUsageSummaryPreferenceController dataUsageSummaryPreferenceController = final DataUsageSummaryPreferenceController dataUsageSummaryPreferenceController =
@@ -194,7 +229,13 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
use(MobileDataPreferenceController.class).setWifiPickerTrackerHelper( use(MobileDataPreferenceController.class).setWifiPickerTrackerHelper(
new WifiPickerTrackerHelper(getSettingsLifecycle(), context, new WifiPickerTrackerHelper(getSettingsLifecycle(), context,
null /* WifiPickerTrackerCallback */)); null /* WifiPickerTrackerCallback */));
use(RoamingPreferenceController.class).init(getFragmentManager(), mSubId);
final RoamingPreferenceController roamingPreferenceController =
use(RoamingPreferenceController.class);
if (roamingPreferenceController != null) {
roamingPreferenceController.init(getFragmentManager(), mSubId,
mMobileNetworkInfoEntity);
}
use(ApnPreferenceController.class).init(mSubId); use(ApnPreferenceController.class).init(mSubId);
use(CarrierPreferenceController.class).init(mSubId); use(CarrierPreferenceController.class).init(mSubId);
use(DataUsagePreferenceController.class).init(mSubId); use(DataUsagePreferenceController.class).init(mSubId);
@@ -258,68 +299,36 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
mMobileNetworkRepository.addRegister(this);
// TODO: remove log after fixing b/182326102 // TODO: remove log after fixing b/182326102
Log.d(LOG_TAG, "onResume() subId=" + mSubId); Log.d(LOG_TAG, "onResume() subId=" + mSubId);
if (mActiveSubscriptionsListener == null) {
mActiveSubscriptionsListener = new ActiveSubscriptionsListener(
getContext().getMainLooper(), getContext(), mSubId) {
public void onChanged() {
onSubscriptionDetailChanged();
}
};
mDropFirstSubscriptionChangeNotify = true;
}
mActiveSubscriptionsListener.start();
} }
private void onSubscriptionDetailChanged() { private void onSubscriptionDetailChanged() {
if (mDropFirstSubscriptionChangeNotify) {
mDropFirstSubscriptionChangeNotify = false;
Log.d(LOG_TAG, "Callback during onResume()");
return;
}
final SubscriptionInfo subInfo = SubscriptionUtil if (mSubscriptionInfoEntity != null) {
.getSubscriptionOrDefault(getContext(), mSubId);
if (subInfo != null) {
/** /**
* Update the title when SIM stats got changed * Update the title when SIM stats got changed
*/ */
final Consumer<Activity> renameTitle = activity -> { final Consumer<Activity> renameTitle = activity -> {
if (activity != null && !activity.isFinishing()) { if (activity != null && !activity.isFinishing()) {
if (activity instanceof SettingsActivity) { if (activity instanceof SettingsActivity) {
final CharSequence displayName = SubscriptionUtil ((SettingsActivity) activity).setTitle(mSubscriptionInfoEntity.uniqueName);
.getUniqueSubscriptionDisplayName(subInfo, activity);
((SettingsActivity)activity).setTitle(displayName);
} }
} }
}; };
ThreadUtils.postOnMainThread(() -> renameTitle.accept(getActivity())); ThreadUtils.postOnMainThread(() -> {
renameTitle.accept(getActivity());
redrawPreferenceControllers();
});
} }
mActiveSubscriptionsListenerCount++;
if (mActiveSubscriptionsListenerCount != 1) {
return;
}
ThreadUtils.postOnMainThread(() -> {
if (subInfo == null) {
finishFragment();
return;
}
mActiveSubscriptionsListenerCount = 0;
redrawPreferenceControllers();
});
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
if (mActiveSubscriptionsListener != null) {
mActiveSubscriptionsListener.stop();
}
super.onDestroy(); super.onDestroy();
mMobileNetworkRepository.removeRegister();
} }
@VisibleForTesting @VisibleForTesting
@@ -375,7 +384,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (SubscriptionManager.isValidSubscriptionId(mSubId)) { if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
final MenuItem item = menu.add(Menu.NONE, R.id.edit_sim_name, Menu.NONE, final MenuItem item = menu.add(Menu.NONE, R.id.edit_sim_name, Menu.NONE,
R.string.mobile_network_sim_name); R.string.mobile_network_sim_name);
item.setIcon(com.android.internal.R.drawable.ic_mode_edit); item.setIcon(com.android.internal.R.drawable.ic_mode_edit);
@@ -386,7 +395,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
@Override @Override
public boolean onOptionsItemSelected(MenuItem menuItem) { public boolean onOptionsItemSelected(MenuItem menuItem) {
if (SubscriptionManager.isValidSubscriptionId(mSubId)) { if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
if (menuItem.getItemId() == R.id.edit_sim_name) { if (menuItem.getItemId() == R.id.edit_sim_name) {
RenameMobileNetworkDialogFragment.newInstance(mSubId).show( RenameMobileNetworkDialogFragment.newInstance(mSubId).show(
getFragmentManager(), RenameMobileNetworkDialogFragment.TAG); getFragmentManager(), RenameMobileNetworkDialogFragment.TAG);
@@ -422,18 +431,18 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
} }
} }
private void showContactDiscoveryDialog(SubscriptionInfo info) { private void showContactDiscoveryDialog() {
if (info == null) { ContactDiscoveryDialogFragment fragment = getContactDiscoveryFragment(mSubId);
Log.d(LOG_TAG, "Invalid subId request " + mSubId);
if (mSubscriptionInfoEntity == null) {
Log.d(LOG_TAG, "Zoey, showContactDiscoveryDialog, Invalid subId request " + mSubId);
onDestroy(); onDestroy();
return; return;
} }
CharSequence carrierName = SubscriptionUtil.getUniqueSubscriptionDisplayName(info,
getContext());
ContactDiscoveryDialogFragment fragment = getContactDiscoveryFragment(mSubId);
if (fragment == null) { if (fragment == null) {
fragment = ContactDiscoveryDialogFragment.newInstance(mSubId, carrierName); fragment = ContactDiscoveryDialogFragment.newInstance(mSubId,
mSubscriptionInfoEntity.uniqueName);
} }
// Only try to show the dialog if it has not already been added, otherwise we may // Only try to show the dialog if it has not already been added, otherwise we may
// accidentally add it multiple times, causing multiple dialogs. // accidentally add it multiple times, causing multiple dialogs.
@@ -443,12 +452,53 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
} }
} }
private void updateSubscriptions(SubscriptionInfo subscription) { @Override
if (subscription == null) { public void onAvailableSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
return; }
}
final int subscriptionIndex = subscription.getSubscriptionId();
mSubId = subscriptionIndex; @Override
public void onActiveSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
if (DataServiceUtils.shouldUpdateEntityList(mSubInfoEntityList, subInfoEntityList)) {
// Check the current subId is existed or not, if so, finish it.
if (!mSubscriptionInfoMap.isEmpty()) {
// Check each subInfo and remove it in the map based on the new list.
for (SubscriptionInfoEntity entity : subInfoEntityList) {
mSubscriptionInfoMap.remove(Integer.parseInt(entity.subId));
}
Iterator<Integer> iterator = mSubscriptionInfoMap.keySet().iterator();
while (iterator.hasNext()) {
if (iterator.next() == mSubId) {
finishFragment();
return;
}
}
}
mSubInfoEntityList = subInfoEntityList;
mSubInfoEntityList.forEach(entity -> {
int subId = Integer.parseInt(entity.subId);
mSubscriptionInfoMap.put(subId, entity);
if (subId == mSubId) {
mSubscriptionInfoEntity = entity;
onSubscriptionDetailChanged();
}
});
}
}
@Override
public void onAllUiccInfoChanged(List<UiccInfoEntity> uiccInfoEntityList) {
}
@Override
public void onAllMobileNetworkInfoChanged(
List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList) {
}
@Override
public void onAirplaneModeChanged(boolean enabled) {
} }
} }

View File

@@ -16,6 +16,9 @@
package com.android.settings.network.telephony; package com.android.settings.network.telephony;
import static androidx.lifecycle.Lifecycle.Event.ON_START;
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
import android.content.Context; import android.content.Context;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import android.provider.Settings; import android.provider.Settings;
@@ -24,22 +27,32 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.util.Log; import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.settings.network.GlobalSettingsChangeListener; import com.android.settings.network.GlobalSettingsChangeListener;
import com.android.settings.network.MobileNetworkRepository;
import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.mobile.dataservice.DataServiceUtils;
import com.android.settingslib.core.lifecycle.events.OnStop; import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
import com.android.settingslib.mobile.dataservice.UiccInfoEntity;
import java.util.ArrayList;
import java.util.List;
/** /**
* Preference controller for "Roaming" * Preference controller for "Roaming"
*/ */
public class RoamingPreferenceController extends TelephonyTogglePreferenceController implements public class RoamingPreferenceController extends TelephonyTogglePreferenceController implements
LifecycleObserver, OnStart, OnStop { LifecycleObserver, MobileNetworkRepository.MobileNetworkCallback {
private static final String TAG = "RoamingController"; private static final String TAG = "RoamingController";
private static final String DIALOG_TAG = "MobileDataDialog"; private static final String DIALOG_TAG = "MobileDataDialog";
@@ -47,6 +60,9 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
private RestrictedSwitchPreference mSwitchPreference; private RestrictedSwitchPreference mSwitchPreference;
private TelephonyManager mTelephonyManager; private TelephonyManager mTelephonyManager;
private CarrierConfigManager mCarrierConfigManager; private CarrierConfigManager mCarrierConfigManager;
protected MobileNetworkRepository mMobileNetworkRepository;
protected LifecycleOwner mLifecycleOwner;
private List<MobileNetworkInfoEntity> mMobileNetworkInfoEntityList = new ArrayList<>();
/** /**
* There're 2 listeners both activated at the same time. * There're 2 listeners both activated at the same time.
@@ -59,10 +75,18 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
@VisibleForTesting @VisibleForTesting
FragmentManager mFragmentManager; FragmentManager mFragmentManager;
MobileNetworkInfoEntity mMobileNetworkInfoEntity;
public RoamingPreferenceController(Context context, String key) { public RoamingPreferenceController(Context context, String key, Lifecycle lifecycle,
LifecycleOwner lifecycleOwner, int subId) {
super(context, key); super(context, key);
mSubId = subId;
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
mMobileNetworkRepository = MobileNetworkRepository.createBySubId(context, this, mSubId);
mLifecycleOwner = lifecycleOwner;
if (lifecycle != null) {
lifecycle.addObserver(this);
}
} }
@Override @Override
@@ -75,8 +99,9 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
return AVAILABLE; return AVAILABLE;
} }
@Override @OnLifecycleEvent(ON_START)
public void onStart() { public void onStart() {
mMobileNetworkRepository.addRegister(mLifecycleOwner);
if (mListener == null) { if (mListener == null) {
mListener = new GlobalSettingsChangeListener(mContext, mListener = new GlobalSettingsChangeListener(mContext,
Settings.Global.DATA_ROAMING) { Settings.Global.DATA_ROAMING) {
@@ -100,8 +125,9 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
}; };
} }
@Override @OnLifecycleEvent(ON_STOP)
public void onStop() { public void onStop() {
mMobileNetworkRepository.removeRegister();
stopMonitor(); stopMonitor();
stopMonitorSubIdSpecific(); stopMonitorSubIdSpecific();
} }
@@ -114,7 +140,7 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
@Override @Override
public int getAvailabilityStatus(int subId) { public int getAvailabilityStatus(int subId) {
return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
? AVAILABLE ? AVAILABLE
: AVAILABLE_UNSEARCHABLE; : AVAILABLE_UNSEARCHABLE;
} }
@@ -135,19 +161,26 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
super.updateState(preference); super.updateState(preference);
final RestrictedSwitchPreference switchPreference = (RestrictedSwitchPreference) preference; mSwitchPreference = (RestrictedSwitchPreference) preference;
if (!switchPreference.isDisabledByAdmin()) { update();
switchPreference.setEnabled(mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID); }
switchPreference.setChecked(isChecked());
private void update() {
if (mSwitchPreference == null) {
return;
}
if (!mSwitchPreference.isDisabledByAdmin()) {
mSwitchPreference.setEnabled(mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mSwitchPreference.setChecked(isChecked());
} }
} }
@VisibleForTesting @VisibleForTesting
boolean isDialogNeeded() { boolean isDialogNeeded() {
final boolean isRoamingEnabled = mTelephonyManager.isDataRoamingEnabled(); final boolean isRoamingEnabled = mMobileNetworkInfoEntity == null ? false
: mMobileNetworkInfoEntity.isDataRoamingEnabled;
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId( final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(
mSubId); mSubId);
// Need dialog if we need to turn on roaming and the roaming charge indication is allowed // Need dialog if we need to turn on roaming and the roaming charge indication is allowed
if (!isRoamingEnabled && (carrierConfig == null || !carrierConfig.getBoolean( if (!isRoamingEnabled && (carrierConfig == null || !carrierConfig.getBoolean(
CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL))) { CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL))) {
@@ -158,12 +191,14 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
@Override @Override
public boolean isChecked() { public boolean isChecked() {
return mTelephonyManager.isDataRoamingEnabled(); return mMobileNetworkInfoEntity == null ? false
: mMobileNetworkInfoEntity.isDataRoamingEnabled;
} }
public void init(FragmentManager fragmentManager, int subId) { public void init(FragmentManager fragmentManager, int subId, MobileNetworkInfoEntity entity) {
mFragmentManager = fragmentManager; mFragmentManager = fragmentManager;
mSubId = subId; mSubId = subId;
mMobileNetworkInfoEntity = entity;
mTelephonyManager = mContext.getSystemService(TelephonyManager.class); mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
return; return;
@@ -197,4 +232,42 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
mListenerForSubId = null; mListenerForSubId = null;
} }
} }
@VisibleForTesting
public void setMobileNetworkInfoEntity(MobileNetworkInfoEntity mobileNetworkInfoEntity) {
mMobileNetworkInfoEntity = mobileNetworkInfoEntity;
}
@Override
public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
}
@Override
public void onAvailableSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
}
@Override
public void onActiveSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
}
@Override
public void onAllUiccInfoChanged(List<UiccInfoEntity> uiccInfoEntityList) {
}
@Override
public void onAllMobileNetworkInfoChanged(
List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList) {
if (DataServiceUtils.shouldUpdateEntityList(mMobileNetworkInfoEntityList,
mobileNetworkInfoEntityList)) {
mMobileNetworkInfoEntityList = mobileNetworkInfoEntityList;
mMobileNetworkInfoEntityList.forEach(entity -> {
if (Integer.parseInt(entity.subId) == mSubId) {
mMobileNetworkInfoEntity = entity;
update();
refreshSummary(mSwitchPreference);
return;
}
});
}
}
} }

View File

@@ -23,12 +23,14 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.content.Context; import android.content.Context;
import android.os.Looper;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager; import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
@@ -36,12 +38,16 @@ import android.telephony.TelephonyManager;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
import androidx.test.annotation.UiThreadTest; import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -65,15 +71,25 @@ public class RoamingPreferenceControllerTest {
private FragmentTransaction mFragmentTransaction; private FragmentTransaction mFragmentTransaction;
@Mock @Mock
private CarrierConfigManager mCarrierConfigManager; private CarrierConfigManager mCarrierConfigManager;
@Mock
private Lifecycle mLifecycle;
@Mock
private LifecycleOwner mLifecycleOwner;
private LifecycleRegistry mLifecycleRegistry;
private RoamingPreferenceController mController; private RoamingPreferenceController mController;
private RestrictedSwitchPreference mPreference; private RestrictedSwitchPreference mPreference;
private Context mContext; private Context mContext;
private MobileNetworkInfoEntity mMobileNetworkInfoEntity;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
if (Looper.myLooper() == null) {
Looper.prepare();
}
mContext = spy(ApplicationProvider.getApplicationContext()); mContext = spy(ApplicationProvider.getApplicationContext());
doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE); doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
doReturn(mSubscriptionManager).when(mContext).getSystemService( doReturn(mSubscriptionManager).when(mContext).getSystemService(
@@ -87,11 +103,21 @@ public class RoamingPreferenceControllerTest {
doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction(); doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction();
mPreference = spy(new RestrictedSwitchPreference(mContext)); mPreference = spy(new RestrictedSwitchPreference(mContext));
mController = spy(new RoamingPreferenceController(mContext, "roaming")); mController = spy(
mController.init(mFragmentManager, SUB_ID); new RoamingPreferenceController(mContext, "roaming", mLifecycle, mLifecycleOwner,
SUB_ID));
mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner);
when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
mController.init(mFragmentManager, SUB_ID, mMobileNetworkInfoEntity);
mPreference.setKey(mController.getPreferenceKey()); mPreference.setKey(mController.getPreferenceKey());
} }
private MobileNetworkInfoEntity setupMobileNetworkInfoEntity(String subId,
boolean isDataRoaming) {
return new MobileNetworkInfoEntity(subId, false, false, true, false, false, false, false,
false, false, false, isDataRoaming);
}
@Test @Test
public void getAvailabilityStatus_validSubId_returnAvailable() { public void getAvailabilityStatus_validSubId_returnAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo( assertThat(mController.getAvailabilityStatus()).isEqualTo(
@@ -100,9 +126,11 @@ public class RoamingPreferenceControllerTest {
@Test @Test
public void getAvailabilityStatus_invalidSubId_returnUnsearchable() { public void getAvailabilityStatus_invalidSubId_returnUnsearchable() {
mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID); mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
mMobileNetworkInfoEntity);
assertThat(mController.getAvailabilityStatus()).isEqualTo( assertThat(mController.getAvailabilityStatus(
SubscriptionManager.INVALID_SUBSCRIPTION_ID)).isEqualTo(
BasePreferenceController.AVAILABLE_UNSEARCHABLE); BasePreferenceController.AVAILABLE_UNSEARCHABLE);
} }
@@ -111,14 +139,16 @@ public class RoamingPreferenceControllerTest {
final PersistableBundle bundle = new PersistableBundle(); final PersistableBundle bundle = new PersistableBundle();
bundle.putBoolean(CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL, false); bundle.putBoolean(CarrierConfigManager.KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
doReturn(false).when(mTelephonyManager).isDataRoamingEnabled(); mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false);
mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
assertThat(mController.isDialogNeeded()).isTrue(); assertThat(mController.isDialogNeeded()).isTrue();
} }
@Test @Test
public void isDialogNeeded_roamingEnabled_returnFalse() { public void isDialogNeeded_roamingEnabled_returnFalse() {
doReturn(true).when(mTelephonyManager).isDataRoamingEnabled(); mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
assertThat(mController.isDialogNeeded()).isFalse(); assertThat(mController.isDialogNeeded()).isFalse();
} }
@@ -126,10 +156,10 @@ public class RoamingPreferenceControllerTest {
@Test @Test
@UiThreadTest @UiThreadTest
public void setChecked_needDialog_showDialog() { public void setChecked_needDialog_showDialog() {
doReturn(false).when(mTelephonyManager).isDataRoamingEnabled(); mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false);
mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
doReturn(null).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); doReturn(null).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
mController.setChecked(true); mController.setChecked(true);
verify(mFragmentManager).beginTransaction(); verify(mFragmentManager).beginTransaction();
@@ -137,7 +167,11 @@ public class RoamingPreferenceControllerTest {
@Test @Test
public void updateState_invalidSubId_disabled() { public void updateState_invalidSubId_disabled() {
mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID); mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(
String.valueOf(SubscriptionManager.INVALID_SUBSCRIPTION_ID), false);
mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
mMobileNetworkInfoEntity);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -146,7 +180,8 @@ public class RoamingPreferenceControllerTest {
@Test @Test
public void updateState_validSubId_enabled() { public void updateState_validSubId_enabled() {
doReturn(true).when(mTelephonyManager).isDataRoamingEnabled(); mMobileNetworkInfoEntity = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
mController.setMobileNetworkInfoEntity(mMobileNetworkInfoEntity);
mController.updateState(mPreference); mController.updateState(mPreference);
@@ -191,7 +226,7 @@ public class RoamingPreferenceControllerTest {
@Test @Test
public void getAvailabilityStatus_forceHomeNetworkIsTrue_shouldReturnConditionallyAvailable() { public void getAvailabilityStatus_forceHomeNetworkIsTrue_shouldReturnConditionallyAvailable() {
final PersistableBundle bundle = new PersistableBundle(); final PersistableBundle bundle = new PersistableBundle();
bundle.putBoolean(CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL, false); bundle.putBoolean(CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL, true);
doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE); assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);