GPS系统
相关文件
// 应用层接口 frameworks/base/location/java/android/location/LocationManager.java frameworks/base/location/java/android/location/LocationProvider.java frameworks/base/location/java/android/location/Location.java frameworks/base/location/java/android/location/GpsStatus.java frameworks/base/location/java/android/location/GpsSatellite.java frameworks/base/location/java/android/location/Geocoder.java frameworks/base/location/java/android/location/Criteria.java frameworks/base/location/java/android/location/Address.java // Service frameworks/base/services/java/com/android/server/LocationManagerService.java frameworks/base/services/java/com/android/server/location/GpsLocationProvider.java frameworks/base/services/java/com/android/server/location/GpsXtraDownloader.java // JNI frameworks/base/services/jni/com_android_server_location_GpsLocationProvider.cpp // HAL hardware/libhardware/include/hardware/gps.h
架构描述
-
GPS在APP层的实现主要是android.location包,该包主要有以下几个类:
- LocationManager:Service的接口类,提供了功能接口。
- LocationProvider:获取GPS定位信息的抽象。
- Location:定位后的位置抽象,包括时间、速度、经纬度等信息。
- GpsStatus:GPS的状态抽象,可获得TTFF、卫星数等信息。
- GpsSatellite:卫星抽象,可获取卫星的相关数据。
- Geocoder:地址信息和经纬度转换的辅助类。
- Criteria:GPS的支持的一组标准,包括定位精度和信号强弱等规格。
- Address:符合eXtensible Address Language语法格式的地址信息。
-
GPS在Service层主要是由LocationManagerService实现,并包括几个辅助类:
- GpsLocationProvider:获取GPS定位信息的实现类,LocationProviderInterface接口的实现类之一。
- GpsXtraDownloader:下载GPS辅助数据的实现类。
- JNI提供了GPS功能在HAL层的实现接口,会被LocationProviderInterface接口调用(如GpsLocationProvider)。
- GPS HAL实现标准Android的HAL层模型,为JNI层提供了GPS定位的实现方法。
GPS管理类
- LocationManager为应用层提供操作接口,通过getSystemService(Context.LOCATION_SERVICE)方法获得。
- 该类的构造方法以ILocationManager接口为参数,因此可通过Binder与LocationManagerService的服务类交互。
LocationManager
public LocationManager(ILocationManager service) { mService = service; }
GPS信息的提供者
- 要使用GPS定位,首先要获取定位信息的提供者,它实际上是具体实现GPS功能的模块的抽象,称之为Provider。
- Provider在Service中注册,getProvider只是简单的获取对应name的Provider信息,并提供获取这些信息的接口。
- 其他相关方法还有getProviders、getAllProviders等等。
getProvider
public LocationProvider getProvider(String name) { ...... try { Bundle info = mService.getProviderInfo(name); if (info == null) { return null; } return createProvider(name, info); } catch (RemoteException ex) { } return null; }
注册定位信息的回调
-
ListenerTransport是一个内部类,它实际上是包装了应用层的LocationListener,并具有Binder通讯的功能。从它的静态变量定义来看,它支持4种类型的事件回调。
- TYPE_LOCATION_CHANGED:位置发生变化。
- TYPE_STATUS_CHANGED:状态发生变化。
- TYPE_PROVIDER_ENABLED:开启Provider。
- TYPE_PROVIDER_DISABLED:关闭Provider。
-
LocationManager.requestLocationUpdates向Service发送更新请求时,会创建ListenerTransport对象,并通过ILocationManager.requestLocationUpdates注册该回调,对于应用程序而言即注册
LocationListener
。
ListenerTransport
private class ListenerTransport extends ILocationListener.Stub { private static final int TYPE_LOCATION_CHANGED = 1; private static final int TYPE_STATUS_CHANGED = 2; private static final int TYPE_PROVIDER_ENABLED = 3; private static final int TYPE_PROVIDER_DISABLED = 4; ...... ListenerTransport(LocationListener listener, Looper looper) { mListener = listener; ...... } public void onLocationChanged(Location location) { ...... } public void onStatusChanged(String provider, int status, Bundle extras) { ...... } public void onProviderEnabled(String provider) { ...... } public void onProviderDisabled(String provider) { ...... } }
_requestLocationUpdates
private void _requestLocationUpdates(String provider, Criteria criteria, long minTime, float minDistance, boolean singleShot, LocationListener listener, Looper looper) { ...... try { synchronized (mListeners) { ListenerTransport transport = mListeners.get(listener); if (transport == null) { transport = new ListenerTransport(listener, looper); } mListeners.put(listener, transport); mService.requestLocationUpdates(provider, criteria, minTime, minDistance, singleShot, transport); } } catch (RemoteException ex) { } }
注册状态信息的回调
- GpsStatusListenerTransport是一个内部类,它除了封装了上层的GpsStatusListener外,同样具有Binder通讯功能。
-
它在接收到GPS状态改变时将该信息向上层传递,通过addGpsStatusListener方法注册给Service,对于应用程序而言,即GpsStatusListener。
- onGpsStarted:开启GPS时调用。
- onGpsStopped:关闭GPS时调用。
- onFirstFix:TTFF发生时调用。
- onSvStatusChanged:卫星状态变化时调用。
- onNmeaReceived:收到卫星的原始数据时调用。
- addGpsStatusListener方法会创建GpsStatusListenerTransport对象并调用ILocationManager的addGpsStatusListener注册给Service,同时保存在自己的HashMap中。
private ILocationManager mService; private final HashMap<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners = new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>(); private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners = new HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport>(); private final GpsStatus mGpsStatus = new GpsStatus();
GpsStatusListenerTransport
private class GpsStatusListenerTransport extends IGpsStatusListener.Stub { ...... private class Nmea { ...... } private ArrayList<Nmea> mNmeaBuffer; public void onGpsStarted() { ...... } public void onGpsStopped() { ...... } public void onFirstFix(int ttff) { ...... } public void onSvStatusChanged(int svCount, int[] prns, float[] snrs, float[] elevations, float[] azimuths, int ephemerisMask, int almanacMask, int usedInFixMask) { ...... } public void onNmeaReceived(long timestamp, String nmea) { ...... } }
addGpsStatusListener
public boolean addGpsStatusListener(GpsStatus.Listener listener) { boolean result; ...... try { GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener); result = mService.addGpsStatusListener(transport); if (result) { mGpsStatusListeners.put(listener, transport); } } catch (RemoteException e) { result = false; } return result; }
GPS Service
GPS Service是ILocationManager接口的服务端实现(使用Binder机制),LocationManager管理通常会通过 该Service发送跨进程的请求。
GPS信息的内容提供者
GPS的JNI层
- JNI层为GPS信息的内容提供者提供了访问HAL层的接口,主要定义了如下方法:
static JNINativeMethod sMethods[] = { {"class_init_native", "()V", ......}, {"native_is_supported", "()Z", ......}, {"native_init", "()Z", ......}, {"native_cleanup", "()V", ......}, {"native_set_position_mode", "(IIIII)Z", ......}, {"native_start", "()Z", ......}, {"native_stop", "()Z", ......}, {"native_delete_aiding_data", "(I)V", ......}, {"native_read_sv_status", "([I[F[F[F[I)I", ......}, {"native_read_nmea", "([BI)I", ......}, {"native_inject_time", "(JJI)V", ......}, {"native_inject_location", "(DDF)V", ......}, {"native_supports_xtra", "()Z", ......}, {"native_inject_xtra_data", "([BI)V", ......}, {"native_agps_data_conn_open", "(Ljava/lang/String;)V", ......}, {"native_agps_data_conn_closed", "()V", ......}, {"native_agps_data_conn_failed", "()V", ......}, {"native_agps_set_id","(ILjava/lang/String;)V", ......}, {"native_agps_set_ref_location_cellid","(IIIII)V", ......}, {"native_set_agps_server", "(ILjava/lang/String;I)V", ......}, {"native_send_ni_response", "(II)V", ......}, {"native_agps_ni_message", "([BI)V", ......}, {"native_get_internal_state", "()Ljava/lang/String;", ......}, {"native_update_network_state", "(ZIZLjava/lang/String;)V", ......}, };