码迷,mamicode.com
首页 > 其他好文 > 详细

(gps)gps搜星流程(下)

时间:2015-03-10 19:26:38      阅读:3634      评论:0      收藏:0      [点我收藏+]

标签: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的logvirtual的,只能在子类里面去找实现了,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)gps搜星流程(下)

标签:gps

原文地址:http://blog.csdn.net/lele_cheny/article/details/44178473

(0)
(2)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!