2022年androidGPS架构分析 .pdf
Android 系统 Gps分析1,GPS 架构:2,GPS 分析:2.1 头文件:头文件定 义在头文件定义在:hardware/libhardware/include/hardware/gps.h,定义了 GPS底层相关的结构体和接口:1,GpsLocation:GPS位置信息结构体,包含经度,纬度,高度,速度,方位角等.typedef struct /*set to sizeof(GpsLocation)*/size_t size;名师资料总结-精品资料欢迎下载-名师精心整理-第 1 页,共 23 页 -/*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.*/double altitude;/*Represents speed in meters per second.*/float speed;/*Represents heading in degrees.*/float bearing;/*Represents expected accuracy in meters.*/float accuracy;/*Timestamp for the location fix.*/GpsUtcTime timestamp;GpsLocation;2,GpsStatus:GPS状态包括5种状态,分别为未知,正在定位,停止定位,启动未定义,未启动。typedef struct /*set to sizeof(GpsStatus)*/size_t size;GpsStatusValue status;名师资料总结-精品资料欢迎下载-名师精心整理-第 2 页,共 23 页 -GpsStatus;3,GpsSvInfo:GPS卫星信息,包含卫星编号,信号强度,卫星仰望角,方位角等。typedef struct /*set to sizeof(GpsSvInfo)*/size_t size;/*Pseudo-random number for the SV.*/int prn;/*Signal to noise ratio.*/float snr;/*Elevation of SV in degrees.*/float elevation;/*Azimuth of SV in degrees.*/float azimuth;GpsSvInfo;4,GpsSvStatus:GPS卫星状态,包含可见卫星数和信息,星历时间,年历时间等。typedef struct /*set to sizeof(GpsSvStatus)*/size_t size;/*Number of SVs currently visible.*/int num_svs;/*Contains an array of SV information.*/名师资料总结-精品资料欢迎下载-名师精心整理-第 3 页,共 23 页 -GpsSvInfo sv_listGPS_MAX_SVS;/*Represents a bit mask indicating which SVs *have ephemeris data.*/uint32_t ephemeris_mask;/*Represents a bit mask indicating which SVs *have almanac data.*/uint32_t almanac_mask;/*Represents a bit mask indicating which SVs *were used for computing the most recent position fix.*/uint32_t used_in_fix_mask;GpsSvStatus;5,GpsCallbacks:/*Callback with location information.*Can only be called from a thread created by create_thread_cb.*/typedef void(*gps_location_callback)(GpsLocation*location);/向上层传递GPS位置信息名师资料总结-精品资料欢迎下载-名师精心整理-第 4 页,共 23 页 -/*Callback with status information.*Can only be called from a thread created by create_thread_cb.*/typedef void(*gps_status_callback)(GpsStatus*status);/向上层传递GPS状态信息/*Callback with SV status information.*Can only be called from a thread created by create_thread_cb.*/typedef void(*gps_sv_status_callback)(GpsSvStatus*sv_info);/向上层传递GPS卫星信息/*Callback for reporting NMEA sentences.*Can only be called from a thread created by create_thread_cb.*/typedef void(*gps_nmea_callback)(GpsUtcTime timestamp,const char*nmea,int length);/向上层传递NMEA数据/*Callback to inform framework of the GPS engines capabilities.*Capability parameter is a bit field of GPS_CAPABILITY_*flags.*/typedef void(*gps_set_capabilities)(uint32_t capabilities);/告知GPS模块可以实现的功能/*Callback utility for acquiring the GPS wakelock.名师资料总结-精品资料欢迎下载-名师精心整理-第 5 页,共 23 页 -*This can be used to prevent the CPU from suspending while handling GPS events.*/typedef void(*gps_acquire_wakelock)();/上锁,防止处理GPS时间时终止/*Callback utility for releasing the GPS wakelock.*/typedef void(*gps_release_wakelock)();/释放锁/*Callback for creating a thread that can call into the Java framework code.*This must be used to create any threads that report events up to the framework.*/typedef pthread_t(*gps_create_thread)(const char*name,void(*start)(void*),void*arg);/等待上层请求/*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;名师资料总结-精品资料欢迎下载-名师精心整理-第 6 页,共 23 页 -gps_release_wakelock release_wakelock_cb;gps_create_thread create_thread_cb;GpsCallbacks;6,GpsInterface:GPS最重要的结构体,上层通过次接口与硬件适配层交互的。/*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);/关闭GPS接口名师资料总结-精品资料欢迎下载-名师精心整理-第 7 页,共 23 页 -/*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.*/名师资料总结-精品资料欢迎下载-名师精心整理-第 8 页,共 23 页 -int (*set_position_mode)(GpsPositionMode mode,GpsPositionRecurrence recurrence,uint32_t min_interval,uint32_t preferred_accuracy,uint32_t preferred_time);/设置定位模式和GPS工作模式等 /*Get a pointer to extension information.*/const void*(*get_extension)(const char*name);/自定义的接口 GpsInterface;7,gps_device_t:GPS设备结构体,向上层提供了重要的get_gps_interface 接口struct gps_device_t struct hw_device_t common;/*Set the provided lights to the provided values.*Returns:0 on succes,error code on failure.*/const GpsInterface*(*get_gps_interface)(struct gps_device_t*dev);2,2硬件适配层:broadcom GPS硬件适配层的源码位于:/home/ls/Broadcom21553/hardware/broadcom/gps/allPartners/deliverables/middleware_connectors/unix/Android/gps_jni目录下。在gps_lcsapi.c中,定义了gps设备模块实例:const struct hw_module_t HAL_MODULE_INFO_SYM=名师资料总结-精品资料欢迎下载-名师精心整理-第 9 页,共 23 页 -.tag=HARDWARE_MODULE_TAG,.version_major=1,.version_minor=0,.id=GPS_HARDWARE_MODULE_ID,/JNI层从这个ID来调用HAL层接口 .name=lcsapi GPS Module,.author=Broadcom Corporation,.methods=&hw_module_methods,;这里的methods指向该文件中的hw_module_methods static struct hw_module_methods_t hw_module_methods=.open=open_gps;再看open_gps.static int open_gps(const struct hw_module_t*module,char const*name,struct hw_device_t*device)LOGD(*%s*start!n,_func_);struct gps_device_t*gps_device=malloc(sizeof(struct gps_device_t);if(gps_device)memset(gps_device,0,sizeof(struct gps_device_t);gps_device-common.tag =HARDWARE_DEVICE_TAG;gps_device-common.version =0;名师资料总结-精品资料欢迎下载-名师精心整理-第 10 页,共 23 页 -gps_device-common.module =(struct hw_module_t*)module;gps_device-get_gps_interface=gps_get_hardware_interface;*device=(struct hw_device_t*)gps_device;return 0;return 1;LOGD(*%s*done!n,_func_);此处可以看作是GPS设备的初始化函数,在使用设备前必须执行此函数。函数里面指定了hw_device_t 的module成员,以及gps_device_t的get_gps_interface成员。上层可以通过gps_device_t的get_gps_interface调用gps_get_hardware_interface。gps_get_hardware_interface的定义如下:#ifdef GPS_AS_MODULE const GpsInterface*gps_get_hardware_interface(struct gps_device_t*dev)#else const GpsInterface*gps_get_hardware_interface(void)#endif LOGD(*%s*start!n,_func_);return&_GpsInterface;LOGD(*%s*done!n,_func_);名师资料总结-精品资料欢迎下载-名师精心整理-第 11 页,共 23 页 -2,2,JNI适配层:源码位于:/home/ls/Broadcom21553/frameworks/base/services/jni/com_android_server_location_GpsLocationProvider.cpp 首先看注册JNI方法的函数定义:int register_android_server_location_GpsLocationProvider(JNIEnv*env)return jniRegisterNativeMethods(env,com/android/server/location/GpsLocationProvider,sMethods,NELEM(sMethods);这个函数被同目录下的onload.cpp文件调用,调用地方在:extern C jint JNI_OnLoad(JavaVM*vm,void*reserved)JNIEnv*env=NULL;jint result=-1;if(vm-GetEnv(void*)&env,JNI_VERSION_1_4)!=JNI_OK)LOGE(GetEnv failed!);return result;LOG_ASSERT(env,Could not retrieve the env!);。register_android_server_location_GpsLocationProvider(env);名师资料总结-精品资料欢迎下载-名师精心整理-第 12 页,共 23 页 -return JNI_VERSION_1_4;从这里可以看到,JNI初始化的时候,即会进行JNI方法的注册,从而使上层应用能通过JNI调用c/c+本地方法。回到 register_android_server_location_GpsLocationProvider函数,变量sMethods 定义如下:static JNINativeMethod sMethods=/*name,signature,funcPtr*/class_init_native,()V,(void*)android_location_GpsLocationProvider_class_init_native,native_is_supported,()Z,(void*)android_location_GpsLocationProvider_is_supported,native_init,()Z,(void*)android_location_GpsLocationProvider_init,native_cleanup,()V,(void*)android_location_GpsLocationProvider_cleanup,native_set_position_mode,(IIIII)Z,(void*)android_location_GpsLocationProvider_set_position_mode,native_start,()Z,(void*)android_location_GpsLocationProvider_start,native_stop,()Z,(void*)android_location_GpsLocationProvider_stop,native_delete_aiding_data,(I)V,(void*)android_location_GpsLocationProvider_delete_aiding_data,native_read_sv_status,(IFFFI)I,(void*)android_location_GpsLocationProvider_read_sv_status,native_read_nmea,(BI)I,(void*)android_location_GpsLocationProvider_read_nmea,native_inject_time,(JJI)V,(void*)android_location_GpsLocationProvider_inject_time,native_inject_location,(DDF)V,(void*)android_location_GpsLocationProvider_inject_location,名师资料总结-精品资料欢迎下载-名师精心整理-第 13 页,共 23 页 -native_supports_xtra,()Z,(void*)android_location_GpsLocationProvider_supports_xtra,native_inject_xtra_data,(BI)V,(void*)android_location_GpsLocationProvider_inject_xtra_data,native_agps_data_conn_open,(Ljava/lang/String;)V,(void*)android_location_GpsLocationProvider_agps_data_conn_open,native_agps_data_conn_closed,()V,(void*)android_location_GpsLocationProvider_agps_data_conn_closed,native_agps_data_conn_failed,()V,(void*)android_location_GpsLocationProvider_agps_data_conn_failed,native_agps_set_id,(ILjava/lang/String;)V,(void*)android_location_GpsLocationProvider_agps_set_id,native_agps_set_ref_location_cellid,(IIIII)V,(void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid,native_set_agps_server,(ILjava/lang/String;I)V,(void*)android_location_GpsLocationProvider_set_agps_server,native_send_ni_response,(II)V,(void*)android_location_GpsLocationProvider_send_ni_response,native_agps_ni_message,(BI)V,(void*)android_location_GpsLocationProvider_agps_send_ni_message,native_get_internal_state,()Ljava/lang/String;,(void*)android_location_GpsLocationProvider_get_internal_state,native_update_network_state,(ZIZLjava/lang/String;)V,(void*)android_location_GpsLocationProvider_update_network_state,;这里定义了GPS所有向上层提供的JNI本地方法,这些本地方法是如何与硬件适配层交互的呢?我们看其中一个本地方法android_location_GpsLocationProvider_start static jboolean android_location_GpsLocationProvider_start(JNIEnv*env,jobject 名师资料总结-精品资料欢迎下载-名师精心整理-第 14 页,共 23 页 -obj)if(sGpsInterface)return(sGpsInterface-start()=0);else return false;这个sGpsInterface在android_location_GpsLocationProvider_class_init_native(JNIEnv*env,jclass clazz)函数中调用sGpsInterface=gps_device-get_gps_interface(gps_device);生成。2,3 JAVA Framework 该层的源码位于:/home/ls/Broadcom21553/frameworks/base/location下面:2,3,1接口和类简介:首先对GPS Framework重要的接口和类做一个简单的介绍:接口:GpsStatus.Listener:用于当Gps状态发生变化时接收通知GpsStatus.NmeaListener:用于接收Gps的NMEA数据LocationListener:用于接收当位置信息发生变化时,LocationManager发出的通知类:Address:地址信息类Criteria:用于根据设备情况动态选择provider。Geocoder:用于处理地理编码信息GpsSatellite:用于获取当前卫星状态GpsStatus:用于获取当前Gps状态Location:地理位置信息类LocationManager:用于获取和操作gps系统服务LocationProvider:抽象类,用于提供位置提供者2,3.2 使用Gps编程接口:下面用一个代码示例说明如何在应用层写一个简单的gps程序:1,首先在AndroidManifest.xml中增加位置服务权限:名师资料总结-精品资料欢迎下载-名师精心整理-第 15 页,共 23 页 -2,接着获取位置信息:/获取位置服务 LocationManager locationManager=(LocationManager)getSystemService(Context.LOCATION_SERVICE);Criteria criteria=new Criteria();/获得最好的定位效果 criteria.setAccuracy(Criteria.ACCURACY_FINE);/设置为最大精度 criteria.setAltitudeRequired(false);/不获取海拔信息 criteria.setBearingRequired(false);/不获取方位信息 criteria.setCostAllowed(false);/是否允许付费 criteria.setPowerRequirement(Criteria.POWER_LOW);/使用省电模式 /获得当前的位置提供者 String provider=locationManager.getBestProvider(criteria,true);/获得当前的位置 Location location=locationManager.getLastKnownLocation(provider);Geocoder gc=new Geocoder(this);List addresses=null;try /根据经纬度获得地址信息 addresses=gc.getFromLocation(location.getLatitude(),location.getLongitude(),1);catch(IOException e)e.printStackTrace();if(addresses.size()0)/获取address类的成员信息Sring msg=“”;msg+=AddressLine:+addresses.get(0).getAddressLine(0)+n;msg+=CountryName:+addresses.get(0).getCountryName()+n;msg+=Locality:+addresses.get(0).getLocality()+n;msg+=FeatureName:+addresses.get(0).getFeatureName();3,设置帧听,当位置信息发生变化时,自动更新相关信息:/匿名类,继承自LocationListener接口private final LocationListener locationListener=new LocationListener()public void onLocationChanged(Location location)updateWithNewLocation(location);/更新位置信息 public void onProviderDisabled(String provider)updateWithNewLocation(null);/更新位置信息 public void onProviderEnabled(String provider)public void onStatusChanged(String provider,int status,Bundle 名师资料总结-精品资料欢迎下载-名师精心整理-第 16 页,共 23 页 -extras);/更新位置信息private void updateWithNewLocation(Location location)if(location!=null)/获取经纬度 double lat=location.getLatitude();double lng=location.getLongitude();/添加侦听 locationManager.requestLocationUpdates(provider,2000,10,locationListener);2,3.3接口和类分析:LocationManger的代码文件位于/home/ls/Broadcom21553/frameworks/base/location/java/android/location/LocationManager.java 我们看其构造函数:public LocationManager(ILocationManager service)mService=service;其中mService为ILoctionManager接口类型,其构造函数的参数为service,外部调用时传入LocationManager Service示例。一般由getSystemService获得LocationManagerService服务,再强制转换为LocationManager。如上面代码示例:LocationManager locationManager=(LocationManager)getSystemService(Context.LOCATION_SERVICE);/就是这样获取gps服务的。这里的这里的Context.LOCATION_SERVICE为”location”,标识 gps 服务LocationManagerService服务是整个GpsFramework的核心,首先看它是如何被加载的,代码位于:/home/ls/Broadcom21553/frameworks/base/services/java/com/android/server/SystemServer.java/省略其他代码LocationManagerService location=null;/省略其他代码try Slog.i(TAG,Location Manager);location=new LocationManagerService(context);名师资料总结-精品资料欢迎下载-名师精心整理-第 17 页,共 23 页 -ServiceManager.addService(Context.LOCATION_SERVICE,location);catch(Throwable e)Slog.e(TAG,Failure starting Location Manager,e);此处向SystemManager系统服务管理器注册了新的服务,其名称为“location”,类型为LocationManagerService。注册此服务后,Java应用程序就可以通过ServiceManager获得LocationManagerService的代理接口ILocationManager.Stub,从而调用LocationManagerServce提供的接口函数。IlocationManager位于:/home/ls/Broadcom21553/frameworks/base/location/java/android/location/ILocationManager.aidl /*System private API for talking with the location service.*hide */interface ILocationManager List getAllProviders();List getProviders(in Criteria criteria,boolean enabledOnly);String getBestProvider(in Criteria criteria,boolean enabledOnly);boolean providerMeetsCriteria(String provider,in Criteria criteria);void requestLocationUpdates(String provider,in Criteria criteria,long minTime,float minDistance,boolean singleShot,in ILocationListener listener);void requestLocationUpdatesPI(String provider,in Criteria criteria,long minTime,float minDistance,boolean singleShot,in PendingIntent intent);void removeUpdates(in ILocationListener listener);void removeUpdatesPI(in PendingIntent intent);boolean addGpsStatusListener(IGpsStatusListener listener);void removeGpsStatusListener(IGpsStatusListener listener);/for reporting callback completion void locationCallbackFinished(ILocationListener listener);boolean sendExt