From c77daa8226ceed74cd6ecaddc131379aadf80836 Mon Sep 17 00:00:00 2001 From: Alan Evans Date: Fri, 19 Apr 2019 14:14:53 -0300 Subject: [PATCH] Display carrier or number if any SIM descriptions clash. Fixes #8725 --- .../securesms/TransportOptions.java | 12 ++- .../components/ConversationItemFooter.java | 2 +- .../dualsim/SubscriptionManagerCompat.java | 94 ++++++++++++++----- 3 files changed, 78 insertions(+), 30 deletions(-) diff --git a/src/org/thoughtcrime/securesms/TransportOptions.java b/src/org/thoughtcrime/securesms/TransportOptions.java index 93d174f606..889e8dea73 100644 --- a/src/org/thoughtcrime/securesms/TransportOptions.java +++ b/src/org/thoughtcrime/securesms/TransportOptions.java @@ -14,6 +14,8 @@ import org.thoughtcrime.securesms.util.dualsim.SubscriptionInfoCompat; import org.thoughtcrime.securesms.util.dualsim.SubscriptionManagerCompat; import org.whispersystems.libsignal.util.guava.Optional; +import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -155,14 +157,14 @@ public class TransportOptions { @NonNull String composeHint, @NonNull CharacterCalculator characterCalculator) { - List results = new LinkedList<>(); - SubscriptionManagerCompat subscriptionManager = new SubscriptionManagerCompat(context); - List subscriptions; + List results = new LinkedList<>(); + SubscriptionManagerCompat subscriptionManager = new SubscriptionManagerCompat(context); + Collection subscriptions; if (Permissions.hasAll(context, Manifest.permission.READ_PHONE_STATE)) { - subscriptions = subscriptionManager.getActiveSubscriptionInfoList(); + subscriptions = subscriptionManager.getActiveAndReadySubscriptionInfos(); } else { - subscriptions = new LinkedList<>(); + subscriptions = Collections.emptyList(); } if (subscriptions.size() < 2) { diff --git a/src/org/thoughtcrime/securesms/components/ConversationItemFooter.java b/src/org/thoughtcrime/securesms/components/ConversationItemFooter.java index b88d3d4ac8..69bb4a3ebb 100644 --- a/src/org/thoughtcrime/securesms/components/ConversationItemFooter.java +++ b/src/org/thoughtcrime/securesms/components/ConversationItemFooter.java @@ -106,7 +106,7 @@ public class ConversationItemFooter extends LinearLayout { private void presentSimInfo(@NonNull MessageRecord messageRecord) { SubscriptionManagerCompat subscriptionManager = new SubscriptionManagerCompat(getContext()); - if (messageRecord.isPush() || messageRecord.getSubscriptionId() == -1 || !Permissions.hasAll(getContext(), Manifest.permission.READ_PHONE_STATE) || subscriptionManager.getActiveSubscriptionInfoList().size() < 2) { + if (messageRecord.isPush() || messageRecord.getSubscriptionId() == -1 || !Permissions.hasAll(getContext(), Manifest.permission.READ_PHONE_STATE) || subscriptionManager.getActiveAndReadySubscriptionInfos().size() < 2) { simView.setVisibility(View.GONE); } else { Optional subscriptionInfo = subscriptionManager.getActiveSubscriptionInfo(messageRecord.getSubscriptionId()); diff --git a/src/org/thoughtcrime/securesms/util/dualsim/SubscriptionManagerCompat.java b/src/org/thoughtcrime/securesms/util/dualsim/SubscriptionManagerCompat.java index d2c5bf577c..e9c53d20b6 100644 --- a/src/org/thoughtcrime/securesms/util/dualsim/SubscriptionManagerCompat.java +++ b/src/org/thoughtcrime/securesms/util/dualsim/SubscriptionManagerCompat.java @@ -9,10 +9,19 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import org.thoughtcrime.securesms.util.ServiceUtil; +import org.whispersystems.libsignal.util.guava.Function; import org.whispersystems.libsignal.util.guava.Optional; +import org.whispersystems.signalservice.api.util.InvalidNumberException; +import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; -import java.util.LinkedList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.Set; public final class SubscriptionManagerCompat { @@ -35,48 +44,85 @@ public final class SubscriptionManagerCompat { return Optional.absent(); } - SubscriptionInfo subscriptionInfo = getSubscriptionManager().getActiveSubscriptionInfo(subscriptionId); - - if (subscriptionInfo != null) { - return Optional.of(new SubscriptionInfoCompat(subscriptionId, subscriptionInfo.getDisplayName(), - subscriptionInfo.getMcc(), subscriptionInfo.getMnc())); - } else { - return Optional.absent(); - } + return Optional.fromNullable(getActiveSubscriptionInfoMap(false).get(subscriptionId)); } - public @NonNull List getActiveSubscriptionInfoList() { + public @NonNull Collection getActiveAndReadySubscriptionInfos() { if (Build.VERSION.SDK_INT < 22) { - return new LinkedList<>(); + return Collections.emptyList(); } - List subscriptionInfos = getSubscriptionManager().getActiveSubscriptionInfoList(); + return getActiveSubscriptionInfoMap(true).values(); + } + + @RequiresApi(api = 22) + private @NonNull Map getActiveSubscriptionInfoMap(boolean excludeUnreadySubscriptions) { + List subscriptionInfos = ServiceUtil.getSubscriptionManager(context).getActiveSubscriptionInfoList(); if (subscriptionInfos == null || subscriptionInfos.isEmpty()) { - return new LinkedList<>(); + return Collections.emptyMap(); } - List compatList = new LinkedList<>(); + Map descriptions = getDescriptionsFor(subscriptionInfos); + Map map = new LinkedHashMap<>(); for (SubscriptionInfo subscriptionInfo : subscriptionInfos) { - if (isReady(subscriptionInfo)) { - compatList.add(new SubscriptionInfoCompat(subscriptionInfo.getSubscriptionId(), - subscriptionInfo.getDisplayName(), - subscriptionInfo.getMcc(), - subscriptionInfo.getMnc())); + if (!excludeUnreadySubscriptions || isReady(subscriptionInfo)) { + map.put(subscriptionInfo.getSubscriptionId(), + new SubscriptionInfoCompat(subscriptionInfo.getSubscriptionId(), + descriptions.get(subscriptionInfo), + subscriptionInfo.getMcc(), + subscriptionInfo.getMnc())); } } - return compatList; + return map; } - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1) - private SubscriptionManager getSubscriptionManager() { - return ServiceUtil.getSubscriptionManager(context); + @RequiresApi(api = 22) + private static Map getDescriptionsFor(@NonNull Collection subscriptions) { + Map descriptions; + + descriptions = createDescriptionMap(subscriptions, SubscriptionInfo::getDisplayName); + if (hasNoDuplicates(descriptions.values())) return descriptions; + + descriptions = createDescriptionMap(subscriptions, SubscriptionInfo::getCarrierName); + if (hasNoDuplicates(descriptions.values())) return descriptions; + + return createDescriptionMap(subscriptions, (subscriptionInfo) -> formatNumber(subscriptionInfo.getNumber())); + } + + private static Map createDescriptionMap(@NonNull Collection subscriptions, + @NonNull Function createDescription) + { + Map descriptions = new HashMap<>(); + for (SubscriptionInfo subscriptionInfo: subscriptions) { + descriptions.put(subscriptionInfo, createDescription.apply(subscriptionInfo)); + } + return descriptions; + } + + private static boolean hasNoDuplicates(Collection collection) { + final Set set = new HashSet<>(); + + for (T t : collection) { + if (!set.add(t)) { + return false; + } + } + return true; + } + + private static String formatNumber(String number) { + try { + return PhoneNumberFormatter.formatNumber(number, number); + } catch (InvalidNumberException e) { + return number; + } } private boolean isReady(@NonNull SubscriptionInfo subscriptionInfo) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return true; + if (Build.VERSION.SDK_INT < 24) return true; TelephonyManager telephonyManager = ServiceUtil.getTelephonyManager(context);