Chinaunix首页 | 论坛 | 博客
  • 博客访问: 842038
  • 博文数量: 244
  • 博客积分: 10000
  • 博客等级: 上将
  • 技术积分: 2420
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-29 09:07
文章分类

全部博文(244)

文章存档

2011年(4)

2010年(3)

2009年(72)

2008年(119)

2007年(46)

我的朋友

分类: LINUX

2009-12-28 21:57:00

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调用。
========================
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
========================

参考文档:
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

补充信息:
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

===============================
 
阅读(2753) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-04-16 16:39:40

你好,请问能不能用C代码获取GPS的位置信息呢? 能不能指导一下,我的QQ:383498029

chinaunix网友2010-04-13 11:04:49

请问下: 我这是marvell的, 你还举例了htc的。 这两个加的LIBRARIES 是不是不一样。 marvell 的只加个libgps就行了。 你写的这个 librpc 需要么?什么用? BOARD_GPS_LIBRARIES := libgps librpc 谢谢!

chinaunix网友2010-04-13 10:55:16

太精华了,找了很久 , 这篇对我刚接手的工作 太有针对性了