aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:14:25 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:14:25 +0000
commitcfe370aa8412485fa52da5c4731915eeab65194d (patch)
tree53a5565a52e2ee903caf5840cdb6569b722e2223
parent69065119202269600dbfd07b49a9e4258f6e444f (diff)
parentac35454ec959667d4992f90acbdf86cc54e0c0be (diff)
downloadcarrier_settings-android14-mainline-os-statsd-release.tar.gz
Change-Id: I3fc255acbd10c8fc384d148900ea042578abc992
-rw-r--r--Android.bp1
-rw-r--r--OWNERS5
-rw-r--r--java/CarrierConfigConverterV2.java205
-rw-r--r--proto/carrier_settings.proto2
-rw-r--r--python/update_apn.py117
5 files changed, 303 insertions, 27 deletions
diff --git a/Android.bp b/Android.bp
index 350af13..cddcf64 100644
--- a/Android.bp
+++ b/Android.bp
@@ -22,6 +22,7 @@ python_binary_host {
srcs: [
"python/update_apn.py",
"proto/*.proto",
+ ":telephonyprovider-proto-sources",
],
proto: {
canonical_path_from_root: false
diff --git a/OWNERS b/OWNERS
index b5cab7d..efe940c 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,3 @@
mewan@google.com
-mberionne@google.com
-amruthr@google.com
-satk@google.com
+cey@google.com
+akaustubh@google.com
diff --git a/java/CarrierConfigConverterV2.java b/java/CarrierConfigConverterV2.java
index 2f8d254..feceabf 100644
--- a/java/CarrierConfigConverterV2.java
+++ b/java/CarrierConfigConverterV2.java
@@ -102,6 +102,9 @@ public final class CarrierConfigConverterV2 {
@Parameter(names = "--version", description = "The version number for all output textpb.")
private long version = 1L;
+ @Parameter(names = "--consider_parent_canonical_id", arity = 1, description = "To consider parent_canonical_id")
+ private static boolean considerParentCanonicalId = false;
+
private static final String MCCMNC_FOR_DEFAULT_SETTINGS = "000000";
// Resource file path to the AOSP carrier list file
@@ -125,13 +128,14 @@ public final class CarrierConfigConverterV2 {
/** Entry point when invoked from other Java code, eg. the server side conversion tool. */
public static void convert(
- String vendorXmlFile, String assetsDirName, String outputDir, long version)
+ String vendorXmlFile, String assetsDirName, String outputDir, long version, boolean considerParentCanonicalId)
throws IOException {
CarrierConfigConverterV2 converter = new CarrierConfigConverterV2();
converter.vendorXmlFiles = ImmutableList.of(vendorXmlFile);
converter.assetsDirName = assetsDirName;
converter.outputDir = outputDir;
converter.version = version;
+ converter.considerParentCanonicalId = considerParentCanonicalId;
converter.convert();
}
@@ -147,6 +151,7 @@ public final class CarrierConfigConverterV2 {
DocumentBuilder xmlDocBuilder = getDocumentBuilder();
Multimap<Integer, CarrierId> aospCarrierList = loadAospCarrierList();
Multimap<CarrierId, Integer> reverseAospCarrierList = reverseAospCarrierList(aospCarrierList);
+ Multimap<CarrierId, Integer> reverseAospCarrierListPerParentCanonicalId = reverseAospCarrierListPerParentCanonicalId();
/*
* High-level flow:
@@ -264,10 +269,11 @@ public final class CarrierConfigConverterV2 {
}
// 3. For each CarrierId, build its carrier configs, following AOSP DefaultCarrierConfigService.
+ loadUniqueRulesFromVendorXml(vendorXmls);
for (CarrierId carrier : carriers) {
Map<String, CarrierConfig.Config> config = ImmutableMap.of();
- CarrierIdentifier id = getCid(carrier, reverseAospCarrierList);
+ CarrierIdentifier id = getCid(carrier, reverseAospCarrierList, reverseAospCarrierListPerParentCanonicalId);
if (id.getCarrierId() != -1) {
HashMap<String, CarrierConfig.Config> configBySpecificCarrierId =
parseCarrierConfigFromXml(
@@ -407,6 +413,31 @@ public final class CarrierConfigConverterV2 {
MultimapBuilder.linkedHashKeys().arrayListValues()::build));
}
+ private static Multimap<CarrierId, Integer> reverseAospCarrierListPerParentCanonicalId() throws IOException {
+
+ com.android.providers.telephony.CarrierIdProto.CarrierList.Builder aospCarrierList =
+ com.android.providers.telephony.CarrierIdProto.CarrierList.newBuilder();
+ try (InputStream textpb =
+ CarrierConfigConverterV2.class.getResourceAsStream(RESOURCE_CARRIER_LIST);
+ BufferedReader textpbReader = new BufferedReader(new InputStreamReader(textpb, UTF_8))) {
+ TextFormat.getParser().merge(textpbReader, aospCarrierList);
+ }
+ Multimap<Integer, CarrierId> res = aospCarrierList.getCarrierIdList().stream()
+ .filter(cid -> cid.getParentCanonicalId() > 0)
+ .collect(
+ flatteningToMultimap(
+ cid -> cid.getParentCanonicalId(),
+ cid -> carrierAttributeToCarrierId(cid.getCarrierAttributeList()).stream(),
+ MultimapBuilder.linkedHashKeys().arrayListValues()::build));
+
+ return res.entries().stream()
+ .collect(
+ toMultimap(
+ entry -> entry.getValue(),
+ entry -> entry.getKey(),
+ MultimapBuilder.linkedHashKeys().arrayListValues()::build));
+ }
+
// Convert `CarrierAttribute`s to `CarrierId`s.
// A CarrierAttribute message with fields not supported by CarrierSettings, like preferred_apn,
// is ignored.
@@ -566,13 +597,19 @@ public final class CarrierConfigConverterV2 {
* @return a map, key being the carrier config key, value being a {@link CarrierConfig.Config}
* with one of the value set.
*/
- private static HashMap<String, CarrierConfig.Config> parseCarrierConfigFromVendorXml(
+ private HashMap<String, CarrierConfig.Config> parseCarrierConfigFromVendorXml(
Document xmlDoc, CarrierIdentifier carrier) throws IOException {
HashMap<String, CarrierConfig.Config> configMap = new HashMap<>();
for (Element element : getElementsByTagName(xmlDoc, TAG_CARRIER_CONFIG)) {
if (carrier != null && !checkFilters(element, carrier)) {
continue;
}
+
+ Element parent_config = findParentConfigByUniqueRuleId(element);
+ if (parent_config != null) {
+ configMap.putAll(parseCarrierConfigToMap(parent_config));
+ }
+
configMap.putAll(parseCarrierConfigToMap(element));
}
return configMap;
@@ -592,7 +629,8 @@ public final class CarrierConfigConverterV2 {
nList = element.getElementsByTagName("boolean");
for (int i = 0; i < nList.getLength(); i++) {
Node nNode = nList.item(i);
- if (nNode.getNodeType() != Node.ELEMENT_NODE) {
+ if (nNode.getNodeType() != Node.ELEMENT_NODE ||
+ !nNode.getParentNode().isSameNode(element)) {
continue;
}
Element eElement = (Element) nNode;
@@ -604,7 +642,8 @@ public final class CarrierConfigConverterV2 {
nList = element.getElementsByTagName("int");
for (int i = 0; i < nList.getLength(); i++) {
Node nNode = nList.item(i);
- if (nNode.getNodeType() != Node.ELEMENT_NODE) {
+ if (nNode.getNodeType() != Node.ELEMENT_NODE ||
+ !nNode.getParentNode().isSameNode(element)) {
continue;
}
Element eElement = (Element) nNode;
@@ -616,7 +655,8 @@ public final class CarrierConfigConverterV2 {
nList = element.getElementsByTagName("long");
for (int i = 0; i < nList.getLength(); i++) {
Node nNode = nList.item(i);
- if (nNode.getNodeType() != Node.ELEMENT_NODE) {
+ if (nNode.getNodeType() != Node.ELEMENT_NODE ||
+ !nNode.getParentNode().isSameNode(element)) {
continue;
}
Element eElement = (Element) nNode;
@@ -624,11 +664,25 @@ public final class CarrierConfigConverterV2 {
long value = Long.parseLong(eElement.getAttribute("value"));
configMap.put(key, CarrierConfig.Config.newBuilder().setLongValue(value).build());
}
+ // double value
+ nList = element.getElementsByTagName("double");
+ for (int i = 0; i < nList.getLength(); i++) {
+ Node nNode = nList.item(i);
+ if (nNode.getNodeType() != Node.ELEMENT_NODE ||
+ !nNode.getParentNode().isSameNode(element)) {
+ continue;
+ }
+ Element eElement = (Element) nNode;
+ String key = eElement.getAttribute("name");
+ double value = Double.parseDouble(eElement.getAttribute("value"));
+ configMap.put(key, CarrierConfig.Config.newBuilder().setDoubleValue(value).build());
+ }
// text value
nList = element.getElementsByTagName("string");
for (int i = 0; i < nList.getLength(); i++) {
Node nNode = nList.item(i);
- if (nNode.getNodeType() != Node.ELEMENT_NODE) {
+ if (nNode.getNodeType() != Node.ELEMENT_NODE ||
+ !nNode.getParentNode().isSameNode(element)) {
continue;
}
Element eElement = (Element) nNode;
@@ -643,7 +697,8 @@ public final class CarrierConfigConverterV2 {
nList = element.getElementsByTagName("string-array");
for (int i = 0; i < nList.getLength(); i++) {
Node nNode = nList.item(i);
- if (nNode.getNodeType() != Node.ELEMENT_NODE) {
+ if (nNode.getNodeType() != Node.ELEMENT_NODE ||
+ !nNode.getParentNode().isSameNode(element)) {
continue;
}
Element eElement = (Element) nNode;
@@ -662,11 +717,12 @@ public final class CarrierConfigConverterV2 {
}
configMap.put(key, cccb.setTextArray(cctb.build()).build());
}
- // bool array
+ // int array
nList = element.getElementsByTagName("int-array");
for (int i = 0; i < nList.getLength(); i++) {
Node nNode = nList.item(i);
- if (nNode.getNodeType() != Node.ELEMENT_NODE) {
+ if (nNode.getNodeType() != Node.ELEMENT_NODE ||
+ !nNode.getParentNode().isSameNode(element)) {
continue;
}
Element eElement = (Element) nNode;
@@ -685,6 +741,20 @@ public final class CarrierConfigConverterV2 {
}
configMap.put(key, cccb.setIntArray(ccib.build()).build());
}
+ // pbundle_as_map
+ nList = element.getElementsByTagName("pbundle_as_map");
+ for (int i = 0; i < nList.getLength(); i++) {
+ Node nNode = nList.item(i);
+ if (nNode.getNodeType() != Node.ELEMENT_NODE ||
+ !nNode.getParentNode().isSameNode(element)) {
+ continue;
+ }
+ Element eElement = (Element) nNode;
+ String key = eElement.getAttribute("name");
+ HashMap<String, CarrierConfig.Config> value = parseCarrierConfigToMap(eElement);
+ configMap.put(key, CarrierConfig.Config.newBuilder()
+ .setBundle(toCarrierConfigBuilder(value)).build());
+ }
return configMap;
}
@@ -723,6 +793,8 @@ public final class CarrierConfigConverterV2 {
break;
case "name":
// name is used together with cid for readability. ignore for filter.
+ case "unique_rule_id":
+ case "following":
break;
default:
System.err.println("Unsupported attribute " + attribute + "=" + value);
@@ -838,32 +910,127 @@ public final class CarrierConfigConverterV2 {
}
private static CarrierIdentifier getCid(
- CarrierId carrierId, Multimap<CarrierId, Integer> reverseAospCarrierList) {
+ CarrierId carrierId, Multimap<CarrierId, Integer> reverseAospCarrierList,
+ Multimap<CarrierId, Integer> reverseAospCarrierListPerParentCanonicalId) {
// Mimic TelephonyManager#getCarrierIdFromMccMnc, which is implemented by
// CarrierResolver#getCarrierIdFromMccMnc.
CarrierId mccMnc = CarrierId.newBuilder().setMccMnc(carrierId.getMccMnc()).build();
int mccMncCarrierId = reverseAospCarrierList.get(mccMnc).stream().findFirst().orElse(-1);
-
List<Integer> cids = ImmutableList.copyOf(reverseAospCarrierList.get(carrierId));
+ int parentCanonicalId = getParentCanonicalId(carrierId, cids, reverseAospCarrierListPerParentCanonicalId);
// No match: use -1
if (cids.isEmpty()) {
- return CarrierIdentifier.create(carrierId, -1, -1, mccMncCarrierId);
+ if (considerParentCanonicalId) {
+ return CarrierIdentifier.create(carrierId, parentCanonicalId, -1, mccMncCarrierId);
+ } else {
+ return CarrierIdentifier.create(carrierId, -1, -1, mccMncCarrierId);
+ }
}
// One match: use as both carrierId and specificCarrierId
if (cids.size() == 1) {
- return CarrierIdentifier.create(carrierId, cids.get(0), cids.get(0), mccMncCarrierId);
+ if (considerParentCanonicalId) {
+ return CarrierIdentifier.create(carrierId, parentCanonicalId, cids.get(0), mccMncCarrierId);
+ } else {
+ return CarrierIdentifier.create(carrierId, cids.get(0), cids.get(0), mccMncCarrierId);
+ }
}
// Two matches: specificCarrierId is always bigger than carrierId
if (cids.size() == 2) {
- return CarrierIdentifier.create(
- carrierId,
- Math.min(cids.get(0), cids.get(1)),
- Math.max(cids.get(0), cids.get(1)),
- mccMncCarrierId);
+ if (considerParentCanonicalId) {
+ return CarrierIdentifier.create(
+ carrierId,
+ parentCanonicalId,
+ Math.max(cids.get(0), cids.get(1)),
+ mccMncCarrierId);
+ } else {
+ return CarrierIdentifier.create(
+ carrierId,
+ Math.min(cids.get(0), cids.get(1)),
+ Math.max(cids.get(0), cids.get(1)),
+ mccMncCarrierId);
+ }
}
// Cannot be more than 2 matches.
throw new IllegalStateException("More than two cid's found for " + carrierId + ": " + cids);
}
+ private static int getParentCanonicalId(
+ CarrierId carrierId,
+ List<Integer> cids,
+ Multimap<CarrierId, Integer> reverseAospCarrierListPerParentCanonicalId) {
+
+ List<Integer> parentCids = ImmutableList.copyOf(reverseAospCarrierListPerParentCanonicalId.get(carrierId));
+ if (cids.isEmpty()) {
+ if (parentCids.isEmpty()) {
+ return -1;
+ } else {
+ return parentCids.get(0);
+ }
+ } else if (cids.size() == 1) {
+ if (parentCids.isEmpty()) {
+ return cids.get(0);
+ } else {
+ return parentCids.get(0);
+ }
+ } else if (cids.size() == 2) {
+ if (parentCids.isEmpty()) {
+ return Math.min(cids.get(0), cids.get(1));
+ } else {
+ return parentCids.get(0);
+ }
+ } else {
+ return -1;
+ }
+ }
private CarrierConfigConverterV2() {}
+
+ // The hash map to store all the configs with attribute "unique_rule_id".
+ // The config entry with attribute "following" can inherit from the config
+ // with matching "unique_rule_id".
+ // Both "unique_rule_id" and "following" attributes can only appear in vendor xml.
+ private HashMap<String, Element> mUniqueRules = new HashMap<>();
+
+ private void loadUniqueRulesFromVendorXml(List<Document> vendorXmls)
+ throws IOException {
+ for (Document vendorXml : vendorXmls) {
+ for (Element element : getElementsByTagName(vendorXml, TAG_CARRIER_CONFIG)) {
+ NamedNodeMap attributes = element.getAttributes();
+ boolean uniqueRuleIdSeen = false;
+ for (int i = 0; i < attributes.getLength(); i++) {
+ String attribute = attributes.item(i).getNodeName();
+ String value = attributes.item(i).getNodeValue();
+ switch (attribute) {
+ case "unique_rule_id":
+ if (mUniqueRules.containsKey(value)) {
+ throw new IOException("The carrier_config has duplicated unique_rule_id: " + attributes);
+ } else if (uniqueRuleIdSeen) {
+ throw new IOException("The carrier_config has more than 1 unique_rule_id: " + attributes);
+ }
+ mUniqueRules.put(value, element);
+ uniqueRuleIdSeen = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ private Element findParentConfigByUniqueRuleId(Element childElement) {
+ NamedNodeMap attributes = childElement.getAttributes();
+ for (int i = 0; i < attributes.getLength(); i++) {
+ String attribute = attributes.item(i).getNodeName();
+ String value = attributes.item(i).getNodeValue();
+ switch (attribute) {
+ case "following":
+ return mUniqueRules.get(value);
+ //break;
+ default:
+ break;
+ }
+ }
+ return null;
+ }
+
}
diff --git a/proto/carrier_settings.proto b/proto/carrier_settings.proto
index 1a8a77f..5a18c24 100644
--- a/proto/carrier_settings.proto
+++ b/proto/carrier_settings.proto
@@ -182,6 +182,8 @@ message CarrierConfig {
bool bool_value = 5;
TextArray text_array = 6;
IntArray int_array = 7;
+ CarrierConfig bundle = 8;
+ double double_value = 9;
}
}
diff --git a/python/update_apn.py b/python/update_apn.py
index 0ee32aa..2a74149 100644
--- a/python/update_apn.py
+++ b/python/update_apn.py
@@ -30,6 +30,7 @@ from google.protobuf import text_format
import carrier_list_pb2
import carrier_settings_pb2
+import carrierId_pb2
parser = argparse.ArgumentParser()
parser.add_argument(
@@ -37,6 +38,10 @@ parser.add_argument(
parser.add_argument(
'--data_dir', default='./data', help='Folder path for CarrierSettings data')
parser.add_argument(
+ '--support_carrier_id', action='store_true', help='To support using carrier_id in apns.xml')
+parser.add_argument(
+ '--aosp_carrier_list', default='packages/providers/TelephonyProvider/assets/latest_carrier_id/carrier_list.textpb', help='Resource file path to the AOSP carrier list file')
+parser.add_argument(
'--out_file', default='./tmpapns.textpb', help='Temp APN file')
FLAGS = parser.parse_args()
@@ -68,13 +73,14 @@ def get_cname(cid, known_carriers):
Returns:
string for canonical name, like verizon_us or 27402
"""
- name = to_string(cid)
+ return get_known_cname(to_string(cid), known_carriers)
+
+def get_known_cname(name, known_carriers):
if name in known_carriers:
return known_carriers[name]
else:
return name
-
def get_knowncarriers(files):
"""Create a mapping from mccmnc and possible mvno data to canonical name.
@@ -233,6 +239,99 @@ def gen_apnitem(node):
return apn
+def is_mccmnc_only_attribute(attribute):
+ """Check if the given CarrierAttribute only contains mccmnc_tuple
+
+ Args:
+ attribute: message CarrierAttribute defined in carrierId.proto
+
+ Returns:
+ True, if the given CarrierAttribute only contains mccmnc_tuple
+ False, otherwise
+ """
+ for descriptor in attribute.DESCRIPTOR.fields:
+ if descriptor.name != "mccmnc_tuple":
+ if len(getattr(attribute, descriptor.name)):
+ return False
+ return True
+
+def process_apnmap_by_mccmnc(apn_node, pb2_carrier_id, known, apn_map):
+ """Process apn map based on the MCCMNC combination in apns.xml.
+
+ Args:
+ apn_node: APN node
+ pb2_carrier_id: carrier id proto from APN node
+ known: mapping from mccmnc and possible mvno data to canonical name
+ apn_map: apn map
+
+ Returns:
+ None by default
+ """
+ apn_carrier_id = apn_node.getAttribute('carrier_id')
+ if apn_carrier_id != '':
+ print("Cannot use mccmnc and carrier_id at the same time,"
+ + " carrier_id<" + apn_carrier_id + "> is ignored.")
+ cname = get_cname(pb2_carrier_id, known)
+ apn = gen_apnitem(apn_node)
+ apn_map[cname].append(apn)
+
+def process_apnmap_by_carrier_id(apn_node, aospCarrierList, known, apn_map):
+ """Process apn map based on the carrier_id in apns.xml.
+
+ Args:
+ apn_node: APN node
+ aospCarrierList: CarrierList from AOSP
+ known: mapping from mccmnc and possible mvno data to canonical name
+ apn_map: apn map
+
+ Returns:
+ None by default
+ """
+ cname_map = dict()
+ apn_carrier_id = apn_node.getAttribute('carrier_id')
+ if apn_carrier_id != '':
+ if apn_carrier_id in cname_map:
+ for cname in cname_map[apn_carrier_id]:
+ apn_map[cname].append(gen_apnitem(apn_node))
+ else:
+ # convert cid to mccmnc combination
+ cnameList = []
+ for aosp_carrier_id in aospCarrierList.carrier_id:
+ aosp_canonical_id = str(aosp_carrier_id.canonical_id)
+ if aosp_canonical_id == apn_carrier_id:
+ for attribute in aosp_carrier_id.carrier_attribute:
+ mcc_mnc_only = is_mccmnc_only_attribute(attribute)
+ for mcc_mnc in attribute.mccmnc_tuple:
+ cname = mcc_mnc
+ # Handle gid1, spn, imsi in the order used by
+ # CarrierConfigConverterV2#generateCanonicalNameForOthers
+ gid1_list = attribute.gid1 if len(attribute.gid1) else [""]
+ for gid1 in gid1_list:
+ cname_gid1 = cname + ("GID1=" + gid1.upper() if gid1 else "")
+
+ spn_list = attribute.spn if len(attribute.spn) else [""]
+ for spn in spn_list:
+ cname_spn = cname_gid1 + ("SPN=" + spn.upper() if spn else "")
+
+ imsi_list = attribute.imsi_prefix_xpattern if\
+ len(attribute.imsi_prefix_xpattern) else [""]
+ for imsi in imsi_list:
+ cname_imsi = cname_spn + ("IMSI=" + imsi.upper() if imsi else "")
+
+ if cname_imsi == cname and not mcc_mnc_only:
+ # Ignore fields which cannot be handled for now
+ continue
+
+ cnameList.append(get_known_cname(cname_imsi, known))
+ break # break from aospCarrierList.carrier_id since cid is found
+ if cnameList:
+ for cname in cnameList:
+ apn_map[cname].append(gen_apnitem(apn_node))
+
+ # cache cnameList to avoid searching again
+ cname_map[aosp_canonical_id] = cnameList
+ else:
+ print("Can't find cname list, carrier_id in APN files might be wrong : " + apn_carrier_id)
def main():
known = get_knowncarriers([FLAGS.data_dir + '/' + f for f in CARRIER_LISTS])
@@ -240,11 +339,19 @@ def main():
with open(FLAGS.apn_file, 'r', encoding='utf-8') as apnfile:
dom = minidom.parse(apnfile)
+ with open(FLAGS.aosp_carrier_list, 'r', encoding='utf-8', newline='\n') as f:
+ aospCarrierList = text_format.Parse(f.read(), carrierId_pb2.CarrierList())
+
apn_map = collections.defaultdict(list)
for apn_node in dom.getElementsByTagName('apn'):
- cname = get_cname(gen_cid(apn_node), known)
- apn = gen_apnitem(apn_node)
- apn_map[cname].append(apn)
+ pb2_carrier_id = gen_cid(apn_node)
+ if pb2_carrier_id.mcc_mnc or not FLAGS.support_carrier_id:
+ # case 1 : mccmnc
+ # case 2 : mccmnc+mvno
+ process_apnmap_by_mccmnc(apn_node, pb2_carrier_id, known, apn_map)
+ else:
+ # case 3 : carrier_id
+ process_apnmap_by_carrier_id(apn_node, aospCarrierList, known, apn_map)
mcs = carrier_settings_pb2.MultiCarrierSettings()
for c in apn_map: