Adding ATL call flow to new Loc API interface

Re-designed the ATL call flow, to fit along with
updated Location API.

Change-Id: If22e672d1c233c55b6b52107be7169b3036d9a3e
CRs-fixed: 1112712
This commit is contained in:
Saurabh Srivastava 2017-02-03 00:46:48 +05:30 committed by Gerrit - the friendly Code Review server
parent 52b413eb44
commit 5fecc1979b
9 changed files with 1879 additions and 16 deletions

View file

@ -23,6 +23,7 @@
#include <log_util.h>
#include "Gnss.h"
#include "AGnss.h"
#include <gps_extended_c.h>
namespace android {
namespace hardware {
@ -30,9 +31,73 @@ namespace gnss {
namespace V1_0 {
namespace implementation {
sp<IAGnssCallback> AGnss::sAGnssCbIface = nullptr;
AGnss::AGnss(Gnss* gnss) : mGnss(gnss) {
}
void AGnss::agnssStatusIpV4Cb(IAGnssCallback::AGnssStatusIpV4 status){
sAGnssCbIface->agnssStatusIpV4Cb(status);
}
Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
LOC_LOGE("Null GNSS interface");
return Void();
}
// Save the interface
sAGnssCbIface = callback;
mGnss->getGnssInterface()->agpsInit((void*)agnssStatusIpV4Cb);
return Void();
}
Return<bool> AGnss::dataConnClosed() {
if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
LOC_LOGE("Null GNSS interface");
return false;
}
mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL);
return true;
}
Return<bool> AGnss::dataConnFailed() {
if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
LOC_LOGE("Null GNSS interface");
return false;
}
mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL);
return true;
}
Return<bool> AGnss::dataConnOpen(const hidl_string& apn,
IAGnss::ApnIpType apnIpType) {
if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){
LOC_LOGE("Null GNSS interface");
return false;
}
/* Validate */
if(apn.empty()){
LOC_LOGE("Invalid APN");
return false;
}
LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str());
mGnss->getGnssInterface()->agpsDataConnOpen(
LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)apnIpType);
return true;
}
Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
const hidl_string& hostname,
int32_t port) {

View file

@ -40,35 +40,31 @@ using ::android::sp;
struct Gnss;
struct AGnss : public IAGnss {
AGnss(Gnss* gnss);
~AGnss() = default;
/*
* Methods from ::android::hardware::gnss::V1_0::IAGnss interface follow.
* These declarations were generated from IAGnss.hal.
*/
inline Return<void> setCallback(const sp<IAGnssCallback>& /*callback*/) override {
return Void();
}
Return<void> setCallback(const sp<IAGnssCallback>& callback) override;
inline Return<bool> dataConnClosed() override {
return false;
}
Return<bool> dataConnClosed() override;
inline Return<bool> dataConnFailed() override {
return false;
}
Return<bool> dataConnFailed() override;
inline Return<bool> dataConnOpen(const hidl_string& /*apn*/,
IAGnss::ApnIpType /*apnIpType*/) override {
return false;
}
Return<bool> dataConnOpen(const hidl_string& apn,
IAGnss::ApnIpType apnIpType) override;
Return<bool> setServer(IAGnssCallback::AGnssType type,
const hidl_string& hostname, int32_t port) override;
/* Data call setup callback passed down to GNSS HAL implementation */
static void agnssStatusIpV4Cb(IAGnssCallback::AGnssStatusIpV4 status);
private:
Gnss* mGnss = nullptr;
static sp<IAGnssCallback> sAGnssCbIface;
};
} // namespace implementation

963
gnss/Agps.cpp Normal file
View file

