您现在的位置是:首页 >其他 >Android telephony | supl PDN建立和定位信息获取网站首页其他

Android telephony | supl PDN建立和定位信息获取

Dic- 2025-03-21 12:01:03
简介supl流程步骤

在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的连接请求。主要流程描述如下:

  1. 检查当前网络状态

    • 如果设备已经连接到互联网,Telephony会检查是否已经存在一个合适的APN连接(例如,default APN)。
    • 如果不存在合适的APN连接,Telephony会发起一个新的APN连接请求。
  2. 创建APN连接请求

    • Telephony会创建一个DataConnection对象,用于管理APN连接。
    • 该对象会包含APN的配置信息,如APN名称、类型、协议等。
  3. 发送连接请求到RIL(Radio Interface Layer)

    • Telephony通过RIL与基带处理器通信,发送建立PDN连接的请求。
    • RIL会将请求转换为基带处理器可以理解的指令,并发送给基带处理器。
2.3 RIL层的处理

RIL层负责与基带处理器通信,执行实际的PDN连接建立过程。

  1. 发送PDN连接请求

    • RIL向基带处理器发送RIL_REQUEST_SETUP_DATA_CALL请求,包含APN配置信息。
    • 基带处理器根据APN配置信息,与网络进行协商,建立PDN连接。
  2. 处理基带处理器的响应

    • 基带处理器在成功建立PDN连接后,会返回一个DataCallResponse对象,包含连接的相关信息(如IP地址、DNS服务器等)。
    • RIL将这些信息传递给Telephony层。
2.4 Telephony层的响应处理

Telephony层接收到RIL的响应后,会进行以下处理:

  1. 更新连接状态

    • Telephony会更新DataConnection对象的状态,标记为已连接。
    • 同时,Telephony会通知上层应用,SUPL APN连接已建立。
  2. 配置网络路由

    • 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建立的主要步骤:

  1. 获取TelephonyManager实例

    TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    
  2. 检查设备是否支持双卡

    if (telephonyManager.getPhoneCount() > 1) {
        // 设备支持双卡
    }
    
  3. 获取SubscriptionManager实例

    SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
    
  4. 获取所有活跃的订阅信息

   List<SubscriptionInfo> subscriptionInfos = subscriptionManager.getActiveSubscriptionInfoList();
  1. 创建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                       // 认证类型
);
  1. 发起数据连接请求
// 发起PDN连接请求
DataConnection dataConnection = new DataConnection(context, phone, apnSetting);
dataConnection.connect();

Note:在旧版本的Android上,是在DcTracker中,调用setupDataCall方法发起数据连接请求。(Android T/U已经不使用)

DcTracker dcTracker = phone.getDcTracker();
dcTracker.setupDataCall(apnSetting);
  1. 处理数据连接状态
  • 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建立的主要步骤:

  1. 创建RIL请求
    • RIL中,创建一个RIL_REQUEST_SETUP_DATA_CALL请求。
    RILRequest rr = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
    
  2. 发送RIL请求
    • 将请求发送到基带处理器。
    rr.mParcel.writeInt(radioTechnology);
    rr.mParcel.writeString(apn);
    rr.mParcel.writeString(protocol);
    send(rr);
    
  3. 处理基带处理器的响应
  • 基带处理器返回一个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();
  1. 返回响应给Telephony层
  • DataCallResponse对象返回给Telephony层。
if (rr.mResult != null) {
    AsyncResult.forMessage(rr.mResult, response, null);
    rr.mResult.sendToTarget();
}
  1. 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_LOCATIONINTERNET等。
  • 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建立后,设备获取定位信息的典型流程:

  1. SUPL PDN建立

    • 设备通过SUPL APN连接到运营商的位置服务器(SUPL服务器)。
  2. 请求A-GPS辅助数据

    • 设备向SUPL服务器发送请求,获取A-GPS辅助数据(如卫星星历、粗略时间等)。
  3. GPS模块初始化

    • 设备使用A-GPS辅助数据初始化GPS模块,加速卫星信号的锁定。
  4. GPS定位计算

    • GPS模块接收卫星信号,计算设备的精确位置(经纬度、海拔等)。
  5. 返回定位信息

    • 设备将GPS定位信息返回给应用层,供应用使用。

3. 定位信息的类型

根据定位方式的不同,设备可能返回以下类型的定位信息:

3.1 GPS定位信息
  • 数据类型:经纬度、海拔、速度、方向等。
  • 精度:高(通常在几米以内)。
  • 获取方式:通过LocationManagerGPS_PROVIDER获取。
3.2 网络定位信息
  • 数据类型:基于网络小区(Cell ID)或Wi-Fi的粗略位置。
  • 精度:低(通常在几百米到几公里)。
  • 获取方式:通过LocationManagerNETWORK_PROVIDER获取。
3.3 混合定位信息
  • 数据类型:结合GPS和网络定位的混合数据。
  • 精度:中等(通常在几十米到几百米)。
  • 获取方式:通过LocationManagerFUSED_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设备可以快速、准确地获取设备的精确位置信息。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。