问题
在高通平台上验证 GPS 功能流程时候,block 在 APN 数据库的查询。经查,发现高通有内部实现的 LocationService(aosp源码和mtk都没有的类) 包含查询 TelephonyProvider 数据库的逻辑,直接原因是查询到 APN Protocol 不符合预期,直接fail。
关于 Android APN 数据列的更新,涉及的代码主要存在于 Android 的 Telephony Provider 数据库实现中。
先抛出本文关注的疑问:
- 什么时候会把数据库单行 APN 的 current 列置为1?
- 在 DataProfile 结构中是否会打印 current 信息?不会,看ApnSetting存的信息不包含current。
日志分析
// 用于数据建立的 APN 是正常的,按照插入卡的 MCCMNC+MVNO 完全匹配。
// 如下案例,Home Protocol 是仅 IPV6,Roaming 使用仅IPV4
12-18 02:49:23.140 D/DPM-0 ( 4432): Found 6 data profiles. profiles = [[DataProfile=[ApnSetting] T-Mobile US, 2062, 310260, fast.t-mobile.com, , http://mms.msg.eng.t-mobile.com/mms/wapenc, , null, null, 0, mms | supl | hipri | default | xcap | rcs, IPV6, IP, true, 0, false, 0, 0, 0, 1440, 1440, gid, 544D, false, GPRS|EDGE|UMTS|CDMA|CDMA - EvDo rev. 0|CDMA - EvDo rev. A|CDMA - 1xRTT|HSDPA|HSUPA|HSPA|iDEN|CDMA - EvDo rev. B|LTE|CDMA - eHRPD|HSPA+|GSM|TD_SCDMA|LTE_CA|NR, UNKNOWN, 0, -1, -1, false, 3, 961, false, UNEDITED, TrafficDescriptor={mDnn=fast.t-mobile.com, null}, preferred=false],
// 没查到protocol的时候默认是双栈(因为此时插卡后第一次开机,所有 APN 的 current 都没有被置为1,导致无法查询成功,所以什么时候将 APN 设置成 current?)
12-18 02:52:56.719 D/LocSvc_java(10198): ipProtocol: null apn: fast.t-mobile.com networkType: LTE state: 1
12-18 02:52:56.719 W/LocSvc_java(10198): ipProtocol not found in db, default to ipv4v6
// 前后的Dataprofile都是正常的,同上
12-18 02:53:23.463 V/DPM-0 ( 4432): Satisfied profile: [DataProfile=[ApnSetting] T-Mobile US, 2062, 310260, fast.t-mobile.com, , http://mms.msg.eng.t-mobile.com/mms/wapenc, , null, null, 0, mms | supl | hipri | default | xcap | rcs, IPV6, IP, true, 0, false, 0, 0, 0, 1440, 1440, gid, 544D, false, GPRS|EDGE|UMTS|CDMA|CDMA - EvDo rev. 0|CDMA - EvDo rev. A|CDMA - 1xRTT|HSDPA|HSUPA|HSPA|iDEN|CDMA - EvDo rev. B|LTE|CDMA - eHRPD|HSPA+|GSM|TD_SCDMA|LTE_CA|NR, UNKNOWN, 0, -1, -1, false, 3, 961, false, UNEDITED, TrafficDescriptor={mDnn=fast.t-mobile.com, null}, preferred=true], last setup=02:49:23.348
// 同步核实 attach 网络正常
12-18 02:58:27.509 D/RILJ ( 3502): [0634]> SET_INITIAL_ATTACH_APN[DataProfile=[ApnSetting] T-Mobile US, 2062, 310260, fast.t-mobile.com, , http://mms.msg.eng.t-mobile.com/mms/wapenc, , null, null, 0, mms | supl | hipri | default | xcap | rcs, IPV6, IP, true, 0, false, 0, 0, 0, 1440, 1440, gid, 544D, false, GPRS|EDGE|UMTS|CDMA|CDMA - EvDo rev. 0|CDMA - EvDo rev. A|CDMA - 1xRTT|HSDPA|HSUPA|HSPA|iDEN|CDMA - EvDo rev. B|LTE|CDMA - eHRPD|HSPA+|GSM|TD_SCDMA|LTE_CA|NR, UNKNOWN, 0, -1, -1, false, 3, 961, false, UNEDITED, TrafficDescriptor={mDnn=fast.t-mobile.com, null}, preferred=true] [PHONE0]
// AGPS查询到 APN 时, protocol 仍然是有问题的
12-18 02:58:45.445 D/LocSvc_java( 6627): ipProtocol: IPV4V6 apn: fast.t-mobile.com networkType: LTE state: 1
12-18 02:58:45.446 D/LocSvc_java( 6627): handleAgpsConnOpen mAgpsType: 1 mAPN: fast.t-mobile.com mBearerType: 3
代码分析
直接原因:核对代码是查询条件的差异。
AGPS查询激活的APN
定位服务没有按照卡和APN类型进行查询,而是通过apn值以及激活的APN匹配??
Cursor cursor = mContext.getContentResolver().query(Carriers.CONTENT_URI,new String[] {Carriers.PROTOCOL},selection, null,Carriers.DEFAULT_SORT_ORDER);
调用的形参是 Carriers 的 CONTENT_URI 是 TelephonyProvider 的定义,通用Google 数据库 "content://telephony/carriers"
/*** Carriers class contains information about APNs, including MMSC information.*/public static final class Carriers implements BaseColumns {/*** The {@code content://} style URL for this table.* For MSIM, this will return APNs for the default subscription* {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId for MSIM,* use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.*/@NonNullpublic static final Uri CONTENT_URI = Uri.parse("content://telephony/carriers");}
一开始认为是客制化 URI 的问题,但是更换了 URL 仍然查询有问题,根因还是筛选的行数据不准确。
TelephonyProvider 的数据库
在 data/user_de/0/com.android.providers.telephony/databases 的 telephony.db 中,APN 配置会加载到 carriers 表。
经过格式化的建表DDL SQL,包含49列(不是全部都会存在ApnSetting里面),UNIQUE 有28列,可见不是仅通过mccmnc+mvno 差分APN的。
CREATE TABLE carriers (_id INTEGER PRIMARY KEY,name TEXT DEFAULT '',numeric TEXT DEFAULT '',mcc TEXT DEFAULT '',mnc TEXT DEFAULT '',class TEXT DEFAULT '',apn_source INTEGER DEFAULT -1,modify_apn_name_id INTEGER DEFAULT -1,carrier_id INTEGER DEFAULT -1,apn TEXT DEFAULT '',user TEXT DEFAULT '',server TEXT DEFAULT '',password TEXT DEFAULT '',proxy TEXT DEFAULT '',port TEXT DEFAULT '',mmsproxy TEXT DEFAULT '',mmsport TEXT DEFAULT '',mmsc TEXT DEFAULT '',authtype INTEGER DEFAULT -1,type TEXT DEFAULT '',current INTEGER,sourcetype INTEGER DEFAULT 0,protocol TEXT DEFAULT 'IP',roaming_protocol TEXT DEFAULT 'IP',carrier_enabled BOOLEAN DEFAULT 1,bearer INTEGER DEFAULT 0,bearer_bitmask INTEGER DEFAULT 0,network_type_bitmask INTEGER DEFAULT 0,lingering_network_type_bitmask INTEGER DEFAULT 0,mvno_type TEXT DEFAULT '',mvno_match_data TEXT DEFAULT '',sub_id INTEGER DEFAULT -1,profile_id INTEGER DEFAULT 0,modem_cognitive BOOLEAN DEFAULT 0,max_conns INTEGER DEFAULT 0,wait_time INTEGER DEFAULT 0,max_conns_time INTEGER DEFAULT 0,mtu INTEGER DEFAULT 0,mtu_v4 INTEGER DEFAULT 0,mtu_v6 INTEGER DEFAULT 0,edited INTEGER DEFAULT 0,user_visible BOOLEAN DEFAULT 1,user_editable BOOLEAN DEFAULT 1,owned_by INTEGER DEFAULT 1,apn_set_id INTEGER DEFAULT 0,skip_464xlat INTEGER DEFAULT -1,always_on INTEGER DEFAULT 0,infrastructure_bitmask INTEGER DEFAULT 3,esim_bootstrap_provisioning BOOLEAN DEFAULT 0,UNIQUE (apn_set_id,mmsc,mmsport,numeric,mcc,carrier_enabled,carrier_id,protocol,bearer,mvno_type,infrastructure_bitmask,sourcetype,class,apn,user_editable,mnc,mvno_match_data,owned_by,network_type_bitmask,modify_apn_name_id,proxy,esim_bootstrap_provisioning,port,profile_id,roaming_protocol,name,apn_source,mmsproxy)
);
UNIQUE
是 SQL 中的一种约束条件,用于确保表中某一列或多列的值唯一。它可以防止在数据库表中插入重复的值,从而维护数据的完整性和一致性。
current=1表示正在活跃使用的APN,默认是null的。
current 激活案例
插入联通卡驻网,可见current会置为1.
Note:换卡可能不会更新db数据值,这是个问题。必现步骤,刷机插卡开机,能查看到TMO卡各种310-260 160+条被更新为current=1,为什么移动卡不会呢?
adb debug 查询
通过 adb 命令,在 debug 阶段可以方便数据数据
adb shell
# 查询激活的 “ims” APN
content query --uri content://telephony/carriers --where "current=1 AND apn='ims' AND carrier_enabled=1" --sort "name ASC"
# 按值查询APN
content query --uri content://telephony/carriers --where "apn='fast.t-mobile.com' AND carrier_enabled=1" --sort "name ASC"
DataProfile APN配置
在 DPM 中获取并打印ApnSetting信息,结构看ApnSetting builder的字段定义和实现赋值,由 makeApnSetting 查询数据库得到builder 信息。
01-06 19:54:12.753 4552 4552 V DPM-0 : Satisfied profile: [DataProfile=[ApnSetting] T-Mobile US, 2062, 310260, fast.t-mobile.com, , http://mms.msg.eng.t-mobile.com/mms/wapenc, , null, null, 0, mms | supl | hipri | default | xcap | rcs, IPV6, IP, true, 0, false, 0, 0, 0, 1440, 1440, gid, 544D, false, GPRS|EDGE|UMTS|CDMA|CDMA - EvDo rev. 0|CDMA - EvDo rev. A|CDMA - 1xRTT|HSDPA|HSUPA|HSPA|iDEN|CDMA - EvDo rev. B|LTE|CDMA - eHRPD|HSPA+|GSM|TD_SCDMA|LTE_CA|NR, UNKNOWN, 0, -1, -1, false, 3, 961, false, UNEDITED, TrafficDescriptor={mDnn=fast.t-mobile.com, null}, preferred=false], last setup=never
顺序
mEntryName。mId,
mCarrierEnabled, mProfileId,
Note:没有current的值,说明驻网不会用到和修改。
ApnSetting 字段(按结构体字段) | 参考值 | toString顺序编号 | 备注 |
---|---|---|---|
mEntryName | T-Mobile US | 1 | 配置的carrier字段 |
mApnName | fast.t-mobile.com | 4 | 实际入网用的APN值 |
mProxyAddress | 空 | 5 | |
mProxyPort | 9 | portToString(mProxyPort) | |
mMmsc | 6 |