Support multiple sessions

Start more than one sessions by calling
locAPIStartSession multiple times

Change-Id: I1625faaab0f69fcb2700b6dbd695f59061c6a88d
CRs-fixed: 2079631
This commit is contained in:
Baili Feng 2017-07-20 17:02:26 +08:00
parent 1bd0de5d87
commit 2df685d3ec
2 changed files with 130 additions and 106 deletions

View file

@ -176,7 +176,7 @@ void LocationAPIControlClient::onCtrlResponseCb(LocationError error, uint32_t id
}
LocationAPIRequest* request = getRequestBySession(id);
if (request) {
request->onResponse(error);
request->onResponse(error, id);
delete request;
}
}
@ -366,7 +366,7 @@ uint32_t LocationAPIClientBase::locAPIStartSession(uint32_t id, uint32_t session
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
if (mSessionMap.find(id) != mSessionMap.end()) {
if (mSessionBiDict.hasId(id)) {
LOC_LOGE("%s:%d] session %d has already started.", __FUNCTION__, __LINE__, id);
retVal = LOCATION_ERROR_ALREADY_STARTED;
} else {
@ -376,21 +376,22 @@ uint32_t LocationAPIClientBase::locAPIStartSession(uint32_t id, uint32_t session
if (sessionMode == SESSION_MODE_ON_FIX) {
trackingSession = mLocationAPI->startTracking(options);
LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, trackingSession);
mRequestQueues[REQUEST_TRACKING].reset(trackingSession);
mRequestQueues[REQUEST_TRACKING].push(new StartTrackingRequest(*this));
mRequestQueues[REQUEST_SESSION].push(new StartTrackingRequest(*this));
} else if (sessionMode == SESSION_MODE_ON_FULL) {
batchingSession = mLocationAPI->startBatching(options);
LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, batchingSession);
mRequestQueues[REQUEST_BATCHING].reset(batchingSession);
mRequestQueues[REQUEST_BATCHING].push(new StartBatchingRequest(*this));
mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
mRequestQueues[REQUEST_SESSION].push(new StartBatchingRequest(*this));
}
uint32_t session =
(sessionMode == SESSION_MODE_ON_FULL) ? batchingSession : trackingSession;
SessionEntity entity;
entity.id = id;
entity.trackingSession = trackingSession;
entity.batchingSession = batchingSession;
entity.sessionMode = sessionMode;
mSessionMap[id] = entity;
mSessionBiDict.set(id, session, entity);
retVal = LOCATION_ERROR_SUCCESS;
}
@ -407,31 +408,21 @@ uint32_t LocationAPIClientBase::locAPIStopSession(uint32_t id)
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
if (mSessionMap.find(id) != mSessionMap.end()) {
SessionEntity entity = mSessionMap[id];
if (mSessionBiDict.hasId(id)) {
SessionEntity entity = mSessionBiDict.getExtById(id);
uint32_t trackingSession = entity.trackingSession;
uint32_t batchingSession = entity.batchingSession;
uint32_t sMode = entity.sessionMode;
mSessionMap.erase(id);
if (sMode == SESSION_MODE_ON_FIX) {
if (mRequestQueues[REQUEST_TRACKING].getSession() == trackingSession) {
mRequestQueues[REQUEST_TRACKING].push(new StopTrackingRequest(*this));
mLocationAPI->stopTracking(trackingSession);
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
mRequestQueues[REQUEST_TRACKING].getSession());
}
mRequestQueues[REQUEST_SESSION].push(new StopTrackingRequest(*this));
mLocationAPI->stopTracking(trackingSession);
} else if (sMode == SESSION_MODE_ON_FULL) {
if (mRequestQueues[REQUEST_BATCHING].getSession() == batchingSession) {
mRequestQueues[REQUEST_BATCHING].push(new StopBatchingRequest(*this));
mLocationAPI->stopBatching(batchingSession);
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
mRequestQueues[REQUEST_BATCHING].getSession());
}
mRequestQueues[REQUEST_SESSION].push(new StopBatchingRequest(*this));
mLocationAPI->stopBatching(batchingSession);
} else {
LOC_LOGE("%s:%d] unknown mode %d.", __FUNCTION__, __LINE__, sMode);
}
retVal = LOCATION_ERROR_SUCCESS;
@ -452,79 +443,68 @@ uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions(uint32_t id, uint32_t
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
if (mSessionMap.find(id) != mSessionMap.end()) {
SessionEntity& entity = mSessionMap[id];
if (mSessionBiDict.hasId(id)) {
SessionEntity entity = mSessionBiDict.getExtById(id);
uint32_t trackingSession = entity.trackingSession;
uint32_t batchingSession = entity.batchingSession;
uint32_t sMode = entity.sessionMode;
if (sessionMode == SESSION_MODE_ON_FIX) {
// we only add an UpdateTrackingOptionsRequest to mRequestQueues[REQUEST_SESSION],
// even if this update request will stop batching and then start tracking.
mRequestQueues[REQUEST_SESSION].push(new UpdateTrackingOptionsRequest(*this));
if (sMode == SESSION_MODE_ON_FIX) {
if (mRequestQueues[REQUEST_TRACKING].getSession() == trackingSession) {
mRequestQueues[REQUEST_TRACKING].push(new UpdateTrackingOptionsRequest(*this));
mLocationAPI->updateTrackingOptions(trackingSession, options);
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
mRequestQueues[REQUEST_TRACKING].getSession());
}
mLocationAPI->updateTrackingOptions(trackingSession, options);
} else if (sMode == SESSION_MODE_ON_FULL) {
// stop batching
{
if (mRequestQueues[REQUEST_BATCHING].getSession() == batchingSession) {
mRequestQueues[REQUEST_BATCHING].push(new StopBatchingRequest(*this));
mLocationAPI->stopBatching(batchingSession);
batchingSession = 0;
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
mRequestQueues[REQUEST_BATCHING].getSession());
}
}
// batchingSession will be removed from mSessionBiDict soon,
// so we don't need to add a new request to mRequestQueues[REQUEST_SESSION].
mLocationAPI->stopBatching(batchingSession);
batchingSession = 0;
mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
// start tracking
{
trackingSession = mLocationAPI->startTracking(options);
LOC_LOGI("%s:%d] start new session: %d",
__FUNCTION__, __LINE__, trackingSession);
mRequestQueues[REQUEST_TRACKING].reset(trackingSession);
mRequestQueues[REQUEST_TRACKING].push(new StartTrackingRequest(*this));
}
trackingSession = mLocationAPI->startTracking(options);
LOC_LOGI("%s:%d] start new session: %d",
__FUNCTION__, __LINE__, trackingSession);
} else {
LOC_LOGE("%s:%d] unknown mode %d", __FUNCTION__, __LINE__, sMode);
}
} else if (sessionMode == SESSION_MODE_ON_FULL) {
// we only add an UpdateBatchingOptionsRequest to mRequestQueues[REQUEST_SESSION],
// even if this update request will stop tracking and then start batching.
mRequestQueues[REQUEST_SESSION].push(new UpdateBatchingOptionsRequest(*this));
if (sMode == SESSION_MODE_ON_FIX) {
// stop tracking
{
if (mRequestQueues[REQUEST_TRACKING].getSession() == trackingSession) {
mRequestQueues[REQUEST_TRACKING].push(new StopTrackingRequest(*this));
mLocationAPI->stopTracking(trackingSession);
trackingSession = 0;
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
mRequestQueues[REQUEST_TRACKING].getSession());
}
}
// trackingSession will be removed from mSessionBiDict soon,
// so we don't need to add a new request to mRequestQueues[REQUEST_SESSION].
mLocationAPI->stopTracking(trackingSession);
trackingSession = 0;
// start batching
{
batchingSession = mLocationAPI->startBatching(options);
LOC_LOGI("%s:%d] start new session: %d",
__FUNCTION__, __LINE__, batchingSession);
mRequestQueues[REQUEST_BATCHING].reset(batchingSession);
mRequestQueues[REQUEST_BATCHING].push(new StartBatchingRequest(*this));
}
batchingSession = mLocationAPI->startBatching(options);
LOC_LOGI("%s:%d] start new session: %d",
__FUNCTION__, __LINE__, batchingSession);
mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
} else if (sMode == SESSION_MODE_ON_FULL) {
if (mRequestQueues[REQUEST_BATCHING].getSession() == batchingSession) {
mRequestQueues[REQUEST_BATCHING].push(
new UpdateBatchingOptionsRequest(*this));
mLocationAPI->updateBatchingOptions(batchingSession, options);
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
mRequestQueues[REQUEST_BATCHING].getSession());
}
mLocationAPI->updateBatchingOptions(batchingSession, options);
} else {
LOC_LOGE("%s:%d] unknown mode %d", __FUNCTION__, __LINE__, sMode);
}
} else {
LOC_LOGE("%s:%d] unknown mode %d.", __FUNCTION__, __LINE__, sessionMode);
}
uint32_t session =
(sessionMode == SESSION_MODE_ON_FULL) ? batchingSession : trackingSession;
entity.trackingSession = trackingSession;
entity.batchingSession = batchingSession;
entity.sessionMode = sessionMode;
// remove the old values from mSessionBiDict before we add a new one.
mSessionBiDict.rmById(id);
mSessionBiDict.set(id, session, entity);
retVal = LOCATION_ERROR_SUCCESS;
} else {
@ -542,9 +522,9 @@ void LocationAPIClientBase::locAPIGetBatchedLocations(size_t count)
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
uint32_t session = 0;
session = mRequestQueues[REQUEST_BATCHING].getSession();
session = mRequestQueues[REQUEST_SESSION].getSession();
if (session > 0) {
mRequestQueues[REQUEST_BATCHING].push(new GetBatchedLocationsRequest(*this));
mRequestQueues[REQUEST_SESSION].push(new GetBatchedLocationsRequest(*this));
mLocationAPI->getBatchedLocations(session, count);
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
@ -785,7 +765,7 @@ void LocationAPIClientBase::beforeGeofenceBreachCb(
for (size_t i = 0; i < n; i++) {
uint32_t id = mGeofenceBiDict.getId(geofenceBreachNotification.ids[i]);
GeofenceBreachTypeMask type =
mGeofenceBiDict.getType(geofenceBreachNotification.ids[i]);
mGeofenceBiDict.getExtBySession(geofenceBreachNotification.ids[i]);
// if type == 0, we will not head into the fllowing block anyway.
// so we don't need to check id and type
if ((geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER &&
@ -823,7 +803,7 @@ void LocationAPIClientBase::onResponseCb(LocationError error, uint32_t id)
}
LocationAPIRequest* request = getRequestBySession(id);
if (request) {
request->onResponse(error);
request->onResponse(error, id);
delete request;
}
}
@ -850,17 +830,31 @@ void LocationAPIClientBase::onCollectiveResponseCb(
}
}
void LocationAPIClientBase::removeSession(uint32_t session) {
if (mSessionBiDict.hasSession(session)) {
mSessionBiDict.rmBySession(session);
}
}
LocationAPIRequest* LocationAPIClientBase::getRequestBySession(uint32_t session)
{
pthread_mutex_lock(&mMutex);
LocationAPIRequest* request = nullptr;
for (int i = 0; i < REQUEST_MAX; i++) {
if (i != REQUEST_GEOFENCE &&
i != REQUEST_SESSION &&
mRequestQueues[i].getSession() == session) {
request = mRequestQueues[i].pop();
break;
}
}
if (request == nullptr) {
// Can't find a request with correct session,
// try to find it from mSessionBiDict
if (mSessionBiDict.hasSession(session)) {
request = mRequestQueues[REQUEST_SESSION].pop();
}
}
pthread_mutex_unlock(&mMutex);
return request;
}

View file

@ -45,7 +45,7 @@ enum SESSION_MODE {
enum REQUEST_TYPE {
REQUEST_TRACKING = 0,
REQUEST_BATCHING,
REQUEST_SESSION,
REQUEST_GEOFENCE,
REQUEST_NIRESPONSE,
REQUEST_MAX,
@ -64,7 +64,7 @@ class LocationAPIRequest {
public:
LocationAPIRequest() {}
virtual ~LocationAPIRequest() {}
virtual void onResponse(LocationError /*error*/) {}
virtual void onResponse(LocationError /*error*/, uint32_t /*id*/) {}
virtual void onCollectiveResponse(
size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
};
@ -76,6 +76,7 @@ public:
virtual ~RequestQueue() {
reset(0);
}
void inline setSession(uint32_t session) { mSession = session; }
void reset(uint32_t session) {
LocationAPIRequest* request = nullptr;
while (!mQueue.empty()) {
@ -130,7 +131,7 @@ public:
class GnssDeleteAidingDataRequest : public LocationAPIRequest {
public:
GnssDeleteAidingDataRequest(LocationAPIControlClient& API) : mAPI(API) {}
inline void onResponse(LocationError error) {
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onGnssDeleteAidingDataCb(error);
}
LocationAPIControlClient& mAPI;
@ -139,7 +140,7 @@ public:
class EnableRequest : public LocationAPIRequest {
public:
EnableRequest(LocationAPIControlClient& API) : mAPI(API) {}
inline void onResponse(LocationError error) {
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onEnableCb(error);
}
LocationAPIControlClient& mAPI;
@ -148,7 +149,7 @@ public:
class DisableRequest : public LocationAPIRequest {
public:
DisableRequest(LocationAPIControlClient& API) : mAPI(API) {}
inline void onResponse(LocationError error) {
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onDisableCb(error);
}
LocationAPIControlClient& mAPI;
@ -179,6 +180,7 @@ public:
LocationAPIClientBase& operator=(const LocationAPIClientBase&) = delete;
void locAPISetCallbacks(LocationCallbacks& locationCallbacks);
void removeSession(uint32_t session);
LocationAPIRequest* getRequestBySession(uint32_t session);
// LocationAPI
@ -257,6 +259,7 @@ private:
uint32_t sessionMode;
} SessionEntity;
template<typename T>
class BiDict {
public:
BiDict() {
@ -271,24 +274,30 @@ private:
pthread_mutex_unlock(&mBiDictMutex);
return ret;
}
void set(uint32_t id, uint32_t session, uint32_t type) {
bool hasSession(uint32_t session) {
pthread_mutex_lock(&mBiDictMutex);
bool ret = (mBackwardMap.find(session) != mBackwardMap.end());
pthread_mutex_unlock(&mBiDictMutex);
return ret;
}
void set(uint32_t id, uint32_t session, T& ext) {
pthread_mutex_lock(&mBiDictMutex);
mForwardMap[id] = session;
mBackwardMap[session] = id;
mTypeMap[session] = type;
mExtMap[session] = ext;
pthread_mutex_unlock(&mBiDictMutex);
}
void clear() {
pthread_mutex_lock(&mBiDictMutex);
mForwardMap.clear();
mBackwardMap.clear();
mTypeMap.clear();
mExtMap.clear();
pthread_mutex_unlock(&mBiDictMutex);
}
void rmById(uint32_t id) {
pthread_mutex_lock(&mBiDictMutex);
mBackwardMap.erase(mForwardMap[id]);
mTypeMap.erase(mForwardMap[id]);
mExtMap.erase(mForwardMap[id]);
mForwardMap.erase(id);
pthread_mutex_unlock(&mBiDictMutex);
}
@ -296,7 +305,7 @@ private:
pthread_mutex_lock(&mBiDictMutex);
mForwardMap.erase(mBackwardMap[session]);
mBackwardMap.erase(session);
mTypeMap.erase(session);
mExtMap.erase(session);
pthread_mutex_unlock(&mBiDictMutex);
}
uint32_t getId(uint32_t session) {
@ -319,11 +328,26 @@ private:
pthread_mutex_unlock(&mBiDictMutex);
return ret;
}
uint32_t getType(uint32_t session) {
T getExtById(uint32_t id) {
pthread_mutex_lock(&mBiDictMutex);
uint32_t ret = 0;
auto it = mTypeMap.find(session);
if (it != mTypeMap.end()) {
T ret;
memset(&ret, 0, sizeof(T));
uint32_t session = mForwardMap[id];
if (session > 0) {
auto it = mExtMap.find(session);
if (it != mExtMap.end()) {
ret = it->second;
}
}
pthread_mutex_unlock(&mBiDictMutex);
return ret;
}
T getExtBySession(uint32_t session) {
pthread_mutex_lock(&mBiDictMutex);
T ret;
memset(&ret, 0, sizeof(T));
auto it = mExtMap.find(session);
if (it != mExtMap.end()) {
ret = it->second;
}
pthread_mutex_unlock(&mBiDictMutex);
@ -344,14 +368,14 @@ private:
std::map<uint32_t, uint32_t> mForwardMap;
// mBackwardMap mapping session->id
std::map<uint32_t, uint32_t> mBackwardMap;
// mTypeMap mapping session->type
std::map<uint32_t, uint32_t> mTypeMap;
// mExtMap mapping session->ext
std::map<uint32_t, T> mExtMap;
};
class StartTrackingRequest : public LocationAPIRequest {
public:
StartTrackingRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error) {
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onStartTrackingCb(error);
}
LocationAPIClientBase& mAPI;
@ -360,8 +384,11 @@ private:
class StopTrackingRequest : public LocationAPIRequest {
public:
StopTrackingRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error) {
inline void onResponse(LocationError error, uint32_t id) {
mAPI.onStopTrackingCb(error);
if (error == LOCATION_ERROR_SUCCESS) {
mAPI.removeSession(id);
}
}
LocationAPIClientBase& mAPI;
};
@ -369,7 +396,7 @@ private:
class UpdateTrackingOptionsRequest : public LocationAPIRequest {
public:
UpdateTrackingOptionsRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error) {
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onUpdateTrackingOptionsCb(error);
}
LocationAPIClientBase& mAPI;
@ -378,7 +405,7 @@ private:
class StartBatchingRequest : public LocationAPIRequest {
public:
StartBatchingRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error) {
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onStartBatchingCb(error);
}
LocationAPIClientBase& mAPI;
@ -387,8 +414,11 @@ private:
class StopBatchingRequest : public LocationAPIRequest {
public:
StopBatchingRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error) {
inline void onResponse(LocationError error, uint32_t id) {
mAPI.onStopBatchingCb(error);
if (error == LOCATION_ERROR_SUCCESS) {
mAPI.removeSession(id);
}
}
LocationAPIClientBase& mAPI;
};
@ -396,7 +426,7 @@ private:
class UpdateBatchingOptionsRequest : public LocationAPIRequest {
public:
UpdateBatchingOptionsRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error) {
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onUpdateBatchingOptionsCb(error);
}
LocationAPIClientBase& mAPI;
@ -405,7 +435,7 @@ private:
class GetBatchedLocationsRequest : public LocationAPIRequest {
public:
GetBatchedLocationsRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error) {
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onGetBatchedLocationsCb(error);
}
LocationAPIClientBase& mAPI;
@ -485,7 +515,7 @@ private:
class GnssNiResponseRequest : public LocationAPIRequest {
public:
GnssNiResponseRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error) {
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onGnssNiResponseCb(error);
}
LocationAPIClientBase& mAPI;
@ -499,8 +529,8 @@ private:
LocationAPI* mLocationAPI;
RequestQueue mRequestQueues[REQUEST_MAX];
BiDict mGeofenceBiDict;
std::map<uint32_t, SessionEntity> mSessionMap;
BiDict<GeofenceBreachTypeMask> mGeofenceBiDict;
BiDict<SessionEntity> mSessionBiDict;
int32_t mBatchSize;
};