Location服务分析
===============================================
启动Location服务。
ServiceManager.addService(Context.LOCATION_SERVICE, new LocationManagerService(context));
new LocationManagerService
调用了 LocationManagerService类的 构造函数 LocationManagerService()
构造函数调用了
loadProviders();
LocationManagerService.java (frameworks/base/services/java/com/android/server):
void loadProviders()
LocationManagerService.java (frameworks/base/services/java/com/android/server)
loadProvidersLocked()
LocationManagerService.java (frameworks/base/services/java/com/android/server)
_loadProvidersLocked()
LocationManagerService.java (frameworks/base/services/java/com/android/server)
private void _loadProvidersLocked() {
// Attempt to load "real" providers first
if (GpsLocationProvider.isSupported())
return native_is_supported()
native_is_supported本地调用:
static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz)
if (!sGpsInterface)
sGpsInterface = gps_get_interface();
gps_find_hardware() //获取gps接口
return (sGpsInterface != NULL);
{
//创建一gpslocation provider
mGpsLocationProvider = new GpsLocationProvider(mContext);
LocationProviderImpl.addProvider(mGpsLocationProvider);
}
...
updateProvidersLocked();
updateProviderListenersLocked(name,true)
if (enabled)
p.enable();
此处调用的是:
GpsLocationProvider.java (frameworks/base/location/java/com/android/internal/location)
中的 void enable()
mEnabled = native_init();
native_init 本地调用的是:
static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
if (!sGpsInterface)
sGpsInterface = gps_get_interface();
return (sGpsInterface && sGpsInterface->init(&sGpsCallbacks) == 0);
native_is_supported中调用了 gps_get_interface 所以此处的 sGpsInterface 不为NULL
mEventThread = new GpsEventThread()
run() //GpsLocationProvider.java (frameworks/base/location/java/com/android/internal/location)
native_wait_for_event();
native_wait_for_event 本地调用的是:
void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, jobject obj)
env->CallVoidMethod(obj, method_reportStatus, sGpsStatusCopy.status);
获取gps接口:
const GpsInterface* gps_get_interface()
{
if (sGpsInterface == NULL)
gps_find_hardware();
return sGpsInterface;
}
static void gps_find_hardware( void )
{
#ifdef HAVE_QEMU_GPS_HARDWARE
if (qemu_check()) {
sGpsInterface = gps_get_qemu_interface();
if (sGpsInterface) {
LOGD("using QEMU GPS Hardware emulation/n");
return;
}
}
#endif
#ifdef HAVE_GPS_HARDWARE
sGpsInterface = gps_get_hardware_interface();
#endif
if (!sGpsInterface)
LOGD("no GPS hardware on this device/n");
}
因为 gps_find_hardware 没有实际的硬件,所以调用的是:
const GpsInterface* gps_get_qemu_interface()
{
return &qemuGpsInterface;
}
因为有下面的定义:
static const GpsInterface qemuGpsInterface = {
qemu_gps_init,
qemu_gps_start,
qemu_gps_stop,
qemu_gps_set_fix_frequency,
qemu_gps_cleanup,
qemu_gps_inject_time,
qemu_gps_delete_aiding_data,
qemu_gps_set_position_mode,
qemu_gps_get_extension,
};
因为:
static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
{
if (!sGpsInterface)
sGpsInterface = gps_get_interface();
return (sGpsInterface && sGpsInterface->init(&sGpsCallbacks) == 0);
}
此时执行了 :qemu_gps_init
Gps_qemu.c (hardware/libhardware_legacy/gps)
static int qemu_gps_init(GpsCallbacks* callbacks)
GpsState* s = _gps_state;
if (!s->init)
gps_state_init(s);
static void gps_state_init( GpsState* state )
if ( pthread_create( &state->thread, NULL, gps_state_thread, state ) != 0 )
static void* gps_state_thread( void* arg )
ret = read( fd, &cmd, 1 );
...
cmd == CMD_START
nmea_reader_set_callback( reader, state->callbacks.location_cb );
因为有:
android_location_GpsLocationProvider.cpp (frameworks/base/core/jni):
GpsCallbacks sGpsCallbacks = {
location_callback,
status_callback,
sv_status_callback,
};
所以 state->callbacks.location_cb 执行的是:
static void location_callback(GpsLocation* location)
{
pthread_mutex_lock(&sEventMutex);
//置sPendingCallbacks 标记为 kLocation
sPendingCallbacks |= kLocation;
memcpy(&sGpsLocation, location, sizeof(sGpsLocation));
pthread_cond_signal(&sEventCond);
pthread_mutex_unlock(&sEventMutex);
}
static pthread_mutex_t sEventMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t sEventCond = PTHREAD_COND_INITIALIZER;
GpsLocationProvider.java (frameworks/base/location/java/com/android/internal/location):
因为线程 GpsEventThread 类的run函数循环调用了 native_wait_for_event,实际本地调用:
static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, jobject obj)
{
pthread_mutex_lock(&sEventMutex);
//等待信号量 sEventCond 和 锁
pthread_cond_wait(&sEventCond, &sEventMutex);
//拷贝并且清除 sPendingCallbacks 表记,如果收到的信号量是由 location_callback 函数触发,
//那么此时 sPendingCallbacks 为 kLocation
int pendingCallbacks = sPendingCallbacks;
sPendingCallbacks = 0;
// copy everything and unlock the mutex before calling into Java code to avoid the possibility
// of timeouts in the GPS engine.
memcpy(&sGpsLocationCopy, &sGpsLocation, sizeof(sGpsLocationCopy));
memcpy(&sGpsStatusCopy, &sGpsStatus, sizeof(sGpsStatusCopy));
memcpy(&sGpsSvStatusCopy, &sGpsSvStatus, sizeof(sGpsSvStatusCopy));
pthread_mutex_unlock(&sEventMutex);
//如果信号量由 location_callback 触发,那么执行 method_reportLocation 方法。
if (pendingCallbacks & kLocation) {
env->CallVoidMethod(obj, method_reportLocation, sGpsLocationCopy.flags,
(jdouble)sGpsLocationCopy.latitude, (jdouble)sGpsLocationCopy.longitude,
(jdouble)sGpsLocationCopy.altitude,
(jfloat)sGpsLocationCopy.speed, (jfloat)sGpsLocationCopy.bearing,
(jfloat)sGpsLocationCopy.accuracy, (jlong)sGpsLocationCopy.timestamp);
}
if (pendingCallbacks & kStatus) {
env->CallVoidMethod(obj, method_reportStatus, sGpsStatusCopy.status);
}
if (pendingCallbacks & kSvStatus) {
env->CallVoidMethod(obj, method_reportSvStatus);
}
if (pendingCallbacks & kXtraDownloadRequest) {
env->CallVoidMethod(obj, method_xtraDownloadRequest);
}
if (pendingCallbacks & kDisableRequest) {
// don't need to do anything - we are just poking so wait_for_event will return.
}
}
上面函数的:
env->CallVoidMethod(obj, method_reportLocation, sGpsLocationCopy.flags,
(jdouble)sGpsLocationCopy.latitude, (jdouble)sGpsLocationCopy.longitude,
(jdouble)sGpsLocationCopy.altitude,
(jfloat)sGpsLocationCopy.speed, (jfloat)sGpsLocationCopy.bearing,
(jfloat)sGpsLocationCopy.accuracy, (jlong)sGpsLocationCopy.timestamp);
由于 method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
所以实际上执行的是:
文件 GpsLocationProvider.java (frameworks/base/location/java/com/android/internal/location) 中的函数:
private void reportLocation(int flags, double latitude, double longitude, double altitude,
float speed, float bearing, float accuracy, long timestamp)
{
}
private void reportStatus(int status)
{
...
//发送一个intent 通知 :GPS 已经被开启或者关闭。
Intent intent = new Intent(GPS_ENABLED_CHANGE_ACTION);
intent.putExtra(EXTRA_ENABLED, mNavigating);
mContext.sendBroadcast(intent);
...
}
//called from native code to update SV info
private void reportSvStatus()
{
}
GpsLocationProvider.java (frameworks/base/location/java/com/android/internal/location)
GpsLocationProvider 类里面初始了 class_init_native
实际调用:
{"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
}
上面的 reportStatus 发送了一个 GPS_ENABLED_CHANGE_ACTION 的 intent
mContext.sendBroadcast(intent) 实际上调用的是:
ApplicationContext.java (frameworks/base/core/java/android/app) 文件中的:
void sendBroadcast(Intent intent)
ActivityManagerNative.getDefault().broadcastIntent(mMainThread.getApplicationThread(), intent,...)
因为有:
public abstract class ActivityManagerNative extends Binder implements IActivityManager
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor
所以 broadcastIntent 最终执行的是文件:ActivityManagerService.java (frameworks/base/services/java/com/android/server/am)
中类 ActivityManagerService 的 broadcastIntent 函数
int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized, boolean sticky)
调用:int res = broadcastIntentLocked(callerApp,callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo,
resultCode, resultData, map, requiredPermission, serialized,
sticky, callingPid, callingUid);
接着调用:
broadcastIntentLocked
scheduleBroadcastsLocked()
mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
以上完成发送一个消息。
============
以下为消息接收流程:
ActivityManagerService.java (frameworks/base/services/java/com/android/server/am)
void handleMessage(Message msg)
case BROADCAST_INTENT_MSG:
processNextBroadcast(true);
BroadcastRecord r;
...
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
deliverToRegisteredReceiver(r, filter, r.ordered);
performReceive(filter.receiverList.app, filter.receiverList.receiver,new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, r.ordered);
if (app != null && app.thread != null)
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,data, extras, ordered);
else
receiver.performReceive(intent, resultCode, data, extras, ordered);
因为有:
class ApplicationThreadProxy implements IApplicationThread
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread
private final class ApplicationThread extends ApplicationThreadNative
所以调用的是 ActivityThread.java (frameworks/base/core/java/android/app)
ApplicationThread 类中的
void schedulePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges)
receiver.performReceive(intent, resultCode, dataStr, extras, ordered);
因为有:
final static class InnerReceiver extends IIntentReceiver.Stub
void performReceive(Intent intent, int resultCode,String data, Bundle extras, boolean ordered)
rd.performReceive(intent, resultCode, data, extras, ordered);
最终执行的是:ReceiverDispatcher 类中的 performReceive 函数
performReceive 调用了 mActivityThread.post(args)
Args args = new Args();
args.mCurIntent = intent;
args.mCurCode = resultCode;
args.mCurData = data;
args.mCurMap = extras;
args.mCurOrdered = ordered;
if (!mActivityThread.post(args))
...
因为有 final class Args implements Runnable
执行 Args 的run 函数,在run函数里面执行 :receiver.onReceive(mContext, intent);
这里的 onReceive
======================================
分析文件:
hardware/libhardware_legacy/gps/Android.mk
===============================
# Use hardware GPS implementation if available.
#
ifneq ($(BOARD_GPS_LIBRARIES),)
LOCAL_CFLAGS += -DHAVE_GPS_HARDWARE
LOCAL_SHARED_LIBRARIES += $(BOARD_GPS_LIBRARIES)
endif
# Use emulator GPS implementation if QEMU_HARDWARE is set.
#
USE_QEMU_GPS_HARDWARE := $(QEMU_HARDWARE)
ifeq ($(USE_QEMU_GPS_HARDWARE),true)
LOCAL_CFLAGS += -DHAVE_QEMU_GPS_HARDWARE
LOCAL_SRC_FILES += gps/gps_qemu.c
endif
LOCAL_SRC_FILES += gps/gps.cpp
===============================
因为文件 hardware/libhardware_legacy/Android.mk 中有:
ifneq ($(TARGET_SIMULATOR),true)
LOCAL_CFLAGS += -DQEMU_HARDWARE
QEMU_HARDWARE := true
endif
当编译的是模拟器版本的时候 QEMU_HARDWARE 为true,所以使用的是模拟的gps调用。
如果编译相关的硬件版本,那么必须给 BOARD_GPS_LIBRARIES 赋值,因为从语句:
LOCAL_SHARED_LIBRARIES += $(BOARD_GPS_LIBRARIES) 可以看出,变量
BOARD_GPS_LIBRARIES 指定的应该是一个库的名称,通常为 libgps,也可以自定义
对于变量 BOARD_GPS_LIBRARIES 我们可以在文件:
vendor/marvell/littleton/BoardConfig.mk
或者
vendor/htc/dream-open/BoardConfig.mk
里面进行指定。
BOARD_GPS_LIBRARIES := libgps librpc
BOARD_GPS_LIBRARIES := libgps
指定变量 BOARD_GPS_LIBRARIES 表明我们依赖的是外部库 libgps.so,所以我们还必须
准备一个libgps.so 库,由它完成实际的gps调用。http://koudai.360.cn/
========================
libgps.so 是gps接口:
./hardware/libhardware_legacy/include/hardware_legacy/gps.h
的实现,所以根据不同的硬件,libgps.so的实现方式是不一样的,但是接口一致。
关于怎样添加一个 gps 库,可以参考文档:
http://www.netmite.com/android/mydroid/cupcake/development/pdk/docs/gps.html
========================
http://linux.die.net/man/3/libgps
参考文档:
BOARD_GPS_LIBRARIES := libgps
BOARD_GPS_LIBRARIES := libgps librpc
--- freedroid.orig/vendor/htc/dream/BoardConfig.mk
+++ freedroid/vendor/htc/dream/BoardConfig.mk
@@ -13,7 +13,8 @@ HAVE_CUSTOM_WIFI_DRIVER_2 := true
http://groups.fsf.org/wiki/Hardware/Replicant
补充信息:
target thumb C: libgps <= hardware/bbk/libgps/MyGpsLibrary.c
target thumb C: librpc <= hardware/bbk/librpc/svc.c
target SharedLib: libgps (out/target/product/littleton/obj/SHARED_LIBRARIES/libgps_intermediates/LINKED/libgps.so)
target StaticLib: librpc (out/target/product/littleton/obj/STATIC_LIBRARIES/librpc_intermediates/librpc.a)
target SharedLib: librpc (out/target/product/littleton/obj/SHARED_LIBRARIES/librpc_intermediates/LINKED/librpc.so)
target Prelink: libgps (out/target/product/littleton/symbols/system/lib/libgps.so)
target Prelink: librpc (out/target/product/littleton/symbols/system/lib/librpc.so)
target Strip: librpc (out/target/product/littleton/obj/lib/librpc.so)
target Strip: libgps (out/target/product/littleton/obj/lib/libgps.so)
Install: out/target/product/littleton/system/lib/librpc.so
target SharedLib: libhardware_legacy (out/target/product/littleton/obj/SHARED_LIBRARIES/libhardware_legacy_intermediates/LINKED/libhardware_legacy.so)
Install: out/target/product/littleton/system/lib/libgps.so
===============================