@ -0,0 +1,963 @@
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define LOG_TAG "LocSvc_Agps"
#include <Agps.h>
#include <platform_lib_includes.h>
#include <ContextBase.h>
#include <loc_timer.h>
/* --------------------------------------------------------------------
* AGPS State Machine Methods
* -------------------------------------------------------------------*/
void AgpsStateMachine::processAgpsEvent(AgpsEvent event){
LOC_LOGD("processAgpsEvent(): SM %p, Event %d, State %d",
this, event, mState);
switch (event){
case AGPS_EVENT_SUBSCRIBE:
processAgpsEventSubscribe();
break;
case AGPS_EVENT_UNSUBSCRIBE:
processAgpsEventUnsubscribe();
break;
case AGPS_EVENT_GRANTED:
processAgpsEventGranted();
break;
case AGPS_EVENT_RELEASED:
processAgpsEventReleased();
break;
case AGPS_EVENT_DENIED:
processAgpsEventDenied();
break;
default:
LOC_LOGE("Invalid Loc Agps Event");
}
}
void AgpsStateMachine::processAgpsEventSubscribe(){
switch (mState){
case AGPS_STATE_RELEASED:
/* Add subscriber to list
* No notifications until we get RSRC_GRANTED */
addSubscriber(mCurrentSubscriber);
/* Send data request
* The if condition below is added so that if the data call setup
* fails for DS State Machine, we want to retry in released state.
* for Agps State Machine, sendRsrcRequest() will always return
* success. */
if(requestOrReleaseDataConn(true) == 0){
// If data request successful, move to pending state
transitionState(AGPS_STATE_PENDING);
}
break;
case AGPS_STATE_PENDING:
/* Already requested for data connection,
* do nothing until we get RSRC_GRANTED event;
* Just add this subscriber to the list, for notifications */
addSubscriber(mCurrentSubscriber);
break;
case AGPS_STATE_ACQUIRED:
/* We already have the data connection setup,
* Notify current subscriber with GRANTED event,
* And add it to the subscriber list for further notifications. */
notifyEventToSubscriber(AGPS_EVENT_GRANTED, mCurrentSubscriber, false);
addSubscriber(mCurrentSubscriber);
break;
case AGPS_STATE_RELEASING:
addSubscriber(mCurrentSubscriber);
break;
default:
LOC_LOGE("Invalid state: %d", mState);
}
}
void AgpsStateMachine::processAgpsEventUnsubscribe(){
switch (mState){
case AGPS_STATE_RELEASED:
notifyEventToSubscriber(
AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, false);
break;
case AGPS_STATE_PENDING:
case AGPS_STATE_ACQUIRED:
/* If the subscriber wishes to wait for connection close,
* before being removed from list, move to inactive state
* and notify */
if(mCurrentSubscriber->mWaitForCloseComplete){
mCurrentSubscriber->mIsInactive = true;
notifyEventToSubscriber(
AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, false);
}
else{
/* Notify only current subscriber and then delete it from
* subscriberList */
notifyEventToSubscriber(
AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, true);
}
/* If no subscribers in list, release data connection */
if(mSubscriberList.empty()){
transitionState(AGPS_STATE_RELEASED);
requestOrReleaseDataConn(false);
}
/* Some subscribers in list, but all inactive;
* Release data connection */
else if(!anyActiveSubscribers()){
transitionState(AGPS_STATE_RELEASING);
requestOrReleaseDataConn(false);
}
break;
case AGPS_STATE_RELEASING:
/* If the subscriber wishes to wait for connection close,
* before being removed from list, move to inactive state
* and notify */
if(mCurrentSubscriber->mWaitForCloseComplete){
mCurrentSubscriber->mIsInactive = true;
notifyEventToSubscriber(
AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, false);
}
else{
/* Notify only current subscriber and then delete it from
* subscriberList */
notifyEventToSubscriber(
AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, true);
}
/* If no subscribers in list, just move the state.
* Request for releasing data connection should already have been
* sent */
if(mSubscriberList.empty()){
transitionState(AGPS_STATE_RELEASED);
}
break;
default:
LOC_LOGE("Invalid state: %d", mState);
}
}
void AgpsStateMachine::processAgpsEventGranted(){
switch (mState){
case AGPS_STATE_RELEASED:
case AGPS_STATE_ACQUIRED:
case AGPS_STATE_RELEASING:
LOC_LOGE("Unexpected event GRANTED in state %d", mState);
break;
case AGPS_STATE_PENDING:
// Move to acquired state
transitionState(AGPS_STATE_ACQUIRED);
notifyAllSubscribers(
AGPS_EVENT_GRANTED, false,
AGPS_NOTIFICATION_TYPE_FOR_ACTIVE_SUBSCRIBERS);
break;
default:
LOC_LOGE("Invalid state: %d", mState);
}
}
void AgpsStateMachine::processAgpsEventReleased(){
switch (mState){
case AGPS_STATE_RELEASED:
LOC_LOGE("Unexpected event RELEASED in state %d", mState);
break;
case AGPS_STATE_ACQUIRED:
/* Force release received */
LOC_LOGW("Force RELEASED event in ACQUIRED state");
transitionState(AGPS_STATE_RELEASED);
notifyAllSubscribers(
AGPS_EVENT_RELEASED, true,
AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS);
break;
case AGPS_STATE_RELEASING:
/* Notify all inactive subscribers about the event */
notifyAllSubscribers(
AGPS_EVENT_RELEASED, true,
AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS);
/* If we have active subscribers now, they must be waiting for
* data conn setup */
if(anyActiveSubscribers()){
transitionState(AGPS_STATE_PENDING);
requestOrReleaseDataConn(true);
}
/* No active subscribers, move to released state */
else{
transitionState(AGPS_STATE_RELEASED);
}
break;
case AGPS_STATE_PENDING:
/* NOOP */
break;
default:
LOC_LOGE("Invalid state: %d", mState);
}
}
void AgpsStateMachine::processAgpsEventDenied(){
switch (mState){
case AGPS_STATE_RELEASED:
LOC_LOGE("Unexpected event DENIED in state %d", mState);
break;
case AGPS_STATE_ACQUIRED:
/* NOOP */
break;
case AGPS_STATE_RELEASING:
/* Notify all inactive subscribers about the event */
notifyAllSubscribers(
AGPS_EVENT_RELEASED, true,
AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS);
/* If we have active subscribers now, they must be waiting for
* data conn setup */
if(anyActiveSubscribers()){
transitionState(AGPS_STATE_PENDING);
requestOrReleaseDataConn(true);
}
/* No active subscribers, move to released state */
else{
transitionState(AGPS_STATE_RELEASED);
}
break;
case AGPS_STATE_PENDING:
transitionState(AGPS_STATE_RELEASED);
notifyAllSubscribers(
AGPS_EVENT_DENIED, true,
AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS);
break;
default:
LOC_LOGE("Invalid state: %d", mState);
}
}
/* Request or Release data connection
* bool request :
* true = Request data connection
* false = Release data connection */
int AgpsStateMachine::requestOrReleaseDataConn(bool request){
AgpsFrameworkInterface::AGnssStatusIpV4 nifRequest;
memset(&nifRequest, 0, sizeof(nifRequest));
nifRequest.type = (AgpsFrameworkInterface::AGnssType)mAgpsType;
if(request){
LOC_LOGD("AGPS Data Conn Request");
nifRequest.status = (AgpsFrameworkInterface::AGnssStatusValue)
LOC_GPS_REQUEST_AGPS_DATA_CONN;
}
else{
LOC_LOGD("AGPS Data Conn Release");
nifRequest.status = (AgpsFrameworkInterface::AGnssStatusValue)
LOC_GPS_RELEASE_AGPS_DATA_CONN;
}
mAgpsManager->mFrameworkStatusV4Cb(nifRequest);
return 0;
}
void AgpsStateMachine::notifyAllSubscribers(
AgpsEvent event, bool deleteSubscriberPostNotify,
AgpsNotificationType notificationType){
LOC_LOGD("notifyAllSubscribers(): "
"SM %p, Event %d Delete %d Notification Type %d",
this, event, deleteSubscriberPostNotify, notificationType);
std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
while ( it != mSubscriberList.end() ){
AgpsSubscriber* subscriber = *it;
if(notificationType == AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS ||
(notificationType == AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS &&
subscriber->mIsInactive) ||
(notificationType == AGPS_NOTIFICATION_TYPE_FOR_ACTIVE_SUBSCRIBERS &&
!subscriber->mIsInactive)) {
/* Deleting via this call would require another traversal
* through subscriber list, inefficient; hence pass in false*/
notifyEventToSubscriber(event, subscriber, false);
if(deleteSubscriberPostNotify){
it = mSubscriberList.erase(it);
delete subscriber;
} else{
it++;
}
} else{
it++;
}
}
}
void AgpsStateMachine::notifyEventToSubscriber(
AgpsEvent event, AgpsSubscriber* subscriberToNotify,
bool deleteSubscriberPostNotify) {
LOC_LOGD("notifyEventToSubscriber(): "
"SM %p, Event %d Subscriber %p Delete %d",
this, event, subscriberToNotify, deleteSubscriberPostNotify);
switch (event){
case AGPS_EVENT_GRANTED:
mAgpsManager->mAtlOpenStatusCb(
subscriberToNotify->mConnHandle, 1, getAPN(),
getBearer(), mAgpsType);
break;
case AGPS_EVENT_DENIED:
mAgpsManager->mAtlOpenStatusCb(
subscriberToNotify->mConnHandle, 0, getAPN(),
getBearer(), mAgpsType);
break;
case AGPS_EVENT_UNSUBSCRIBE:
case AGPS_EVENT_RELEASED:
mAgpsManager->mAtlCloseStatusCb(subscriberToNotify->mConnHandle, 1);
break;
default:
LOC_LOGE("Invalid event %d", event);
}
/* Search this subscriber in list and delete */
if (deleteSubscriberPostNotify) {
deleteSubscriber(subscriberToNotify);
}
}
void AgpsStateMachine::transitionState(AgpsState newState){
LOC_LOGD("transitionState(): SM %p, old %d, new %d",
this, mState, newState);
mState = newState;
// notify state transitions to all subscribers ?
}
void AgpsStateMachine::addSubscriber(AgpsSubscriber* subscriberToAdd){
LOC_LOGD("addSubscriber(): SM %p, Subscriber %p",
this, subscriberToAdd);
// Check if subscriber is already present in the current list
// If not, then add
std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
for(; it != mSubscriberList.end(); it++){
AgpsSubscriber* subscriber = *it;
if(subscriber->equals(subscriberToAdd)){
LOC_LOGE("Subscriber already in list");
return;
}
}
AgpsSubscriber* cloned = subscriberToAdd->clone();
LOC_LOGD("addSubscriber(): cloned subscriber: %p", cloned);
mSubscriberList.push_back(cloned);
}
void AgpsStateMachine::deleteSubscriber(AgpsSubscriber* subscriberToDelete){
LOC_LOGD("deleteSubscriber(): SM %p, Subscriber %p",
this, subscriberToDelete);
std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
while ( it != mSubscriberList.end() ) {
AgpsSubscriber* subscriber = *it;
if(subscriber && subscriber->equals(subscriberToDelete)){
it = mSubscriberList.erase(it);
delete subscriber;
}else{
it++;
}
}
}
bool AgpsStateMachine::anyActiveSubscribers(){
std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
for(; it != mSubscriberList.end(); it++){
AgpsSubscriber* subscriber = *it;
if(!subscriber->mIsInactive){
return true;
}
}
return false;
}
void AgpsStateMachine::setAPN(char* apn, unsigned int len){
if (NULL != mAPN) {
delete mAPN;
}
if(apn == NULL || len <= 0){
LOC_LOGD("Invalid apn len (%d) or null apn", len);
mAPN = NULL;
mAPNLen = 0;
}
if (NULL != apn) {
mAPN = new char[len+1];
memcpy(mAPN, apn, len);
mAPN[len] = '\0';
mAPNLen = len;
}
}
AgpsSubscriber* AgpsStateMachine::getSubscriber(int connHandle){
/* Go over the subscriber list */
std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
for(; it != mSubscriberList.end(); it++){
AgpsSubscriber* subscriber = *it;
if(subscriber->mConnHandle == connHandle){
return subscriber;
}
}
/* Not found, return NULL */
return NULL;
}
AgpsSubscriber* AgpsStateMachine::getFirstSubscriber(bool isInactive){
/* Go over the subscriber list */
std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
for(; it != mSubscriberList.end(); it++){
AgpsSubscriber* subscriber = *it;
if(subscriber->mIsInactive == isInactive){
return subscriber;
}
}
/* Not found, return NULL */
return NULL;
}
void AgpsStateMachine::dropAllSubscribers(){
LOC_LOGD("dropAllSubscribers(): SM %p", this);
/* Go over the subscriber list */
std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
while ( it != mSubscriberList.end() ){
AgpsSubscriber* subscriber = *it;
it = mSubscriberList.erase(it);
delete subscriber;
}
}
/* --------------------------------------------------------------------
* DS State Machine Methods
* -------------------------------------------------------------------*/
const int DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4;
const int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500;
/* Overridden method
* DS SM needs to handle one scenario differently */
void DSStateMachine::processAgpsEvent(AgpsEvent event){
LOC_LOGD("DSStateMachine::processAgpsEvent() %d", event);
/* DS Client call setup APIs don't return failure/closure separately.
* Hence we receive RELEASED event in both cases.
* If we are in pending, we should consider RELEASED as DENIED */
if(event == AGPS_EVENT_RELEASED && mState == AGPS_STATE_PENDING){
LOC_LOGD("Translating RELEASED to DENIED event");
event = AGPS_EVENT_DENIED;
}
/* Redirect process to base class */
AgpsStateMachine::processAgpsEvent(event);
}
/* Timer Callback
* For the retry timer started in case of DS Client call setup failure */
void delay_callback(void *callbackData, int result)
{
LOC_LOGD("delay_callback(): cbData %p", callbackData);
(void)result;
if(callbackData == NULL) {
LOC_LOGE("delay_callback(): NULL argument received !");
return;
}
DSStateMachine* dsStateMachine = (DSStateMachine *)callbackData;
dsStateMachine->retryCallback();
}
/* Invoked from Timer Callback
* For the retry timer started in case of DS Client call setup failure */
void DSStateMachine :: retryCallback()
{
LOC_LOGD("DSStateMachine::retryCallback()");
/* Request SUPL ES
* There must be at least one active subscriber in list */
AgpsSubscriber* subscriber = getFirstSubscriber(false);
if(subscriber == NULL) {
LOC_LOGE("No active subscriber for DS Client call setup");
return;
}
/* Send message to retry */
mAgpsManager->mSendMsgToAdapterQueueFn(
new AgpsMsgRequestATL(
mAgpsManager, subscriber->mConnHandle,
LOC_AGPS_TYPE_SUPL_ES));
}
/* Overridden method
* Request or Release data connection
* bool request :
* true = Request data connection
* false = Release data connection */
int DSStateMachine::requestOrReleaseDataConn(bool request){
LOC_LOGD("DSStateMachine::requestOrReleaseDataConn(): "
"request %d", request);
/* Release data connection required ? */
if(!request && mAgpsManager->mDSClientStopDataCallFn){
mAgpsManager->mDSClientStopDataCallFn();
LOC_LOGD("DS Client release data call request sent !");
return 0;
}
/* Setup data connection request
* There must be at least one active subscriber in list */
AgpsSubscriber* subscriber = getFirstSubscriber(false);
if(subscriber == NULL) {
LOC_LOGE("No active subscriber for DS Client call setup");
return -1;
}
/* DS Client Fn registered ? */
if(!mAgpsManager->mDSClientOpenAndStartDataCallFn){
LOC_LOGE("DS Client start fn not registered, fallback to SUPL ATL");
notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
return -1;
}
/* Setup the call */
int ret = mAgpsManager->mDSClientOpenAndStartDataCallFn();
/* Check if data call start failed */
switch (ret) {
case LOC_API_ADAPTER_ERR_ENGINE_BUSY:
LOC_LOGE("DS Client open call failed, err: %d", ret);
mRetries++;
if(mRetries > MAX_START_DATA_CALL_RETRIES) {
LOC_LOGE("DS Client call retries exhausted, "
"falling back to normal SUPL ATL");
notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
}
/* Retry DS Client call setup after some delay */
else if(loc_timer_start(
DATA_CALL_RETRY_DELAY_MSEC, delay_callback, this)) {
LOC_LOGE("Error: Could not start delay thread\n");
return -1;
}
break;
case LOC_API_ADAPTER_ERR_UNSUPPORTED:
LOC_LOGE("No emergency profile found. Fall back to normal SUPL ATL");
notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
break;
case LOC_API_ADAPTER_ERR_SUCCESS:
LOC_LOGD("Request to start data call sent");
break;
default:
LOC_LOGE("Unrecognized return value: %d", ret);
}
return ret;
}
void DSStateMachine::notifyEventToSubscriber(
AgpsEvent event, AgpsSubscriber* subscriberToNotify,
bool deleteSubscriberPostNotify) {
LOC_LOGD("DSStateMachine::notifyEventToSubscriber");
switch (event){
case AGPS_EVENT_GRANTED:
mAgpsManager->mAtlOpenStatusCb(
subscriberToNotify->mConnHandle, 1, NULL,
AGPS_APN_BEARER_INVALID, LOC_AGPS_TYPE_SUPL_ES);
break;
case AGPS_EVENT_DENIED:
/* Now try with regular SUPL
* We need to send request via message queue */
mRetries = 0;
mAgpsManager->mSendMsgToAdapterQueueFn(
new AgpsMsgRequestATL(
mAgpsManager, subscriberToNotify->mConnHandle,
LOC_AGPS_TYPE_SUPL));
break;
case AGPS_EVENT_UNSUBSCRIBE:
mAgpsManager->mAtlCloseStatusCb(subscriberToNotify->mConnHandle, 1);
break;
case AGPS_EVENT_RELEASED:
mAgpsManager->mDSClientCloseDataCallFn();
break;
default:
LOC_LOGE("Invalid event %d", event);
}
/* Search this subscriber in list and delete */
if (deleteSubscriberPostNotify) {
deleteSubscriber(subscriberToNotify);
}
}
/* --------------------------------------------------------------------
* Loc AGPS Manager Methods
* -------------------------------------------------------------------*/
/* CREATE AGPS STATE MACHINES
* Must be invoked in Msg Handler context */
void AgpsManager::createAgpsStateMachines() {
LOC_LOGD("AgpsManager::createAgpsStateMachines");
bool agpsCapable =
((loc_core::ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA) ||
(loc_core::ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB));
if (NULL == mInternetNif) {
mInternetNif = new AgpsStateMachine(this, LOC_AGPS_TYPE_WWAN_ANY);
LOC_LOGD("Internet NIF: %p", mInternetNif);
}
if (agpsCapable) {
if (NULL == mAgnssNif) {
mAgnssNif = new AgpsStateMachine(this, LOC_AGPS_TYPE_SUPL);
LOC_LOGD("AGNSS NIF: %p", mAgnssNif);
}
if (NULL == mDsNif &&
loc_core::ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL){
if(!mDSClientInitFn){
LOC_LOGE("DS Client Init Fn not registered !");
return;
}
if(mDSClientInitFn(false) != 0){
LOC_LOGE("Failed to init data service client");
return;
}
mDsNif = new DSStateMachine(this);
LOC_LOGD("DS NIF: %p", mDsNif);
}
}
}
AgpsStateMachine* AgpsManager::getAgpsStateMachine(AGpsExtType agpsType) {
LOC_LOGD("AgpsManager::getAgpsStateMachine(): agpsType %d", agpsType);
switch (agpsType) {
case LOC_AGPS_TYPE_INVALID:
case LOC_AGPS_TYPE_SUPL:
if(mAgnssNif == NULL){
LOC_LOGE("NULL AGNSS NIF !");
}
return mAgnssNif;
case LOC_AGPS_TYPE_SUPL_ES:
if (loc_core::ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
if (mDsNif == NULL) {
createAgpsStateMachines();
}
return mDsNif;
} else {
return mAgnssNif;
}
default:
return mInternetNif;
}
LOC_LOGE("No SM found !");
return NULL;
}
void AgpsManager::requestATL(int connHandle, AGpsExtType agpsType){
LOC_LOGD("AgpsManager::requestATL(): connHandle %d, agpsType %d",
connHandle, agpsType);
AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
if(sm == NULL){
LOC_LOGE("No AGPS State Machine for agpsType: %d", agpsType);
mAtlOpenStatusCb(
connHandle, 0, NULL, AGPS_APN_BEARER_INVALID, agpsType);
return;
}
/* Invoke AGPS SM processing */
AgpsSubscriber subscriber(connHandle);
sm->setCurrentSubscriber(&subscriber);
/* If DS State Machine, wait for close complete */
if(agpsType == LOC_AGPS_TYPE_SUPL_ES){
subscriber.mWaitForCloseComplete = true;
}
/* Send subscriber event */
sm->processAgpsEvent(AGPS_EVENT_SUBSCRIBE);
}
void AgpsManager::releaseATL(int connHandle){
LOC_LOGD("AgpsManager::releaseATL(): connHandle %d", connHandle);
/* First find the subscriber with specified handle.
* We need to search in all state machines. */
AgpsStateMachine* sm = NULL;
AgpsSubscriber* subscriber = NULL;
if (mAgnssNif &&
(subscriber = mAgnssNif->getSubscriber(connHandle)) != NULL) {
sm = mAgnssNif;
}
else if (mInternetNif &&
(subscriber = mInternetNif->getSubscriber(connHandle)) != NULL) {
sm = mInternetNif;
}
else if (mDsNif &&
(subscriber = mDsNif->getSubscriber(connHandle)) != NULL) {
sm = mDsNif;
}
if(sm == NULL){
LOC_LOGE("Subscriber with connHandle %d not found in any SM",
connHandle);
mAtlCloseStatusCb(connHandle, 0);
return;
}
/* Now send unsubscribe event */
sm->setCurrentSubscriber(subscriber);
sm->processAgpsEvent(AGPS_EVENT_UNSUBSCRIBE);
}
void AgpsManager::reportDataCallOpened(){
LOC_LOGD("AgpsManager::reportDataCallOpened");
if (mDsNif) {
mDsNif->processAgpsEvent(AGPS_EVENT_GRANTED);
}
}
void AgpsManager::reportDataCallClosed(){
LOC_LOGD("AgpsManager::reportDataCallClosed");
if (mDsNif) {
mDsNif->processAgpsEvent(AGPS_EVENT_RELEASED);
}
}
void AgpsManager::reportAtlOpenSuccess(
AGpsExtType agpsType, char* apnName, int apnLen,
LocApnIpType ipType){
LOC_LOGD("AgpsManager::reportAtlOpenSuccess(): "
"AgpsType %d, APN [%s], Len %d, IPType %d",
agpsType, apnName, apnLen, ipType);
/* Find the state machine instance */
AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
/* Convert LocApnIpType sent by framework to AGpsBearerType */
AGpsBearerType bearerType;
switch (ipType) {
case LOC_APN_IP_IPV4:
bearerType = AGPS_APN_BEARER_IPV4;
break;
case LOC_APN_IP_IPV6:
bearerType = AGPS_APN_BEARER_IPV6;
break;
case LOC_APN_IP_IPV4V6:
bearerType = AGPS_APN_BEARER_IPV4V6;
break;
default:
bearerType = AGPS_APN_BEARER_IPV4;
break;
}
/* Set bearer and apn info in state machine instance */
sm->setBearer(bearerType);
sm->setAPN(apnName, apnLen);
/* Send GRANTED event to state machine */
sm->processAgpsEvent(AGPS_EVENT_GRANTED);
}
void AgpsManager::reportAtlOpenFailed(AGpsExtType agpsType){
LOC_LOGD("AgpsManager::reportAtlOpenFailed(): AgpsType %d", agpsType);
/* Fetch SM and send DENIED event */
AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
sm->processAgpsEvent(AGPS_EVENT_DENIED);
}
void AgpsManager::reportAtlClosed(AGpsExtType agpsType){
LOC_LOGD("AgpsManager::reportAtlClosed(): AgpsType %d", agpsType);
/* Fetch SM and send RELEASED event */
AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
sm->processAgpsEvent(AGPS_EVENT_RELEASED);
}
void AgpsManager::handleModemSSR(){
LOC_LOGD("AgpsManager::handleModemSSR");
/* Drop subscribers from all state machines */
if (mAgnssNif){
mAgnssNif->dropAllSubscribers();
}
if (mInternetNif){
mInternetNif->dropAllSubscribers();
}
if(mDsNif){
mDsNif->dropAllSubscribers();
}
// reinitialize DS client in SSR mode
if(loc_core::ContextBase::mGps_conf.
USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL){
mDSClientStopDataCallFn();
mDSClientCloseDataCallFn();
mDSClientReleaseFn();
mDSClientInitFn(true);
}
}
AGpsBearerType AgpsUtils::ipTypeToBearerType(LocApnIpType ipType) {
switch (ipType) {
case LOC_APN_IP_IPV4:
return AGPS_APN_BEARER_IPV4;
case LOC_APN_IP_IPV6:
return AGPS_APN_BEARER_IPV6;
case LOC_APN_IP_IPV4V6:
return AGPS_APN_BEARER_IPV4V6;
default:
return AGPS_APN_BEARER_IPV4;
}
}
LocApnIpType AgpsUtils::bearerTypeToIpType(AGpsBearerType bearerType){
switch (bearerType) {
case AGPS_APN_BEARER_IPV4:
return LOC_APN_IP_IPV4;
case AGPS_APN_BEARER_IPV6:
return LOC_APN_IP_IPV6;
case AGPS_APN_BEARER_IPV4V6:
return LOC_APN_IP_IPV4V6;
default:
return LOC_APN_IP_IPV4;
}
}

