应用程序不能直接创建
LocationManager
实例对象,必须通过调用
Context
的
getSystemService
方
法获取,例如:
mLocationManager =
(LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
往下跟踪,如何通过
Context
的
getSystemService
获取实例的:
private
LocationManager getLocationManager() {
synchronized
(sSync)
{
if
(sLocationManager
==
null)
{
IBinder
b
= ServiceManager.getService(LOCATION_SERVICE);
ILocationManager
service
= ILocationManager.Stub.asInterface(
b
);
sLocationManager
=
new
LocationManager(
service
);
}
}
return
sLocationManager;
}
从这里可以看到,
会创建一个
LocationManager
实例并返回,
并且
LocationManager
通过
IBinder
和
AIDL
接口
ILocationManager
和
LocationManagerService
通信。
获得
LocationManager
服务实例后,就可以通过调用它的
API
了,
LocationManager
一些
API
说明:
public boolean addGpsStatusListener(GpsStatus.Listener listener)
:添加一个监听
GPS
状态的监听器。
public void addProximityAlert(double latitude, double longitude,
float
radius,
long
expiration,
PendingIntent
intent)
:添加一个临近警告。
public Location getLastKnownLocation(String provider)
:根据
LocationProvider
获取最近一次已知的
location
信息
public void requestLocationUpdates(String provider,
long
minTime,
float
minDistance,
LocationListener
listener)
通过制定的
LocationProvider
周期性
地获取定位信息,并处罚
listener
对应的触发器。
还有其他的一些接口,就不一一介绍了。
4
、
JNI
层
JNI
层只有一个文件,起到承上启下的作用。上层承接
Framework
,下层调用
HAL
层具体硬件抽象
实现。
com_android_server_location_GpsLocationProvider
.cpp
。
JNI
重要的回调函数:
GpsCallbacks sGpsCallbacks = {
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
层中。这组回
调函数,
通过
JNI
机制,
和
Framework
层进行通信,
所以在
HAL
层中,
通过调用注册的回调函数,
将
GPS
数据上报。
static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) {
// this must 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;
return NULL;
}
return
sGpsInterface;
}
其中
sGpsInterface->init(&
sGpsCallbacks
)
将
sGpsCallbacks
回调函数注册到
HAL
层去。
5
、
HAL
层
GpsInterface
接口是
gps
模块中最重要的数据结构,它是底层驱动实现的接口,定义在
gps.h
中定义,
然后根据具体的硬件,实现这组接口。在
12007
项目中,这组接口定义如下:
static const 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
数据上报的流程:
static void 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));
}
}
继续往下跟踪
static void 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->CallV
oidMethod(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 void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz){
method_reportLocation
= env->GetMethodID(clazz, "
reportLocation
", "(IDDDFFFJ)V");
}
从中可以看出,通过
JNI
方法,将数据上报到
GpsLocationProvider. reportLocation
,完成了数据从
C/C++
层
上报到
Java
层的过程。
分析
GpsLocationProvider. reportLocation
函数:
private void reportLocation(int flags, double latitude, double longitude, double altitude,
float speed, float bearing, float accuracy, long timestamp){
try
{
mLocationManager. reportLocation
(mLocation, false);
catch (RemoteException e) {
Log.e(TAG
, "RemoteException calling reportLocation");
}
}
在
GpsLocationProvider. reportLocation
中,调用了成员变量
mLocationManager
的
reportLocation
方法。
mLocationManager
是什么呢?我们来看
GpsLocationProvider
的构造函数
public GpsLocationProvider(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
方法,
具体定义如下:
public void 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
处理消息如下:
private class LocationWorkerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
try {
if
(msg.what
==
MESSAGE_LOCATION_CHANGED)
{
…
handleLocationChangedLocked
(location, passive);
}
…
}
调用了
handleLocationChangedLocked
方法如下:
private void handleLocationChangedLocked(Location location, boolean passive) {
Location
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
信息的流
程分析完毕。
其流程图如下:
应用程序不能直接创建
LocationManager
实例对象,必须通过调用
Context
的
getSystemService
方
法获取,例如:
mLocationManager =
(LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
往下跟踪,如何通过
Context
的
getSystemService
获取实例的:
private
LocationManager getLocationManager() {
synchronized
(sSync)
{
if
(sLocationManager
==
null)
{
IBinder
b
= ServiceManager.getService(LOCATION_SERVICE);
ILocationManager
service
= ILocationManager.Stub.asInterface(
b
);
sLocationManager
=
new
LocationManager(
service
);
}
}
return
sLocationManager;
}
从这里可以看到,
会创建一个
LocationManager
实例并返回,
并且
LocationManager
通过
IBinder
和
AIDL
接口
ILocationManager
和
LocationManagerService
通信。
获得
LocationManager
服务实例后,就可以通过调用它的
API
了,
LocationManager
一些
API
说明:
public boolean addGpsStatusListener(GpsStatus.Listener listener)
:添加一个监听
GPS
状态的监听器。
public void addProximityAlert(double latitude, double longitude,
float
radius,
long
expiration,
PendingIntent
intent)
:添加一个临近警告。
public Location getLastKnownLocation(String provider)
:根据
LocationProvider
获取最近一次已知的
location
信息
public void requestLocationUpdates(String provider,
long
minTime,
float
minDistance,
LocationListener
listener)
通过制定的
LocationProvider
周期性
地获取定位信息,并处罚
listener
对应的触发器。
还有其他的一些接口,就不一一介绍了。
4
、
JNI
层
JNI
层只有一个文件,起到承上启下的作用。上层承接
Framework
,下层调用
HAL
层具体硬件抽象
实现。
com_android_server_location_GpsLocationProvider
.cpp
。
JNI
重要的回调函数:
GpsCallbacks sGpsCallbacks = {
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
层中。这组回
调函数,
通过
JNI
机制,
和
Framework
层进行通信,
所以在
HAL
层中,
通过调用注册的回调函数,
将
GPS
数据上报。
static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) {
// this must 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;
return NULL;
}
return
sGpsInterface;
}
其中
sGpsInterface->init(&
sGpsCallbacks
)
将
sGpsCallbacks
回调函数注册到
HAL
层去。
5
、
HAL
层
GpsInterface
接口是
gps
模块中最重要的数据结构,它是底层驱动实现的接口,定义在
gps.h
中定义,
然后根据具体的硬件,实现这组接口。在
12007
项目中,这组接口定义如下:
static const 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
数据上报的流程:
static void 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));
}
}
继续往下跟踪
static void 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->CallV
oidMethod(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 void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz){
method_reportLocation
= env->GetMethodID(clazz, "
reportLocation
", "(IDDDFFFJ)V");
}
从中可以看出,通过
JNI
方法,将数据上报到
GpsLocationProvider. reportLocation
,完成了数据从
C/C++
层
上报到
Java
层的过程。
分析
GpsLocationProvider. reportLocation
函数:
private void reportLocation(int flags, double latitude, double longitude, double altitude,
float speed, float bearing, float accuracy, long timestamp){
try
{
mLocationManager. reportLocation
(mLocation, false);
catch (RemoteException e) {
Log.e(TAG
, "RemoteException calling reportLocation");
}
}
在
GpsLocationProvider. reportLocation
中,调用了成员变量
mLocationManager
的
reportLocation
方法。
mLocationManager
是什么呢?我们来看
GpsLocationProvider
的构造函数
public GpsLocationProvider(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
方法,
具体定义如下:
public void 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
处理消息如下:
private class LocationWorkerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
try {
if
(msg.what
==
MESSAGE_LOCATION_CHANGED)
{
…
handleLocationChangedLocked
(location, passive);
}
…
}
调用了
handleLocationChangedLocked
方法如下:
private void handleLocationChangedLocked(Location location, boolean passive) {
Location
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
信息的流
程分析完毕。
其流程图如下: