《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);
	......
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章