446
gnss/Agps.h Normal file
View file

@ -0,0 +1,446 @@
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef AGPS_H
#define AGPS_H
#include <functional>
#include <list>
#include <MsgTask.h>
#include <gps_extended_c.h>
#include <platform_lib_log_util.h>
/* ATL callback function pointers
* Passed in by Adapter to AgpsManager */
typedef std::function<void(
int handle, int isSuccess, char* apn,
AGpsBearerType bearerType, AGpsExtType agpsType)> AgpsAtlOpenStatusCb;
typedef std::function<void(int handle, int isSuccess)> AgpsAtlCloseStatusCb;
/* DS Client control APIs
* Passed in by Adapter to AgpsManager */
typedef std::function<int(bool isDueToSSR)> AgpsDSClientInitFn;
typedef std::function<int()> AgpsDSClientOpenAndStartDataCallFn;
typedef std::function<void()> AgpsDSClientStopDataCallFn;
typedef std::function<void()> AgpsDSClientCloseDataCallFn;
typedef std::function<void()> AgpsDSClientReleaseFn;
/* Post message to adapter's message queue */
typedef std::function<void(LocMsg* msg)> SendMsgToAdapterMsgQueueFn;
/* AGPS States */
typedef enum {
AGPS_STATE_INVALID = 0,
AGPS_STATE_RELEASED,
AGPS_STATE_PENDING,
AGPS_STATE_ACQUIRED,
AGPS_STATE_RELEASING
} AgpsState;
typedef enum {
AGPS_EVENT_INVALID = 0,
AGPS_EVENT_SUBSCRIBE,
AGPS_EVENT_UNSUBSCRIBE,
AGPS_EVENT_GRANTED,
AGPS_EVENT_RELEASED,
AGPS_EVENT_DENIED
} AgpsEvent;
/* Notification Types sent to subscribers */
typedef enum {
AGPS_NOTIFICATION_TYPE_INVALID = 0,
/* Meant for all subscribers, either active or inactive */
AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS,
/* Meant for only inactive subscribers */
AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS,
/* Meant for only active subscribers */
AGPS_NOTIFICATION_TYPE_FOR_ACTIVE_SUBSCRIBERS
} AgpsNotificationType;
/* Framework AGNSS interface
* This interface is defined in IAGnssCallback provided by
* Android Framework.
* Must be kept in sync with that interface. */
namespace AgpsFrameworkInterface {
/** AGNSS type **/
enum AGnssType : uint8_t {
TYPE_SUPL = 1,
TYPE_C2K = 2
};
enum AGnssStatusValue : uint8_t {
/** GNSS requests data connection for AGNSS. */
REQUEST_AGNSS_DATA_CONN = 1,
/** GNSS releases the AGNSS data connection. */
RELEASE_AGNSS_DATA_CONN = 2,
/** AGNSS data connection initiated */
AGNSS_DATA_CONNECTED = 3,
/** AGNSS data connection completed */
AGNSS_DATA_CONN_DONE = 4,
/** AGNSS data connection failed */
AGNSS_DATA_CONN_FAILED = 5
};
/*
* Represents the status of AGNSS augmented to support IPv4.
*/
struct AGnssStatusIpV4 {
AGnssType type;
AGnssStatusValue status;
/*
* 32-bit IPv4 address.
*/
unsigned int ipV4Addr;
};
/*
* Represents the status of AGNSS augmented to support IPv6.
*/
struct AGnssStatusIpV6 {
AGnssType type;
AGnssStatusValue status;
/*
* 128-bit IPv6 address.
*/
unsigned char ipV6Addr[16];
};
/*
* Callback with AGNSS(IpV4) status information.
*
* @param status Will be of type AGnssStatusIpV4.
*/
typedef void (*AgnssStatusIpV4Cb)(AGnssStatusIpV4 status);
/*
* Callback with AGNSS(IpV6) status information.
*
* @param status Will be of type AGnssStatusIpV6.
*/
typedef void (*AgnssStatusIpV6Cb)(AGnssStatusIpV6 status);
}
/* Classes in this header */
class AgpsSubscriber;
class AgpsManager;
class AgpsStateMachine;
class DSStateMachine;
/* SUBSCRIBER
* Each Subscriber instance corresponds to one AGPS request,
* received by the AGPS state machine */
class AgpsSubscriber {
public:
int mConnHandle;
/* Does this subscriber wait for data call close complete,
* before being notified ATL close ?
* While waiting for data call close, subscriber will be in
* inactive state. */
bool mWaitForCloseComplete;
bool mIsInactive;
inline AgpsSubscriber(int connHandle) :
mConnHandle(connHandle), mWaitForCloseComplete(false),
mIsInactive(false) {}
inline virtual ~AgpsSubscriber() {}
inline virtual bool equals(const AgpsSubscriber *s) const
{ return (mConnHandle == s->mConnHandle); }
inline virtual AgpsSubscriber* clone()
{ return new AgpsSubscriber(mConnHandle); }
};
/* AGPS STATE MACHINE */
class AgpsStateMachine {
protected:
/* AGPS Manager instance, from where this state machine is created */
AgpsManager* mAgpsManager;
/* List of all subscribers for this State Machine.
* Once a subscriber is notified for ATL open/close status,
* it is deleted */
std::list<AgpsSubscriber*> mSubscriberList;
/* Current subscriber, whose request this State Machine is
* currently processing */
AgpsSubscriber* mCurrentSubscriber;
/* Current state for this state machine */
AgpsState mState;
private:
/* AGPS Type for this state machine
LOC_AGPS_TYPE_ANY 0
LOC_AGPS_TYPE_SUPL 1
LOC_AGPS_TYPE_WWAN_ANY 3
LOC_AGPS_TYPE_SUPL_ES 5 */
AGpsExtType mAgpsType;
/* APN and IP Type info for AGPS Call */
char* mAPN;
unsigned int mAPNLen;
AGpsBearerType mBearer;
public:
/* CONSTRUCTOR */
AgpsStateMachine(AgpsManager* agpsManager, AGpsExtType agpsType):
mAgpsManager(agpsManager), mSubscriberList(),
mCurrentSubscriber(NULL), mState(AGPS_STATE_RELEASED),
mAgpsType(agpsType), mAPN(NULL), mAPNLen(0),
mBearer(AGPS_APN_BEARER_INVALID) {};
virtual ~AgpsStateMachine() { if(NULL != mAPN) delete[] mAPN; };
/* Getter/Setter methods */
void setAPN(char* apn, unsigned int len);
inline char* getAPN() const { return (char*)mAPN; }
inline void setBearer(AGpsBearerType bearer) { mBearer = bearer; }
inline AGpsBearerType getBearer() const { return mBearer; }
inline AGpsExtType getType() const { return mAgpsType; }
inline void setCurrentSubscriber(AgpsSubscriber* subscriber)
{ mCurrentSubscriber = subscriber; }
/* Fetch subscriber with specified handle */
AgpsSubscriber* getSubscriber(int connHandle);
/* Fetch first active or inactive subscriber in list
* isInactive = true : fetch first inactive subscriber
* isInactive = false : fetch first active subscriber */
AgpsSubscriber* getFirstSubscriber(bool isInactive);
/* Process LOC AGPS Event being passed in
* onRsrcEvent */
virtual void processAgpsEvent(AgpsEvent event);
/* Drop all subscribers, in case of Modem SSR */
void dropAllSubscribers();
protected:
/* Remove the specified subscriber from list if present.
* Also delete the subscriber instance. */
void deleteSubscriber(AgpsSubscriber* subscriber);
private:
/* Send call setup request to framework
* sendRsrcRequest(LOC_GPS_REQUEST_AGPS_DATA_CONN)
* sendRsrcRequest(LOC_GPS_RELEASE_AGPS_DATA_CONN) */
virtual int requestOrReleaseDataConn(bool request);
/* Individual event processing methods */
void processAgpsEventSubscribe();
void processAgpsEventUnsubscribe();
void processAgpsEventGranted();
void processAgpsEventReleased();
void processAgpsEventDenied();
/* Clone the passed in subscriber and add to the subscriber list
* if not already present */
void addSubscriber(AgpsSubscriber* subscriber);
/* Notify subscribers about AGPS events */
void notifyAllSubscribers(
AgpsEvent event, bool deleteSubscriberPostNotify,
AgpsNotificationType notificationType);
virtual void notifyEventToSubscriber(
AgpsEvent event, AgpsSubscriber* subscriber,
bool deleteSubscriberPostNotify);
/* Do we have any subscribers in active state */
bool anyActiveSubscribers();
/* Transition state */
void transitionState(AgpsState newState);
};
/* DS STATE MACHINE */
class DSStateMachine : public AgpsStateMachine {
private:
static const int MAX_START_DATA_CALL_RETRIES;
static const int DATA_CALL_RETRY_DELAY_MSEC;
int mRetries;
public:
/* CONSTRUCTOR */
DSStateMachine(AgpsManager* agpsManager):
AgpsStateMachine(agpsManager, LOC_AGPS_TYPE_SUPL_ES), mRetries(0) {}
/* Overridden method
* DS SM needs to handle one event differently */
void processAgpsEvent(AgpsEvent event);
/* Retry callback, used in case call failure */
void retryCallback();
private:
/* Overridden method, different functionality for DS SM
* Send call setup request to framework
* sendRsrcRequest(LOC_GPS_REQUEST_AGPS_DATA_CONN)
* sendRsrcRequest(LOC_GPS_RELEASE_AGPS_DATA_CONN) */
int requestOrReleaseDataConn(bool request);
/* Overridden method, different functionality for DS SM */
void notifyEventToSubscriber(
AgpsEvent event, AgpsSubscriber* subscriber,
bool deleteSubscriberPostNotify);
};
/* LOC AGPS MANAGER */
class AgpsManager {
friend class AgpsStateMachine;
friend class DSStateMachine;
public:
/* CONSTRUCTOR */
AgpsManager():
mFrameworkStatusV4Cb(NULL),
mAtlOpenStatusCb(), mAtlCloseStatusCb(),
mDSClientInitFn(), mDSClientOpenAndStartDataCallFn(),
mDSClientStopDataCallFn(), mDSClientCloseDataCallFn(), mDSClientReleaseFn(),
mSendMsgToAdapterQueueFn(),
mAgnssNif(NULL), mInternetNif(NULL), mDsNif(NULL) {}
/* Register callbacks */
void registerCallbacks(
AgpsFrameworkInterface::AgnssStatusIpV4Cb
frameworkStatusV4Cb,
AgpsAtlOpenStatusCb atlOpenStatusCb,
AgpsAtlCloseStatusCb atlCloseStatusCb,
AgpsDSClientInitFn dsClientInitFn,
AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn,
AgpsDSClientStopDataCallFn dsClientStopDataCallFn,
AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn,
AgpsDSClientReleaseFn dsClientReleaseFn,
SendMsgToAdapterMsgQueueFn sendMsgToAdapterQueueFn ){
mFrameworkStatusV4Cb = frameworkStatusV4Cb;
mAtlOpenStatusCb = atlOpenStatusCb;
mAtlCloseStatusCb = atlCloseStatusCb;
mDSClientInitFn = dsClientInitFn;
mDSClientOpenAndStartDataCallFn = dsClientOpenAndStartDataCallFn;
mDSClientStopDataCallFn = dsClientStopDataCallFn;
mDSClientCloseDataCallFn = dsClientCloseDataCallFn;
mDSClientReleaseFn = dsClientReleaseFn;
mSendMsgToAdapterQueueFn = sendMsgToAdapterQueueFn;
}
/* Create all AGPS state machines */
void createAgpsStateMachines();
/* Process incoming ATL requests */
void requestATL(int connHandle, AGpsExtType agpsType);
void releaseATL(int connHandle);
/* Process incoming DS Client data call events */
void reportDataCallOpened();
void reportDataCallClosed();
/* Process incoming framework data call events */
void reportAtlOpenSuccess(
AGpsExtType agpsType, char* apnName, int apnLen,
LocApnIpType ipType);
void reportAtlOpenFailed(AGpsExtType agpsType);
void reportAtlClosed(AGpsExtType agpsType);
/* Handle Modem SSR */
void handleModemSSR();
protected:
AgpsFrameworkInterface::AgnssStatusIpV4Cb mFrameworkStatusV4Cb;
AgpsAtlOpenStatusCb mAtlOpenStatusCb;
AgpsAtlCloseStatusCb mAtlCloseStatusCb;
AgpsDSClientInitFn mDSClientInitFn;
AgpsDSClientOpenAndStartDataCallFn mDSClientOpenAndStartDataCallFn;
AgpsDSClientStopDataCallFn mDSClientStopDataCallFn;
AgpsDSClientCloseDataCallFn mDSClientCloseDataCallFn;
AgpsDSClientReleaseFn mDSClientReleaseFn;
SendMsgToAdapterMsgQueueFn mSendMsgToAdapterQueueFn;
AgpsStateMachine* mAgnssNif;
AgpsStateMachine* mInternetNif;
AgpsStateMachine* mDsNif;
private:
/* Fetch state machine for handling request ATL call */
AgpsStateMachine* getAgpsStateMachine(AGpsExtType agpsType);
};
/* Request SUPL/INTERNET/SUPL_ES ATL
* This LocMsg is defined in this header since it has to be used from more
* than one place, other Agps LocMsg are restricted to GnssAdapter and
* declared inline */
struct AgpsMsgRequestATL: public LocMsg {
AgpsManager* mAgpsManager;
int mConnHandle;
AGpsExtType mAgpsType;
inline AgpsMsgRequestATL(AgpsManager* agpsManager, int connHandle,
AGpsExtType agpsType) :
LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle), mAgpsType(
agpsType) {
LOC_LOGV("AgpsMsgRequestATL");
}
inline virtual void proc() const {
LOC_LOGV("AgpsMsgRequestATL::proc()");
mAgpsManager->requestATL(mConnHandle, mAgpsType);
}
};
namespace AgpsUtils {
AGpsBearerType ipTypeToBearerType(LocApnIpType ipType);
LocApnIpType bearerTypeToIpType(AGpsBearerType bearerType);
}
#endif /* AGPS_H */

