http://fancyerii.github.io/2020/04/06/gps/
信噪比,英文名称叫做SNR或S/N(SIGNAL-NOISE RATIO),又称为讯噪比。
是指一个电子设备或者电子系统中信号与噪声的比例 , 信噪比越大此颗卫星越有效(也就是说可以定位)
伪随机噪声(PRN)码: 用于表示卫星相关的信息
TTFF
Time to first fix (TTFF) is a measure of the time required for a GPS navigation device to acquire satellite signals and navigation data, and calculate a position solution (called a fix).
历书Almanac:
历书仅提供基本轨道参数,精度低,可用于接收机快速捕捉卫星和预报,包括全部卫星的大概位置,用于卫星预报
星历:
含基本轨道参数及摄动改正量,由其确定的卫星位置精度高,可用于定位计算, 只是当前接收机观测到的卫星的精确位置,用于定位
最后我们简单的介绍一下A-GPS,了解一下加快GPS接收器启动速度的方法。
市场上结合了移动无线功能和卫星导航功能(如GPS)的设备数量在不断增加。这种组合通常用于基于位置的服务(LBS)。可以说这些设备并非总处于工作状态,尤其是定位通过GPS完成时更是如此,原因在于GPS接收机的功耗限制了电池工作时间。
由于GPS设备很少工作,它有可能没有关于卫星位置的信息。在停用2h或更长的时间后,为能开始工作它必须首先下载卫星的轨道数据。GPS接收机获取轨道数据并计算出首次位置一般至少需要18~36s的时间(该时间称为首次定位时间:TTFF)。在不利的接收条件下(例如,城区高层建筑妨碍了对天空的直视时),可能需要数分钟才能完成首次位置的计算。启动慢是GPS固有的限制,无法通过改进接收机技术来克服。
当缺少轨道数据时,GPS接收机必须执行一次完整的搜索过程,以便找到可用的卫星、下载数据和计算位置。在编码-频率域内对大约30颗GPS卫星进行搜索非常耗时,编码-频率域每级的积分时间通常至少需要1ms(1个C/A码周期)。如果将频率范围按50Hz的步长划分(即频率间隔为2×6000/50Hz=240Hz),则需要对多达1023×50=51150个位置(bins)进行搜索(需要51s)。
在信号较弱时可通过提供额外的卫星轨道数据和其他GPS信息来快速定位和测量。这些信息可通过其他信道获得,例如通过GSM、GPRS、CDMA或UMTS。这一应用称作辅助服务,并用于辅助GPS(A-GPS或AGPS)。A-GPS是一种使用辅助数据来加速定位的功能或服务。GPS接收机通过移动通信网络或直接经互联网获得辅助数据。辅助数据中包含以下信息:
通过使用这些辅助数据,即便在不利的信号条件下GPS接收机也能够迅速定位。在弱信号条件下,这通常是获取定位的唯一途径。取决于辅助数据的复杂性和完整性,启动时间可能会显著缩短。剩余的启动时间取决于GPS信号的强度。通常辅助信息的可用性和精度越高,启动时间就越短。
集成了GPS设备的移动台仍需至少能看到4颗卫星。使用A-GPS时,GPS接收机需要一个用于接收辅助数据的接口。通过减少轨道数据的接收时间从而最大程度节省了启动时间。因为我们的手机通常会同时有无线网络和GPS,因此它的启动速度比纯GPS设备快。
描述android java层怎样获得定位数据
https://www.runoob.com/w3cnote/android-tutorial-gps.html
以 RequestLocationUpdates GPS的代码流程为例,展示下Location的代码框架
aidl定义的是client 和 service间数据交换的格式包括接口和数据结构,Location相关的aidl文件很多,代码位于
frameworks/base/location/java/android/location/
这里重点关注:
oneway interface ILocationListener
{
@UnsupportedAppUsage
void onLocationChanged(in Location location);
@UnsupportedAppUsage
void onProviderEnabled(String provider);
@UnsupportedAppUsage
void onProviderDisabled(String provider);
// --- deprecated ---
@UnsupportedAppUsage
void onStatusChanged(String provider, int status, in Bundle extras);
}
parcelable Location;
/**
* System private API for talking with the location service.
*
* @hide
*/
interface ILocationManager
{
void requestLocationUpdates(in LocationRequest request, in ILocationListener listener,
in PendingIntent intent, String packageName);
}
LocationManager lManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
/*问什么getSystemService("location")返回的是LocationManager,难道和
@SystemService(Context.LOCATION_SERVICE) 这句话有关系?
*/
frameworks/base/location/java/android/location/LocationManager.java
/**
* This class provides access to the system location services. These
* services allow applications to obtain periodic updates of the
* device's geographical location, or to fire an application-specified
* {@link Intent} when the device enters the proximity of a given
* geographical location.
*/
@SystemService(Context.LOCATION_SERVICE)
@RequiresFeature(PackageManager.FEATURE_LOCATION)
public class LocationManager {
//构造函数得到mService: location的代理,??
public LocationManager(@NonNull Context context, @NonNull ILocationManager service) {
mService = service;
}
private void requestLocationUpdates(LocationRequest request, LocationListener listener,
Looper looper, PendingIntent intent) {
android.util.SeempLog.record(47);
String packageName = mContext.getPackageName();
// wrap the listener class
ListenerTransport transport = wrapListener(listener, looper);
//通过mService调用service
mService.requestLocationUpdates(request, transport, intent, packageName);
}
}
frameworks/base/services/core/java/com/android/server/LocationManagerService.java
frameworks/base/services/core/java/com/android/server/location/
/**
* The service class that manages LocationProviders and issues location
* updates and alerts.
*/
public class LocationManagerService extends ILocationManager.Stub {
}
public void
requestLocationUpdates(LocationRequest request, ILocationListener listener, PendingIntent intent, String packageName)
requestLocationUpdatesLocked(LocationRequest request, Receiver receiver, int uid, String packageName)
applyRequirementsLocked(String providerName)
applyRequirementsLocked(LocationProvider provider)
provider.setRequestLocked(providerRequest, worksource);
setRequest(ProviderRequest request, WorkSource source)
sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
handleMessage(Message msg)
handleSetRequest(gpsRequest.request, gpsRequest.source);[SET_REQUEST]
updateEnabled();
native_init();
updateRequirements();
startNavigating()
setPositionMode
native_set_position_mode
gnssHal_V1_1->setPositionMode_1_1
jni层
frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
//location service层的所有jni实现都是在这个文件,名字可能有点怪
using IGnss_V2_0 = android::hardware::gnss::V2_0::IGnss;
/* Initializes the GNSS service handle. */
static void android_location_GnssLocationProvider_set_gps_service_handle() {
gnssHal_V2_0 = IGnss_V2_0::getService();// 得到了hidl service的代理,通过gnssHal_V2_0访问hidl service
if (gnssHal_V2_0 != nullptr) {
gnssHal = gnssHal_V2_0;
gnssHal_V1_1 = gnssHal_V2_0;
return;
}
}
HIDL hal: jni层通过getService得到 对应hidl service 的代理接口,jni层通过返回的gnssHal_V2_0和hidl service通信;
hidl hal有两个易混淆的宏:
LOC_HIDL_VERSION=3.0
hardware/qcom/gps/android/Android.mk: GNSS_HIDL_VERSION=2.0
vendor/qcom/proprietary/gps-release/gps_vendor_product.mk: LOC_HIDL_VERSION = 3.0
代码路径: 接口的service实现在hardware/qcom/gps/xxx路径下
hardware/interfaces/gnss
hardware/interfaces/gnss/1.0/IGnss.hal
还有一部分接口在:接口的实现在vendor/qcom/proprietary/gps/路径下
vendor/qcom/proprietary/interfaces/gnss/
package [email protected];
import [email protected];
interface ILocHidlGnss extends IGnss { //继承[email protected]
}
/**
* Sets the GnssPositionMode parameter,its associated recurrence value,
* the time between fixes,requested fix accuracy and time to first fix.
*
* @param mode Parameter must be one of MS_BASED or STANDALONE.
* It is allowed by the platform (and it is recommended) to fallback to
* MS_BASED if MS_ASSISTED is passed in, and MS_BASED is supported.
* @recurrence GNSS position recurrence value, either periodic or single.
* @param minIntervalMs Represents the time between fixes in milliseconds.
* @param preferredAccuracyMeters Represents the requested fix accuracy in meters.
* @param preferredTimeMs Represents the requested time to first fix in milliseconds.
* @return success Returns true if successful.
*/
setPositionMode(GnssPositionMode mode, GnssPositionRecurrence recurrence,
uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
uint32_t preferredTimeMs)
generates (bool success);
hardware/qcom/gps/android/2.0/Gnss.cpp
Return
V1_0::IGnss::GnssPositionRecurrence recurrence,
uint32_t minIntervalMs,
uint32_t preferredAccuracyMeters,
uint32_t preferredTimeMs,
bool lowPowerMode) {
ENTRY_LOG_CALLFLOW();
bool retVal = false;
GnssAPIClient* api = getApi();
if (api) {
GnssPowerMode powerMode = lowPowerMode?
GNSS_POWER_MODE_M4 : GNSS_POWER_MODE_M2;
retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs,
preferredAccuracyMeters, preferredTimeMs, powerMode, minIntervalMs);
}
return retVal;
}
bool
GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode,
IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs,
uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs,
GnssPowerMode powerMode, uint32_t timeBetweenMeasurement)
locAPIUpdateTrackingOptions(mTrackingOptions);
void LocationAPIClientBase::locAPIUpdateTrackingOptions(TrackingOptions& options)
{
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
uint32_t session = 0;
session = mRequestQueues[REQUEST_TRACKING].getSession();
if (session > 0) {
mRequestQueues[REQUEST_TRACKING].push(new UpdateTrackingOptionsRequest(*this));
mLocationAPI->updateTrackingOptions(session, options);
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
}
}
pthread_mutex_unlock(&mMutex);
}
mLocationAPI->updateTrackingOptions(session, options);
static void updateTrackingOptions(
LocationAPI* client, uint32_t id, TrackingOptions& trackingOptions)
{
if (NULL != gGnssAdapter) {
gGnssAdapter->updateTrackingOptionsCommand(
client, id, trackingOptions);
}
}
hardware/qcom/gps/gnss/GnssAdapter.cpp
void
GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
TrackingOptions& options)
{
LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
__func__, client, id, options.minInterval, options.mode);
mApi.startDistanceBasedTracking(mSessionId, mOptions,
new LocApiResponse(*mAdapter.getContext(),
[] (LocationError /*err*/) {}));
或者
startTimeBasedTracking;
}
// 不管是startDistanceBasedTracking 还是 startTimeBasedTracking,最终都会调到:
vendor/qcom/opensource/location/loc_api/loc_api_v02/LocApiV02.cpp
vendor/qcom/opensource/location/loc_api/loc_api_v02/loc_api_v02_client.c
/*
@brief Sends a message to the location engine. If the locClientSendMsg()
function is successful, the client should expect an indication
(except start, stop, event reg and sensor injection messages),
through the registered callback in the locOpen() function. The
indication will contain the status of the request and if status is a
success, indication also contains the payload
associated with response.
*/
locClientStatusEnumType locClientSendReq(
locClientHandleType handle,
uint32_t reqId,
locClientReqUnionType reqPayload )
{
qmi_client_send_msg_sync(
pCallbackData->userHandle,
reqId,
pReqData,
reqLen,
&resp,
sizeof(resp),
LOC_CLIENT_ACK_TIMEOUT);
LOC_LOGv("qmi_client_send_msg_sync returned %d", rc);
}
描述定位数据如何上传到Android Java level的。
//vendor/qcom/opensource/location/loc_api/loc_api_v02/LocApiV02.cpp
/* static event callbacks that call the LocApiV02 callbacks*/
/* global event callback, call the eventCb function in loc api adapter v02
instance */
static void globalEventCb(locClientHandleType clientHandle,
uint32_t eventId,
const locClientEventIndUnionType eventPayload,
void* pClientCookie)
{
switch (eventId) {
case QMI_LOC_EVENT_POSITION_REPORT_IND_V02:
LocApiV02 *locApiV02Instance = (LocApiV02 *)pClientCookie;
LOC_LOGv ("client = %p, event id = 0x%X, client cookie ptr = %p",
clientHandle, eventId, pClientCookie);
locApiV02Instance->eventCb(clientHandle, eventId, eventPayload);
}
hardware/qcom/gps/gnss/GnssAdapter.cpp
// prepare the callback functions
// callback function for engine hub to report back position event
GnssAdapterReportEnginePositionsEventCb reportPositionEventCb =
[this](int count, EngineLocationInfo* locationArr) {
// report from engine hub on behalf of PPE will be treated as fromUlp
reportEnginePositionsEvent(count, locationArr);
};
reportEnginePositionsEvent
reportEnginePositions
hardware/qcom/gps/android/1.0/location_api/GnssAPIClient.cpp
void GnssAPIClient::onTrackingCb(Location location)
{
LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags);
mMutex.lock();
auto gnssCbIface(mGnssCbIface);
mMutex.unlock();
if (gnssCbIface != nullptr) {
GnssLocation gnssLocation;
convertGnssLocation(location, gnssLocation);
auto r = gnssCbIface->gnssLocationCb(gnssLocation);
}
}
frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
template
Return
JNIEnv* env = getJniEnv();
jobject jLocation = translateGnssLocation(env, location);
env->CallVoidMethod(mCallbacksObj,
method_reportLocation,
boolToJbool(hasLatLong(location)),
jLocation);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
env->DeleteLocalRef(jLocation);
return Void();
}
Return
return gnssLocationCbImpl
}
Return
GnssCallback::gnssLocationCb_2_0(const GnssLocation_V2_0& location) {
return gnssLocationCbImpl
}
@NativeEntryPoint
private void reportLocation(boolean hasLatLong, Location location) {
sendMessage(REPORT_LOCATION, hasLatLong ? 1 : 0, location);
}
private void handleReportLocation(boolean hasLatLong, Location location) {
if (VERBOSE) Log.v(TAG, "reportLocation " + location.toString());
reportLocation(...);
}
/**
* Call this method to report a new location. May be called from any thread.
*/
protected void reportLocation(Location location) {
mLocationProviderManager.onReportLocation(location);
}
//frameworks/base/services/core/java/com/android/server/LocationManagerService.java
//发送到client
@Override
public void onReportLocation(Location location) {
// no security check necessary because this is coming from an internal-only interface
// move calls coming from below LMS onto a different thread to avoid deadlock
mHandler.post(() -> {
synchronized (mLock) {
handleLocationChangedLocked(location, this);
}
});
}
大概意思作为QMI-loc service (提供定位信息)注册到QCSI框架 .
hal层的框架发展为hidl hal, 以前的文档可能是之前的架构,需要注意
https://www.ibm.com/developerworks/cn/opensource/os-cn-android-location/index.html
Android 系统中 Location Service 的实现与架构
http://zenki2001cn.github.io/Wiki/Android/GPS%E7%B3%BB%E7%BB%9F.html#toc_1
http://zenki2001cn.github.io/Wiki/Android/GPS%E4%BF%A1%E6%81%AF%E7%9A%84%E5%86%85%E5%AE%B9%E6%8F%90%E4%BE%9B%E8%80%85.html
http://zenki2001cn.github.io/Wiki/Android/GPS%E6%9C%8D%E5%8A%A1.html
http://zenki2001cn.github.io/Wiki/Android/GPS%E7%9A%84HAL%E5%B1%82.html