目录
基本环境
- 开发板: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);
......
}