View file

@ -20,7 +20,8 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_SRC_FILES += \
location_gnss.cpp \
GnssAdapter.cpp
GnssAdapter.cpp \
Agps.cpp
LOCAL_CFLAGS += \
-fno-short-enums \

View file

@ -39,6 +39,7 @@
#include <GnssAdapter.h>
#include <string>
#include <loc_log.h>
#include <Agps.h>
using namespace loc_core;
@ -55,7 +56,8 @@ GnssAdapter::GnssAdapter() :
mGnssSvIdUsedInPosAvail(false),
mControlCallbacks(),
mPowerVoteId(0),
mNiData()
mNiData(),
mAgpsManager()
{
LOC_LOGD("%s]: Constructor %p", __func__, this);
mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID;
@ -2878,3 +2880,334 @@ GnssAdapter::generateNmeaGGA(const UlpLocation& ulpLocation,
length = nmeaPutChecksum(sentence, size);
reportNmeaEvent(sentence, length);
}
/* INIT LOC AGPS MANAGER */
void GnssAdapter::initAgpsCommand(void* statusV4Cb){
LOC_LOGI("GnssAdapter::initAgpsCommand");
/* Set ATL open/close callbacks */
AgpsAtlOpenStatusCb atlOpenStatusCb =
[this](int handle, int isSuccess, char* apn,
AGpsBearerType bearerType, AGpsExtType agpsType) {
mLocApi->atlOpenStatus(
handle, isSuccess, apn, bearerType, agpsType);
};
AgpsAtlCloseStatusCb atlCloseStatusCb =
[this](int handle, int isSuccess) {
mLocApi->atlCloseStatus(handle, isSuccess);
};
/* Register DS Client APIs */
AgpsDSClientInitFn dsClientInitFn =
[this](bool isDueToSSR) {
return mLocApi->initDataServiceClient(isDueToSSR);
};
AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn =
[this] {
return mLocApi->openAndStartDataCall();
};
AgpsDSClientStopDataCallFn dsClientStopDataCallFn =
[this] {
mLocApi->stopDataCall();
};
AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn =
[this] {
mLocApi->closeDataCall();
};
AgpsDSClientReleaseFn dsClientReleaseFn =
[this] {
mLocApi->releaseDataServiceClient();
};
/* Send Msg function */
SendMsgToAdapterMsgQueueFn sendMsgFn =
[this](LocMsg* msg) {
sendMsg(msg);
};
/* Message to initialize AGPS module */
struct AgpsMsgInit: public LocMsg {
AgpsManager* mAgpsManager;
AgpsFrameworkInterface::AgnssStatusIpV4Cb mFrameworkStatusV4Cb;
AgpsAtlOpenStatusCb mAtlOpenStatusCb;
AgpsAtlCloseStatusCb mAtlCloseStatusCb;
AgpsDSClientInitFn mDSClientInitFn;
AgpsDSClientOpenAndStartDataCallFn mDSClientOpenAndStartDataCallFn;
AgpsDSClientStopDataCallFn mDSClientStopDataCallFn;
AgpsDSClientCloseDataCallFn mDSClientCloseDataCallFn;
AgpsDSClientReleaseFn mDSClientReleaseFn;
SendMsgToAdapterMsgQueueFn mSendMsgFn;
inline AgpsMsgInit(AgpsManager* agpsManager,
AgpsFrameworkInterface::AgnssStatusIpV4Cb frameworkStatusV4Cb,
AgpsAtlOpenStatusCb atlOpenStatusCb,
AgpsAtlCloseStatusCb atlCloseStatusCb,
AgpsDSClientInitFn dsClientInitFn,
AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn,
AgpsDSClientStopDataCallFn dsClientStopDataCallFn,
AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn,
AgpsDSClientReleaseFn dsClientReleaseFn,
SendMsgToAdapterMsgQueueFn sendMsgFn) :
LocMsg(), mAgpsManager(agpsManager), mFrameworkStatusV4Cb(
frameworkStatusV4Cb), mAtlOpenStatusCb(atlOpenStatusCb), mAtlCloseStatusCb(
atlCloseStatusCb), mDSClientInitFn(dsClientInitFn), mDSClientOpenAndStartDataCallFn(
dsClientOpenAndStartDataCallFn), mDSClientStopDataCallFn(
dsClientStopDataCallFn), mDSClientCloseDataCallFn(
dsClientCloseDataCallFn), mDSClientReleaseFn(
dsClientReleaseFn), mSendMsgFn(sendMsgFn) {
LOC_LOGV("AgpsMsgInit");
}
inline virtual void proc() const {
LOC_LOGV("AgpsMsgInit::proc()");
mAgpsManager->registerCallbacks(mFrameworkStatusV4Cb, mAtlOpenStatusCb,
mAtlCloseStatusCb, mDSClientInitFn,
mDSClientOpenAndStartDataCallFn, mDSClientStopDataCallFn,
mDSClientCloseDataCallFn, mDSClientReleaseFn, mSendMsgFn);
mAgpsManager->createAgpsStateMachines();
}
};
/* Send message to initialize AGPS Manager */
sendMsg(new AgpsMsgInit(
&mAgpsManager,
(AgpsFrameworkInterface::AgnssStatusIpV4Cb)statusV4Cb,
atlOpenStatusCb, atlCloseStatusCb,
dsClientInitFn, dsClientOpenAndStartDataCallFn,
dsClientStopDataCallFn, dsClientCloseDataCallFn,
dsClientReleaseFn,
sendMsgFn));
}
/* GnssAdapter::requestATL
* Method triggered in QMI thread as part of handling below message:
* eQMI_LOC_SERVER_REQUEST_OPEN_V02
* Triggers the AGPS state machine to setup AGPS call for below WWAN types:
* eQMI_LOC_WWAN_TYPE_INTERNET_V02
* eQMI_LOC_WWAN_TYPE_AGNSS_V02 */
bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType){
LOC_LOGI("GnssAdapter::requestATL");
sendMsg( new AgpsMsgRequestATL(
&mAgpsManager, connHandle, (AGpsExtType)agpsType));
return true;
}
/* GnssAdapter::requestSuplES
* Method triggered in QMI thread as part of handling below message:
* eQMI_LOC_SERVER_REQUEST_OPEN_V02
* Triggers the AGPS state machine to setup AGPS call for below WWAN types:
* eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
bool GnssAdapter::requestSuplES(int connHandle){
LOC_LOGI("GnssAdapter::requestSuplES");
sendMsg( new AgpsMsgRequestATL(
&mAgpsManager, connHandle, LOC_AGPS_TYPE_SUPL_ES));
return true;
}
/* GnssAdapter::releaseATL
* Method triggered in QMI thread as part of handling below message:
* eQMI_LOC_SERVER_REQUEST_CLOSE_V02
* Triggers teardown of an existing AGPS call */
bool GnssAdapter::releaseATL(int connHandle){
LOC_LOGI("GnssAdapter::releaseATL");
/* Release SUPL/INTERNET/SUPL_ES ATL */
struct AgpsMsgReleaseATL: public LocMsg {
AgpsManager* mAgpsManager;
int mConnHandle;
inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
LOC_LOGV("AgpsMsgReleaseATL");
}
inline virtual void proc() const {
LOC_LOGV("AgpsMsgReleaseATL::proc()");
mAgpsManager->releaseATL(mConnHandle);
}
};
sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
return true;
}
/* GnssAdapter::reportDataCallOpened
* DS Client data call opened successfully.
* Send message to AGPS Manager to handle. */
bool GnssAdapter::reportDataCallOpened(){
LOC_LOGI("GnssAdapter::reportDataCallOpened");
struct AgpsMsgSuplEsOpened: public LocMsg {
AgpsManager* mAgpsManager;
inline AgpsMsgSuplEsOpened(AgpsManager* agpsManager) :
LocMsg(), mAgpsManager(agpsManager) {
LOC_LOGV("AgpsMsgSuplEsOpened");
}
inline virtual void proc() const {
LOC_LOGV("AgpsMsgSuplEsOpened::proc()");
mAgpsManager->reportDataCallOpened();
}
};
sendMsg( new AgpsMsgSuplEsOpened(&mAgpsManager));
return true;
}
/* GnssAdapter::reportDataCallClosed
* DS Client data call closed.
* Send message to AGPS Manager to handle. */
bool GnssAdapter::reportDataCallClosed(){
LOC_LOGI("GnssAdapter::reportDataCallClosed");
struct AgpsMsgSuplEsClosed: public LocMsg {
AgpsManager* mAgpsManager;
inline AgpsMsgSuplEsClosed(AgpsManager* agpsManager) :
LocMsg(), mAgpsManager(agpsManager) {
LOC_LOGV("AgpsMsgSuplEsClosed");
}
inline virtual void proc() const {
LOC_LOGV("AgpsMsgSuplEsClosed::proc()");
mAgpsManager->reportDataCallClosed();
}
};
sendMsg( new AgpsMsgSuplEsClosed(&mAgpsManager));
return true;
}
void GnssAdapter::dataConnOpenCommand(
AGpsExtType agpsType,
const char* apnName, int apnLen, LocApnIpType ipType){
LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
struct AgpsMsgAtlOpenSuccess: public LocMsg {
AgpsManager* mAgpsManager;
AGpsExtType mAgpsType;
char* mApnName;
int mApnLen;
LocApnIpType mIpType;
inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
const char* apnName, int apnLen, LocApnIpType ipType) :
LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
new char[apnLen + 1]), mApnLen(apnLen), mIpType(ipType) {
LOC_LOGV("AgpsMsgAtlOpenSuccess");
memcpy(mApnName, apnName, apnLen);
mApnName[apnLen] = 0;
}
inline ~AgpsMsgAtlOpenSuccess() {
delete[] mApnName;
}
inline virtual void proc() const {
LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen,
mIpType);
}
};
sendMsg( new AgpsMsgAtlOpenSuccess(
&mAgpsManager, (AGpsExtType)agpsType, apnName, apnLen, ipType));
}
void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
struct AgpsMsgAtlClosed: public LocMsg {
AgpsManager* mAgpsManager;
AGpsExtType mAgpsType;
inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
LOC_LOGV("AgpsMsgAtlClosed");
}
inline virtual void proc() const {
LOC_LOGV("AgpsMsgAtlClosed::proc()");
mAgpsManager->reportAtlClosed(mAgpsType);
}
};
sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
}
void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
struct AgpsMsgAtlOpenFailed: public LocMsg {
AgpsManager* mAgpsManager;
AGpsExtType mAgpsType;
inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
LOC_LOGV("AgpsMsgAtlOpenFailed");
}
inline virtual void proc() const {
LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
mAgpsManager->reportAtlOpenFailed(mAgpsType);
}
};
sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
}

