summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortwyen <twyen@google.com>2018-02-07 17:32:54 -0800
committerEric Erfanian <erfanian@google.com>2018-02-09 21:58:03 +0000
commit981a3e9d384f7c12d1847b1922b1f26115b0f4fd (patch)
treedd60f1ac459e89c718c4f8ed28de2a38190f697c
parent83cd6282a94aea9a4efa766e1b7818e50b68921e (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.java71
-rw-r--r--java/com/android/voicemail/impl/CarrierIdentifierMatcher.java60
-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.java16
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;