Support dynamically update IMSI

Currently, NetworkStatsSubscriptionsMonitor will skip the
listener registration until the IMSI is available to deal
with SIM PIN locked case. However, this solution can only
handle the case that IMSI changes from/to null. And it also
relies on the assumption that IMSI never changes for a subId.

Thus, support dynamically update IMSI to handle IMSI changes
more robustly.

This patch also address leftover comments at ag/12400327.

Test: enable SIM PIN and manually test
Test: atest NetworkStatsSubscriptionsMonitorTest#testSubscriberIdUnavailable
Test: atest NetworkStatsSubscriptionsMonitorTest#testSubscriberIdChanged
Test: ./out/host/linux-x86/bin/statsd_testdrive 10082
Bug: 160941101

Change-Id: I625a5b10ee4806f6fee99c2d9d6c5e7977ff785e
This commit is contained in:
junyulai
2020-08-20 18:23:57 +08:00
parent 4e4e192c97
commit f571003794

View File

@@ -30,6 +30,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.CollectionUtils; import com.android.internal.util.CollectionUtils;
@@ -94,39 +95,41 @@ public class NetworkStatsSubscriptionsMonitor extends
// also needed to track CBRS. // also needed to track CBRS.
final List<Integer> newSubs = getActiveSubIdList(mSubscriptionManager); final List<Integer> newSubs = getActiveSubIdList(mSubscriptionManager);
for (final int subId : newSubs) { // IMSI is needed for every newly added sub. Listener stores subscriberId into it to
final RatTypeListener match = CollectionUtils.find(mRatListeners, // prevent binder call to telephony when querying RAT. Keep listener registration with empty
it -> it.mSubId == subId); // IMSI is meaningless since the RAT type changed is ambiguous for multi-SIM if reported
if (match != null) continue; // with empty IMSI. So filter the subs w/o a valid IMSI to prevent such registration.
final List<Pair<Integer, String>> filteredNewSubs =
CollectionUtils.mapNotNull(newSubs, subId -> {
final String subscriberId = mTeleManager.getSubscriberId(subId);
return TextUtils.isEmpty(subscriberId) ? null : new Pair(subId, subscriberId);
});
// Create listener for every newly added sub. Also store subscriberId into it to for (final Pair<Integer, String> sub : filteredNewSubs) {
// prevent binder call to telephony when querying RAT. If the subscriberId is empty // Fully match listener with subId and IMSI, since in some rare cases, IMSI might be
// for any reason, such as SIM PIN locked, skip registration. // suddenly change regardless of subId, such as switch IMSI feature in modem side.
// SubscriberId will be unavailable again if 1. modem crashed 2. reboot // If that happens, register new listener with new IMSI and remove old one later.
// 3. re-insert SIM. If that happens, the listeners will be eventually synchronized if (CollectionUtils.find(mRatListeners,
// with active sub list once all subscriberIds are ready. it -> it.equalsKey(sub.first, sub.second)) != null) {
final String subscriberId = mTeleManager.getSubscriberId(subId);
if (TextUtils.isEmpty(subscriberId)) {
Log.d(NetworkStatsService.TAG, "Empty subscriberId for newly added sub "
+ subId + ", skip listener registration");
continue; continue;
} }
final RatTypeListener listener = final RatTypeListener listener =
new RatTypeListener(mExecutor, this, subId, subscriberId); new RatTypeListener(mExecutor, this, sub.first, sub.second);
mRatListeners.add(listener); mRatListeners.add(listener);
// Register listener to the telephony manager that associated with specific sub. // Register listener to the telephony manager that associated with specific sub.
mTeleManager.createForSubscriptionId(subId) mTeleManager.createForSubscriptionId(sub.first)
.listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + subId); Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + sub.first);
} }
for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
// If the new list contains the subId of the listener, keeps it. // If there is no subId and IMSI matched the listener, removes it.
final Integer match = CollectionUtils.find(newSubs, it -> it == listener.mSubId); if (CollectionUtils.find(filteredNewSubs,
if (match != null) continue; it -> listener.equalsKey(it.first, it.second)) == null) {
handleRemoveRatTypeListener(listener);
handleRemoveRatTypeListener(listener); }
} }
} }
@@ -232,5 +235,9 @@ public class NetworkStatsSubscriptionsMonitor extends
public int getSubId() { public int getSubId() {
return mSubId; return mSubId;
} }
boolean equalsKey(int subId, @NonNull String subscriberId) {
return mSubId == subId && TextUtils.equals(mSubscriberId, subscriberId);
}
} }
} }