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信息的流程分析完毕。

其流程图如下:

   

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值