/* * Copyright (C) 2020 Google LLC * * 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.google.carrier; import static com.google.common.collect.Multimaps.flatteningToMultimap; import static com.google.common.collect.Multimaps.toMultimap; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Comparator.comparing; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; import com.google.auto.value.AutoValue; import com.google.common.base.Ascii; import com.google.common.base.CharMatcher; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import com.google.common.collect.MultimapBuilder; import com.google.protobuf.Descriptors; import com.google.protobuf.TextFormat; import com.google.carrier.CarrierConfig; import com.google.carrier.CarrierId; import com.google.carrier.CarrierList; import com.google.carrier.CarrierMap; import com.google.carrier.CarrierSettings; import com.google.carrier.IntArray; import com.google.carrier.MultiCarrierSettings; import com.google.carrier.TextArray; import com.android.providers.telephony.CarrierIdProto.CarrierAttribute; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * This command converts carrier config XML into text protobuf. * *
Copied from AOSP DefaultCarrierConfigService.
*/
private static boolean checkFilters(Element element, CarrierIdentifier id) {
boolean result = true;
NamedNodeMap attributes = element.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
String attribute = attributes.item(i).getNodeName();
String value = attributes.item(i).getNodeValue();
switch (attribute) {
case "mcc":
result = result && value.equals(id.getMcc());
break;
case "mnc":
result = result && value.equals(id.getMnc());
break;
case "gid1":
result = result && Ascii.equalsIgnoreCase(value, id.getGid1());
break;
case "spn":
result = result && matchOnSP(value, id);
break;
case "imsi":
result = result && matchOnImsi(value, id);
break;
case "cid":
result =
result
&& ((Integer.parseInt(value) == id.getCarrierId())
|| (Integer.parseInt(value) == id.getSpecificCarrierId()));
break;
case "name":
// name is used together with cid for readability. ignore for filter.
break;
default:
System.err.println("Unsupported attribute " + attribute + "=" + value);
result = false;
}
}
return result;
}
/**
* Returns {@code true} if an "spn" attribute in Copied from AOSP DefaultCarrierConfigService.
*/
private static boolean matchOnSP(String xmlSP, CarrierIdentifier id) {
boolean matchFound = false;
String currentSP = id.getSpn();
// Copied from AOSP DefaultCarrierConfigService.
*/
private static boolean matchOnImsi(String xmlImsi, CarrierIdentifier id) {
boolean matchFound = false;
String currentImsi = id.getImsi();
// If we were able to retrieve current IMSI, see if it matches.
if (currentImsi != null) {
Pattern imsiPattern = Pattern.compile(xmlImsi, Pattern.CASE_INSENSITIVE);
Matcher matcher = imsiPattern.matcher(currentImsi);
matchFound = matcher.matches();
}
return matchFound;
}
/**
* Parses a {@link CarrierId} out of a This is purely used for discover potential carriers expressed by this tag, the return value
* may not reflect all attributes of the tag.
*/
private static CarrierId.Builder parseCarrierId(Element element) {
CarrierId.Builder builder = CarrierId.newBuilder();
String mccMnc = element.getAttribute("mcc") + element.getAttribute("mnc");
builder.setMccMnc(mccMnc);
if (element.hasAttribute("imsi")) {
builder.setImsi(element.getAttribute("imsi"));
} else if (element.hasAttribute("gid1")) {
builder.setGid1(element.getAttribute("gid1"));
} else if (element.hasAttribute("gid2")) {
throw new UnsupportedOperationException(
"Not support attribute `gid2`: " + element.getAttribute("gid2"));
} else if (element.hasAttribute("spn")) {
builder.setSpn(element.getAttribute("spn"));
}
return builder;
}
// Same as {@link java.nio.file.Paths#get} but returns a String
private static String getPathAsString(String first, String... more) {
return java.nio.file.Paths.get(first, more).toString();
}
/** Mirror of Android CarrierIdentifier class. Default value of a carrier id is -1. */
@AutoValue
abstract static class CarrierIdentifier {
abstract String getMcc();
abstract String getMnc();
abstract String getImsi();
abstract String getGid1();
abstract String getSpn();
abstract int getCarrierId();
abstract int getSpecificCarrierId();
abstract int getMccmncCarrierId();
static CarrierIdentifier create(
CarrierId carrier, int carrierId, int specificCarrierId, int mccmncCarrierId) {
String mcc = carrier.getMccMnc().substring(0, 3);
String mnc = carrier.getMccMnc().length() > 3 ? carrier.getMccMnc().substring(3) : "";
return new AutoValue_CarrierConfigConverterV2_CarrierIdentifier(
mcc,
mnc,
carrier.getImsi(),
carrier.getGid1(),
carrier.getSpn(),
carrierId,
specificCarrierId,
mccmncCarrierId);
}
}
private static CarrierIdentifier getCid(
CarrierId carrierId, Multimap