Gps (global Position System 全球定位系统)和定位部分
除此之外还有利用基站(cell)定位的AGPS等设备
定们系列统的基本架构
主要数据来源有两个: GPS定位和network定位(基于cell和wifi热点的定位)
定位部分的结构如图
定位系统的驱动层
Network定位的底层驱动和适配层实际上就是RIL和wifi框架的组成部分
Cell定位就是利用基站的cellID以及LAC实现
Wifi则是利用热点的相关信息 如名字 mac地址 ip地址实现
GPS 设备分为硬GPS 和软GPS
硬GPS上电就可以直接输出NMEA 数据
软GPS需要主控芯片控制其运行状态,需要主控方进行计算才能得到NMEA数据
GPS本地实现
GPS的本地实现部分主要是GPS适配层,头文件的路径为:\hardware\libhardware\include\hardware
该目录下的gps.h提供了JNI层调用的接口,该文件定义的常量,包括位置模式、状态值、定位标志、帮助数据
//定义了标准GPS接口的结构体
typedef struct {
/** set to sizeof(GpsInterface) */
size_t size;
/**
* Opens the interface and provides the callback routines
* to the implemenation of this interface.
初始化GPS,设置回调函数
*/
int (*init)( GpsCallbacks* callbacks );
/** Starts navigating. */
//开始导航
int (*start)( void );
/** Stops navigating. */
//停止导航
int (*stop)( void );
/** Closes the interface. */
//关闭接口
void (*cleanup)( void );
/** Injects the current time. */
//设请求频率
int (*inject_time)(GpsUtcTime time, int64_t timeReference,
int uncertainty);
/** Injects current location from another location provider
* (typically cell ID).
* latitude and longitude are measured in degrees
* expected accuracy is measured in meters
*/
int (*inject_location)(double latitude, double longitude, float accuracy);
/**
* Specifies that the next call to start will not use the
* information defined in the flags. GPS_DELETE_ALL is passed for
* a cold start.
*/
//删除帮助信息
void (*delete_aiding_data)(GpsAidingData flags);
/**
* min_interval represents the time between fixes in milliseconds.
* preferred_accuracy represents the requested fix accuracy in meters.
* preferred_time represents the requested time to first fix in milliseconds.
*/
//设置位置模式
int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
/** Get a pointer to extension information. */
//获得扩展消息的指针
const void* (*get_extension)(const char* name);
} GpsInterface;
//表示GPS的定位信息
typedef struct {
/** set to sizeof(GpsLocation) */
size_t size;
/** Contains GpsLocationFlags bits. */
//标志位
uint16_t flags;
/** Represents latitude in degrees. */
//表示纬度
double latitude;
/** Represents longitude in degrees. */
//表示经度
double longitude;
/** Represents altitude in meters above the WGS 84 reference
* ellipsoid. */
//以WGS84坐标系统表示的高度信息
double altitude;
/** Represents speed in meters per second. */
//速度 m/s
float speed;
/** Represents heading in degrees. */
//表示方向
float bearing;
/** Represents expected accuracy in meters. */
//表示精度
float accuracy;
/** Timestamp for the location fix. */
//表示时间戮
GpsUtcTime timestamp;
} GpsLocation;
当上层调用:GpsInterface.init时,会调用一个gpscallbacks结构指针,注册到适配层
//位置信息的回调函数
typedef void (* gps_location_callback)(GpsLocation* location);
// 状态信息的回调函数
typedef void (* gps_status_callback)(GpsStatus* status);
//SV状态信息的回调函数
typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);
typedef struct {
/** set to sizeof(GpsCallbacks) */
size_t size;
gps_location_callback location_cb;
gps_status_callback status_cb;
gps_sv_status_callback sv_status_cb;
gps_nmea_callback nmea_cb;
gps_set_capabilities set_capabilities_cb;
gps_acquire_wakelock acquire_wakelock_cb;
gps_release_wakelock release_wakelock_cb;
gps_create_thread create_thread_cb;
} GpsCallbacks;
GPS的部分源代码路径为:\hardware\qcom\gps
GPS组件的目标文件是;libhardware_legacy.so
Gps_qemu.c文件是基于模拟器环境的GPS适配层,在编写特定的GPS 适配层时,可以以gps_quemu.c中的大部分处理流程作为基础进行改写,它实现了一套NMEA解析机制,以及gps.h中的gpsInterface接口,
gpsInterface 接口比较简单,包括启动/停止和上报频率等接口,
NEMA解析是核心,是基于文本块的算法
因为是模拟,所以NMEA数据需要从一个socket接口gps_fd传输进来. 在独立线程中进行解析
NMEA数据最终会解析成gps.h中定义的gpsLocation的格式
GPS 部分JNI的实现
代码的路径为:\frameworks\base\services\jni\com_android_server_location_GpsLocationProvider.cpp
JNI层直接与GPS驱动层打交道,它访问适配层定义的GpaInterface 实现自已的gpscallbacks供GPS适配层调用
部分代码如下:
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,
};
JNI实现了一个native_wait_for_event函数,上层如果需要获得消息,则在独立线程中调用此函数阻塞
如果上层有NMEA解析完成并回调,通过线程同步机制,使等待的native_wait_for_event的线程取得上报数据,完成一次数据上报
Xtra是部分增强型GPS的机制,可以提前从网上下载数据
定位系统的java实现
代码路径为:\frameworks\base\location\java\android\location
ILocationManager是android 定们系统的核心
LocationServiceManager是定位系统的服务器端,它在目录:\frameworks\base\services\java\com\android\server下
LocationProviderProxy mNetworkLocationProvider;
LocationProviderInterface mGpsLocationProvider;
**************************************************************
2.3中的变化
**************************************************************
\frameworks\base\services\java\com\android\server\location目录下的GpsLocationProvider.java它直接继承
LocationProviderInterface(在2。3之前可能是LocationProviderImpl), 它提供了底层的控制接口,同时开启一个gpsEventThread通过轮询native_wait_for_event来取得底层上报的数据
App发出定位申请,启动定位服务线程,此线程会在APP framwork中调用location provider
通过被native方法调用到JNI中, JNI获得gpsInterface并传给接口一个回调函数的实现
gpsInterface就是HAL层最主要的实现
上层实现的思路
1、获取GPS的Location Provider。
2、将此Provider传入到requestLocationUpdates()方法,让Android系统获知搜索位置方式。
3、创建实现了GpsStatus.Listener接口的对象,重写onGpsStatusChanged()方法,向LocationManager添加次监听器,检测卫星状态。(可选步骤)
Android GPS 架构分析
Framework 层:
代码路径为:
1 \frameworks\base\location\java\android\location
供api调用
2 frameworks\base\location\java\com\android\internal\location
这个目录是framework对location服务的内部实现
3 \frameworks\base\services\java\com\android\server
这是location服务对内部实现的一个封装
JNI层:
代码路径:
在2。2版本中
frameworks/base/core/jni/android_location_GpsLocationProvider.cpp
在2.3版式本中
\frameworks\base\services\jni\com_android_server_location_GpsLocationProvider.cpp
上层承接freanwork,下层调用HAL
HAL硬件抽象层:
代码路径
2.3 中
\hardware\libhardware\include\hardware
/framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp
相当于linux应用程序的一个接口,直接操作硬件设备
底层几个重要和数据结构
1 gpsInterface 是最重要的数据结构,它是底层实现的接口,如果要porting到自已的板子上,就要实现这这些接口,
该接口的定义在gps.h中,模拟器实现在gps_qemu.c中
typedef struct {
size_t size;
int (*init)( GpsCallbacks* callbacks );
int (*start)( void );
int (*stop)( void );
void (*cleanup)( void );
int (*inject_time)(GpsUtcTime time, int64_t timeReference,
int uncertainty);
int (*inject_location)(double latitude, double longitude, float accuracy);
void (*delete_aiding_data)(GpsAidingData flags);
int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
const void* (*get_extension)(const char* name);
} GpsInterface;
2 gpscallbacks回调函数结构体,定义同上,实现在com_android_server_android_location_GpsLocationProvider.cpp中
typedef struct {
size_t size;
gps_location_callback location_cb;
gps_status_callback status_cb;
gps_sv_status_callback sv_status_cb;
gps_nmea_callback nmea_cb;
//以下几个回调函数是在2.3以后添加的回调函数
gps_set_capabilities set_capabilities_cb;
gps_acquire_wakelock acquire_wakelock_cb;
gps_release_wakelock release_wakelock_cb;
gps_create_thread create_thread_cb;
} GpsCallbacks;
3 Gpslocation表示loaction数据信息 2.3比2.2多了个size属性
typedef struct {
//2.3之后添加
size_t size;
uint16_t flags;
double latitude;
double longitude;
double altitude;
float speed;
float bearing;
float accuracy;
GpsUtcTime timestamp;
} GpsLocation;
Gps的定位服务(locationManager)的启动过程
LocationManager这项服务是systemServer.java 来启动,也就是在系统启动之后就启动
systemServer.java [framework/base/services/java/com/android/server]
public static final void init2() {
Slog.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
在ServerThread线程的run函数中LocationManager服务的代码段如下:
try {
Slog.i(TAG, "Location Manager");
location = new LocationManagerService(context);
ServiceManager.addService(Context.LOCATION_SERVICE, location);
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Location Manager", e);
}
在run函数的后半部分,是服务对系统的反馈,就是systemReady()函数。 LocationManager服务的反馈函数如下:
final LocationManagerService locationF = location;
其中的locationF 是LocationManagerService的final类型,就是一旦赋值,不能更改。
if (locationF != null) locationF.systemReady();
LocationManagerService代码路径如下:\frameworks\base\services\java\com\android\server
构造器如下:
public LocationManagerService(Context context) {
super();
mContext = context;
Resources resources = context.getResources();
mNetworkLocationProviderPackageName = resources.getString(
com.android.internal.R.string.config_networkLocationProvider);
mGeocodeProviderPackageName = resources.getString(
com.android.internal.R.string.config_geocodeProvider);
mPackageMonitor.register(context, true);
if (LOCAL_LOGV) {
Slog.v(TAG, "Constructed LocationManager Service");
}
}
void systemReady() {
// we defer starting up the service until the system is ready
Thread thread = new Thread(null, this, "LocationManagerService");
thread.start();
}
在run函数中,又调用了initialize 函数
public void run()
{
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Looper.prepare();
mLocationHandler = new LocationWorkerHandler();
initialize();//************************
Looper.loop();
}
private void initialize() {
// Create a wake lock, needs to be done before calling loadProviders() below
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
// Load providers
//重要方法
loadProviders();
// Register for Network (Wifi or Mobile) updates
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
// Register for Package Manager updates
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
intentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
mContext.registerReceiver(mBroadcastReceiver, intentFilter);
IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mContext.registerReceiver(mBroadcastReceiver, sdFilter);
// listen for settings changes
ContentResolver resolver = mContext.getContentResolver();
Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
"(" + Settings.System.NAME + "=?)",
new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
null);
mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
SettingsObserver settingsObserver = new SettingsObserver();
mSettings.addObserver(settingsObserver);
}
初始化函数中,最重要的便是 loadProviders()函数。
private void loadProviders() {
synchronized (mLock) {
if (sProvidersLoaded) {
return;
}
// Load providers
loadProvidersLocked();
sProvidersLoaded = true;
}
}
private void loadProvidersLocked() {
try {
_loadProvidersLocked();
} catch (Exception e) {
Slog.e(TAG, "Exception loading providers:", e);
}
}
_loadProvidersLocked函数,
private void _loadProvidersLocked() {
// Attempt to load "real" providers first
//取得GPS的接口
if (GpsLocationProvider.isSupported()) {
// Create a gps location provider
GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
addProvider(gpsProvider);
mGpsLocationProvider = gpsProvider;
}
// create a passive location provider, which is always enabled
PassiveProvider passiveProvider = new PassiveProvider(this);
addProvider(passiveProvider);
mEnabledProviders.add(passiveProvider.getName());
// initialize external network location and geocoder services
if (mNetworkLocationProviderPackageName != null) {
mNetworkLocationProvider =
new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER,
mNetworkLocationProviderPackageName, mLocationHandler);
addProvider(mNetworkLocationProvider);
}
if (mGeocodeProviderPackageName != null) {
mGeocodeProvider = new GeocoderProxy(mContext, mGeocodeProviderPackageName);
}
updateProvidersLocked();
}
GpsLocationProvider.isSupported()得到了HAL层的GPS接口gpsInterface
调用到gps.cpp[hardware/libhardware_legacy/gps]中的gps_get_interface()
GpsLocationProvider的路径为:\frameworks\base\services\java\com\android\server\location
部分代码如下:
public static boolean isSupported() {
//调用的是本地方法
return native_is_supported();
}
函数中只有一句话, 这调用了native方法,既Jni层定义的方法。native_is_supported对应在
framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp文件中的android_location_GpsLocationProvider_is_supported方法。
部分代码如下;
static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz) {
return (sGpsInterface != NULL || get_gps_interface() != NULL);
}
get_gps_interface()的具体代码如下:
static const GpsInterface* get_gps_interface() {
int err;
hw_module_t* module;
const GpsInterface* interface = NULL;
err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0) {
hw_device_t* device;
err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
if (err == 0) {
gps_device_t* gps_device = (gps_device_t *)device;
interface = gps_device->get_gps_interface(gps_device);
}
}
return interface;
}
get_gps_interface去打开模组,之后打开设备,然后通过设备区调用HAL层中的get_gps_interface(gps_device)
在gps.c(代码路径为:\hardware\qcom\gps\loc_api\libloc_api)中实现的gps__get_gps_interfacey调用了loc_eng.cpp
gps.c部分代码如下:
const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
{
return get_gps_interface();
}
loc_eng.cpp的部分代码如下:
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,
};
经过以的操作我们就获得了GPS的接口, 在locationManagerService.java中,如果找到了硬件,并取得了接口后,接着执行下一句
GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
GpsLocationProvider的代码路径为:frameworks\base\services\java\com\android\server\location
public GpsLocationProvider(Context context, ILocationManager locationManager) {
mContext = context;
//mLocationManager就是第二个参数.也就是locationManagerService
mLocationManager = locationManager;
mNIHandler = new GpsNetInitiatedHandler(context);
mLocation.setExtras(mLocationExtras);
....................
}
_loadProvidersLocked函数,在构造完成后,将其add到全局变量ArrayList<LocationProviderInterface> mProviders中,备以后调用.
接着启动了两个线程,但是可惜的是这两个服务都无法启动,因为他们是通过配置文件conifg.xml 得到服务的名字,然后启动服务的。但是在这个配置文件中,两个服务的名字都是null
配置文件的路径为;framework/base/core/res/res/values
部分代码如下:
<!-- Component name of the service providing network location support. -->
<string name="config_networkLocationProvider">@null</string>
<!-- Component name of the service providing geocoder API support. -->
<string name="config_geocodeProvider">@null</string>
这就是为什么在调用getFromLocationName和 getFromLocation时会提示service not available,2.2就存在的bug
在_loadProvidersLocked函数的最后调用的是updateProvidersLocked();也在这个类中
部分代码如下:
private void updateProvidersLocked() {
boolean changesMade = false;
for (int i = mProviders.size() - 1; i >= 0; i--) {
LocationProviderInterface p = mProviders.get(i);
boolean isEnabled = p.isEnabled();
String name = p.getName();
boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
if (isEnabled && !shouldBeEnabled) {
updateProviderListenersLocked(name, false);
changesMade = true;
} else if (!isEnabled && shouldBeEnabled) {
updateProviderListenersLocked(name, true);
changesMade = true;
}
}
if (changesMade) {
mContext.sendBroadcast(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
}
}
在mProviders里面应该存在一个gpsProvider 和PassiveProvider,而gpsProvider是未被enable的。而passiveProvider是enable的。
这边我们对gpsProvider进行讨论,他执行的是updateProviderListenersLocked(name,true) 然后当有发生改变,就是changesMade=true时,它发送了广播,内容是告诉大家LocationManager发生了变化,让需要的接收者自己接收。
updateProviderListenersLocked(name, false)函数的部分代码如下:
private void updateProviderListenersLocked(String provider, boolean enabled) {
int listeners = 0;
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) {
return;
}
ArrayList<Receiver> deadReceivers = null;
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records != null) {
final int N = records.size();
for (int i=0; i<N; i++) {
UpdateRecord record = records.get(i);
// Sends a notification message to the receiver
if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
if (deadReceivers == null) {
deadReceivers = new ArrayList<Receiver>();
}
deadReceivers.add(record.mReceiver);
}
listeners++;
}
}
if (deadReceivers != null) {
for (int i=deadReceivers.size()-1; i>=0; i--) {
removeUpdatesLocked(deadReceivers.get(i));
}
}
//如果为真则启动gas
if (enabled) {
p.enable();
if (listeners > 0) {
p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);
p.enableLocationTracking(true);
}
} else {
p.enableLocationTracking(false);
p.disable();
}
}
在if(enable)中,如果enable 为真,则启动GPS,调用p.enable()方法,该方法的实现是在
GpsLocationProvider.java类中他继承了LocationProviderInterface
代码路径为:\frameworks\base\services\java\com\android\server\location
部分代码如下:
public void enable() {
synchronized (mHandler) {
sendMessage(ENABLE, 1, null);
}
}
//每次进入此消息,就是清除之前所有消息发送消息交给handlerMassage处理
private void sendMessage(int message, int arg, Object obj) {
// hold a wake lock while messages are pending
synchronized (mWakeLock) {
mPendingMessageBits |= (1 << message);
mWakeLock.acquire();
mHandler.removeMessages(message);
Message m = Message.obtain(mHandler, message);
m.arg1 = arg;
m.obj = obj;
mHandler.sendMessage(m);
}
}
在handlerMessage 中的处理. 调用handleEnable();
public void handleMessage(Message msg) {
int message = msg.what;
switch (message) {
case ENABLE:
if (msg.arg1 == 1) {
handleEnable();
} else {
handleDisable();
}
break;
}
handleEnable 主要作了两件事,
1 调用本地方法 native_init(),初始化gps
本地方法的具体实现是在com_android_server_location_GpsLocationProvider.cpp中,
部分内容为下:
static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
{
//取得接口,并初始化gps
const GpsInterface* interface = GetGpsInterface(env, obj);
if (!interface)
return false;
if (!sGpsDebugInterface)
sGpsDebugInterface = (const GpsDebugInterface*)interface->get_extension(GPS_DEBUG_INTERFACE);
return true;
}
2 试图启动AGPS服务
代码如下:
private void handleEnable() {
if (DEBUG) Log.d(TAG, "handleEnable");
if (mEnabled) return;
//调用本地方法初始化GPS
mEnabled = native_init();
//试图启动AGPS服务
if (mEnabled) {
mSupportsXtra = native_supports_xtra();
if (mSuplServerHost != null) {
native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
}
if (mC2KServerHost != null) {
native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
}
} else {
Log.w(TAG, "Failed to enable location provider");
}
}
取得接口的方法中,也调用了 get_gps_interface
代码如下:
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;
}
Gps_qemu.c的代码路径为:\sdk\emulator\gps
这边qemu_gps_init函数即是sGpsInterface->init函数,其中里面做了gps_state_init初始化,并注册了callbacks回调函数,而这个函数也是在JNI层实现的,而且有JNI层传下来的函数。
部分代码为;
qemu_gps_init(GpsCallbacks* callbacks)
{
GpsState* s = _gps_state;
if (!s->init)
gps_state_init(s);
if (s->fd < 0)
return -1;
s->callbacks = *callbacks;
return 0;
}
在这个主方法中首先打开串口,然后进立socket通信,然后建立线程监听底层数据上报
static void
gps_state_init( GpsState* state )
{
state->init = 1;
state->control[0] = -1;
state->control[1] = -1;
state->fd = -1;
state->fd = qemud_channel_open(QEMU_CHANNEL_NAME);
if (state->fd < 0) {
D("no gps emulation detected");
return;
}
D("gps emulation will read from '%s' qemud channel", QEMU_CHANNEL_NAME );
if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {
LOGE("could not create thread control socket pair: %s", strerror(errno));
goto Fail;
}
if ( pthread_create( &state->thread, NULL, gps_state_thread, state ) != 0 ) {
LOGE("could not create gps thread: %s", strerror(errno));
goto Fail;
}
D("gps state initialized");
return;
Fail:
gps_state_done( state );
}
该方法说明在初始化时调用的相关扩展接口是没用的
static const void*
qemu_gps_get_extension(const char* name)
{
// no extensions supported
return NULL;
}
在2。2的时候handlerEnable还创建了一个监听线程
而在2.3中GpsLocationProvider(路径为:frameworks\base\services\java\com\android\server\location)
在构造函数中就创建了这个 监听线程
构造器中的部分代码
mThread = new GpsLocationProviderThread();
mThread.start();
while (true) {
try {
mInitializedLatch.await();
break;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
//run函数的部分内容
//initialize初始化函数,然后新建一个looper,新建一个providerHandler 用于处理该线程的消息
private final class GpsLocationProviderThread extends Thread {
public GpsLocationProviderThread() {
super("GpsLocationProvider");
}
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
initialize();
Looper.prepare();
mHandler = new ProviderHandler();
// signal when we are initialized and ready to go
mInitializedLatch.countDown();
Looper.loop();
}
}
private void initialize() {
// register our receiver on our thread rather than the main thread
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ALARM_WAKEUP);
intentFilter.addAction(ALARM_TIMEOUT);
mContext.registerReceiver(mBroadcastReciever, intentFilter);
}
初始化主要是将线程的接收者注册到我们的线程上,而不是注册到主线程上。
到这边为止我们完成了 p.enable()函数的分析。
在locationManagerService.java中,的run ()---> initialize()--->loadProviders()----->loadProvidersLocked()
------->_loadProvidersLocked()------->updateProvidersLocked()------>updateProviderListenersLocked0
-------->调用到以下方法
private void updateProviderListenersLocked(String provider, boolean enabled) {
int listeners = 0;
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) {
return;
}
ArrayList<Receiver> deadReceivers = null;
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records != null) {
final int N = records.size();
for (int i=0; i<N; i++) {
UpdateRecord record = records.get(i);
// Sends a notification message to the receiver
if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
if (deadReceivers == null) {
deadReceivers = new ArrayList<Receiver>();
}
deadReceivers.add(record.mReceiver);
}
listeners++;
}
}
if (deadReceivers != null) {
for (int i=deadReceivers.size()-1; i>=0; i--) {
removeUpdatesLocked(deadReceivers.get(i));
}
}
if (enabled) {
p.enable();
if (listeners > 0) {
p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);
p.enableLocationTracking(true);
}
} else {
p.enableLocationTracking(false);
p.disable();
}
}
enableLocationTracking在gpsLocationProvider.java中
public void enableLocationTracking(boolean enable) {
// FIXME - should set a flag here to avoid race conditions with single shot request
synchronized (mHandler) {
sendMessage(ENABLE_TRACKING, (enable ? 1 : 0), null);
}
}
private void sendMessage(int message, int arg, Object obj) {
// hold a wake lock while messages are pending
synchronized (mWakeLock) {
mPendingMessageBits |= (1 << message);
mWakeLock.acquire();
mHandler.removeMessages(message);
Message m = Message.obtain(mHandler, message);
m.arg1 = arg;
m.obj = obj;
mHandler.sendMessage(m);
}
}
private final class ProviderHandler extends Handler {
@Override
public void handleMessage(Message msg) {
int message = msg.what;
switch (message) {
case ENABLE:
if (msg.arg1 == 1) {
handleEnable();
} else {
handleDisable();
}
break;
case ENABLE_TRACKING:
//
handleEnableLocationTracking(msg.arg1 == 1);
break;
}
}
}
handleEnableLocationTracking 函数
private void handleEnableLocationTracking(boolean enable) {
if (enable) {
mTTFF = 0;
mLastFixTime = 0;
startNavigating(false);
} else {
if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
mAlarmManager.cancel(mWakeupIntent);
mAlarmManager.cancel(mTimeoutIntent);
}
stopNavigating();
}
}
startNavigating方法 开始导航
代码如下:
private void startNavigating(boolean singleShot) {
if (!mStarted) {
if (DEBUG) Log.d(TAG, "startNavigating");
mStarted = true;
mSingleShot = singleShot;
mPositionMode = GPS_POSITION_MODE_STANDALONE;
if (Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
} else if (hasCapability(GPS_CAPABILITY_MSB)) {
mPositionMode = GPS_POSITION_MODE_MS_BASED;
}
}
int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
//本地方法
if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
interval, 0, 0)) {
mStarted = false;
Log.e(TAG, "set_position_mode failed in startNavigating()");
return;
}
//本地方法
if (!native_start()) {
mStarted = false;
Log.e(TAG, "native_start failed in startNavigating()");
return;
}
// reset SV count to zero
updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
mFixRequestTime = System.currentTimeMillis();
if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
// set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
// and our fix interval is not short
if (mFixInterval >= NO_FIX_TIMEOUT) {
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
}
}
}
}
在开启导航的这个方法中 ,调用的两个重要的本地方法
这两个本地方法可以在 com_android_server_location_GpsLocationProvider.cpp这个文件中找到
1 native_set_position_mode
实现代码如下:
static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* env, jobject obj,
jint mode, jint recurrence, jint min_interval, jint preferred_accuracy, jint preferred_time)
{
const GpsInterface* interface = GetGpsInterface(env, obj);
if (interface)
//这里调用了接口的set_position_mode方法
return (interface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
preferred_time) == 0);
else
return false;
}
该方法调用了接口的set_position_mode方法,这个方法的实现在(模拟器)的相关类中可以看到期实现
部分代码如下;
static int qemu_gps_set_position_mode(GpsPositionMode mode, int fix_frequency)
{
// FIXME - support fix_frequency
return 0;
}
2 native_start 通过向底层发送命令来启动GPS, 这个底层就是enable/init函数中启动的等待数据的线程
static int
qemu_gps_start()
{
GpsState* s = _gps_state;
if (!s->init) {
D("%s: called with uninitialized state !!", __FUNCTION__);
return -1;
}
D("%s: called", __FUNCTION__);
gps_state_start(s);
return 0;
}
static void gps_state_start( GpsState* s )
{
char cmd = CMD_START;
int ret;
do { ret=write( s->control[0], &cmd, 1 ); }
while (ret < 0 && errno == EINTR);
if (ret != 1)
D("%s: could not send CMD_START command: ret=%d: %s",
__FUNCTION__, ret, strerror(errno));
}
数据监听线程
static void* gps_state_thread( void* arg )
{
GpsState* state = (GpsState*) arg;
NmeaReader reader[1];
int epoll_fd = epoll_create(2);
int started = 0;
int gps_fd = state->fd;
int control_fd = state->control[1];
nmea_reader_init( reader );
// register control file descriptors for polling
epoll_register( epoll_fd, control_fd );
epoll_register( epoll_fd, gps_fd );
D("gps thread running");
// now loop
for (;;) {
struct epoll_event events[2];
int ne, nevents;
nevents = epoll_wait( epoll_fd, events, 2, -1 );
if (nevents < 0) {
if (errno != EINTR)
LOGE("epoll_wait() unexpected error: %s", strerror(errno));
continue;
}
D("gps thread received %d events", nevents);
for (ne = 0; ne < nevents; ne++) {
if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
goto Exit;
}
if ((events[ne].events & EPOLLIN) != 0) {
int fd = events[ne].data.fd;
if (fd == control_fd)
{
char cmd = 255;
int ret;
D("gps control fd event");
do {
ret = read( fd, &cmd, 1 );
} while (ret < 0 && errno == EINTR);
if (cmd == CMD_QUIT) {
D("gps thread quitting on demand");
goto Exit;
}
else if (cmd == CMD_START) {
if (!started) {
D("gps thread starting location_cb=%p", state->callbacks.location_cb);
started = 1;
nmea_reader_set_callback( reader, state->callbacks.location_cb );
}
}
else if (cmd == CMD_STOP) {
if (started) {
D("gps thread stopping");
started = 0;
nmea_reader_set_callback( reader, NULL );
}
}
}
else if (fd == gps_fd)
{
char buff[32];
D("gps fd event");
for (;;) {
int nn, ret;
ret = read( fd, buff, sizeof(buff) );
if (ret < 0) {
if (errno == EINTR)
continue;
if (errno != EWOULDBLOCK)
LOGE("error while reading from gps daemon socket: %s:", strerror(errno));
break;
}
D("received %d bytes: %.*s", ret, ret, buff);
for (nn = 0; nn < ret; nn++)
nmea_reader_addc( reader, buff[nn] );
}
D("gps fd event end");
}
else
{
LOGE("epoll_wait() returned unkown fd %d ?", fd);
}
}
}
}
Exit:
return NULL;
}
这个监听线程最主要的一个就是nmea_reader_set_callback( )函数
其实就是注册了一个回调函数,location_cb 这个回调函数就是对底层location数据上报的回调函数。
到此
enableLocationTracking函数完成了,
也就是LocationManageService.java中
updateProviderListenersLocked的完成
也就是updateProvidersLocked的完成,
也就是loadProviders函数的完成
也就是 initialize的完成,
也就是run的完成,
也就是systemReady的完成
所以完了