目錄
基本環境
- 開發板: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接口實現了LocationmangerService
、GnssLocationProvider
、GnssStatusListenerHelper.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);
......
}