国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > 综合技术 > gps搜星流程

gps搜星流程

来源:程序员人生   发布时间:2017-04-06 09:38:59 阅读次数:4853次

前面有讲过gps的搜星流程,本文要讲授的是跟搜星类似的流程–gps定位流程,由于全部进程比较类似,所以决定用1篇文章来说解,modem层到loc eng层的数据传递和loc eng层到android framework层的数据传递


loc eng层的gps location是通过location_cb函数来扔给android framework层的,我们需要看下loc eng层的location_cb是在哪里被调用的,具体以下: 
hardware/qcom/gps/loc_api/libloc_api_50001/loc_eng.cpp

void LocEngReportPosition::proc() const { //跟搜星流程是否是很类似,一样是通过loc eng层的1个proc()方法把location的数据传递给上层的 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) { bool reported = falseif (locEng->location_cb != NULL) { if (LOC_SESS_FAILURE == mStatus) { //如果状态不对,那末给到上层的location信息是NULL // in case we want to handle the failure case locEng->location_cb(NULL, NULL); reported = true; } // what's in the else if is... (line by line) // 1. this is a final fix; and // 1.1 it is a Satellite fix; or // 1.2 it is a sensor fix // 2. (must be intermediate fix... implicit) // 2.1 we accepte intermediate; and // 2.2 it is NOT the case that // 2.2.1 there is inaccuracy; and // 2.2.2 we care about inaccuracy; and // 2.2.3 the inaccuracy exceeds our tolerance else if ((LOC_SESS_SUCCESS == mStatus && ((LOC_POS_TECH_MASK_SATELLITE | LOC_POS_TECH_MASK_SENSORS | LOC_POS_TECH_MASK_HYBRID) & mTechMask)) || (LOC_SESS_INTERMEDIATE == locEng->intermediateFix && !((mLocation.gpsLocation.flags & GPS_LOCATION_HAS_ACCURACY) && (gps_conf.ACCURACY_THRES != 0) && (mLocation.gpsLocation.accuracy > gps_conf.ACCURACY_THRES)))) { //否则把location的信息通过location_cb传递给android framework层, //注意:这里传递的数据类型是UlpLocation*类型的,不是HAL层所能辨认的格式GpsLocation* //搜星流程在这里传递的是HAL层能辨认的GpsSvStatus*类型的,所以一定有1个地方在做UlpLocation到GpsLocation的转换 locEng->location_cb((UlpLocation*)&(mLocation), (void*)mLocationExt); reported = true; } } // if we have reported this fix if (reported && // and if this is a singleshot GPS_POSITION_RECURRENCE_SINGLE == locEng->adapter->getPositionMode().recurrence) { if (LOC_SESS_INTERMEDIATE == mStatus) { // modem could be still working for a final fix, // although we no longer need it. So stopFix(). locEng->adapter->stopFix(); } // turn off the session flag. locEng->adapter->setInSession(false); } if (locEng->generateNmea && mLocation.position_source == ULP_LOCATION_IS_FROM_GNSS && mTechMask & (LOC_POS_TECH_MASK_SATELLITE | LOC_POS_TECH_MASK_SENSORS | LOC_POS_TECH_MASK_HYBRID)) { unsigned char generate_nmea = reported && (mStatus != LOC_SESS_FAILURE); loc_eng_nmea_generate_pos(locEng, mLocation, mLocationExtended, generate_nmea); } // Free the allocated memory for rawData UlpLocation* gp = (UlpLocation*)&(mLocation); if (gp != NULL && gp->rawData != NULL) { delete (char*)gp->rawData; gp->rawData = http://blog.csdn.net/lele_cheny/article/details/NULL; gp->rawDataSize = 0; } } }


gps定位流程跟搜星流程1样,都是消息触发机制,location的信息是从底层(modem层)发送上来的,所以我们从底层往上来跟进全部流程


gps定位流程底层会有比很多callback绑定,如果是跟搜星流程1样的callback的话,我们就1笔带过,如果有不1样的才拿出来分析。

一样从loc_api层的locClientIndCb开始走起: 
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 = http://blog.csdn.net/lele_cheny/article/details/(locClientCallbackDataType *)ind_cb_data; LOC_LOGV("%s:%d]: Indication: msg_id=%d buf_len=%d pCallbackData = http://blog.csdn.net/lele_cheny/article/details/%p/n", __func__, __LINE__, (uint32_t)msg_id, ind_buf_len, pCallbackData); // check callback data if(NULL == pCallbackData ||(pCallbackData != pCallbackData->pMe)) { //如果传进来的参数是NULL,那末1切免谈了 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 iftrue == 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)) { //1般只要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; }

一样到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 = falseswitch(indId) { ... //从这里开始就跟sv_status_cb走不1样的flow了,这里需要care的id是QMI_LOC_EVENT_POSITION_REPORT_IND_V02 // handle position report case QMI_LOC_EVENT_POSITION_REPORT_IND_V02: { status = locClientHandlePosReportInd(indId, indBuffer, indSize); break; } ... return status; }

在往下看之前,有必要看1个数据结构,主要是为了存储decorder出来的信息,具体以下(1个庞大的结构体,主要包括了会话状态,经度,纬度,海拔,速度等信息): 
vendor/qcom/opensource/location/loc_api/loc_api_v02/location_service_v02.h

/** Indication Message; Sends the position report to the control point. */ typedef struct { /* Mandatory */ /* Session Status */ qmiLocSessionStatusEnumT_v02 sessionStatus; //session的状态,具体值下面有列出 /**< Session status. Valid values: \n - eQMI_LOC_SESS_STATUS_SUCCESS (0) -- Session was successful - eQMI_LOC_SESS_STATUS_IN_PROGRESS (1) -- Session is still in progress; further position reports will be generated until either the fix criteria specified by the client are met or the client response timeout occurs - eQMI_LOC_SESS_STATUS_GENERAL_FAILURE (2) -- Session failed - eQMI_LOC_SESS_STATUS_TIMEOUT (3) -- Fix request failed because the session timed out - eQMI_LOC_SESS_STATUS_USER_END (4) -- Fix request failed because the session was ended by the user - eQMI_LOC_SESS_STATUS_BAD_PARAMETER (5) -- Fix request failed due to bad parameters in the request - eQMI_LOC_SESS_STATUS_PHONE_OFFLINE (6) -- Fix request failed because the phone is offline - eQMI_LOC_SESS_STATUS_ENGINE_LOCKED (7) -- Fix request failed because the engine is locked */ /* Mandatory */ /* Session ID */ uint8_t sessionId; /**< ID of the session that was specified in the Start request QMI_LOC_START_REQ. \n - Range: 0 to 255 */ /* Optional */ /* Latitude */ uint8_t latitude_valid; /**< Must be set to true if latitude is being passed */ double latitude; /**< Latitude (specified in WGS84 datum). \begin{itemize1} \item Type: Floating point \item Units: Degrees \item Range: ⑼0.0 to 90.0 \begin{itemize1} \item Positive values indicate northern latitude //北纬度是正数 \item Negative values indicate southern latitude //南纬度是负数 \vspace{-0.18in} \end{itemize1} \end{itemize1} */ /* Optional */ /* Longitude */ uint8_t longitude_valid; /**< Must be set to true if longitude is being passed */ double longitude; /**< Longitude (specified in WGS84 datum). \begin{itemize1} \item Type: Floating point \item Units: Degrees \item Range: ⑴80.0 to 180.0 \begin{itemize1} \item Positive values indicate eastern longitude //东经度是正数 \item Negative values indicate western longitude //西经度是负数 \vspace{-0.18in} \end{itemize1} \end{itemize1} */ /* Optional */ /* Circular Horizontal Position Uncertainty */ uint8_t horUncCircular_valid; /**< Must be set to true if horUncCircular is being passed */ float horUncCircular; /**< Horizontal position uncertainty (circular).\n - Units: Meters */ /* Optional */ /* Horizontal Elliptical Uncertainty (Semi-Minor Axis) */ uint8_t horUncEllipseSemiMinor_valid; /**< Must be set to true if horUncEllipseSemiMinor is being passed */ float horUncEllipseSemiMinor; /**< Semi-minor axis of horizontal elliptical uncertainty.\n - Units: Meters */ /* Optional */ /* Horizontal Elliptical Uncertainty (Semi-Major Axis) */ uint8_t horUncEllipseSemiMajor_valid; /**< Must be set to true if horUncEllipseSemiMajor is being passed */ float horUncEllipseSemiMajor; /**< Semi-major axis of horizontal elliptical uncertainty.\n - Units: Meters */ /* Optional */ /* Elliptical Horizontal Uncertainty Azimuth */ uint8_t horUncEllipseOrientAzimuth_valid; /**< Must be set to true if horUncEllipseOrientAzimuth is being passed */ float horUncEllipseOrientAzimuth; /**< Elliptical horizontal uncertainty azimuth of orientation.\n - Units: Decimal degrees \n - Range: 0 to 180 */ /* Optional */ /* Horizontal Confidence */ uint8_t horConfidence_valid; /**< Must be set to true if horConfidence is being passed */ uint8_t horConfidence; /**< Horizontal uncertainty confidence. If both elliptical and horizontal uncertainties are specified in this message, the confidence corresponds to the elliptical uncertainty. \n - Units: Percent \n - Range: 0 to 99 */ /* Optional */ /* Horizontal Reliability */ uint8_t horReliability_valid; /**< Must be set to true if horReliability is being passed */ qmiLocReliabilityEnumT_v02 horReliability; /**< Specifies the reliability of the horizontal position. Valid values: \n - eQMI_LOC_RELIABILITY_NOT_SET (0) -- Location reliability is not set - eQMI_LOC_RELIABILITY_VERY_LOW (1) -- Location reliability is very low; use it at your own risk - eQMI_LOC_RELIABILITY_LOW (2) -- Location reliability is low; little or no cross-checking is possible - eQMI_LOC_RELIABILITY_MEDIUM (3) -- Location reliability is medium; limited cross-check passed - eQMI_LOC_RELIABILITY_HIGH (4) -- Location reliability is high; strong cross-check passed */ /* Optional */ /* Horizontal Speed */ uint8_t speedHorizontal_valid; /**< Must be set to true if speedHorizontal is being passed */ float speedHorizontal; //水平速度,单位是m/s /**< Horizontal speed.\n - Units: Meters/second */ /* Optional */ /* Speed Uncertainty */ uint8_t speedUnc_valid; /**< Must be set to true if speedUnc is being passed */ float speedUnc; //3维速度,单位是m/s /**< 3-D Speed uncertainty.\n - Units: Meters/second */ /* Optional */ /* Altitude With Respect to Ellipsoid */ uint8_t altitudeWrtEllipsoid_valid; /**< Must be set to true if altitudeWrtEllipsoid is being passed */ float altitudeWrtEllipsoid; /**< Altitude with respect to the WGS84 ellipsoid.\n - Units: Meters \n - Range: ⑸00 to 15883 */ /* Optional */ /* Altitude With Respect to Sea Level */ uint8_t altitudeWrtMeanSeaLevel_valid; /**< Must be set to true if altitudeWrtMeanSeaLevel is being passed */ float altitudeWrtMeanSeaLevel; /**< Altitude with respect to mean sea level.\n - Units: Meters */ /* Optional */ /* Vertical Uncertainty */ uint8_t vertUnc_valid; /**< Must be set to true if vertUnc is being passed */ float vertUnc; /**< Vertical uncertainty.\n - Units: Meters */ /* Optional */ /* Vertical Confidence */ uint8_t vertConfidence_valid; /**< Must be set to true if vertConfidence is being passed */ uint8_t vertConfidence; /**< Vertical uncertainty confidence.\n - Units: Percent \n - Range: 0 to 99 */ /* Optional */ /* Vertical Reliability */ uint8_t vertReliability_valid; /**< Must be set to true if vertReliability is being passed */ qmiLocReliabilityEnumT_v02 vertReliability; /**< Specifies the reliability of the vertical position. Valid values: \n - eQMI_LOC_RELIABILITY_NOT_SET (0) -- Location reliability is not set - eQMI_LOC_RELIABILITY_VERY_LOW (1) -- Location reliability is very low; use it at your own risk - eQMI_LOC_RELIABILITY_LOW (2) -- Location reliability is low; little or no cross-checking is possible - eQMI_LOC_RELIABILITY_MEDIUM (3) -- Location reliability is medium; limited cross-check passed - eQMI_LOC_RELIABILITY_HIGH (4) -- Location reliability is high; strong cross-check passed */ /* Optional */ /* Vertical Speed */ uint8_t speedVertical_valid; /**< Must be set to true if speedVertical is being passed */ float speedVertical; //垂直速度,单位是m/s /**< Vertical speed.\n - Units: Meters/second */ /* Optional */ /* Heading */ uint8_t heading_valid; /**< Must be set to true if heading is being passed */ float heading; /**< Heading.\n - Units: Degrees \n - Range: 0 to 359.999 */ /* Optional */ /* Heading Uncertainty */ uint8_t headingUnc_valid; /**< Must be set to true if headingUnc is being passed */ float headingUnc; /**< Heading uncertainty.\n - Units: Degrees \n - Range: 0 to 359.999 */ /* Optional */ /* Magnetic Deviation */ uint8_t magneticDeviation_valid; /**< Must be set to true if magneticDeviation is being passed */ float magneticDeviation; /**< Difference between the bearing to true north and the bearing shown on a magnetic compass. The deviation is positive when the magnetic north is east of true north. */ /* Optional */ /* Technology Used */ uint8_t technologyMask_valid; /**< Must be set to true if technologyMask is being passed */ qmiLocPosTechMaskT_v02 technologyMask; //定位的方法,方式有卫星,基站,Wi-Fi,传感器等等 /**< Technology used in computing this fix. Valid bitmasks: \n - QMI_LOC_POS_TECH_MASK_SATELLITE (0x00000001) -- Satellites were used to generate the fix - QMI_LOC_POS_TECH_MASK_CELLID (0x00000002) -- Cell towers were used to generate the fix - QMI_LOC_POS_TECH_MASK_WIFI (0x00000004) -- Wi-Fi access points were used to generate the fix - QMI_LOC_POS_TECH_MASK_SENSORS (0x00000008) -- Sensors were used to generate the fix - QMI_LOC_POS_TECH_MASK_REFERENCE_LOCATION (0x00000010) -- Reference Location was used to generate the fix - QMI_LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION (0x00000020) -- Coarse position injected into the location engine was used to generate the fix - QMI_LOC_POS_TECH_MASK_AFLT (0x00000040) -- AFLT was used to generate the fix - QMI_LOC_POS_TECH_MASK_HYBRID (0x00000080) -- GNSS and Network-provided measurements were used to generate the fix */ /* Optional */ /* Dilution of Precision */ uint8_t DOP_valid; /**< Must be set to true if DOP is being passed */ qmiLocDOPStructT_v02 DOP; /**< \vspace{0.06in} \n Dilution of precision associated with this position. */ /* Optional */ /* UTC Timestamp */ uint8_t timestampUtc_valid; /**< Must be set to true if timestampUtc is being passed */ uint64_t timestampUtc; /**< UTC timestamp. \n - Units: Milliseconds since Jan. 1, 1970 */ /* Optional */ /* Leap Seconds */ uint8_t leapSeconds_valid; /**< Must be set to true if leapSeconds is being passed */ uint8_t leapSeconds; /**< Leap second information. If leapSeconds is not available, timestampUtc is calculated based on a hard-coded value for leap seconds. \n - Units: Seconds */ /* Optional */ /* GPS Time */ uint8_t gpsTime_valid; /**< Must be set to true if gpsTime is being passed */ qmiLocGPSTimeStructT_v02 gpsTime; /**< \vspace{0.06in} \n The number of weeks since Jan. 5, 1980, and milliseconds into the current week. */ /* Optional */ /* Time Uncertainty */ uint8_t timeUnc_valid; /**< Must be set to true if timeUnc is being passed */ float timeUnc; /**< Time uncertainty. \n - Units: Milliseconds */ /* Optional */ /* Time Source */ uint8_t timeSrc_valid; /**< Must be set to true if timeSrc is being passed */ qmiLocTimeSourceEnumT_v02 timeSrc; /**< Time source. Valid values: \n - eQMI_LOC_TIME_SRC_INVALID (0) -- Invalid time. - eQMI_LOC_TIME_SRC_NETWORK_TIME_TRANSFER (1) -- Time is set by the 1X system - eQMI_LOC_TIME_SRC_NETWORK_TIME_TAGGING (2) -- Time is set by WCDMA/GSM time tagging (i.e., associating network time with GPS time) - eQMI_LOC_TIME_SRC_EXTERNAL_INPUT (3) -- Time is set by an external injection - eQMI_LOC_TIME_SRC_TOW_DECODE (4) -- Time is set after decoding over-the-air GPS navigation data from one GPS satellite - eQMI_LOC_TIME_SRC_TOW_CONFIRMED (5) -- Time is set after decoding over-the-air GPS navigation data from multiple satellites - eQMI_LOC_TIME_SRC_TOW_AND_WEEK_CONFIRMED (6) -- Both time of the week and the GPS week number are known - eQMI_LOC_TIME_SRC_NAV_SOLUTION (7) -- Time is set by the position engine after the fix is obtained - eQMI_LOC_TIME_SRC_SOLVE_FOR_TIME (8) -- Time is set by the position engine after performing SFT; this is done when the clock time uncertainty is large - eQMI_LOC_TIME_SRC_GLO_TOW_DECODE (9) -- Time is set after decoding GLO satellites - eQMI_LOC_TIME_SRC_TIME_TRANSFORM (10) -- Time is set after transforming the GPS to GLO time - eQMI_LOC_TIME_SRC_WCDMA_SLEEP_TIME_TAGGING (11) -- Time is set by the sleep time tag provided by the WCDMA network - eQMI_LOC_TIME_SRC_GSM_SLEEP_TIME_TAGGING (12) -- Time is set by the sleep time tag provided by the GSM network - eQMI_LOC_TIME_SRC_UNKNOWN (13) -- Source of the time is unknown - eQMI_LOC_TIME_SRC_SYSTEM_TIMETICK (14) -- Time is derived from the system clock (better known as the slow clock); GNSS time is maintained irrespective of the GNSS receiver state - eQMI_LOC_TIME_SRC_QZSS_TOW_DECODE (15) -- Time is set after decoding QZSS satellites - eQMI_LOC_TIME_SRC_BDS_TOW_DECODE (16) -- Time is set after decoding BDS satellites */ /* Optional */ /* Sensor Data Usage */ uint8_t sensorDataUsage_valid; /**< Must be set to true if sensorDataUsage is being passed */ qmiLocSensorUsageIndicatorStructT_v02 sensorDataUsage; /**< \vspace{0.06in} \n Indicates whether sensor data was used in computing the position in this position report. */ /* Optional */ /* Fix Count for This Session */ uint8_t fixId_valid; /**< Must be set to true if fixId is being passed */ uint32_t fixId; /**< Fix count for the session. Starts with 0 and increments by one for each successive position report for a particular session. */ /* Optional */ /* SVs Used to Calculate the Fix */ uint8_t gnssSvUsedList_valid; /**< Must be set to true if gnssSvUsedList is being passed */ uint32_t gnssSvUsedList_len; /**< Must be set to # of elements in gnssSvUsedList */ uint16_t gnssSvUsedList[QMI_LOC_MAX_SV_USED_LIST_LENGTH_V02]; /**< Each entry in the list contains the SV ID of a satellite used for calculating this position report. The following information is associated with each SV ID: \n Range: \n - For GPS: 1 to 32 \n - For SBAS: 33 to 64 \n - For GLONASS: 65 to 96 \n - For QZSS: 193 to 197 \n - For BDS: 201 to 237 */ /* Optional */ /* Altitude Assumed */ uint8_t altitudeAssumed_valid; /**< Must be set to true if altitudeAssumed is being passed */ uint8_t altitudeAssumed; //FALSE说明海拔是计算出来的,TRUE说明海拔是推测的 /**< Indicates whether altitude is assumed or calculated: \begin{itemize1} \item 0x00 (FALSE) -- Altitude is calculated \item 0x01 (TRUE) -- Altitude is assumed; there may not be enough satellites to determine the precise altitude \vspace{-0.18in} \end{itemize1}*/ }qmiLocEventPositionReportIndMsgT_v02; /* Message */

跟locClientHandleSatReportInd的作用类似,locClientHandlePosReportInd的主要作用是打印position相应的信息,具体实现以下: 
vendor/qcom/opensource/location/loc_api/loc_api_v02/loc_api_v02_client.c

static bool locClientHandlePosReportInd ( uint32_t msg_id, const void* ind_buf, uint32_t ind_buf_len ) { // validate position report //把decorder出来的数据强转成qmiLocEventPositionReportIndMsgT_v02*类型的 qmiLocEventPositionReportIndMsgT_v02 *posReport = (qmiLocEventPositionReportIndMsgT_v02 *)ind_buf; //打印相应的position信息 LOC_LOGV ("%s:%d]: len = %d lat = %f, lon = %f, alt = %f\n", __func__, __LINE__, ind_buf_len, posReport->latitude, posReport->longitude, posReport->altitudeWrtEllipsoid); return true; }

localEventCallback终究绑定的是globalEventCb,具体在《gps搜星流程(下)》有讲过,这里就不再讲了,我们直接来看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) { ... //跟搜星流程不1样了哦,这里是position report,不是satellite report了哈 //Position Report case QMI_LOC_EVENT_POSITION_REPORT_IND_V02: reportPosition(eventPayload.pPositionReportEvent); break; ... } }

在看reportPosition之前,有两个结构体需要介绍1下: 
1:loc eng层能辨认的position格式UlpLocation: 
hardware/qcom/gps/core/gps_extended_c.h

typedef struct { /** set to sizeof(UlpLocation) */ size_t size; GpsLocation gpsLocation; //看到了没,HAL层能辨认的GpsLocation类型!!! /* Provider indicator for HYBRID or GPS */ uint16_t position_source; /*allows HAL to pass additional information related to the location */ int rawDataSize; /* in # of bytes */ void * rawData; bool is_indoor; float floor_number; char map_url[GPS_LOCATION_MAP_URL_SIZE]; unsigned char map_index[GPS_LOCATION_MAP_INDEX_SIZE]; } UlpLocation;

2:HAL层能够辨认的position格式GpsLocation: 
hardware/libhardware/include/hardware/gps.h

/** Represents a location. */ typedef struct { /** set to sizeof(GpsLocation) */ size_t size; /** Contains GpsLocationFlags bits. */ uint16_t flags; /** Represents latitude in degrees. */ double latitude; /** Represents longitude in degrees. */ double longitude; /** Represents altitude in meters above the WGS 84 reference * ellipsoid. */ double altitude; /** Represents speed in meters per second. */ float speed; /** Represents heading in degrees. */ float bearing; /** Represents expected accuracy in meters. */ float accuracy; /** Timestamp for the location fix. */ GpsUtcTime timestamp; } GpsLocation;

继续跟进看下reportPosition的具体实现: 
vendor/qcom/opensource/location/loc_api/loc_api_v02/LocApiV02.cpp

/* convert position report to loc eng format and send the converted position to loc eng */ void LocApiV02 :: reportPosition ( const qmiLocEventPositionReportIndMsgT_v02 *location_report_ptr) { //从传入的参数可以看到,loc_api层用的position类型是qmiLocEventPositionReportIndMsgT_v02*类型的 //UlpLocation类型,这个是给loc eng层用的哈,所以可以猜想这个函数的作用是: //把qmiLocEventPositionReportIndMsgT_v02逐渐填充到UlpLocation中,然后传递给loc eng层 UlpLocation location; LocPosTechMask tech_Mask = LOC_POS_TECH_MASK_DEFAULT; LOC_LOGD("Reporting postion from V2 Adapter\n"); memset(&location, 0sizeof (UlpLocation)); location.size = sizeof(location); GpsLocationExtended locationExtended; memset(&locationExtended, 0sizeof (GpsLocationExtended)); locationExtended.size = sizeof(locationExtended); // Process the position from final and intermediate reports if( (location_report_ptr->sessionStatus == eQMI_LOC_SESS_STATUS_SUCCESS_V02) || (location_report_ptr->sessionStatus == eQMI_LOC_SESS_STATUS_IN_PROGRESS_V02) ) { // Latitude & Longitude if( (location_report_ptr->latitude_valid == 1 ) && (location_report_ptr->longitude_valid == 1) && (location_report_ptr->latitude != 0 || location_report_ptr->longitude!= 0)) { //看见没?开始填充了UlpLocation类型了,这里填充的是flags,latitude,longtitude3个 //这里gpsLocation是GpsLocation类型的,所以1步到位直接填充的是HAL层能辨认的GpsLocation类型 location.gpsLocation.flags |= GPS_LOCATION_HAS_LAT_LONG; location.gpsLocation.latitude = location_report_ptr->latitude; location.gpsLocation.longitude = location_report_ptr->longitude; // Time stamp (UTC) if(location_report_ptr->timestampUtc_valid == 1) { //如果timestampUtc是可用的,则填充到GpsLocation的timestamp location.gpsLocation.timestamp = location_report_ptr->timestampUtc; } // Altitude if(location_report_ptr->altitudeWrtEllipsoid_valid == 1 ) { //填充GpsLocation的altitude location.gpsLocation.flags |= GPS_LOCATION_HAS_ALTITUDE; location.gpsLocation.altitude = location_report_ptr->altitudeWrtEllipsoid; } // Speed if((location_report_ptr->speedHorizontal_valid == 1) && (location_report_ptr->speedVertical_valid ==1 ) ) { //原来GpsLocation的速度是用勾股定理算出来的,水平速度和海拔速度的平方和开根号 location.gpsLocation.flags |= GPS_LOCATION_HAS_SPEED; location.gpsLocation.speed = sqrt( (location_report_ptr->speedHorizontal * location_report_ptr->speedHorizontal) + (location_report_ptr->speedVertical * location_report_ptr->speedVertical) ); } // Heading if(location_report_ptr->heading_valid == 1) { location.gpsLocation.flags |= GPS_LOCATION_HAS_BEARING; location.gpsLocation.bearing = location_report_ptr->heading; } // Uncertainty (circular) if( (location_report_ptr->horUncCircular_valid ) ) { //GpsLocation的精度,单位是m location.gpsLocation.flags |= GPS_LOCATION_HAS_ACCURACY; location.gpsLocation.accuracy = location_report_ptr->horUncCircular; } // Technology Mask tech_Mask |= location_report_ptr->technologyMask; //Mark the location source as from GNSS location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO; //填充UlpLocation的position_source location.position_source = ULP_LOCATION_IS_FROM_GNSS; if (location_report_ptr->magneticDeviation_valid) { locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_MAG_DEV; locationExtended.magneticDeviation = location_report_ptr->magneticDeviation; } if (location_report_ptr->DOP_valid) { locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_DOP; locationExtended.pdop = location_report_ptr->DOP.PDOP; locationExtended.hdop = location_report_ptr->DOP.HDOP; locationExtended.vdop = location_report_ptr->DOP.VDOP; } if (location_report_ptr->altitudeWrtMeanSeaLevel_valid) { locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL; locationExtended.altitudeMeanSeaLevel = location_report_ptr->altitudeWrtMeanSeaLevel; } if (location_report_ptr->vertUnc_valid) { locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_UNC; locationExtended.vert_unc = location_report_ptr->vertUnc; } if (location_report_ptr->speedUnc_valid ) { locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_SPEED_UNC; locationExtended.speed_unc = location_report_ptr->speedUnc; } //经过上面的1堆填充,总算拿到了完全的UlpLocation数据,固然也就包括了完全的GpsLocation数据, //然后调用LocApiBase::reportPosition,带着UlpLocation的数据进入到了loc eng层哈 LocApiBase::reportPosition( location, locationExtended, (void*)location_report_ptr, (location_report_ptr->sessionStatus == eQMI_LOC_SESS_STATUS_IN_PROGRESS_V02 ? LOC_SESS_INTERMEDIATE : LOC_SESS_SUCCESS), tech_Mask); } } else { LocApiBase::reportPosition(location, locationExtended, NULL, LOC_SESS_FAILURE); LOC_LOGD("%s:%d]: Ignoring position report with sess status = %d, " "fix id = %u\n", __func__, __LINE__, location_report_ptr->sessionStatus, location_report_ptr->fixId ); } }

继续跟进LocApiBase::reportPosition的实现: 
hardware/qcom/gps/core/LocApiBase.cpp

void LocApiBase::reportPosition(UlpLocation &location, GpsLocationExtended &locationExtended, void* locationExt, enum loc_sess_status status, LocPosTechMask loc_technology_mask) { // loop through adapters, and deliver to all adapters. TO_ALL_LOCADAPTERS( mLocAdapters[i]->reportPosition(location, locationExtended, locationExt, status, loc_technology_mask) ); }

TO_ALL_LOCADAPTERS的define前面有讲过,这里就不再赘述了,直接看下LocAdapterBase的reportPosition具体定义: 
hardware/qcom/gps/core/LocAdapterBase.h

class LocAdapterBase { ... public//带着UlpLocation类型的参数,postion的数据就这么传到了loc eng层 virtual void reportPosition(UlpLocation &location, GpsLocationExtended &locationExtended, void* locationExt, enum loc_sess_status sta

生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生