android gps机制分析--之四

来源:互联网 发布:mac 终端如何上传文件 编辑:程序博客网 时间:2024/06/07 03:23

2,启动GPS

2.1 Java层分析

在gps定位的apk中,启动GPS的方法如下,

mLocationManager.requestLocationUpdates(provider, 500, 0, mLocationListener);

调用LocationManager的requestLocationUpdates方法,调用流程图如下,


在startNavigating方法中,首先获取系统支持的GPS工作模式,主要有三种,

private static final int GPS_POSITION_MODE_STANDALONE = 0;//仅GPS工作private static final int GPS_POSITION_MODE_MS_BASED = 1;// AGPS MSB模式private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;// AGPS MSA模式

当然,这三种模式在gps.h也有对应的定义,定义如下,

#define GPS_POSITION_MODE_STANDALONE    0#define GPS_POSITION_MODE_MS_BASED      1#define GPS_POSITION_MODE_MS_ASSISTED   2

调用native_set_position_mode方法进行设置。然后调用native_start方法启动GPS。


2.2 HAL 层启动GPS

com_android_server_location_GpsLocationProvider的方法如下,

static jboolean android_location_GpsLocationProvider_start(JNIEnv* /* env */, jobject /* obj */){    if (sGpsInterface) {        if (sGpsInterface->start() == 0) {            return JNI_TRUE;        } else {            return JNI_FALSE;        }    }    else        return JNI_FALSE;}

直接调用HAL的start方法,对应的方法为loc.cpp中的loc_start方法,

static int loc_start(){    ENTRY_LOG();    int ret_val = loc_eng_start(loc_afw_data);    EXIT_LOG(%d, ret_val);    if (writeValue(high) < 0){        return -1;    }    return ret_val;}

loc_afw_data在loc_init方法中进行初始化, loc_afw_data是loc_eng_data_s_type类型的结构体,在loc_eng.h中定义的。

整个流程图如下,



loc_eng.cpp的方法如下,

int loc_eng_start(loc_eng_data_s_type &loc_eng_data){   ENTRY_LOG_CALLFLOW();   INIT_CHECK(loc_eng_data.adapter, return -1);   if(! loc_eng_data.adapter->getUlpProxy()->sendStartFix())   {       loc_eng_data.adapter->sendMsg(new LocEngStartFix(loc_eng_data.adapter));   }   EXIT_LOG(%d, 0);   return 0;}

loc_eng_data.adapter指向的是LocEngAdapter对象,最后实际调用的是MsgTask.cpp方法,

void MsgTask::sendMsg(const LocMsg* msg) const {    msg_q_snd((void*)mQ, (void*)msg, LocMsgDestroy);}

sendMsg函数通过msg_q_snd会把msg发送到消息队列mQ中:

msq_q_err_type msg_q_snd(void* msg_q_data, void* msg_obj, void (*dealloc)(void*)){   msq_q_err_type rv;   if( msg_q_data == NULL )   {      LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);      return eMSG_Q_INVALID_HANDLE;   }   if( msg_obj == NULL )   {      LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__);      return eMSG_Q_INVALID_PARAMETER;   }   msg_q* p_msg_q = (msg_q*)msg_q_data;   pthread_mutex_lock(&p_msg_q->list_mutex);   LOC_LOGV("%s: Sending message with handle = 0x%08X\n", __FUNCTION__, msg_obj);   if( p_msg_q->unblocked )   {      LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);      pthread_mutex_unlock(&p_msg_q->list_mutex);      return eMSG_Q_UNAVAILABLE_RESOURCE;   }   rv = convert_linked_list_err_type(linked_list_add(p_msg_q->msg_list, msg_obj, dealloc));   /* Show data is in the message queue. */   pthread_cond_signal(&p_msg_q->list_cond);   pthread_mutex_unlock(&p_msg_q->list_mutex);   LOC_LOGV("%s: Finished Sending message with handle = 0x%08X\n", __FUNCTION__, msg_obj);   return rv;}

在MsgTask.cpp的MsgTask构造方法中,

MsgTask::MsgTask(LocThread::tCreate tCreator,                 const char* threadName, bool joinable) :    mQ(msg_q_init2()), mThread(new LocThread()) {    if (!mThread->start(tCreator, threadName, this, joinable)) {        delete mThread;        mThread = NULL;    }}

MsgTask开启一子线程并运行,run方法如下,

bool MsgTask::run() {    LOC_LOGV("MsgTask::loop() listening ...\n");    LocMsg* msg;    msq_q_err_type result = msg_q_rcv((void*)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));        return false;    }    msg->log();    // there is where each individual msg handling is invoked    msg->proc();    delete msg;    return true;}

Modem的定位消息传到AP侧之后,就可以通过run函数调用msg_q_rcv接受消息队列mQ的消息,

读取msg,依次执行msg的log()和proc()。这部分内容后面再论述。

原创粉丝点击