《Android架构从入门到入土》之定位系统——GNSS框架

基本环境

  • 开发板:hikey960 (4G+32G版本)
  • 代码:aosp,android-10.0.0_r33
  • 开发环境:64bit ubuntu 16.04

演示场景

  自上而下分析定位系统。

一、GPS通信协议

GPS:定位系统
  gps芯片------串口-----soc
  读串口数据——nmea0183协议数据如下所示。

$GPGGA,235949.042,0000.0000,N,00000.0000,E,0,00,,0.0,M,0.0,M,,0000*45  
$GPGLL,0000.0000,N,00000.0000,E,235949.042,V,N*47  
$GPGSA,A,1,,,,,,,,,,,,,,,*1E  
$GPGSV,1,1,00*79  
$GPRMC,235949.042,V,0000.0000,N,00000.0000,E,,,140209,,,N*7E  
$GPVTG,,T,,M,,N,,K,N*2C  

例:$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1F

  • 字段0:$GPGGA,语句ID,表明该语句为Global Positioning System Fix Data(GGA)GPS定位信息
  • 字段1:UTC 时间,hhmmss.sss,时分秒格式
  • 字段2:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
  • 字段3:纬度N(北纬)或S(南纬)
  • 字段4:经度dddmm.mmmm,度分格式(前导位数不足则补0)
  • 字段5:经度E(东经)或W(西经)
  • 字段6:GPS状态,0=未定位,1=非差分定位,2=差分定位,3=无效PPS,6=正在估算
  • 字段7:正在使用的卫星数量(00 - 12)(前导位数不足则补0)
  • 字段8:HDOP水平精度因子(0.5 - 99.9)
  • 字段9:海拔高度(-9999.9 - 99999.9)
  • 字段10:地球椭球面相对大地水准面的高度
  • 字段11:差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空)
  • 字段12:差分站ID号0000 - 1023(前导位数不足则补0,如果不是差分定位将为空)
  • 字段13:校验值

二、app获取定位信息

使用定位服务的app如:百度地图,谷歌地图,各种软件。一般如下方式应用定位服务。

	Location location = null;
	
	// 获取LocationManager对象--连接服务
	LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);  
	
	location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
				|
				 return mService.getLastLocation(request, packageName);
	/* 获取经纬度 */
	location.getLongitude();
	location.getLatitude();  

三、封装AIDL接口和系统服务注册

frameworks/base/location/java/android/location/LocationManager.java封装aidl接口,在app中通过系统服务获取并调用。

public class LocationManager {
	private final ILocationManager mService; //ILocationManager就是一个aidl

	void removeGpsStatusListener(GpsStatus.Listener listener) {
		mService.removeGpsStatusListener(transport);//调用了aidl中接口
	}
	
	public boolean addNmeaListener(GpsStatus.NmeaListener listener){
		mService.addGpsStatusListener(transport, mContext.getPackageName());//调用了aidl中接口
	}
	
	public List<String> getAllProviders() {
		return mService.getAllProviders();   //调用了aidl中接口
	}

	public LocationManager(@NonNull Context context, @NonNull ILocationManager service) {
		mService = service;   // 构造函数通过参数初始化aidl接口服务变量
		.......
	}

  frameworks/base/core/java/android/app/SystemServiceRegistry.java 用 aidl 接口构造LocationManager 并注册成系统服务。

registerService(Context.LOCATION_SERVICE, LocationManager.class,
	new CachedServiceFetcher<LocationManager>() {
	@Override
	public LocationManager createService(ContextImpl ctx) throws ServiceNotFoundException {
		IBinder b = ServiceManager.getServiceOrThrow(Context.LOCATION_SERVICE);
		return new LocationManager(ctx, ILocationManager.Stub.asInterface(b));
	}});

四、AIDL接口

frameworks/base/location/java/android/location/ILocationManager.aidl

interface ILocationManager
{
	List<String> getAllProviders();
	List<String> getProviders(in Criteria criteria, boolean enabledOnly);
	String getBestProvider(in Criteria criteria, boolean enabledOnly);
	boolean providerMeetsCriteria(String provider, in Criteria criteria);
	 boolean addGpsStatusListener(IGpsStatusListener listener);
	void removeGpsStatusListener(IGpsStatusListener listener);
	...
}

五、实例化AIDL接口

  framework中为实例化AIDL接口实现了LocationmangerServiceGnssLocationProviderGnssStatusListenerHelper.java
  frameworks/base/services/core/java/com/android/server/LocationManagerService.java 实例化了 aidl接口。

public class LocationManagerService extends ILocationManager.Stub  {
	public boolean addGpsStatusListener(IGpsStatusListener listener) {//实现接口
		if (mGpsStatusProvider == null) {
			return false;
		}
	}

	private void _loadProvidersLocked() {
		// Attempt to load "real" providers first
		if (GpsLocationProvider.isSupported()) {
			......
		}
	}
	.......
}

frameworks/base/services/java/com/android/server/SystemServer.java中将定位服务加到 ServiceManager

public final class SystemServer {
	......
	private void startOtherServices() {
		......
		LocationManagerService location = null;
		......
		traceBeginAndSlog("StartLocationManagerService");                               
		try {                               
			location = new LocationManagerService(context);                               
			ServiceManager.addService(Context.LOCATION_SERVICE, location);                               
		} catch (Throwable e) {                               
			reportWtf("starting Location Manager", e);                               
		}                               
		traceEnd();
	}
}

frameworks/base/services/core/java/com/android/server/location/GnssLocationProvider.java中调用native接口。

public class GnssLocationProvider extends AbstractLocationProvider implements
		InjectNtpTimeCallback,
		GnssSatelliteBlacklistCallback {
	......
	static { class_init_native(); }//这个先执行
	private static native void class_init_native();
	private static native boolean native_is_supported();

	private native boolean native_init();
	private native void native_cleanup();
	private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
		int preferred_accuracy, int preferred_time);
	private native boolean native_start();
	private native boolean native_stop();

	public static boolean isSupported() {
		return native_is_supported();
	}
}

六、实现JNI调用HIDL HAL接口

frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp

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},
	......
}

static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
	android_location_GnssLocationProvider_set_gps_service_handle() {
		gnssHal_V2_0 = IGnss_V2_0::getService();
		if (gnssHal_V2_0 != nullptr) {
			gnssHal = gnssHal_V2_0;
			gnssHal_V1_1 = gnssHal_V2_0;
			return;
		}
	};
}

七、实现Gnss的HIDL HAL

hardware/interfaces/gnss/2.0/IGnss.hal

interface IGnss extends @1.1::IGnss {
	setCallback_2_0(IGnssCallback callback) generates (bool success);
	getExtensionGnssConfiguration_2_0() generates (IGnssConfiguration gnssConfigurationIface);
	getExtensionGnssDebug_2_0() generates (IGnssDebug gnssDebugIface);
	getExtensionAGnss_2_0() generates (IAGnss aGnssIface);
	......
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章