View file

@ -33,6 +33,7 @@
#include <LocDualContext.h>
#include <UlpProxyBase.h>
#include <LocationAPI.h>
#include <Agps.h>
#define MAX_URL_LEN 256
#define NMEA_SENTENCE_MAX_LENGTH 200
@ -95,6 +96,10 @@ class GnssAdapter : public LocAdapterBase {
/* ==== NI ============================================================================= */
NiData mNiData;
/* ==== AGPS ========================================================*/
// This must be initialized via initAgps()
AgpsManager mAgpsManager;
/*==== CONVERSION ===================================================================*/
static void convertOptions(LocPosMode& out, const LocationOptions& options);
static void convertLocation(Location& out, const LocGpsLocation& locGpsLocation,
@ -177,6 +182,14 @@ public:
void setConfigCommand();
uint32_t* gnssUpdateConfigCommand(GnssConfig config);
uint32_t gnssDeleteAidingDataCommand(GnssAidingData& data);
void initAgpsCommand(void* statusV4Cb);
void dataConnOpenCommand(
AGpsExtType agpsType,
const char* apnName, int apnLen, LocApnIpType ipType);
void dataConnClosedCommand(AGpsExtType agpsType);
void dataConnFailedCommand(AGpsExtType agpsType);
/* ======== RESPONSES ================================================================== */
void reportResponse(LocationError err, uint32_t sessionId);
void reportResponse(size_t count, LocationError* errs, uint32_t* ids);
@ -201,6 +214,13 @@ public:
virtual void reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurementsNotify);
virtual void reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet);
virtual void reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial);
virtual bool requestATL(int connHandle, LocAGpsType agps_type);
virtual bool releaseATL(int connHandle);
virtual bool requestSuplES(int connHandle);
virtual bool reportDataCallOpened();
virtual bool reportDataCallClosed();
/* ======== UTILITIES ================================================================= */
void reportPosition(const UlpLocation &ulpLocation,
const GpsLocationExtended &locationExtended,

View file

@ -54,6 +54,11 @@ static uint32_t* gnssUpdateConfig(GnssConfig config);
static void injectLocation(double latitude, double longitude, float accuracy);
static void injectTime(int64_t time, int64_t timeReference, int32_t uncertainty);
static void agpsInit(void* statusV4Cb);
static void agpsDataConnOpen(AGpsExtType agpsType, const char* apnName, int apnLen, int ipType);
static void agpsDataConnClosed(AGpsExtType agpsType);
static void agpsDataConnFailed(AGpsExtType agpsType);
static const GnssInterface gGnssInterface = {
sizeof(GnssInterface),
initialize,
@ -71,7 +76,11 @@ static const GnssInterface gGnssInterface = {
gnssUpdateConfig,
gnssDeleteAidingData,
injectLocation,
injectTime
injectTime,
agpsInit,
agpsDataConnOpen,
agpsDataConnClosed,
agpsDataConnFailed
};
#ifndef DEBUG_X86
@ -204,3 +213,29 @@ static void injectTime(int64_t time, int64_t timeReference, int32_t uncertainty)
}
}
static void agpsInit(void* statusV4Cb) {
if (NULL != gGnssAdapter) {
gGnssAdapter->initAgpsCommand(statusV4Cb);
}
}
static void agpsDataConnOpen(
AGpsExtType agpsType, const char* apnName, int apnLen, int ipType) {
if (NULL != gGnssAdapter) {
gGnssAdapter->dataConnOpenCommand(
agpsType, apnName, apnLen, ipType);
}
}
static void agpsDataConnClosed(AGpsExtType agpsType) {
if (NULL != gGnssAdapter) {
gGnssAdapter->dataConnClosedCommand(agpsType);
}
}
static void agpsDataConnFailed(AGpsExtType agpsType) {
if (NULL != gGnssAdapter) {
gGnssAdapter->dataConnFailedCommand(agpsType);
}
}

View file

@ -49,6 +49,10 @@ struct GnssInterface {
uint32_t (*gnssDeleteAidingData)(GnssAidingData& data);
void (*injectLocation)(double latitude, double longitude, float accuracy);
void (*injectTime)(int64_t time, int64_t timeReference, int32_t uncertainty);
void (*agpsInit)(void* statusV4Cb);
void (*agpsDataConnOpen)(short agpsType, const char* apnName, int apnLen, int ipType);
void (*agpsDataConnClosed)(short agpsType);
void (*agpsDataConnFailed)(short agpsType);
};
struct FlpInterface {