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信息的流程分析完毕。
其流程图如下: