Reduce Repetitive Calls to TelephonyManager From Telephony2gUpdater
Only update allowed network status for a subId if one of the following
conditions is met:
1. The subId is newly added.
2. The DISALLOW_CELLULAR_2G user restriction changes, in which case all
subIds are updated.
Also fixes a bug in which hidden subscriptions were not being updated.
Test: atest Telephony2gUpdaterTest
Test: Manual testing w/ TestDPC app and inserting and removing SIM
Bug: 263869683
Change-Id: I9a59046fbfb5da2525e208ea7e26973fa62792e9
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index bdbd5f9..ba8b330 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -2347,8 +2347,7 @@
mRadioInterfaceCapabilities = RadioInterfaceCapabilityController.getInstance();
mNotifyUserActivity = new AtomicBoolean(false);
PropertyInvalidatedCache.invalidateCache(TelephonyManager.CACHE_KEY_PHONE_ACCOUNT_TO_SUBID);
- mTelephony2gUpdater = new Telephony2gUpdater(
- Executors.newSingleThreadExecutor(), mApp);
+ mTelephony2gUpdater = new Telephony2gUpdater(mApp);
mTelephony2gUpdater.init();
publish();
}
diff --git a/src/com/android/phone/Telephony2gUpdater.java b/src/com/android/phone/Telephony2gUpdater.java
index 0919385..baaa684 100644
--- a/src/com/android/phone/Telephony2gUpdater.java
+++ b/src/com/android/phone/Telephony2gUpdater.java
@@ -30,8 +30,13 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.RILConstants;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
/**
* A {@link BroadcastReceiver} that ensures that user restrictions are correctly applied to
@@ -39,27 +44,50 @@
* This includes handling broadcasts from user restriction state changes, as well as ensuring that
* SIM-specific settings are correctly applied when new subscriptions become active.
*
+ * <p>
* Callers are expected to call {@code init()} and keep an instance of this class alive.
+ * </p>
*/
public class Telephony2gUpdater extends BroadcastReceiver {
- private static final String TAG = "TelephonyUserManagerReceiver";
+ private static final String TAG = "Telephony2gUpdater";
// We can't interact with the HAL on the main thread of the phone process (where
// receivers are run by default), so we execute our logic from a separate thread.
+ // The correctness of this implementation relies heavily on this executor ensuring
+ // tasks are serially executed i.e. ExecutorService.newSingleThreadExecutor()
private final Executor mExecutor;
private final Context mContext;
private final long mBaseAllowedNetworks;
- public Telephony2gUpdater(Executor executor, Context context) {
- this(executor, context,
+ private UserManager mUserManager;
+ private TelephonyManager mTelephonyManager;
+ private SubscriptionManager mSubscriptionManager;
+
+ // The current subscription ids
+ // Ensure this value is never accessed concurrently
+ private Set<Integer> mCurrentSubscriptions;
+ // We keep track of the last value to avoid updating when unrelated user restrictions change
+ // Ensure this value is never accessed concurrently
+ private boolean mDisallowCellular2gRestriction;
+
+ public Telephony2gUpdater(Context context) {
+ this(Executors.newSingleThreadExecutor(), context,
RadioAccessFamily.getRafFromNetworkType(RILConstants.PREFERRED_NETWORK_MODE));
}
- public Telephony2gUpdater(Executor executor, Context context,
- long baseAllowedNetworks) {
+ @VisibleForTesting
+ public Telephony2gUpdater(Executor executor, Context context, long baseAllowedNetworks) {
mExecutor = executor;
mContext = context;
mBaseAllowedNetworks = baseAllowedNetworks;
+
+ mUserManager = mContext.getSystemService(UserManager.class);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+
+ // All user restrictions are false by default
+ mDisallowCellular2gRestriction = false;
+ mCurrentSubscriptions = new HashSet<>();
}
/**
@@ -80,41 +108,42 @@
Log.i(TAG, "Received callback for action " + intent.getAction());
final PendingResult result = goAsync();
mExecutor.execute(() -> {
- Log.i(TAG, "Running handler for action " + intent.getAction());
- handleUserRestrictionsChanged(context);
- result.finish();
+ boolean disallow2g = mUserManager.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G);
+ if (mDisallowCellular2gRestriction == disallow2g) {
+ Log.i(TAG, "No update to DISALLOW_CELLULAR_2G restriction.");
+ return;
+ }
+
+ mDisallowCellular2gRestriction = disallow2g;
+
+ Log.i(TAG, "Running handler for all subscriptions based on DISALLOW_CELLULAR_2G change."
+ + " Restriction value: " + mDisallowCellular2gRestriction);
+ handleUserRestrictionsChanged(mCurrentSubscriptions);
+ if (result != null) {
+ result.finish();
+ }
});
}
/**
- * Update all active subscriptions with allowed network types depending on the current state
- * of the {@link UserManager.DISALLOW_2G}.
+ * Update subscriptions with allowed network types depending on the current state
+ * of the {@link UserManager#DISALLOW_CELLULAR_2G}.
+ *
+ * @param subIds A list of subIds to update.
*/
- @VisibleForTesting
- public void handleUserRestrictionsChanged(Context context) {
- UserManager um = context.getSystemService(UserManager.class);
- TelephonyManager tm = context.getSystemService(TelephonyManager.class);
- SubscriptionManager sm = context.getSystemService(SubscriptionManager.class);
+ private void handleUserRestrictionsChanged(Collection<Integer> subIds) {
final long twoGBitmask = TelephonyManager.NETWORK_CLASS_BITMASK_2G;
- boolean shouldDisable2g = um.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G);
-
- // This is expected when subscription info cannot be determined. We'll get another
- // callback in the future from our SubscriptionListener once we have valid subscriptions.
- List<SubscriptionInfo> subscriptionInfoList = sm.getAvailableSubscriptionInfoList();
- if (subscriptionInfoList == null) {
- return;
- }
-
long allowedNetworkTypes = mBaseAllowedNetworks;
// 2G device admin controls are global
- for (SubscriptionInfo info : subscriptionInfoList) {
- TelephonyManager telephonyManager = tm.createForSubscriptionId(
- info.getSubscriptionId());
- if (shouldDisable2g) {
+ for (Integer subId : subIds) {
+ TelephonyManager telephonyManager = mTelephonyManager.createForSubscriptionId(subId);
+ if (mDisallowCellular2gRestriction) {
+ Log.i(TAG, "Disabling 2g based on user restriction for subId: " + subId);
allowedNetworkTypes &= ~twoGBitmask;
} else {
+ Log.i(TAG, "Enabling 2g based on user restriction for subId: " + subId);
allowedNetworkTypes |= twoGBitmask;
}
telephonyManager.setAllowedNetworkTypesForReason(
@@ -126,8 +155,30 @@
private class SubscriptionListener extends SubscriptionManager.OnSubscriptionsChangedListener {
@Override
public void onSubscriptionsChanged() {
- Log.i(TAG, "Running handler for subscription change.");
- handleUserRestrictionsChanged(mContext);
+ // Note that this entire callback gets invoked in the single threaded executor
+ List<SubscriptionInfo> allSubscriptions =
+ mSubscriptionManager.getCompleteActiveSubscriptionInfoList();
+
+ HashSet<Integer> updatedSubIds = new HashSet<>(allSubscriptions.size());
+ List<Integer> newSubIds = new ArrayList<>();
+
+ for (SubscriptionInfo info : allSubscriptions) {
+ updatedSubIds.add(info.getSubscriptionId());
+ if (!mCurrentSubscriptions.contains(info.getSubscriptionId())) {
+ newSubIds.add(info.getSubscriptionId());
+ }
+ }
+
+ mCurrentSubscriptions = updatedSubIds;
+
+ if (newSubIds.isEmpty()) {
+ Log.d(TAG, "No new subIds. Skipping update.");
+ return;
+ }
+
+ Log.i(TAG, "New subscriptions found. Running handler to update 2g restrictions with "
+ + "subIds " + newSubIds.toString());
+ handleUserRestrictionsChanged(newSubIds);
}
}