Binder进程间通信是Android的标准框架,使用模式固定,比较简单,故略过.本文主要偏向于JNI层的实现及JNI层与HAL层的通信.
除开应用层,整个服务其实分为四层:JAVA层、JNI层、HAL层、硬件层,其中JAVA层通过JNI层实现与HAL层的通信,HAL层采用高通的RPC协议与硬件通信.
一、首先,讲一下后面分析要用到的基础
1.相关源代码
HAL层所涉及到的主要代码:gps.h gps.c hardware.h loc_eng.cpp loc_api_rpc_glue.cpp loc_apicb_appinit.c
与HAL层通信的JNI层代码:GpsLocationProvider.cpp
与JNI对应的JAVA代码:GpsLocationProvider.java
Service实现代码:LocationManagerServicer.java
应用层与Service通讯的代码:LocationManager.java
2.gps.h里面定义了两个非常重要的结构体:
/** GPS callback structure. */ 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; gps_request_utc_time request_utc_time_cb; } GpsCallbacks;
/** Represents the standard GPS interface. */ typedef struct { /** set to sizeof(GpsInterface) */ size_t size; /** * Opens the interface and provides the callback routines * to the implemenation of this interface. */ 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;
GpsCallbacks这个结构体里成员变量基本上都是函数指针,
具体的实现都在GpsLocationProvider.cpp中,这些函数指针变量最终会赋给HAL层,供HAL层回调,见GpsLocationProvider.cpp里第138行:
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, request_utc_time_callback, };
sGpsCallbacks是一个全局变量,结构体在初始化时就对各个变量进行了赋值,各成员变量的值为GpsLocationProvider.cpp
里的一些函数,此变量通过GpsInterface里的(*init)( GpsCallbacks* callbacks )函数传递给HAL层,
见GpsLocationProvider.cpp里第287行:
if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) return false;
GpsInterface这个结构体也有一堆函数指针成员变量,这个结构体是在HAL层实现的,主要作用是给JNI层调用,达到
JNI向HAL层传递信息的作用;sGpsInterface是在初始化时取到的,下面会讲到.
3.综合起来说:GpsInterface与GpsInterface达到了JNI层与HAL层交互的目的,分别实现JNI层操作HAL层及HAL层往JNI层传递数据的作用,
比如:JNI层通过调用GpsInterface里的(*start)( void ),这个函数告诉HAL层启动定位,而HAL层通过location_callback向JNI层传递GPS位置信息
二、初始化与启动
Service里的Java层,JNI层与HAL层,都是运行在一个进程中的,Service启动时会进行一系列初始化工作,比如启动服务Looper线程、HAL层的工作线程等等
1.入口函数
系统进程随开机启动,会自动调用Location服务的systemReady()函数来启动定位服务线程,见SystemServer.java第946行:
try { if (locationF != null) locationF.systemReady(); } catch (Throwable e) { reportWtf("making Location Service ready", e); }
此处locationF即为LocationManagerService的实例.
2.入口函数LocationManagerService.systemReady()的作用
此函数很简单,开始了一个线程并建立消息循环及执行init()函数,见LocationManagerService.java第199行:
@Override public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); Looper.prepare(); mLocationHandler = new LocationWorkerHandler(); init(); Looper.loop(); }
重点在init()函数里,此函数里调用了两个非常重要的函数:
loadProvidersLocked();与updateProvidersLocked();
分别见LocationManagerService.java的219行与252行
3. loadProvidersLocked()函数作用
加载各种Provider,最重要的一项就是创建GpsLocationProvider对象,见LocationManagerService.java的330行:
if (GpsLocationProvider.isSupported()) { // Create a gps location provider GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this); mGpsStatusProvider = gpsProvider.getGpsStatusProvider(); mNetInitiatedListener = gpsProvider.getNetInitiatedListener(); addProviderLocked(gpsProvider); mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider); }
GpsLocationProvider里与JNI层进行了交互,GpsLocationProvider承担了GPS定位的主要的工作.
mGpsStatusProvider是GPS模块向上层提供的一个窗口,可以add与remove IGpsStatusListener接口,而此接口在APP层对应GpsStatus.Listener接口即GPS状态监听器
mNetInitiatedListener用来初始化网络监听
GpsLocationProvider.java里有一段static代码,执行了class_init_native()函数,在此函数中获取了HAL层开放给上层的GpsInterface接口,
见GpsLocationProvider.java的1606行:
static { class_init_native(); }
class_init_native()函数对应JNI函数即GpsLocationProvider.cpp里的android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz)
此函数还有一个重要作用,即提取出GpsLocationProvider.java里部分函数的id,当HAL层通知消息给JNI层时,JNI层再通过调用这些函数通知上层
4.updateProvidersLocked()函数
此函数在切换用户的时候也会被调用,最重要的作用是调用GpsLocationProvider.java的enable()与disable()函数
而enable()最终调用了native_init()函数与native_supports_xtra()函数、
disable()最终调用了 native_stop()函数native_cleanup()函数
native_init()是非常重要的函数,对应于JNI函数:android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
它将GpsCallbacks传给了HAL层
即上面提到的一段代码:
if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
5.loc_eng_init()函数
此函数由native_init()调用,位于loc_eng.cpp的第177行
因为native_init()实际上是GpsLocationProvider.cpp中的android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)函数,android_location_GpsLocationProvider_init中调用了sGpsInterface->init(&sGpsCallbacks),而sGpsInterface变量是由loadProvidersLocked()函数执行而得到的,
所以找到了sGpsInterface变量的由来,就知道为什么sGpsInterface->init实际上是loc_eng.cpp的loc_eng_init()函数
从第3条的分析得知,loadProvidersLocked()最终会调用到
android_location_GpsLocationProvider_class_init_native()函数,里面最重要的一段,见GpsLocationProvider.cpp第253行:
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; sGpsInterface = gps_device->get_gps_interface(gps_device); } }
其中hw_get_module函数是从lib动态库中获取到gps模块的hw_module_t变量,这块属于HAL框架,先不管是怎么取到的,
先看看hw_module_t变量在哪里设置的,见gps.c里的第60行:
const struct hw_module_t HAL_MODULE_INFO_SYM = { .tag = HARDWARE_MODULE_TAG, .version_major = 1, .version_minor = 0, .id = GPS_HARDWARE_MODULE_ID, .name = "loc_api GPS Module", .author = "Qualcomm USA, Inc.", .methods = &gps_module_methods, };
HAL_MODULE_INFO_SYM这个变量即为hw_module_t结构体的实例,再看这段代码:
err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
这里调用了hw_module_t里的methods结构体里的open函数,
methods结构体值为gps_module_methods,见gps.c的56行:
static struct hw_module_methods_t gps_module_methods = { .open = open_gps };
其中的open函数指针指向了open_gps函数, 即module->methods->open实际上调用的是open_gps()函数,定义见gps.c的第41行:
static int open_gps(const struct hw_module_t* module, char const* name, struct hw_device_t** device) { struct gps_device_t *dev = malloc(sizeof(struct gps_device_t)); memset(dev, 0, sizeof(*dev)); dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.version = 0; dev->common.module = (struct hw_module_t*)module; dev->get_gps_interface = gps__get_gps_interface; *device = (struct hw_device_t*)dev; return 0; }
重点为这句:
dev->get_gps_interface = gps__get_gps_interface;
再回过头去分析
sGpsInterface = gps_device->get_gps_interface(gps_device);
可知sGpsInterface的值为gps__get_gps_interface函数所返回的值,gps__get_gps_interface定义在gps.c的第36行:
const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev) { return get_gps_interface(); }
而get_gps_interface()函数的定义在loc_eng.cpp的第1530行:
extern "C" const GpsInterface* get_gps_interface() { return &sLocEngInterface; }
再看sLocEngInterface的定义,loc_eng.cpp的第97行:
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, };
结合GpsInterface的声明,最终找到了loc_eng_init()函数即为sGpsInterface->init(&sGpsCallbacks)中的init
loc_eng_init()里作了什么呢?
最重要的就是调了函数
loc_api_glue_init()与sGpsCallbacks的函数create_thread_callback;
loc_api_glue_init()位于loc_api_rpc_glue.c的第158行
create_thread_callback函数在GpsLocationProvider.cpp里第133行:
static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg) { return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg); }
很明显是启动了一个线程,start为线程执行的函数,此参为在loc_eng_init()里传入,见loc_eng.cpp第236行:
loc_eng_data.deferred_action_thread = callbacks->create_thread_cb("loc_api",loc_eng_process_deferred_action, NULL);
里面的create_thread_cb即为create_thread_callback,所以最终执行的是loc_eng_process_deferred_action函数,见loc_eng.cpp第1422行
里面是一个while循环
loc_api_glue_init函数作用:创建一个与ARM9 RPC通讯的通道,与loc_eng_process_deferred_action线程配合使用,loc_eng_process_deferred_action线程会等待数据到来,当RPC通道从硬件取到数据时,会激活线程中的等待循环,从全局变量loc_eng_data里拿数据
loc_eng_process_deferred_action函数作用:当GPS有数据解析上报时,回调JNI函数,JNI函数会执行JAVA里的对应函数,最终通知给上层
还往下面分析涉及到高通自有的RPC协议实现与GPS专业知识,暂不作深究.
6.到此可以进行一下小结:
LocationManagerSerivce线程启动时,同时作了两个工作:
a.初始化GpsLocationProvider对象并获取HAL层的操作接口
b.将上层的回调接口GpsCallbacks传递给HAL层,供HAL进行回调,同时HAL层创建RPC通讯与上报数据线程
三、回调接口的设置
要分两部分讲,一部分是Framework层的回调接口设置,一部分是JNI层的回调接口设置
为什么是两部分,主要是因为JAVA与C++的回调有点不一样,JAVA层采用的是设置接口的方式
而C++采用的是设置函数指针的方式,整个设置分两部分,那么回调也就分两部分
1.JNI层的回调接口设置在前面提到过,即在Service初始化时完成,由前面提到的
“if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)”
这句代码完成;其中的函数变量sGpsCallbacks为JNI的结构体,里面成员为一系列的函数指针,指向JNI里实现的函数,供HAL层调用;
JNI层也是C++代码,JAVA层的监听器设置不能设置到JNI层的,那么如何衔接的呢?主要是由JNI机制实现的,即JNI里可以直接调用java对象里的函数,
在初始化时,GpsLocationProvider.cpp的android_location_GpsLocationProvider_class_init_native函数中,有一段代码:
method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V"); method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V"); method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V"); method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(III)V"); method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V"); method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V"); method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V"); method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification", "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V"); method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V"); method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V"); method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
这一系列的代码目的就是先缓存JAVA里的函数id到JNI本地,当GPS数据上来时,由JNI调用,达到JNI层向JAVA层传送数据的目的
再来看sGpsCallbacks被传到HAL层后,是怎么被HAL层保存的
通过前面的分析,sGpsInterface->init(&sGpsCallbacks)这句其实调用的是static int loc_eng_init(GpsCallbacks* callbacks),
里面与callbacks相关的逻辑如下:
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;
所以这些接口函数又保存到了本地的变量loc_eng_data中,实际上GPS有数据通知上层时,最先调用的就是loc_eng_data里的这些函数
对比一下loc_eng_data_s_type结构体与GpsCallbacks
typedef struct { rpc_loc_client_handle_type client_handle; gps_location_callback location_cb; gps_status_callback status_cb; gps_sv_status_callback sv_status_cb; agps_status_callback agps_status_cb; gps_nmea_callback nmea_cb; gps_ni_notify_callback ni_notify_cb; gps_acquire_wakelock acquire_wakelock_cb; gps_release_wakelock release_wakelock_cb; int agps_status; // used to defer stopping the GPS engine until AGPS data calls are done boolean agps_request_pending; boolean stop_request_pending; pthread_mutex_t deferred_stop_mutex; loc_eng_xtra_data_s_type xtra_module_data; loc_eng_ioctl_data_s_type ioctl_data; // data from loc_event_cb rpc_loc_event_mask_type loc_event; rpc_loc_event_payload_u_type loc_event_payload; // TBD: char agps_server_host[256]; int agps_server_port; uint32 agps_server_address; char apn_name[100]; int position_mode; rpc_loc_server_connection_handle conn_handle; // GPS engine status GpsStatusValue engine_status; // Aiding data information to be deleted, aiding data can only be deleted when GPS engine is off GpsAidingData aiding_data_for_deletion; // Data variables used by deferred action thread pthread_t deferred_action_thread; // Mutex used by deferred action thread pthread_mutex_t deferred_action_mutex; // Condition variable used by deferred action thread pthread_cond_t deferred_action_cond; // flags for pending events for deferred action thread int deferred_action_flags; } loc_eng_data_s_type;
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; gps_request_utc_time request_utc_time_cb; } GpsCallbacks;
其对应关系很明显
2.JAVA层回调接口设置比较简单即设置接口,当然与一般的JAVA接口设置有点不一样,主要是因为涉及到进程间通讯,APP接口要先转成Binder机制支持的接口形式,然后再传给Service
以设置GPS状态监听为例:
APP层的监听器为GpsStatus.Listener,因为此接口不能直接跨进程设置,故在LocationManager.java中会自动转化为GpsStatusListenerTransport,
此类其实是实现了IGpsStatusListener.Stub接口,符合Binder机制要求,所以应用层添加GPS状态监听最初是调用LocationManager.addGpsStatusListener(GpsStatus.Listener listener),
实际上被转化成调用service的addGpsStatusListener(IGpsStatusListener listener),GpsStatusListenerTransport中保存了GpsStatus.Listener引用.
而Service的addGpsStatusListener里实际调用了mGpsStatusProvider.addGpsStatusListener(listener);而mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
gpsProvider为GpsLocationProvider类的实例,实际getGpsStatusProvider()函数只是返回变量mGpsStatusProvider
其初始化语句为,见GpsLocationProvider.java 312行:
private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() { @Override public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException { if (listener == null) { throw new NullPointerException("listener is null in addGpsStatusListener"); } synchronized (mListeners) { IBinder binder = listener.asBinder(); int size = mListeners.size(); for (int i = 0; i < size; i++) { Listener test = mListeners.get(i); if (binder.equals(test.mListener.asBinder())) { // listener already added return; } } Listener l = new Listener(listener); binder.linkToDeath(l, 0); mListeners.add(l); } } @Override public void removeGpsStatusListener(IGpsStatusListener listener) { if (listener == null) { throw new NullPointerException("listener is null in addGpsStatusListener"); } synchronized (mListeners) { IBinder binder = listener.asBinder(); Listener l = null; int size = mListeners.size(); for (int i = 0; i < size && l == null; i++) { Listener test = mListeners.get(i); if (binder.equals(test.mListener.asBinder())) { l = test; } } if (l != null) { mListeners.remove(l); binder.unlinkToDeath(l, 0); } } } };
这里比较奇怪,因为LocationManagerservice.java在调用GpsLocationProvider时实际是处于同进程的,但是这里却用到了Binder机制,其实不用这个机制应该是没什么关系的;通过上面代码可知,添加的监听接口最后保存在了mListeners里,看mListeners的定义:private ArrayList<Listener> mListeners = new ArrayList<Listener>();
一个普通List而已
到此可知JAVA层回调接口设置就这么简单
再看看最后是哪里调用了mListeners里的这些接口,比如reportLocation函数,这个函数的id在JNI里对应于method_reportLocation这个变量,
很明显了,JNI会调用到这些接口,来通知上层.
移除接口就是添加的反操作,比较简单,不再分析,但有一点要注意,删除时虽然传入的变量与添加的变量是同一个,但是到了服务端时,实际上是不一样的,主要就是因为进程间通讯的原因,接口都做了转化;那删除时如何能找到添加时对应的接口呢,也比较简单,因为两者的asBinder()是一样的,通过比较
二者的asBinder()值即可
四、底层消息上传
前面讲的回调接口的设置就是为底层消息上传服务的,GPS模块有定位数据后利用回调机制一级级上传,最后发送给应用
以GPS状态数据为例
首先Service初始化时,HAL层通过loc_api_glue_init函数创建与硬件的RPC通讯通道,同进启动线程不断等待数据的到来;
当硬件有数据后,会激活线程,线程里会调用相关函数:
loc_event = loc_eng_data.loc_event;此句是线程循环里的一句代码,即获取由RPC通道传递来的GPS数据,接下来会调用
if (loc_event != 0) { loc_eng_process_loc_event(loc_event, &loc_event_payload); }在loc_eng_process_loc_event里有一句:
if (loc_event & RPC_LOC_EVENT_STATUS_REPORT) { loc_eng_report_status (&(loc_event_payload->rpc_loc_event_payload_u_type_u.status_report)); }再看 loc_eng_report_status函数里会执行loc_eng_data.status_cb(&status);
通过之前的分析:loc_eng_data.status_cb = callbacks->status_cb;而callbacks即为sGpsCallbacks变量,
callbacks->status_cb对应于JNI函数:status_callback
可知,最终是调用了JNI传过来的函数status_callback,其定义见GpsLocationProvider.cpp第82行:
static void status_callback(GpsStatus* status) { JNIEnv* env = AndroidRuntime::getJNIEnv(); env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status); checkAndClearExceptionFromCallback(env, __FUNCTION__); }
mCallbacksObj即java层的GpsLocationProvider对象;再看初始化时的这句:
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
其最终是调用了JAVA函数reportStatus,再看它的定义:
private void reportStatus(int status) { if (DEBUG) Log.v(TAG, "reportStatus status: " + status); synchronized (mListeners) { boolean wasNavigating = mNavigating; switch (status) { case GPS_STATUS_SESSION_BEGIN: mNavigating = true; mEngineOn = true; break; case GPS_STATUS_SESSION_END: mNavigating = false; break; case GPS_STATUS_ENGINE_ON: mEngineOn = true; break; case GPS_STATUS_ENGINE_OFF: mEngineOn = false; mNavigating = false; break; } if (wasNavigating != mNavigating) { int size = mListeners.size(); for (int i = 0; i < size; i++) { Listener listener = mListeners.get(i); try { if (mNavigating) { listener.mListener.onGpsStarted(); } else { listener.mListener.onGpsStopped(); } } catch (RemoteException e) { Log.w(TAG, "RemoteException in reportStatus"); mListeners.remove(listener); // adjust for size of list changing size--; } } // send an intent to notify that the GPS has been enabled or disabled. Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION); intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); } } }
这里很明显了,最后是调用了之前设置的监听器IGpsStatusListener
看看应用层监听器与Binder监听器之间的关系:
private class GpsStatusListenerTransport extends IGpsStatusListener.Stub { private final GpsStatus.Listener mListener; private final GpsStatus.NmeaListener mNmeaListener; // This must not equal any of the GpsStatus event IDs private static final int NMEA_RECEIVED = 1000; private class Nmea { long mTimestamp; String mNmea; Nmea(long timestamp, String nmea) { mTimestamp = timestamp; mNmea = nmea; } } private ArrayList<Nmea> mNmeaBuffer; GpsStatusListenerTransport(GpsStatus.Listener listener) { mListener = listener; mNmeaListener = null; } GpsStatusListenerTransport(GpsStatus.NmeaListener listener) { mNmeaListener = listener; mListener = null; mNmeaBuffer = new ArrayList<Nmea>(); } @Override public void onGpsStarted() { if (mListener != null) { Message msg = Message.obtain(); msg.what = GpsStatus.GPS_EVENT_STARTED; mGpsHandler.sendMessage(msg); } } @Override public void onGpsStopped() { if (mListener != null) { Message msg = Message.obtain(); msg.what = GpsStatus.GPS_EVENT_STOPPED; mGpsHandler.sendMessage(msg); } } @Override public void onFirstFix(int ttff) { if (mListener != null) { mGpsStatus.setTimeToFirstFix(ttff); Message msg = Message.obtain(); msg.what = GpsStatus.GPS_EVENT_FIRST_FIX; mGpsHandler.sendMessage(msg); } } @Override public void onSvStatusChanged(int svCount, int[] prns, float[] snrs, float[] elevations, float[] azimuths, int ephemerisMask, int almanacMask, int usedInFixMask) { if (mListener != null) { mGpsStatus.setStatus(svCount, prns, snrs, elevations, azimuths, ephemerisMask, almanacMask, usedInFixMask); Message msg = Message.obtain(); msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS; // remove any SV status messages already in the queue mGpsHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS); mGpsHandler.sendMessage(msg); } } @Override public void onNmeaReceived(long timestamp, String nmea) { if (mNmeaListener != null) { synchronized (mNmeaBuffer) { mNmeaBuffer.add(new Nmea(timestamp, nmea)); } Message msg = Message.obtain(); msg.what = NMEA_RECEIVED; // remove any NMEA_RECEIVED messages already in the queue mGpsHandler.removeMessages(NMEA_RECEIVED); mGpsHandler.sendMessage(msg); } } private final Handler mGpsHandler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == NMEA_RECEIVED) { synchronized (mNmeaBuffer) { int length = mNmeaBuffer.size(); for (int i = 0; i < length; i++) { Nmea nmea = mNmeaBuffer.get(i); mNmeaListener.onNmeaReceived(nmea.mTimestamp, nmea.mNmea); } mNmeaBuffer.clear(); } } else { // synchronize on mGpsStatus to ensure the data is copied atomically. synchronized(mGpsStatus) { mListener.onGpsStatusChanged(msg.what); } } } }; }
从上可知,Service调用IGpsStatusListener实际触发应用层调用了GpsStatus.Listener
五、对HAL层的操作
JNI层保留对HAL层操作的接口GpsInterface,对应的实例HAL层见loc_eng.cpp第97行:
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层为GpsLocationProvider.cpp中的sGpsInterface变量,
前面已经讲过了一个操作,即将JNI层回调接口传递到HAL层,用到其中的loc_eng_init函数
这里再分析一下loc_eng_start操作,其调用在GpsLocationProvider.cpp中第320行:
static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj) { if (sGpsInterface) return (sGpsInterface->start() == 0); else return false; }android_location_GpsLocationProvider_start对应JAVA函数native_start()在startNavigating()中被调用,
此函数在好几个地方有被调用,其中有setRequest()函数,在Service被requestLocationUpdates函数间接调用,
此函数应用层能通过进程间通讯调用,目的是注册位置通知的接收器,见LocationManager.java里的requestLocationUpdates函数