标签:gps
上一篇讲到了loc eng是如何把sv status(sv是satellite value,可以看做是卫星信息的简称)信息传递给android framework的,都是一系列callback而已,本文需要讲的是sv status信息如何从modem层(由于QMI层是高通的ap跟modem的通信机制,不需要我们来处理,所以我这里把QMI+modem统称为modem层,可能不准确,但是大家理解了就行)传递到loc eng层。
loc eng层的sv status信息是通过sv_status_cb函数来扔给android framework层的,我们需要看下loc eng层的sv_status_cb是在哪里被调用的,具体如下:
hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.cpp
void LocEngReportSv::proc() const {
//我们需要记住的是:loc eng层是通过一个proc()的方法把数据传递到上层的
LocEngAdapter* adapter = (LocEngAdapter*)mAdapter;
loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)adapter->getOwner();
if (locEng->mute_session_state != LOC_MUTE_SESS_IN_SESSION)
{
if (locEng->sv_status_cb != NULL) {
//locEng是loc_eng_data_s_type*类型的(就是loc eng层),所以这个sv_status_cb就是对应android framework层的reportSvStatus
locEng->sv_status_cb((GpsSvStatus*)&(mSvStatus),
(void*)mSvExt);
}
if (locEng->generateNmea)
{
loc_eng_nmea_generate_sv(locEng, mSvStatus, mLocationExtended);
}
}
}
由于loc eng层到modem层是属于消息触发的,也就是说正常的流程是:modem层传上来一个消息,经过一系列处理传递到loc eng层,loc eng层传递给android framework层,然后交给apk来处理。所以本文的讲解flow跟上一篇可能有一些不一样,需要从底层(loc_api层)往上层讲(loc eng层)。
在讲解flow之前,有一个架构性的东西需要讲解一下,高通平台的GPS核心部分都在modem里面,这里面实现了GPS相关的协议,类似Wi-Fi的supplicant+driver部分,我们把这个部分看做是GPS service,另外一部分在ap里面,我们把这部分看做是GPS client,client主要是通过QMI的通信方式接收service发过来的信息,当然client也可以通过QMI发送信息给service,这个就是GPS的最大的框架。
qmi暂时不是本文需要关注的,所以这里从qmi之上开始讲起,qmi之上有一个叫loc_api的层,具体作用是通过qmi读取service发送过来的信息,当然也可以通过qmi发送信息给service,有一个专门处理service发送过来信息的callback需要重点关注,在看callback之前有一些数据结构需要先给出来,不然后续代码理解起来可能会比较麻烦。
locClientCallbackDataType的各种callback定义:
vendor/qcom/opensource/location/loc_api/loc_api_v02/loc_api_v02_client.c
typedef struct locClientCbDataStructT locClientCallbackDataType;
struct locClientCbDataStructT
{
// client cookie
void *pClientCookie;
//QCCI handle for this control point
qmi_client_type userHandle;
// callbacks registered by the clients
locClientEventIndCbType eventCallback;
locClientRespIndCbType respCallback;
locClientErrorCbType errorCallback;
// the event mask the client has registered for
locClientEventMaskType eventRegMask;
//pointer to itself for checking consistency data
locClientCallbackDataType *pMe;
};
vendor/qcom/opensource/location/loc_api/loc_api_v02/loc_api_v02_client.c
static void locClientIndCb
(
qmi_client_type user_handle,
unsigned int msg_id,
void *ind_buf,
unsigned int ind_buf_len,
void *ind_cb_data
)
{
//定义和初始化,关键参数ind_cb_data会赋值给locClientCallbackDataType类型的pCallbackData
locClientIndEnumT indType;
size_t indSize = 0;
qmi_client_error_type rc ;
locClientCallbackDataType* pCallbackData =
(locClientCallbackDataType *)ind_cb_data;
LOC_LOGV("%s:%d]: Indication: msg_id=%d buf_len=%d pCallbackData = %p\n",
__func__, __LINE__, (uint32_t)msg_id, ind_buf_len,
pCallbackData);
// check callback data
if(NULL == pCallbackData ||(pCallbackData != pCallbackData->pMe))
{
//如果传进来的参数是NULL,那么一切面谈了
LOC_LOGE("%s:%d]: invalid callback data", __func__, __LINE__);
return;
}
// check user handle
if(memcmp(&pCallbackData->userHandle, &user_handle, sizeof(user_handle)))
{
LOC_LOGE("%s:%d]: invalid user_handle got %p expected %p\n",
__func__, __LINE__,
user_handle, pCallbackData->userHandle);
//填充callback的userHandle,如果异常则返回
return;
}
// Get the indication size and type ( eventInd or respInd)
//顾名思义从msg_id里面获取size和type,type分为event和response
if( true == locClientGetSizeAndTypeByIndId(msg_id, &indSize, &indType))
{
void *indBuffer = NULL;
// if the client did not register for this event then just drop it
if( (eventIndType == indType) &&
( (NULL == pCallbackData->eventCallback) ||
(false == isClientRegisteredForEvent(pCallbackData->eventRegMask, msg_id)) ) )
{
//如果是eventIndType,但是eventCallback是NULL,或者msg_id的eventRegMask是没有注册的
LOC_LOGW("%s:%d]: client is not registered for event %d\n",
__func__, __LINE__, (uint32_t)msg_id);
return;
}
// decode the indication
indBuffer = malloc(indSize);
if(NULL == indBuffer)
{
//分配内存失败
LOC_LOGE("%s:%d]: memory allocation failed\n", __func__, __LINE__);
return;
}
//初始化rc为QMI_NO_ERR
rc = QMI_NO_ERR;
if (ind_buf_len > 0)
{
// decode the indication
//解析qmi message,ind_buf是传入数据,indBuffer是解析之后的数据
rc = qmi_client_message_decode(
user_handle,
QMI_IDL_INDICATION,
msg_id,
ind_buf,
ind_buf_len,
indBuffer,
indSize);
}
if( rc == QMI_NO_ERR )
{
//validate indication
//解析完毕之后就要开始switch case了,其中case是msg_id
if (true == locClientHandleIndication(msg_id, indBuffer, indSize))
{
//一般只要indBuffer没有问题,就会走这个flow
if(eventIndType == indType)
{
locClientEventIndUnionType eventIndUnion;
/* copy the eventCallback function pointer from the callback
* data to local variable. This is to protect against the race
* condition between open/close and indication callback.
*/
//这里可以看到eventCallback赋值给了localEventCallback,就是等于后面的globalEventCb(具体后面有讲),这里是重点!!!
locClientEventIndCbType localEventCallback =
pCallbackData->eventCallback;
// dummy event
eventIndUnion.pPositionReportEvent =
(qmiLocEventPositionReportIndMsgT_v02 *)indBuffer;
/* call the event callback
* To avoid calling the eventCallback after locClientClose
* is called, check pCallbackData->eventCallback again here
*/
if((NULL != localEventCallback) &&
(NULL != pCallbackData->eventCallback))
{
//如果LocalEventCallback不为NULL,则调用callback所绑定的函数,也就是globalEventCb
localEventCallback(
(locClientHandleType)pCallbackData,
msg_id,
eventIndUnion,
pCallbackData->pClientCookie);
}
}
else if(respIndType == indType)
{
//resp类型的msg先不讲
locClientRespIndUnionType respIndUnion;
/* copy the respCallback function pointer from the callback
* data to local variable. This is to protect against the race
* condition between open/close and indication callback.
*/
locClientRespIndCbType localRespCallback =
pCallbackData->respCallback;
// dummy to suppress compiler warnings
respIndUnion.pDeleteAssistDataInd =
(qmiLocDeleteAssistDataIndMsgT_v02 *)indBuffer;
/* call the response callback
* To avoid calling the respCallback after locClientClose
* is called, check pCallbackData->respCallback again here
*/
if((NULL != localRespCallback) &&
(NULL != pCallbackData->respCallback))
{
localRespCallback(
(locClientHandleType)pCallbackData,
msg_id,
respIndUnion,
pCallbackData->pClientCookie);
}
}
}
else // error handling indication
{
LOC_LOGE("%s:%d]: Error handling the indication %d\n",
__func__, __LINE__, (uint32_t)msg_id);
}
}
else
{
LOC_LOGE("%s:%d]: Error decoding indication %d\n",
__func__, __LINE__, rc);
}
if(indBuffer)
{
free (indBuffer);
}
}
else // Id not found
{
LOC_LOGE("%s:%d]: Error indication not found %d\n",
__func__, __LINE__,(uint32_t)msg_id);
}
return;
}
qmi_client_message_decode结果为QMI_NO_ERR之后有一个locClientHandleIndication,我们看下具体实现:
vendor/qcom/opensource/location/loc_api/loc_api_v02/loc_api_v02_client.c
static bool locClientHandleIndication(
uint32_t indId,
void* indBuffer,
size_t indSize
)
{
bool status = false;
switch(indId)
{
...
//暂时只看跟sv status相关的flow
// handle satellite report
case QMI_LOC_EVENT_GNSS_SV_INFO_IND_V02:
{
status = locClientHandleSatReportInd(indId, indBuffer, indSize);
break;
}
...
return status;
}
在往下看之前,有必要看一个数据结构,主要是为了存储decorder之后的信息,具体如下:
vendor/qcom/opensource/location/loc_api/loc_api_v02/location_service_v02.h
typedef struct {
/* Mandatory */
/* Altitude Assumed */
uint8_t altitudeAssumed; //海拔是假设的?FALSE代表海拔是计算出来的,TRUE代表海拔是假设的,也就是说没有足够的卫星来确定精确的海拔
/**< Indicates whether altitude is assumed or calculated: \begin{itemize1}
\item 0x00 (FALSE) -- Valid altitude is calculated
\item 0x01 (TRUE) -- Valid altitude is assumed; there may not be
enough satellites to determine precise altitude
\vspace{-0.18in} \end{itemize1}*/
/* Optional */
/* Satellite Info */
uint8_t svList_valid; /**< Must be set to true if svList is being passed */ //如果svList被赋值过,就应该是true
uint32_t svList_len; /**< Must be set to # of elements in svList */
qmiLocSvInfoStructT_v02 svList[QMI_LOC_SV_INFO_LIST_MAX_SIZE_V02]; //qmiLocSvInfoStructT_v02类型的一个数组
/**< \vspace{0.06in} \n SV information list. */
}qmiLocEventGnssSvInfoIndMsgT_v02; /* Message */
qmiLocEventGnssSvInfoIndMsgT_v02里面有一个类型为qmiLocSvInfoStructT_v02的数组,这个存储了sv status的重要信息(包含了elevation,azimuth,snr等信息),具体属性如下:
typedef struct {
qmiLocSvInfoValidMaskT_v02 validMask;
/**< Bitmask indicating which of the fields in this TLV are valid.
Valid bitmasks: \begin{itemize1}
\item 0x00000001 -- VALID_SYSTEM
\item 0x00000002 -- VALID_GNSS_SVID
\item 0x00000004 -- VALID_HEALTH_ STATUS
\item 0x00000008 -- VALID_PROCESS_ STATUS
\item 0x00000010 -- VALID_SVINFO_ MASK
\item 0x00000020 -- VALID_ELEVATION
\item 0x00000040 -- VALID_AZIMUTH
\item 0x00000080 -- VALID_SNR
\vspace{-0.18in} \end{itemize1} */
qmiLocSvSystemEnumT_v02 system;
/**< Indicates to which constellation this SV belongs.
Valid values: \n
- eQMI_LOC_SV_SYSTEM_GPS (1) -- GPS satellite
- eQMI_LOC_SV_SYSTEM_GALILEO (2) -- GALILEO satellite
- eQMI_LOC_SV_SYSTEM_SBAS (3) -- SBAS satellite
- eQMI_LOC_SV_SYSTEM_COMPASS (4) -- COMPASS satellite
- eQMI_LOC_SV_SYSTEM_GLONASS (5) -- GLONASS satellite
- eQMI_LOC_SV_SYSTEM_BDS (6) -- BDS satellite
*/
uint16_t gnssSvId; //gnssSvId,这个跟后面的prn有关系,重要参数之一
/**< GNSS SV ID.
\begin{itemize1}
\item Range: \begin{itemize1}
\item For GPS: 1 to 32
\item For GLONASS: 1 to 32
\item For SBAS: 120 to 151
\item For BDS: 201 to 237
\end{itemize1} \end{itemize1}
The GPS and GLONASS SVs can be disambiguated using the system field. */
uint8_t healthStatus;
/**< Health status.
\begin{itemize1}
\item Range: 0 to 1; 0 = unhealthy, \n 1 = healthy
\vspace{-0.18in} \end{itemize1}*/
qmiLocSvStatusEnumT_v02 svStatus;
/**< SV processing status.
Valid values: \n
- eQMI_LOC_SV_STATUS_IDLE (1) -- SV is not being actively processed
- eQMI_LOC_SV_STATUS_SEARCH (2) -- The system is searching for this SV
- eQMI_LOC_SV_STATUS_TRACK (3) -- SV is being tracked
*/
qmiLocSvInfoMaskT_v02 svInfoMask;
/**< Indicates whether almanac and ephemeris information is available. \n
Valid bitmasks:
- 0x01 -- SVINFO_HAS_EPHEMERIS \n
- 0x02 -- SVINFO_HAS_ALMANAC
*/
float elevation; //海拔,重要参数之一
/**< SV elevation angle.\n
- Units: Degrees \n
- Range: 0 to 90 */
float azimuth; //方位角,重要参数之一
/**< SV azimuth angle.\n
- Units: Degrees \n
- Range: 0 to 360 */
float snr; //snr,重要参数之一
/**< SV signal-to-noise ratio. \n
- Units: dB-Hz */
}qmiLocSvInfoStructT_v02; /* Type */
svStatus是qmiLocSvStatusEnumT_v02类型的,具体定义如下:
typedef enum {
QMILOCSVSTATUSENUMT_MIN_ENUM_VAL_V02 = -2147483647, /**< To force a 32 bit signed enum. Do not change or use*/
eQMI_LOC_SV_STATUS_IDLE_V02 = 1, /**< SV is not being actively processed */
eQMI_LOC_SV_STATUS_SEARCH_V02 = 2, /**< The system is searching for this SV */
eQMI_LOC_SV_STATUS_TRACK_V02 = 3, /**< SV is being tracked */
QMILOCSVSTATUSENUMT_MAX_ENUM_VAL_V02 = 2147483647 /**< To force a 32 bit signed enum. Do not change or use*/
}qmiLocSvStatusEnumT_v02;
locClientHandleSatReportInd的主要作用是打印相应的sv info,具体实现如下:
vendor/qcom/opensource/location/loc_api/loc_api_v02/loc_api_v02_client.c
/** locClientHandleSatReportInd
* @brief Validates a satellite report indication. Dk
* @param [in] msg_id
* @param [in] ind_buf
* @param [in] ind_buf_len
* @return true if sat report is valid, false otherwise
*/
static bool locClientHandleSatReportInd
(
uint32_t msg_id,
const void* ind_buf,
uint32_t ind_buf_len
)
{
// validate sat reports
unsigned int idx = 0;
//把decorder出来的数据强转成qmiLocEventGnssSvInfoIndMsgT_v02*类型的
qmiLocEventGnssSvInfoIndMsgT_v02 *satReport =
(qmiLocEventGnssSvInfoIndMsgT_v02 *)ind_buf;
//先打印len,altitude assumed,num SV‘s等信息
LOC_LOGV ("%s:%d]: len = %u , altitude assumed = %u, num SV‘s = %u"
" validity = %d \n ", __func__, __LINE__,
ind_buf_len, satReport->altitudeAssumed,
satReport->svList_len, satReport->svList_valid);
//Log SV report
for( idx = 0; idx <satReport->svList_len; idx++ )
{
//然后打印每个satellite的info,在这个阶段是valid_mask,prn,system,status等信息
LOC_LOGV("%s:%d]: valid_mask = %x, prn = %u, system = %d, "
"status = %d \n", __func__, __LINE__,
satReport->svList[idx].validMask, satReport->svList[idx].gnssSvId,
satReport->svList[idx].system, satReport->svList[idx].svStatus);
}
return true;
}
前面有提到callback,我们看下callback是在什么时候绑定的:
vendor/qcom/opensource/location/loc_api/loc_api_v02/LocApiV02.cpp
enum loc_api_adapter_err
LocApiV02 :: open(LOC_API_ADAPTER_EVENT_MASK_T mask)
{
...
/* initialize the loc api v02 interface, note that
the locClientOpen() function will block if the
service is unavailable for a fixed time out */
// it is important to cap the mask here, because not all LocApi‘s
// can enable the same bits, e.g. foreground and bckground.
//在进入locClientOpen之前,有一个很重要的地方需要注意,那就是&globalCallbacks
status = locClientOpen(adjustMaskForNoSession(qmiMask), &globalCallbacks,
&clientHandle, (void *)this);
...
}
看下globalCallbacks的赋值:
/* global structure containing the callbacks */
locClientCallbacksType globalCallbacks =
{
sizeof(locClientCallbacksType),
globalEventCb,
globalRespCb,
globalErrorCb
};
globalCallbacks的赋值又是一个典型的callback绑定动作,需要高度注意,由于类型是locClientCallbacksType,所以应该是要把globalEventCb绑定到locClientCallbacksType的一个成员函数上,这个成员函数就是eventIndCb。
locClientCallbacksType的定义如下:
vendor/qcom/opensource/location/loc_api/loc_api_v02/loc_api_v02_client.h
typedef struct
{
uint32_t size; /**< Size of the structure. */
locClientEventIndCbType eventIndCb; /**< Event indication callback. */
locClientRespIndCbType respIndCb; /**< Response indication callback. */
locClientErrorCbType errorCb; /**< Error indication callback.
@newpagetable */
}locClientCallbacksType;
接下来跟到locClientOpen里面去看下:
vendor/qcom/opensource/location/loc_api/loc_api_v02/loc_api_v02_client.c
locClientStatusEnumType locClientOpen (
locClientEventMaskType eventRegMask,
const locClientCallbacksType* pLocClientCallbacks,
locClientHandleType* pLocClientHandle,
const void* pClientCookie)
{
...
while ((status = locClientOpenInstance(eventRegMask, instanceId, pLocClientCallbacks,
pLocClientHandle, pClientCookie)) != eLOC_CLIENT_SUCCESS) {
...
}
接下来看下locClientOpenInstance的具体实现:
vendor/qcom/opensource/location/loc_api/loc_api_v02/loc_api_v02_client.c
locClientStatusEnumType locClientOpenInstance (
locClientEventMaskType eventRegMask,
int instanceId,
const locClientCallbacksType* pLocClientCallbacks,
locClientHandleType* pLocClientHandle,
const void* pClientCookie)
{
...
//fill in the event callback
//这里又在绑定callback,也就是说eventCallback就是eventIndCb,也就是globalEventCb
pCallbackData->eventCallback = pLocClientCallbacks->eventIndCb;
...
}
到目前为止,eventCallback跟eventIndCb成功绑定,也就是说eventCallback跟globalEventCb绑定在一起了,由于eventCallback在前面绑定到了localEventCallback,所以就是说localEventCallback绑定的是globalEventCb,头都晕了+_+。
既然localEventCallback最终绑定的是globalEventCb,所以需要跟到globalEventCb中看下具体的实现:
vendor/qcom/opensource/location/loc_api/loc_api_v02/LocApiV02.cpp
static void globalEventCb(locClientHandleType clientHandle,
uint32_t eventId,
const locClientEventIndUnionType eventPayload,
void* pClientCookie)
{
MODEM_LOG_CALLFLOW(%s, loc_get_v02_event_name(eventId));
LocApiV02 *locApiV02Instance =
(LocApiV02 *)pClientCookie;
LOC_LOGV ("%s:%d] client = %p, event id = %d, client cookie ptr = %p\n",
__func__, __LINE__, clientHandle, eventId, pClientCookie);
// return if null is passed
if( NULL == locApiV02Instance)
{
LOC_LOGE ("%s:%d] NULL object passed : client = %p, event id = %d\n",
__func__, __LINE__, clientHandle, eventId);
return;
}
locApiV02Instance->eventCb(clientHandle, eventId, eventPayload);
}
看下eventCb的具体实现:
vendor/qcom/opensource/location/loc_api/loc_api_v02/LocApiV02.cpp
/* event callback registered with the loc_api v02 interface */
void LocApiV02 :: eventCb(locClientHandleType clientHandle,
uint32_t eventId, locClientEventIndUnionType eventPayload)
{
LOC_LOGD("%s:%d]: event id = %d\n", __func__, __LINE__,
eventId);
switch(eventId)
{
...
// Satellite report
case QMI_LOC_EVENT_GNSS_SV_INFO_IND_V02:
reportSv(eventPayload.pGnssSvInfoReportEvent);
break;
...
}
}
看下reportSv的定义和具体实现:
vendor/qcom/opensource/location/loc_api/loc_api_v02/LocApiV02.h
/* convert satellite report to loc eng format and send the converted
report to loc eng */
void reportSv (const qmiLocEventGnssSvInfoIndMsgT_v02 *gnss_report_ptr);
vendor/qcom/opensource/location/loc_api/loc_api_v02/LocApiV02.cpp
void LocApiV02 :: reportSv (
const qmiLocEventGnssSvInfoIndMsgT_v02 *gnss_report_ptr)
{
//LocApiV02 :: reportSv函数的功能就是把qmiLocEventGnssSvInfoIndMsgT_v02*类型的数据填充成GpsSvStatus类型数据,
//然后传递给LocApiBase::reportSv函数,GpsSvStatus是loc eng层能识别的数据类型
//定义一堆loc eng需要的param
GpsSvStatus SvStatus;
GpsLocationExtended locationExtended;
int num_svs_max, i;
const qmiLocSvInfoStructT_v02 *sv_info_ptr;
LOC_LOGV ("%s:%d]: num of sv = %d\n", __func__, __LINE__,
gnss_report_ptr->svList_len);
//初始化这些param
num_svs_max = 0;
memset (&SvStatus, 0, sizeof (GpsSvStatus));
memset(&locationExtended, 0, sizeof (GpsLocationExtended));
locationExtended.size = sizeof(locationExtended);
if(gnss_report_ptr->svList_valid == 1)
{
//gnss_report_ptr可用才有后面的flow,否则GG
num_svs_max = gnss_report_ptr->svList_len;
if(num_svs_max > GPS_MAX_SVS)
{
//最多只能32个卫星
num_svs_max = GPS_MAX_SVS;
}
SvStatus.num_svs = 0;
for(i = 0; i < num_svs_max; i++)
{
sv_info_ptr = &(gnss_report_ptr->svList[i]);
if((sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_SYSTEM_V02) &&
(sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_GNSS_SVID_V02)
&& (sv_info_ptr->gnssSvId != 0 ))
{
//这两个mask在前面已经有定义过了,意思是sv info里面的system和gnssSvId的值是valid的
//从定义来看,gnssSvId为0是invalid的
if(sv_info_ptr->system == eQMI_LOC_SV_SYSTEM_GPS_V02)
{
//如果是GPS卫星,则走这条flow
//感觉这个比较奇怪,size从define上来看应该是GpsSvInfo的size才对,除非直接是SvStatus.size = sizeof(GpsSvStatus)
SvStatus.sv_list[SvStatus.num_svs].size = sizeof(GpsSvStatus);
//prn原来就是gnssSvId,说到这里插播一个gnssSvId的定义,也就是说1-32是GPS和GLONASS,120-151是SBAS,201-237是传说中的北斗
//uint16_t gnssSvId;
/**< GNSS SV ID.
\begin{itemize1}
\item Range: \begin{itemize1}
\item For GPS: 1 to 32
\item For GLONASS: 1 to 32
\item For SBAS: 120 to 151
\item For BDS: 201 to 237
\end{itemize1} \end{itemize1}
*/
//gps的gnss svid跟prn是对应的,1-32区间
SvStatus.sv_list[SvStatus.num_svs].prn = (int)sv_info_ptr->gnssSvId;
// We only have the data field to report gps eph and alm mask
//sv info里面sv info mask的值是valid的
if(sv_info_ptr->validMask &
QMI_LOC_SV_INFO_MASK_VALID_SVINFO_MASK_V02)
{
//星历表置位
if(sv_info_ptr->svInfoMask &
QMI_LOC_SVINFO_MASK_HAS_EPHEMERIS_V02)
{
SvStatus.ephemeris_mask |= (1 << (sv_info_ptr->gnssSvId-1));
}
//年历表置位
if(sv_info_ptr->svInfoMask &
QMI_LOC_SVINFO_MASK_HAS_ALMANAC_V02)
{
SvStatus.almanac_mask |= (1 << (sv_info_ptr->gnssSvId-1));
}
}
//sv info里面的sv info mask值是valid的
//process status是valid的,svStatus是tracked
if((sv_info_ptr->validMask &
QMI_LOC_SV_INFO_MASK_VALID_PROCESS_STATUS_V02)
&&
(sv_info_ptr->svStatus == eQMI_LOC_SV_STATUS_TRACK_V02))
{
SvStatus.used_in_fix_mask |= (1 << (sv_info_ptr->gnssSvId-1));
}
}
// SBAS: GPS PRN: 120-151,
// In exteneded measurement report, we follow nmea standard,
// which is from 33-64.
else if(sv_info_ptr->system == eQMI_LOC_SV_SYSTEM_SBAS_V02)
{
//SBAS卫星则走这条flow,应该是为了遵循nmea标准,把SBAS的gnss svid从120-151转换到prn的33-64
SvStatus.sv_list[SvStatus.num_svs].prn =
sv_info_ptr->gnssSvId + 33 - 120;
}
// Gloness: Slot id: 1-32
// In extended measurement report, we follow nmea standard,
// which is 65-96
else if(sv_info_ptr->system == eQMI_LOC_SV_SYSTEM_GLONASS_V02)
{
//GLONASS走这条路,应该是为了遵循nmea标准,把GLONASS的gnss svid从1-32转换到prn的65-96
SvStatus.sv_list[SvStatus.num_svs].prn =
sv_info_ptr->gnssSvId + (65-1);
}
//BeiDou: Slot id: 1-37
//In extended measurement report, we follow nmea standard,
//which is 201-237
else if(sv_info_ptr->system == eQMI_LOC_SV_SYSTEM_BDS_V02)
{
//大北斗走这里,gnss svid跟prn是对应的,201-237区间
SvStatus.sv_list[SvStatus.num_svs].prn =
sv_info_ptr->gnssSvId;
}
// Unsupported SV system
else
{
continue;
}
}
if(sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_SNR_V02 )
{
//snr直接是对应的,直接把qmiLocSvInfoStructT_v02的snr数据填充到GpsSvStatus的GpsSvInfo中
SvStatus.sv_list[SvStatus.num_svs].snr = sv_info_ptr->snr;
}
if(sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_ELEVATION_V02)
{
//elevation直接是对应的,直接把qmiLocSvInfoStructT_v02的elevation数据填充到GpsSvStatus的GpsSvInfo中
SvStatus.sv_list[SvStatus.num_svs].elevation = sv_info_ptr->elevation;
}
if(sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_AZIMUTH_V02)
{
//azimuth直接是对应的,直接把qmiLocSvInfoStructT_v02的azimuth数据填充到GpsSvStatus的GpsSvInfo中
SvStatus.sv_list[SvStatus.num_svs].azimuth = sv_info_ptr->azimuth;
}
GpsSvStatus的卫星数目+1
SvStatus.num_svs++;
}
}
if (SvStatus.num_svs >= 0)
{
//如果卫星数目大于等于0,则继续汇报给上层,我们发现了传进来的qmiLocEventGnssSvInfoIndMsgT_v02格式已经被转换成GpsSvStatus参数了
LOC_LOGV ("%s:%d]: firing SV callback\n", __func__, __LINE__);
LocApiBase::reportSv(SvStatus,
locationExtended,
(void*)gnss_report_ptr);
}
}
reportSv里面常用到的一个变量是SvStatus,是GpsSvStatus类型的,loc eng层就用这个来存储sv status信息哦,具体定义如下:
hardware/libhardware/include/hardware/gps.h
/** Represents SV status. */
typedef struct {
/** set to sizeof(GpsSvStatus) */
size_t size;
/** Number of SVs currently visible. */
int num_svs;
/** Contains an array of SV information. */
GpsSvInfo sv_list[GPS_MAX_SVS];
/** Represents a bit mask indicating which SVs
* have ephemeris data.
*/
uint32_t ephemeris_mask;
/** Represents a bit mask indicating which SVs
* have almanac data.
*/
uint32_t almanac_mask;
/**
* Represents a bit mask indicating which SVs
* were used for computing the most recent position fix.
*/
uint32_t used_in_fix_mask;
} GpsSvStatus;
继续跟进LocApiBase::reportSv的实现:
hardware/qcom/gps/core/LocApiBase.cpp
void LocApiBase::reportSv(GpsSvStatus &svStatus,
GpsLocationExtended &locationExtended,
void* svExt)
{
// loop through adapters, and deliver to all adapters.
TO_ALL_LOCADAPTERS(
mLocAdapters[i]->reportSv(svStatus,
locationExtended,
svExt)
);
}
看下这个define是什么意思:
hardware/qcom/gps/core/LocApiBase.cpp
#define TO_ALL_LOCADAPTERS(call) TO_ALL_ADAPTERS(mLocAdapters, (call))
看下mLocAdapters的定义:
hardware/qcom/gps/core/LocApiBase.h
LocAdapterBase* mLocAdapters[MAX_ADAPTERS];
其中MAX_ADAPTERS的定义如下:
hardware/qcom/gps/core/LocApiBase.h
#define MAX_ADAPTERS 10
看下TO_ALL_ADAPTERS的定义,大致意思应该是针对每个LocAdapterBase*类型的adapter依次调用他们的reportSv方法:
hardware/qcom/gps/core/LocApiBase.h
#define TO_ALL_ADAPTERS(adapters, call) \
for (int i = 0; i < MAX_ADAPTERS && NULL != (adapters)[i]; i++) { call; }
具体来看下LocAdapterBase的reportSv方法的具体定义:
hardware/qcom/gps/core/LocAdapterBase.h
class LocAdapterBase {
...
public:
virtual void reportSv(GpsSvStatus &svStatus,
GpsLocationExtended &locationExtended,
void* svExt);
...
}
具体实现:
hardware/qcom/gps/core/LocAdapterBase.cpp
void LocAdapterBase::
reportSv(GpsSvStatus &svStatus,
GpsLocationExtended &locationExtended,
void* svExt)
DEFAULT_IMPL()
看下DEFAULT_IMPL是个什么东西:
hardware/qcom/gps/core/gps_extended_c.h
#define DEFAULT_IMPL(rtv) \
{ LOC_LOGD("%s: default implementation invoked", __func__); return rtv; }
就一行打印啊,好像跟丢了!!!有必要仔细看下reportSv的定义,这是一个虚函数,也就是说具体实现需要看子类,关于reportSv的具体实现,我们可以在LocalAdapterBase的子类LocInternalAdapter里面看下,具体定义如下:
hardware/qcom/gps/loc_api/libloc_api_50001/LocEngAdapter.h
class LocInternalAdapter : public LocAdapterBase {
LocEngAdapter* mLocEngAdapter;
public:
LocInternalAdapter(LocEngAdapter* adapter);
...
virtual void reportSv(GpsSvStatus &svStatus,
GpsLocationExtended &locationExtended,
void* svExt);
...
};
具体实现如下:
hardware/qcom/gps/loc_api/libloc_api_50001/LocEngAdapter.cpp
void LocInternalAdapter::reportSv(GpsSvStatus &svStatus,
GpsLocationExtended &locationExtended,
void* svExt){
sendMsg(new LocEngReportSv(mLocEngAdapter, svStatus,
locationExtended, svExt));
}
发现LocInternalAdapter没有实现sendMsg,但是在父类有找到相应的实现:
hardware/qcom/gps/core/vi LocAdapterBase.h
inline void sendMsg(const LocMsg* msg) const {
mMsgTask->sendMsg(msg);
}
我们有必要看下MsgTask中的sendMsg的实现:
hardware/qcom/gps/core/MsgTask.cpp
void MsgTask::sendMsg(const LocMsg* msg) const {
//其实就是发送LocEngReportSv的msg到message queue中
msg_q_snd((void*)mQ, (void*)msg, LocMsgDestroy);
}
既然把msg发送到message queue中了,那么必然有一个地方在从message queue中读取相应的数据来处理,具体如下:
hardware/qcom/gps/core/MsgTask.cpp
void* MsgTask::loopMain(void* arg) {
MsgTask* copy = (MsgTask*)arg;
// make sure we do not run in background scheduling group
set_sched_policy(gettid(), SP_FOREGROUND);
if (NULL != copy->mAssociator) {
copy->mAssociator();
}
LocMsg* msg;
int cnt = 0;
while (1) {
LOC_LOGD("MsgTask::loop() %d listening ...\n", cnt++);
//总算看到了msg_q_rcv了
msq_q_err_type result = msg_q_rcv((void*)copy->mQ, (void **)&msg);
if (eMSG_Q_SUCCESS != result) {
LOC_LOGE("%s:%d] fail receiving msg: %s\n", __func__, __LINE__,
loc_get_msg_q_status(result));
// destroy the Q and exit
msg_q_destroy((void**)&(copy->mQ));
delete copy;
return NULL;
}
msg->log();
// there is where each individual msg handling is invoked
msg->proc();
delete msg;
}
delete copy;
return NULL;
}
```c
可以看到MsgTask的log是virtual的,只能在子类里面去找实现了,LocEngReportSv刚好是LocMsg的子类哈:
hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng_msg.h
<div class="se-preview-section-delimiter"></div>
```c
struct LocEngReportSv : public LocMsg {
LocAdapterBase* mAdapter;
const GpsSvStatus mSvStatus;
const GpsLocationExtended mLocationExtended;
const void* mSvExt;
LocEngReportSv(LocAdapterBase* adapter,
GpsSvStatus &sv,
GpsLocationExtended &locExtended,
void* svExtended);
virtual void proc() const;
void locallog() const;
virtual void log() const;
void send() const;
};
具体实现如下:
hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.cpp
inline void LocEngReportSv::log() const {
locallog();
}
接下来看下locallog的具体实现:
hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.cpp
void LocEngReportSv::locallog() const {
//只是把GpsSvStatus的信息打印出来,看来这里不是重点,这里mSvStatus存储的就是底层给上来的GpsSvStatus类型数据
LOC_LOGV("num sv: %d\n ephemeris mask: %dxn almanac mask: %x\n "
"used in fix mask: %x\n sv: prn snr "
"elevation azimuth",
mSvStatus.num_svs, mSvStatus.ephemeris_mask,
mSvStatus.almanac_mask, mSvStatus.used_in_fix_mask);
for (int i = 0; i < mSvStatus.num_svs && i < GPS_MAX_SVS; i++) {
LOC_LOGV(" %d: %d %f %f %f\n ",
i,
mSvStatus.sv_list[i].prn,
mSvStatus.sv_list[i].snr,
mSvStatus.sv_list[i].elevation,
mSvStatus.sv_list[i].azimuth);
}
}
还记得sendMsg的参数吗?new出来的一个LocEngReportSv对象,底层传递上来的GpsSvStatus类型数据放在了第二个参数里面,我们来看下LocEngReportSv构造函数的具体实现:
hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.cpp
LocEngReportSv::LocEngReportSv(LocAdapterBase* adapter,
GpsSvStatus &sv,
GpsLocationExtended &locExtended,
void* svExt) :
//在不经意间,底层传递上来的数据就被存储到了同样类型的mSvStatus里面
LocMsg(), mAdapter(adapter), mSvStatus(sv),
mLocationExtended(locExtended),
mSvExt(((loc_eng_data_s_type*)
((LocEngAdapter*)
(mAdapter))->getOwner())->sv_ext_parser(svExt))
{
locallog();
}
loopMain的while循环里面msg的最后一个动作就是proc,我们来看下具体实现:
hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.cpp
void LocEngReportSv::proc() const {
LocEngAdapter* adapter = (LocEngAdapter*)mAdapter;
loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)adapter->getOwner();
if (locEng->mute_session_state != LOC_MUTE_SESS_IN_SESSION)
{
//loc eng不是在session中的话,就走这个flow
if (locEng->sv_status_cb != NULL) {
//这个是一个callback,上一篇有讲过:loc eng层的sv_status_cb就是对应的是android framework层的reportSvStatus
//参数mSvStatus就是底层(modem层)给上来的GpsSvStatus数据
locEng->sv_status_cb((GpsSvStatus*)&(mSvStatus),
(void*)mSvExt);
}
if (locEng->generateNmea)
{
loc_eng_nmea_generate_sv(locEng, mSvStatus, mLocationExtended);
}
}
}
到这里modem层到loc eng层的flow就打通了,sv status的信息在loc_api层是qmiLocEventGnssSvInfoIndMsgT_v02类型的数据,在LocApiV02 :: reportSv函数里面转换成GpsSvStatus类型的数据,然后经过一系列步骤发送到message queue中,loopMain函数从message queue中取出相应的数据,然后调用proc()函数,在proc()函数里loc eng层的callback把数据传递到android framework层,这个就是gps搜星ap层大致的流程,简单的来说就是gps client从gps server端收取相应的sv status信息,然后通过一系列callback传递到android framework,最终给到上层apk
标签:gps
原文地址:http://blog.csdn.net/lele_cheny/article/details/44178473