在Android系统中,SUPL(Secure User Plane Location)是一种用于辅助GPS定位的技术,它通过建立特定的APN(Access Point Name)连接来传输定位数据。
以下介绍Android Telephony发起SUPL APN的PDN(Packet Data Network)建立的详细过程。
一、定位PDN建立流程
1. 【前置条件】SUPL APN的配置
SUPL APN通常由运营商在SIM卡中配置,或者在设备的APN设置中手动配置。
APN配置包括以下关键信息:
- APN名称:例如
supl
。 - APN类型:通常为
supl
。 - APN协议:IPv4、IPv6或两者都支持。
2. 【文字流程】发起SUPL APN的PDN建立
2.1 应用层请求
当应用需要使用SUPL服务时(例如,使用GPS定位),Android的定位服务(如LocationManager
)会请求建立SUPL连接。
2.2 Telephony层的处理
Telephony层是Android系统中负责管理电话功能的核心模块,包括SIM卡管理、网络连接、通话状态等。
Telephony层负责处理APN的连接请求。主要流程描述如下:
-
检查当前网络状态:
- 如果设备已经连接到互联网,Telephony会检查是否已经存在一个合适的APN连接(例如,
default
APN)。 - 如果不存在合适的APN连接,Telephony会发起一个新的APN连接请求。
- 如果设备已经连接到互联网,Telephony会检查是否已经存在一个合适的APN连接(例如,
-
创建APN连接请求:
- Telephony会创建一个
DataConnection
对象,用于管理APN连接。 - 该对象会包含APN的配置信息,如APN名称、类型、协议等。
- Telephony会创建一个
-
发送连接请求到RIL(Radio Interface Layer):
- Telephony通过RIL与基带处理器通信,发送建立PDN连接的请求。
- RIL会将请求转换为基带处理器可以理解的指令,并发送给基带处理器。
2.3 RIL层的处理
RIL层负责与基带处理器通信,执行实际的PDN连接建立过程。
-
发送PDN连接请求:
- RIL向基带处理器发送
RIL_REQUEST_SETUP_DATA_CALL
请求,包含APN配置信息。 - 基带处理器根据APN配置信息,与网络进行协商,建立PDN连接。
- RIL向基带处理器发送
-
处理基带处理器的响应:
- 基带处理器在成功建立PDN连接后,会返回一个
DataCallResponse
对象,包含连接的相关信息(如IP地址、DNS服务器等)。 - RIL将这些信息传递给Telephony层。
- 基带处理器在成功建立PDN连接后,会返回一个
2.4 Telephony层的响应处理
Telephony层接收到RIL的响应后,会进行以下处理:
-
更新连接状态:
- Telephony会更新
DataConnection
对象的状态,标记为已连接。 - 同时,Telephony会通知上层应用,SUPL APN连接已建立。
- Telephony会更新
-
配置网络路由:
- Telephony会配置设备的网络路由,确保SUPL数据通过正确的APN连接传输。
3. 【流程图】时序图
以下是一个简化的时序图,展示了SUPL APN的PDN建立过程:
应用层 -> Telephony层: 请求建立SUPL连接
Telephony层 -> RIL层: 发送PDN连接请求 (RIL_REQUEST_SETUP_DATA_CALL)
RIL层 -> 基带处理器: 发送PDN连接请求
基带处理器 -> 网络: 协商建立PDN连接
网络 -> 基带处理器: 返回PDN连接响应
基带处理器 -> RIL层: 返回DataCallResponse
RIL层 -> Telephony层: 返回PDN连接响应
Telephony层 -> 应用层: 通知SUPL连接已建立
4. 【功能实现】关键代码示例
以下是一些关键代码示例,展示了如何在Android Telephony中发起SUPL APN的PDN建立:
4.1 发起PDN连接请求(Telephony层响应处理)
4.1.1 关键类
TelephonyManager
:提供访问设备电话功能的接口。SubscriptionManager
:管理设备的SIM卡订阅信息。DataConnection
:管理数据连接(如APN连接)的状态和配置。Phone
:表示一个电话实例,管理通话、数据连接等功能。DcTracker
:数据连接跟踪器,负责管理数据连接的建立、断开等操作。
4.1.2 代码逻辑
以下是Telephony层处理SUPL APN建立的主要步骤:
-
获取TelephonyManager实例:
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
-
检查设备是否支持双卡:
if (telephonyManager.getPhoneCount() > 1) { // 设备支持双卡 }
-
获取SubscriptionManager实例:
SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
-
获取所有活跃的订阅信息:
List<SubscriptionInfo> subscriptionInfos = subscriptionManager.getActiveSubscriptionInfoList();
- 创建APN配置:
// 创建APN配置
ApnSetting apnSetting = new ApnSetting(
id, // ID
"supl", // APN名称
null, // Proxy
-1, // Port
null, // MMSC
null, // MMS Proxy
-1, // MMS Port
"supl", // APN类型
ApnSetting.PROTOCOL_IP, // 协议
ApnSetting.PROTOCOL_IP, // 漫游协议
true, // 启用状态
0, // 网络类型
true, // 可承载
false, // 漫游时启用
0, // 用户可见
null, // 用户
null, // 密码
0 // 认证类型
);
- 发起数据连接请求:
// 发起PDN连接请求
DataConnection dataConnection = new DataConnection(context, phone, apnSetting);
dataConnection.connect();
Note:在旧版本的Android上,是在DcTracker
中,调用setupDataCall
方法发起数据连接请求。(Android T/U已经不使用)
DcTracker dcTracker = phone.getDcTracker();
dcTracker.setupDataCall(apnSetting);
- 处理数据连接状态:
-
DcTracker
会监听数据连接的状态变化,并通过回调通知上层应用。dcTracker.registerForDataStateChanged(handler, EVENT_DATA_STATE_CHANGED);
-
新版本在
DataNetwork
中注册监听(以下是Android V的代码案例)- frameworks/opt/telephony/src/java/com/android/internal/telephony/data/DataNetwork.java
for (int transport : mAccessNetworksManager.getAvailableTransports()) {
mDataServiceManagers.get(transport)
.registerForDataCallListChanged(getHandler(), EVENT_DATA_STATE_CHANGED);
}
4.2 处理PDN连接响应(RIL层处理)
RIL层是Android系统中负责与基带处理器通信的模块。它将Telephony层的请求转换为基带处理器可以理解的指令,并处理基带处理器的响应。
4.2.1 关键类
RIL
:实现与基带处理器的通信。RILRequest
:表示一个RIL请求。RILConstants
:定义RIL请求和响应的常量。DataCallResponse
:表示数据连接的响应。
4.2.2 代码逻辑
以下是RIL层处理SUPL APN建立的主要步骤:
- 创建RIL请求:
- 在
RIL
中,创建一个RIL_REQUEST_SETUP_DATA_CALL
请求。
RILRequest rr = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
- 在
- 发送RIL请求:
- 将请求发送到基带处理器。
rr.mParcel.writeInt(radioTechnology); rr.mParcel.writeString(apn); rr.mParcel.writeString(protocol); send(rr);
- 处理基带处理器的响应:
- 基带处理器返回一个
DataCallResponse
对象,包含连接的相关信息。
DataCallResponse response = new DataCallResponse();
response.status = parcel.readInt();
response.suggestedRetryTime = parcel.readInt();
response.cid = parcel.readInt();
response.active = parcel.readInt();
response.type = parcel.readString();
response.ifname = parcel.readString();
response.addresses = parcel.readStringArray();
response.dnses = parcel.readStringArray();
response.gateways = parcel.readStringArray();
- 返回响应给Telephony层:
- 将
DataCallResponse
对象返回给Telephony层。
if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, response, null);
rr.mResult.sendToTarget();
}
- Telephony 收到回调
// 上层处理PDN连接响应
void onDataCallResponse(DataCallResponse response) {
if (response.status == DataCallResponse.STATUS_SUCCESS) {
// 更新连接状态
updateConnectionState(ConnectionState.CONNECTED);
// 配置网络路由
configureNetworkRouting(response);
// 通知上层应用
notifySuplConnectionEstablished();
} else {
// 处理连接失败
handleConnectionFailure(response);
}
}
5. 注意事项
- 权限:在AndroidManifest.xml中需要声明相关权限,如
ACCESS_FINE_LOCATION
、INTERNET
等。 - API级别:部分API可能需要较高的Android版本支持,需注意兼容性。
- 运营商配置:不同运营商的SUPL APN配置可能不同,需确保配置正确。
通过以上步骤,Android Telephony可以成功发起SUPL APN的PDN建立,从而支持SUPL定位服务。
6. 总结
- Telephony层负责管理数据连接的逻辑,包括APN配置、连接请求和状态管理。
// 获取TelephonyManager实例
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
// 检查设备是否支持双卡
if (telephonyManager.getPhoneCount() > 1) {
// 获取SubscriptionManager实例
SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
// 获取所有活跃的订阅信息
List<SubscriptionInfo> subscriptionInfos = subscriptionManager.getActiveSubscriptionInfoList();
// 创建APN配置
ApnSetting apnSetting = new ApnSetting(
id, // ID
"supl", // APN名称
null, // Proxy
-1, // Port
null, // MMSC
null, // MMS Proxy
-1, // MMS Port
"supl", // APN类型
ApnSetting.PROTOCOL_IP, // 协议
ApnSetting.PROTOCOL_IP, // 漫游协议
true, // 启用状态
0, // 网络类型
true, // 可承载
false, // 漫游时启用
0, // 用户可见
null, // 用户
null, // 密码
0 // 认证类型
);
// 发起数据连接请求
DcTracker dcTracker = phone.getDcTracker();
dcTracker.setupDataCall(apnSetting);
}
- RIL层负责与基带处理器通信,将Telephony层的请求转换为基带指令,并处理基带处理器的响应。
// 创建RIL请求
RILRequest rr = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
// 发送RIL请求
rr.mParcel.writeInt(radioTechnology);
rr.mParcel.writeString(apn);
rr.mParcel.writeString(protocol);
send(rr);
// 处理基带处理器的响应
DataCallResponse response = new DataCallResponse();
response.status = parcel.readInt();
response.suggestedRetryTime = parcel.readInt();
response.cid = parcel.readInt();
response.active = parcel.readInt();
response.type = parcel.readString();
response.ifname = parcel.readString();
response.addresses = parcel.readStringArray();
response.dnses = parcel.readStringArray();
response.gateways = parcel.readStringArray();
// 返回响应给Telephony层
if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, response, null);
rr.mResult.sendToTarget();
}
- 通过Telephony层和RIL层的协作,Android系统可以成功建立SUPL APN连接,并支持SUPL定位服务。
二、定位信息获取
在Android系统中,SUPL(Secure User Plane Location)协议的主要目的是辅助GPS定位,以提高定位的速度和精度。当SUPL APN的PDN建立成功后,设备可以通过SUPL协议从网络获取辅助数据(A-GPS数据),并结合GPS模块获取精确的定位信息。以下是详细的解释:
1. SUPL PDN建立后的定位信息来源
SUPL PDN建立后,设备可以通过以下方式获取定位信息:
1.1 A-GPS辅助数据
- 作用:A-GPS(Assisted GPS)数据用于加速GPS定位过程,尤其是在冷启动(Cold Start)情况下。
- 内容:
- 卫星星历(Ephemeris Data):提供GPS卫星的精确位置信息。
- 粗略时间(Coarse Time):帮助设备快速锁定卫星信号。
- 粗略位置(Coarse Position):基于网络小区(Cell ID)或Wi-Fi的粗略位置。
- 获取方式:通过SUPL协议从运营商的位置服务器(如SUPL服务器)下载。
1.2 GPS定位信息
- 作用:GPS模块通过接收卫星信号计算设备的精确位置。
- 内容:
- 经纬度(Latitude and Longitude):设备的精确地理位置。
- 海拔高度(Altitude):设备的海拔高度(如果支持)。
- 速度(Speed):设备的移动速度(如果支持)。
- 方向(Bearing):设备的移动方向(如果支持)。
- 获取方式:GPS模块直接接收卫星信号并计算。
1.3 网络小区信息
- 作用:在网络辅助定位(如A-GPS或基于网络的定位)中,网络小区信息用于提供设备的粗略位置。
- 内容:
- 小区ID(Cell ID):设备当前连接的基站小区。
- 位置区码(LAC):基站的位置区域。
- 信号强度(Signal Strength):设备的信号强度。
- 获取方式:通过Telephony API获取。
2. 定位信息的获取流程
以下是SUPL PDN建立后,设备获取定位信息的典型流程:
-
SUPL PDN建立:
- 设备通过SUPL APN连接到运营商的位置服务器(SUPL服务器)。
-
请求A-GPS辅助数据:
- 设备向SUPL服务器发送请求,获取A-GPS辅助数据(如卫星星历、粗略时间等)。
-
GPS模块初始化:
- 设备使用A-GPS辅助数据初始化GPS模块,加速卫星信号的锁定。
-
GPS定位计算:
- GPS模块接收卫星信号,计算设备的精确位置(经纬度、海拔等)。
-
返回定位信息:
- 设备将GPS定位信息返回给应用层,供应用使用。
3. 定位信息的类型
根据定位方式的不同,设备可能返回以下类型的定位信息:
3.1 GPS定位信息
- 数据类型:经纬度、海拔、速度、方向等。
- 精度:高(通常在几米以内)。
- 获取方式:通过
LocationManager
的GPS_PROVIDER
获取。
3.2 网络定位信息
- 数据类型:基于网络小区(Cell ID)或Wi-Fi的粗略位置。
- 精度:低(通常在几百米到几公里)。
- 获取方式:通过
LocationManager
的NETWORK_PROVIDER
获取。
3.3 混合定位信息
- 数据类型:结合GPS和网络定位的混合数据。
- 精度:中等(通常在几十米到几百米)。
- 获取方式:通过
LocationManager
的FUSED_PROVIDER
获取(需要Google Play服务支持)。
4. 代码示例
以下是通过LocationManager
获取定位信息的代码示例:
4.1 获取GPS定位信息
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// 监听GPS定位
LocationListener gpsListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
double latitude = location.getLatitude(); // 纬度
double longitude = location.getLongitude(); // 经度
double altitude = location.getAltitude(); // 海拔
float speed = location.getSpeed(); // 速度
float bearing = location.getBearing(); // 方向
Log.d("GPS Location", "Lat: " + latitude + ", Lon: " + longitude);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onProviderDisabled(String provider) {}
};
// 请求GPS定位更新
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, gpsListener);
4.2 获取网络定位信息
LocationListener networkListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
double latitude = location.getLatitude(); // 纬度
double longitude = location.getLongitude(); // 经度
Log.d("Network Location", "Lat: " + latitude + ", Lon: " + longitude);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onProviderDisabled(String provider) {}
};
// 请求网络定位更新
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, networkListener);
5. 时序图
以下是SUPL PDN建立后,设备获取定位信息的时序图:
设备 -> SUPL服务器: 建立SUPL PDN连接
设备 -> SUPL服务器: 请求A-GPS辅助数据
SUPL服务器 -> 设备: 返回A-GPS辅助数据
设备 -> GPS模块: 初始化GPS模块
GPS模块 -> 卫星: 接收卫星信号
GPS模块 -> 设备: 计算并返回GPS定位信息
设备 -> 应用层: 返回定位信息(经纬度等)
6. 总结
- SUPL PDN建立后,设备主要通过GPS模块获取精确的定位信息(如经纬度、海拔等)。
- A-GPS辅助数据用于加速GPS定位过程,但不会直接提供定位信息。
- 网络小区信息通常用于粗略定位,精度较低。
- 最终的定位信息通常是经纬度,这是GPS定位的核心输出。
通过SUPL协议和GPS模块的结合,Android设备可以快速、准确地获取设备的精确位置信息。