Android GPS 简介

GPS源码简介

1.  源码结构

主要分为四部分,client ,service ,jni ,hardware

·        client

用于上层APP调用,API包是android.location

/frameworks/base/location/*

·        service

/frameworks/base/services/java/com/android/server/location/

/frameworks/base/services/java/com/android/server/LocationManagerService.java

·        JNI

JNI层只有一个文件,起到承上启下的作用。上层承接Framework,下层调用HAL层具体硬件抽象实现。

frameworks/base/core/jni/android_location_GpsLocationProvider.cpp

·        hardware

HardwareAbstract Layer 硬件抽象层,

HAL层相当于一个linux应用程序接口,通过open,close等操作,操作硬件设备。

hardware/libhardware_legacy/gps/*(hardware 接口部分)。

2. location服务

location服务是在SystemServer.java 中启动的,也就是系统启动之后,在SystemServer.java中,向ServiceManager中添加服务:

try {

Slog.i(TAG, 'LocationManager');

location = newLocationManagerService(context); //实例化一个LocationManagerService对象。

ServiceManager.addService(Context.LOCATION_SERVICE,location);

} catch (Throwable e) {

Slog.e(TAG, 'Failure startingLocation Manager', e);

}

这时候服务就已经启动了,但是启动后,还得判断服务是否可用,在SystemServer.java中判断如下:

final LocationManagerService locationF = location;

if (locationF != null) locationF.systemReady(); //调用LocationManagerService对象的

通过 locationF.systemReady()判断是否可用,locationF.systemReady()的调用流程如下:

a、locationF.systemReady()启动了SystemServer.java的一个线程。

void systemReady() {

// we defer starting up theservice until the system is ready

Thread thread = newThread(null, this, 'LocationManagerService');

thread.start();

}

b、在SystemServer.java的线程run函数中调用initialize()初始化。

public void run() {

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

Looper.prepare();

mLocationHandler = newLocationWorkerHandler();

initialize();

Looper.loop();

}

c、初始化函数中,调用loadProviders() 函数Load providers。

privatevoid initialize()

{

......

loadProviders();

......

}

d、最后调用到GpsLocationProvider.isSupported()判断是否支持GPS。

privatevoid _loadProvidersLocked() {

if (GpsLocationProvider.isSupported())

GpsLocationProvidergpsProvider = new GpsLocationProvider(mContext,this);

addProvider(gpsProvider);

}

updateProvidersLocked();

}

_loadProvidersLocked()主要完成三部分工作,判断是否支持GPS,如果支持GPS,创建GpsLocationProvider对象,并加入到mProviders表中,最后调用updateProvidersLocked()更新GpsLocationProvider,打开或关闭GPS。

e、boolean isSupported 通过JNI方法,调用JNI层接口native_is_supported()判断是否支持GPS。

GpsLocationProvider.java

publicstatic boolean isSupported() {

returnnative_is_supported(); // JNI调用方法,//native 是java关键字,表示它将由

JNI完成判断GPS模块是否存在

}

LocationManagerService服务启动相关先介绍到这里,下面介绍GPS另外一个重要的API:GpsLocationProvider。

3、GpsLocationProvider

GpsLocationProvider也是一个很重要的接口,是连接framework和JNI的纽带,创建一个线程GpsLocationProviderThread来处理上层对底层的消息命令。

在LocationManagerService中,判断GPS可用后,会创建一个GpsLocationProvider实例,并加入到mProviders表中。

GpsLocationProvidergpsProvider = new GpsLocationProvider(mContext,this);

addProvider(gpsProvider);

在LocationManagerService的updateProvidersLocked()中,会开启或关闭GPS,调用GpsLocationProvider的enable方法开启、调用disable方法关闭GPS。

GpsLocationProvider的构造函数中,会创建一个线程GpsLocationProviderThread来处理上层对底层的消息命令:

mThread = newGpsLocationProviderThread();

mThread.start();

在GpsLocationProviderThread的run中:

public void run() {

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

initialize();

Looper.prepare();

mHandler = new ProviderHandler();

// signal when we are initialized andready to go

mInitializedLatch.countDown();

Looper.loop();

}

创建一个ProviderHandler的循环消息处理上层的消息。现在反过来看GpsLocationProvider的enable和disable方法:

publicvoid enable() {

synchronized(mHandler) {

sendMessage(ENABLE, 1, null);

}

}

publicvoid disable() {

synchronized(mHandler) {

sendMessage(ENABLE, 0, null);

}

}

从上可以看出,通过发送消息ENABLE,在消息处理里面处理ENABLE消息

privatefinal class ProviderHandler extends Handler {

@Override

publicvoid handleMessage(Message msg) {

intmessage = msg.what;

switch(message) {

caseENABLE:

if(msg.arg1 == 1) {

handleEnable();

} else {

handleDisable();

}

break;

}

}

handleEnable和handleDisable最后通过native_init、native_stop等调用JNI层C++代码方法,JNI层在com_android_server_location_GpsLocationProvider.cpp文件中。

3、LocationManager

LocationManager系统服务是位置服务的核心组件,它提供了一系列方法来处理与位置相关的问题,包括查询上一个已知位置、注册和注销来自某个LocationProvider的周期性的位置更新、注册和注销接近某个坐标时对一个已定义的Intent的触发等。

应用程序不能直接创建LocationManager实例对象,必须通过调用Context的getSystemService方法获取,例如:

mLocationManager =

(LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);

往下跟踪,如何通过Context的getSystemService获取实例的:

privateLocationManager getLocationManager() {

synchronized(sSync) {

if(sLocationManager == null) {

IBinder b =ServiceManager.getService(LOCATION_SERVICE);

ILocationManagerservice =ILocationManager.Stub.asInterface(b);

sLocationManager= new LocationManager(service);

}

}

returnsLocationManager;

}

从这里可以看到,会创建一个LocationManager实例并返回,并且LocationManager通过IBinder和AIDL接口ILocationManager和LocationManagerService通信。

获得LocationManager服务实例后,就可以通过调用它的API了,LocationManager一些API说明:

publicboolean addGpsStatusListener(GpsStatus.Listener listener):添加一个监听GPS状态的监听器。

publicvoid addProximityAlert(double latitude, double longitude,

floatradius, long expiration, PendingIntent intent):添加一个临近警告。

publicLocation getLastKnownLocation(String provider):根据LocationProvider获取最近一次已知的location信息

publicvoid requestLocationUpdates(String provider,

longminTime, float minDistance, LocationListener listener)通过制定的LocationProvider周期性地获取定位信息,并处罚listener对应的触发器。

还有其他的一些接口,就不一一介绍了。

4、JNI层

JNI层只有一个文件,起到承上启下的作用。上层承接Framework,下层调用HAL层具体硬件抽象实现。

com_android_server_location_GpsLocationProvider.cpp。

JNI重要的回调函数:

GpsCallbackssGpsCallbacks = {

sizeof(GpsCallbacks),

location_callback,

status_callback,

sv_status_callback,

nmea_callback,

set_capabilities_callback,

acquire_wakelock_callback,

release_wakelock_callback,

create_thread_callback,

};

这组回调函数,在初始化的时候,会通过GpsInterface接口函数注册到HAL层,在HAL层中。这组回上报。

staticconst GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) {

// thismust be set before calling into the HAL library

if(!mCallbacksObj)

mCallbacksObj= env->NewGlobalRef(obj);

if(!sGpsInterface) {

sGpsInterface= get_gps_interface();

}

if(!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) {

sGpsInterface= NULL;

returnNULL;

}

returnsGpsInterface;

}

其中sGpsInterface->init(&sGpsCallbacks)将sGpsCallbacks回调函数注册到HAL层去。

5、HAL层

GpsInterface接口是gps模块中最重要的数据结构,它是底层驱动实现的接口,定义在gps.h中定义,然后根据具体的硬件,实现这组接口。在12007项目中,这组接口定义如下:

staticconst GpsInterface sLocEngInterface =

{

sizeof(GpsInterface),

loc_eng_init,

loc_eng_start,

loc_eng_stop,

loc_eng_cleanup,

loc_eng_inject_time,

loc_eng_inject_location,

loc_eng_delete_aiding_data,

loc_eng_set_position_mode,

loc_eng_get_extension,

};

在JNI层,利用static const GpsInterface*get_gps_interface()函数获取这组GpsInterface接口。在上述的JNI层中,通过sGpsInterface->init(&sGpsCallbacks)来注册JNI层的回调函数,即通过loc_eng_init来注册JNI层的回调函数。

loc_eng_init是一个非常重要的函数,在该函数中,主要作用如下:

a、注册sGpsCallbacks回调函数

loc_eng_data.location_cb= callbacks->location_cb;

loc_eng_data.sv_status_cb= callbacks->sv_status_cb;

loc_eng_data.status_cb= callbacks->status_cb;

loc_eng_data.nmea_cb= callbacks->nmea_cb;

loc_eng_data.acquire_wakelock_cb= callbacks->acquire_wakelock_cb;

loc_eng_data.release_wakelock_cb =callbacks->release_wakelock_cb;

b、在loc_api_glue_init中创建一个RPC client通讯,获取底层GPS数据

c、创建处理GPS数据的线程

loc_eng_data.deferred_action_thread= callbacks->create_thread_cb('loc_api', loc_eng_process_deferred_action, NULL);

loc_eng_process_deferred_action专门用来处理GPS数据。

进入loc_eng_process_deferred_action中的loc_eng_process_loc_event处理函数,分析一下position数据上报的流程:

staticvoid loc_eng_process_loc_event (rpc_loc_event_mask_type loc_event,

rpc_loc_event_payload_u_type*loc_event_payload)

{

if(loc_event & RPC_LOC_EVENT_PARSED_POSITION_REPORT)

{

loc_eng_report_position(&(loc_event_payload->rpc_loc_event_payload_u_type_u.parsed_location_report));

}

}

继续往下跟踪

staticvoid loc_eng_report_position (const rpc_loc_parsed_position_s_type*location_report_ptr)

{

loc_eng_data.location_cb (&location);

}

loc_eng_data.location_cb调用这个函数的时候相当于真正调的是JNI注册到hal的函数,通过这种方式就实现了jni与hal的数据传递。loc_eng_data.location_cb就是JNI层的回调函数location_callback。

6、GPS数据上传流程

应用通过GPS服务的getLastKnownLocation方法获得最近一次已知的Location信息,这Location信息是如何从底层往上传递而来的呢?下面以Location为例,分析从底层数据往上传递,一直到应用通过getLastKnownLocation获得最近信息的整个流程。

从上述HAL层的分析,数据通过loc_eng_data.location_cb(&location),也就是通过JNI层的回调函数location_callback将数据上报到JNI层,看一下JNI层location_callback具体代码:

static void location_callback(GpsLocation* location)

{

JNIEnv* env = AndroidRuntime::getJNIEnv();

env->CallVoidMethod(mCallbacksObj, method_reportLocation,location->flags,

(jdouble)location->latitude,(jdouble)location->longitude,

(jdouble)location->altitude,

(jfloat)location->speed,(jfloat)location->bearing,

(jfloat)location->accuracy,(jlong)location->timestamp);

checkAndClearExceptionFromCallback(env, __FUNCTION__);

}

再看一下JNI初始化语句:

static voidandroid_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclassclazz){

method_reportLocation = env->GetMethodID(clazz, 'reportLocation', '(IDDDFFFJ)V');

}

从中可以看出,通过JNI方法,将数据上报到GpsLocationProvider.reportLocation,完成了数据从C/C++层上报到Java层的过程。

分析GpsLocationProvider. reportLocation函数:

privatevoid reportLocation(int flags, double latitude, double longitude, doublealtitude,

floatspeed, float bearing, float accuracy, long timestamp){

try {

mLocationManager. reportLocation(mLocation, false);

catch (RemoteException e) {

Log.e(TAG, 'RemoteException callingreportLocation');

}

}

在GpsLocationProvider. reportLocation中,调用了成员变量mLocationManager的reportLocation方法。

mLocationManager是什么呢?我们来看GpsLocationProvider的构造函数

publicGpsLocationProvider(Context context, ILocationManager locationManager) {

mContext = context;

mLocationManager = locationManager;

}

再看GpsLocationProvider创建实例的地方,在LocationManagerService类中创建实例GpsLocationProvider:

private void _loadProvidersLocked() {

if (GpsLocationProvider.isSupported())

GpsLocationProvider gpsProvider =new GpsLocationProvider(mContext,this);

addProvider(gpsProvider);

}

updateProvidersLocked();

}

可以看出,GpsLocationProvider中的mLocationManager是LocationManagerService的引用,所以

mLocationManager的reportLocation方法是LocationManagerService中reportLocation方法,具体定义如下:

publicvoid reportLocation(Location location, boolean passive) {

mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED,location);

Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);

m.arg1 = (passive ? 1 : 0);

mLocationHandler.sendMessageAtFrontOfQueue(m);

}

向mLocationHandler发了一条消息MESSAGE_LOCATION_CHANGED,mLocationHandler处理消息如下:

privateclass LocationWorkerHandler extends Handler {

@Override

publicvoid handleMessage(Message msg) {

try {

if(msg.what == MESSAGE_LOCATION_CHANGED) {

handleLocationChangedLocked(location, passive);

}

lastLocation = mLastKnownLocation.get(provider);

if (lastLocation == null) {

mLastKnownLocation.put(provider, new Location(location));

} else {

lastLocation.set(location);

}

}

最终将Location信息添加到mLastKnownLocation中,到这里Location信息上报流程基本结束了,再从应用层看,LocationManager.getLastKnownLocation是如何获得Location信息的。

public Location getLastKnownLocation(String provider) {

return mService.getLastKnownLocation(provider);

}

getLastKnownLocation调用LocationManager的成员变量mService的getLastKnownLocation方法,从Context的方法getSystemService获取LocationManager实例可知,mService是LocationManagerService的引用,所以通过LocationManagerService的getLastKnownLocation方法获得Location信息:

public Location getLastKnownLocation(String provider) {

Location loc = _getLastKnownLocationLocked(provider);

return loc

}

private Location _getLastKnownLocationLocked(String provider) {

Location loc = mLastKnownLocation.get(provider);

return loc

}

Location信息最终是从mLastKnownLocation中获得,而通过上面数据上报的分析可知,Location信息最终也是上报到mLastKnownLocation表中,到此,Location信息从底层上报,一直到应用层获得Location信息的流程分析完毕。

其流程图如下:

(0)

相关推荐

  • 基于python和OpenCV构建智能停车系统

    重磅干货,第一时间送达 当今时代最令人头疼的事情就是找不到停车位,尤其是找20分钟还没有找到停车位. 根据复杂性和效率的不同,任何问题都具有一个或多个解决方案.目前智能停车系统的解决方案,主要包括基于 ...

  • gps 简介

    3.GPS接收机 3.1 接收机的组成 1)天线单元 GPS信号接收机的天线单元为接收设备的前置部分.天线单元包含接收天线和前置放大器两部分. 其中天线部分可能是全向振子天线或小型螺旋天线或微带天线, ...

  • android GPS

    转自 https://blog.csdn.net/liwei405499/article/details/42642553 关于android定位方式 android 定位一般有四种方法,这四种方式分 ...

  • android GPS驱动

    关于android定位方式 android 定位一般有四种方法,这四种方式分别是GPS定位.WIFI定位.基站定位.AGPS定位. 1. Android GPS 需要GPS硬件支持直接和卫星交互来获取 ...

  • Android开发知识简介

    手机操作系统 Windows Mobile 由微软公司推出的移动设备操作系统 播放音视频.浏览网页.MSN聊天.收发电子邮件 硬件配置高.耗电量大.电池续航时间短.硬件成本高 PalmOS 由3Com ...

  • 我这里整理了一个关于中药剂量的一个常识的简介,分享给各位朋友。

    关于度量:秦始皇统一六国,统一度量衡,但是通过中医的学习会发现度量衡还是很混乱,半斤八两,那么一两是多少呢?还有论钱论厘的,有的说一小勺,有的说一小杯,有的说一小碗,你怎么弄?我这里整理了一个关于中药 ...

  • 趋势丨蔗糖理想替代品——阿洛酮糖简介

    导语 作为蔗糖的理想替代品,阿洛酮糖是什么?有何特点? 文:中国食品报网丨欣文 图:Stockfood 我们曾分享过一篇关于甜味剂的解读文章,对甜味剂的优点及工业应用进行了介绍,指出世界范围内无糖和低 ...

  • 李默飞个人简介

    易学是我国劳动人民智慧的结晶,是一门古老的学科,自古就充满了无限的神秘,一直是人们不断探索和研究的学科.古往今来有无数名人都在易学上有突出成就,如谷鬼子.诸葛亮.袁天罡等名人.近当代更是涌现出数不胜数 ...

  • 冉龙清老师个人简介

    国际易学联盟副主席 四川易经协会名誉会长 中华易经风水学院常务院长 中国易经协会会员 四川周易研究院副院长 本人于五十年代中期出生于寺庙林立的大巴山中麓,其间多有大贤隐士深隐于此.上小学初中适逢&qu ...

  • 人MTHFR基因多态性检测试剂盒(荧光PCR法)简介

    产品介绍 [注册证编号]:国械注准20173403239 [产品规格]:30人份/盒 [存储条件]:1.-20±3℃避光保存,有效期10个月 2.试剂盒在-16℃~8℃的温度范围内运输,运输时间不超过 ...