需求:
如果存在用户配置的DNS服务器,则切面拦截运行商下发的DNS,替换为用户自己配置的DNS.
实现:
直接上代码:
1:TelephonyProperties 内新增属性保存用户设置的dns
//QSSI.13/frameworks/base/telephony/java/com/android/internal/telephony/TelephonyProperties.java
/**
* PROPERTY_SIM_DEFAULT_DNS is to set the default DNS
*/
static String PROPERTY_SIM_DEFAULT_DNS = "sim.default.dns";
这里我们注意下TelephonyProperties 为接口类,系统未找到相关的实现类,其实此处的用法类似于aidl文件到java文件的转换,是编译脚本进行转换(build/soong/sysprop/sysprop_library.go)
即会将libsysprop目录下的.sysprop文件编译成对应的.jar给系统调用,即会编译为:PlatformProperties.jar,我们可以把以下目录中的源码文件拖到AS看下
目录:QSSI.13\out\soong\.intermediates\system\libsysprop\srcs\PlatformProperties\android_common\javac\PlatformProperties.jar
我们截取部分TelephonyProperties.class代码看下
public static Optional<Boolean> airplane_mode_on() {
String value = SystemProperties.get("persist.radio.airplane_mode_on");
return Optional.ofNullable(tryParseBoolean(value));
}
public static void airplane_mode_on(Boolean value) {
SystemProperties.set("persist.radio.airplane_mode_on", value == null ? "" : (value ? "1" : "0"));
}
从这个反编译出来的文件可以看到,实际上就是对SystemProperties做了一层封装。
2:在TelephonyProperties.sysprop 中定义属性
//QSSI.13/system/libsysprop/srcs/android/sysprop/TelephonyProperties.sysprop
# set default dns list
prop {
api_name: "sim_default_dns"
type: StringList
scope: Public
access: ReadWrite
prop_name: "sim.default.dns"
}
注意我们新增了属性,需要执行如下指令,更新api文件,具体的详见脚本文件:/build/soong/scripts/freeze-sysprop-api-files.sh
m PlatformProperties-dump-api && rm -rf system/libsysprop/srcs/api/PlatformProperties-current.txt && cp -f out/soong/.intermediates/system/libsysprop/srcs/PlatformProperties_sysprop_library/api-dump.txt system/libsysprop/srcs/api/PlatformProperties-current.txt
执行上述指令以后会更新如下文件
//QSSI.13/system/libsysprop/srcs/api/PlatformProperties-current.txt
prop {
api_name: "sim_default_dns"
type: StringList
access: ReadWrite
prop_name: "sim.default.dns"
}
3:我们新增了属性为sim.default.dns,我们还需要增加selinux权限,即为此属性配置上下文,可直接使用之前系统定义好的上下文
//QSSI.13/system/sepolicy/private/property_contexts
sim.default.dns u:object_r:telephony_status_prop:s0 exact string
//QSSI.13/system/sepolicy/prebuilts/api/33.0/private/property_contexts
sim.default.dns u:object_r:telephony_status_prop:s0 exact string
4:经过上述步骤,我们即可在TelephonyManager内对属性sim.default.dns进行读写
//QSSI.13/frameworks/base/telephony/java/android/telephony/TelephonyManager.java
/**
* Set TelephonyProperties.default_dns for dns.
*
* @hide
*/
public void setSimDnsServers(int phoneId, String dnsStr) {
if (SubscriptionManager.isValidPhoneId(phoneId)) {
List<String> newList = new ArrayList();
if (!TextUtils.isEmpty(dnsStr)) {
List<String> tList = updateTelephonyProperty(TelephonyProperties.sim_default_dns(), phoneId, dnsStr);
newList.addAll(tList);
}
for (int i = 0; i < newList.size(); i++) {
Log.e(TAG, "setSimDns...." + newList.get(i));
}
Log.e(TAG, "setSimDnsList...." + dnsStr + ":" + newList);
TelephonyProperties.sim_default_dns(newList);
}
}
/**
* get TelephonyProperties.default_dns
*
* @hide
*/
public String getSimDnsServers(int phoneId) {
return getTelephonyProperty(phoneId, TelephonyProperties.sim_default_dns(), "");
}
5:我们在建立datacall的时候,就可以读取配置的dns服务器,然后更新,我是在DataNetwork 中处理的,当然也可以在ConnectivityService内处理
//QSSI.13/frameworks/opt/telephony/src/java/com/android/internal/telephony/data/DataNetwork.java
/**
* Update data network based on the latest {@link DataCallResponse}.
*
* @param response The data call response from data service.
*/
private void updateDataNetwork(@NonNull DataCallResponse response) {
.......
//phoebe add for set default dns
// Set DNS servers
List<InetAddress> defaultDns = getDefaultDns(mPhone.getPhoneId());
if (defaultDns != null && defaultDns.size() > 0) {
loge("set default dns:" + defaultDns);
linkProperties.setDnsServers(defaultDns);
} else {
if (response.getDnsAddresses().size() > 0) {
for (InetAddress dns : response.getDnsAddresses()) {
if (!dns.isAnyLocalAddress()) {
linkProperties.addDnsServer(dns);
}
}
} else {
loge("Empty dns response");
}
}
....
}
public List<InetAddress> getDefaultDns(int phoneId) {
String dnsStr = mTelephonyManager.getSimDnsServers(phoneId);
logl("zmm add for getDefaultDns..." + dnsStr);
String[] split = TextUtils.isEmpty(dnsStr) ? null : dnsStr.trim().split(",");
if (split == null || split.length == 0) {
return null;
}
List<InetAddress> dnsService = new ArrayList<>();
try {
for (String str : split) {
if (!str.trim().isEmpty()) {
InetAddress dns = InetAddress.parseNumericAddress(str);
logl("zmm add for default dns..." + dns);
dnsService.add(dns);
}
}
} catch (Exception e) {
e.printStackTrace();
loge("zmm add for default dns..." + e.getMessage());
}
return dnsService;
}
6:设置客户自定义的dns,我是在SIMRecords中设置默认的dns的,当然也可在别的地方通过mTelephonyManager.setSimDnsServers()方法设置不同sim卡的不同dns
当然需要再setdatacall建立成功之前,就设置到属性中去。
//QSSI.13/frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/SIMRecords.java
多个dns服务器用逗号隔开
mTelephonyManager.setSimDnsServers(mPhoneId(), "dns1,dns2");