diff options
author | twyen <twyen@google.com> | 2018-02-07 17:32:54 -0800 |
---|---|---|
committer | Eric Erfanian <erfanian@google.com> | 2018-02-09 21:58:03 +0000 |
commit | 981a3e9d384f7c12d1847b1922b1f26115b0f4fd (patch) | |
tree | dd60f1ac459e89c718c4f8ed28de2a38190f697c | |
parent | 83cd6282a94aea9a4efa766e1b7818e50b68921e (diff) |
Support GID1 for VVM configs
This CL allows VVM configs to be specifed with Group identifier, which takes precedence over configs with only MCC/MNC.
TelephonyVvmConfigManger is renamed to DialerVvmConfigManger. It was created when VVM was still in telephony, and need to separate itself from the CarrierConfig app.
Bug: 72666573
Test: Unit tests
PiperOrigin-RevId: 184924155
Change-Id: Ic71e99ed2b3015eed87dfb7e111538ff3b744206
-rw-r--r-- | java/com/android/voicemail/impl/CarrierIdentifier.java | 71 | ||||
-rw-r--r-- | java/com/android/voicemail/impl/CarrierIdentifierMatcher.java | 60 | ||||
-rw-r--r-- | java/com/android/voicemail/impl/DialerVvmConfigManager.java (renamed from java/com/android/voicemail/impl/TelephonyVvmConfigManager.java) | 106 | ||||
-rw-r--r-- | java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java | 16 |
4 files changed, 228 insertions, 25 deletions
diff --git a/java/com/android/voicemail/impl/CarrierIdentifier.java b/java/com/android/voicemail/impl/CarrierIdentifier.java new file mode 100644 index 000000000..82b6a2440 --- /dev/null +++ b/java/com/android/voicemail/impl/CarrierIdentifier.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2018 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.voicemail.impl; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build.VERSION_CODES; +import android.telecom.PhoneAccountHandle; +import android.telephony.TelephonyManager; +import com.google.auto.value.AutoValue; + +/** Identifies a carrier. */ +@AutoValue +@TargetApi(VERSION_CODES.O) +@SuppressWarnings("missingpermission") +public abstract class CarrierIdentifier { + + public abstract String mccMnc(); + + /** + * Group ID Level 1. Used to identify MVNO(Mobile Virtual Network Operators) who subleases other + * carrier's network and share their mccMnc. MVNO should have a GID1 different from the host. + */ + public abstract String gid1(); + + /** Builder for the matcher */ + @AutoValue.Builder + public abstract static class Builder { + + public abstract Builder setMccMnc(String mccMnc); + + public abstract Builder setGid1(String gid1); + + public abstract CarrierIdentifier build(); + } + + public static Builder builder() { + return new AutoValue_CarrierIdentifier.Builder().setGid1(""); + } + + public static CarrierIdentifier forHandle( + Context context, PhoneAccountHandle phoneAccountHandle) { + TelephonyManager telephonyManager = + context + .getSystemService(TelephonyManager.class) + .createForPhoneAccountHandle(phoneAccountHandle); + if (telephonyManager == null) { + throw new IllegalArgumentException("Invalid PhoneAccountHandle"); + } + String gid1 = telephonyManager.getGroupIdLevel1(); + if (gid1 == null) { + gid1 = ""; + } + + return builder().setMccMnc(telephonyManager.getSimOperator()).setGid1(gid1).build(); + } +} diff --git a/java/com/android/voicemail/impl/CarrierIdentifierMatcher.java b/java/com/android/voicemail/impl/CarrierIdentifierMatcher.java new file mode 100644 index 000000000..d7c28fe77 --- /dev/null +++ b/java/com/android/voicemail/impl/CarrierIdentifierMatcher.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 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.voicemail.impl; + +import com.google.auto.value.AutoValue; +import com.google.common.base.Optional; + +/** + * Matches a {@link CarrierIdentifier}. Full equality check on CarrierIdentifiers is often unfit + * because non-MVNO carriers usually just specify the {@link CarrierIdentifier#mccMnc()} while their + * {@link CarrierIdentifier#gid1()} could be anything. This matcher ignore fields that are not + * specified in the matcher. + */ +@AutoValue +public abstract class CarrierIdentifierMatcher { + + public abstract String mccMnc(); + + public abstract Optional<String> gid1(); + + public static Builder builder() { + return new AutoValue_CarrierIdentifierMatcher.Builder(); + } + + /** Builder for the matcher */ + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder setMccMnc(String mccMnc); + + public abstract Builder setGid1(String gid1); + + public abstract CarrierIdentifierMatcher build(); + } + + public boolean matches(CarrierIdentifier carrierIdentifier) { + if (!mccMnc().equals(carrierIdentifier.mccMnc())) { + return false; + } + if (gid1().isPresent()) { + if (!gid1().get().equals(carrierIdentifier.gid1())) { + return false; + } + } + return true; + } +} diff --git a/java/com/android/voicemail/impl/TelephonyVvmConfigManager.java b/java/com/android/voicemail/impl/DialerVvmConfigManager.java index ecf4e6ffc..7fa960e34 100644 --- a/java/com/android/voicemail/impl/TelephonyVvmConfigManager.java +++ b/java/com/android/voicemail/impl/DialerVvmConfigManager.java @@ -17,37 +17,86 @@ package com.android.voicemail.impl; import android.content.Context; +import android.net.Uri; import android.os.PersistableBundle; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.util.ArrayMap; import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.voicemail.impl.utils.XmlUtils; +import com.google.common.collect.ComparisonChain; import java.io.IOException; import java.util.ArrayList; import java.util.Map; import java.util.Map.Entry; +import java.util.SortedSet; +import java.util.TreeSet; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -/** Load and caches telephony vvm config from res/xml/vvm_config.xml */ -public class TelephonyVvmConfigManager { +/** Load and caches dialer vvm config from res/xml/vvm_config.xml */ +public class DialerVvmConfigManager { + private static class ConfigEntry implements Comparable<ConfigEntry> { - private static final String TAG = "TelephonyVvmCfgMgr"; + final CarrierIdentifierMatcher matcher; + final PersistableBundle config; - private static final boolean USE_DEBUG_CONFIG = false; + ConfigEntry(CarrierIdentifierMatcher matcher, PersistableBundle config) { + this.matcher = matcher; + this.config = config; + } + + /** + * A more specific matcher should return a negative value to have higher priority over generic + * matchers. + */ + @Override + public int compareTo(@NonNull ConfigEntry other) { + ComparisonChain comparisonChain = ComparisonChain.start(); + if (!(matcher.gid1().isPresent() && other.matcher.gid1().isPresent())) { + if (matcher.gid1().isPresent()) { + return -1; + } else if (other.matcher.gid1().isPresent()) { + return 1; + } else { + return 0; + } + } else { + comparisonChain = comparisonChain.compare(matcher.gid1().get(), other.matcher.gid1().get()); + } + + return comparisonChain.compare(matcher.mccMnc(), other.matcher.mccMnc()).result(); + } + } private static final String TAG_PERSISTABLEMAP = "pbundle_as_map"; + /** + * A string array of MCCMNC the config applies to. Addtional filters should be appended as the URI + * query parameter format. + * + * <p>For example{@code <string-array name="mccmnc"> <item value="12345?gid1=foo"/> <item + * value="67890"/> </string-array> } + * + * @see #KEY_GID1 + */ @VisibleForTesting static final String KEY_MCCMNC = "mccmnc"; + /** + * Additional query parameter in {@link #KEY_MCCMNC} to filter by the Group ID level 1. + * + * @see CarrierIdentifierMatcher#gid1() + */ + private static final String KEY_GID1 = "gid1"; + private static final String KEY_FEATURE_FLAG_NAME = "feature_flag_name"; - private static Map<String, PersistableBundle> cachedConfigs; + private static Map<String, SortedSet<ConfigEntry>> cachedConfigs; - private final Map<String, PersistableBundle> configs; + private final Map<String, SortedSet<ConfigEntry>> configs; - public TelephonyVvmConfigManager(Context context) { + public DialerVvmConfigManager(Context context) { if (cachedConfigs == null) { cachedConfigs = loadConfigs(context, context.getResources().getXml(R.xml.vvm_config)); } @@ -55,20 +104,26 @@ public class TelephonyVvmConfigManager { } @VisibleForTesting - TelephonyVvmConfigManager(Context context, XmlPullParser parser) { + DialerVvmConfigManager(Context context, XmlPullParser parser) { configs = loadConfigs(context, parser); } @Nullable - public PersistableBundle getConfig(String mccMnc) { - if (USE_DEBUG_CONFIG) { - return configs.get("TEST"); + public PersistableBundle getConfig(CarrierIdentifier carrierIdentifier) { + if (!configs.containsKey(carrierIdentifier.mccMnc())) { + return null; + } + for (ConfigEntry configEntry : configs.get(carrierIdentifier.mccMnc())) { + if (configEntry.matcher.matches(carrierIdentifier)) { + return configEntry.config; + } } - return configs.get(mccMnc); + return null; } - private static Map<String, PersistableBundle> loadConfigs(Context context, XmlPullParser parser) { - Map<String, PersistableBundle> configs = new ArrayMap<>(); + private static Map<String, SortedSet<ConfigEntry>> loadConfigs( + Context context, XmlPullParser parser) { + Map<String, SortedSet<ConfigEntry>> configs = new ArrayMap<>(); try { ArrayList list = readBundleList(parser); for (Object object : list) { @@ -83,12 +138,27 @@ public class TelephonyVvmConfigManager { continue; } - String[] mccMncs = bundle.getStringArray(KEY_MCCMNC); - if (mccMncs == null) { + String[] identifiers = bundle.getStringArray(KEY_MCCMNC); + if (identifiers == null) { throw new IllegalArgumentException("MCCMNC is null"); } - for (String mccMnc : mccMncs) { - configs.put(mccMnc, bundle); + for (String identifier : identifiers) { + Uri uri = Uri.parse(identifier); + String mccMnc = uri.getPath(); + SortedSet<ConfigEntry> set; + if (configs.containsKey(mccMnc)) { + set = configs.get(mccMnc); + } else { + // Need a SortedSet so matchers will be sorted by priority. + set = new TreeSet<>(); + configs.put(mccMnc, set); + } + CarrierIdentifierMatcher.Builder matcherBuilder = CarrierIdentifierMatcher.builder(); + matcherBuilder.setMccMnc(mccMnc); + if (uri.getQueryParameterNames().contains(KEY_GID1)) { + matcherBuilder.setGid1(uri.getQueryParameter(KEY_GID1)); + } + set.add(new ConfigEntry(matcherBuilder.build(), bundle)); } } } catch (IOException | XmlPullParserException e) { diff --git a/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java b/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java index ef62d2a75..f8a9e4bcf 100644 --- a/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java +++ b/java/com/android/voicemail/impl/OmtpVvmCarrierConfigHelper.java @@ -55,6 +55,7 @@ import java.util.Set; * <p>TODO(twyen): refactor this to an interface. */ @TargetApi(VERSION_CODES.O) +@SuppressWarnings("missingpermission") public class OmtpVvmCarrierConfigHelper { private static final String TAG = "OmtpVvmCarrierCfgHlpr"; @@ -131,7 +132,8 @@ public class OmtpVvmCarrierConfigHelper { carrierConfig = getCarrierConfig(telephonyManager); telephonyConfig = - new TelephonyVvmConfigManager(context).getConfig(telephonyManager.getSimOperator()); + new DialerVvmConfigManager(context) + .getConfig(CarrierIdentifier.forHandle(context, phoneAccountHandle)); } vvmType = getVvmType(); @@ -199,12 +201,6 @@ public class OmtpVvmCarrierConfigHelper { } @Nullable - public Set<String> getCarrierVvmPackageNames() { - Assert.checkArgument(isValid()); - return getCarrierVvmPackageNamesWithoutValidation(); - } - - @Nullable private Set<String> getCarrierVvmPackageNamesWithoutValidation() { Set<String> names = getCarrierVvmPackageNames(overrideConfig); if (names != null) { @@ -217,6 +213,12 @@ public class OmtpVvmCarrierConfigHelper { return getCarrierVvmPackageNames(telephonyConfig); } + @Nullable + public Set<String> getCarrierVvmPackageNames() { + Assert.checkArgument(isValid()); + return getCarrierVvmPackageNamesWithoutValidation(); + } + private static Set<String> getCarrierVvmPackageNames(@Nullable PersistableBundle bundle) { if (bundle == null) { return null; |