Merge "GPS location API: support destroy with callback for completion"

This commit is contained in:
Linux Build Service Account 2018-11-28 20:43:25 -08:00 committed by Gerrit - the friendly Code Review server
commit 372ec44be0
7 changed files with 159 additions and 40 deletions

View file

@ -1859,25 +1859,32 @@ GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& call
} }
void void
GnssAdapter::removeClientCommand(LocationAPI* client) GnssAdapter::removeClientCommand(LocationAPI* client,
removeClientCompleteCallback rmClientCb)
{ {
LOC_LOGD("%s]: client %p", __func__, client); LOC_LOGD("%s]: client %p", __func__, client);
struct MsgRemoveClient : public LocMsg { struct MsgRemoveClient : public LocMsg {
GnssAdapter& mAdapter; GnssAdapter& mAdapter;
LocationAPI* mClient; LocationAPI* mClient;
removeClientCompleteCallback mRmClientCb;
inline MsgRemoveClient(GnssAdapter& adapter, inline MsgRemoveClient(GnssAdapter& adapter,
LocationAPI* client) : LocationAPI* client,
removeClientCompleteCallback rmCb) :
LocMsg(), LocMsg(),
mAdapter(adapter), mAdapter(adapter),
mClient(client) {} mClient(client),
mRmClientCb(rmCb){}
inline virtual void proc() const { inline virtual void proc() const {
mAdapter.stopClientSessions(mClient); mAdapter.stopClientSessions(mClient);
mAdapter.eraseClient(mClient); mAdapter.eraseClient(mClient);
if (nullptr != mRmClientCb) {
mRmClientCb(mClient);
}
} }
}; };
sendMsg(new MsgRemoveClient(*this, client)); sendMsg(new MsgRemoveClient(*this, client, rmClientCb));
} }
void void

View file

@ -128,6 +128,8 @@ typedef std::function<void(
uint64_t gnssEnergyConsumedFromFirstBoot uint64_t gnssEnergyConsumedFromFirstBoot
)> GnssEnergyConsumedCallback; )> GnssEnergyConsumedCallback;
typedef void (*removeClientCompleteCallback)(LocationAPI* client);
class GnssAdapter : public LocAdapterBase { class GnssAdapter : public LocAdapterBase {
/* ==== Engine Hub ===================================================================== */ /* ==== Engine Hub ===================================================================== */
@ -206,7 +208,8 @@ public:
/* ==== CLIENT ========================================================================= */ /* ==== CLIENT ========================================================================= */
/* ======== COMMANDS ====(Called from Client Thread)==================================== */ /* ======== COMMANDS ====(Called from Client Thread)==================================== */
void addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks); void addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks);
void removeClientCommand(LocationAPI* client); void removeClientCommand(LocationAPI* client,
removeClientCompleteCallback rmClientCb);
void requestCapabilitiesCommand(LocationAPI* client); void requestCapabilitiesCommand(LocationAPI* client);
/* ======== UTILITIES ================================================================== */ /* ======== UTILITIES ================================================================== */
void saveClient(LocationAPI* client, const LocationCallbacks& callbacks); void saveClient(LocationAPI* client, const LocationCallbacks& callbacks);

View file

@ -36,7 +36,7 @@ static void initialize();
static void deinitialize(); static void deinitialize();
static void addClient(LocationAPI* client, const LocationCallbacks& callbacks); static void addClient(LocationAPI* client, const LocationCallbacks& callbacks);
static void removeClient(LocationAPI* client); static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb);
static void requestCapabilities(LocationAPI* client); static void requestCapabilities(LocationAPI* client);
static uint32_t startTracking(LocationAPI* client, TrackingOptions&); static uint32_t startTracking(LocationAPI* client, TrackingOptions&);
@ -140,10 +140,10 @@ static void addClient(LocationAPI* client, const LocationCallbacks& callbacks)
} }
} }
static void removeClient(LocationAPI* client) static void removeClient(LocationAPI* client, removeClientCompleteCallback rmClientCb)
{ {
if (NULL != gGnssAdapter) { if (NULL != gGnssAdapter) {
gGnssAdapter->removeClientCommand(client); gGnssAdapter->removeClientCommand(client, rmClientCb);
} }
} }

View file

@ -36,15 +36,37 @@
#include <map> #include <map>
typedef void* (getLocationInterface)(); typedef void* (getLocationInterface)();
typedef uint16_t LocationAdapterTypeMask;
typedef enum {
LOCATION_ADAPTER_GNSS_TYPE_BIT = (1<<0), // adapter type is GNSS
LOCATION_ADAPTER_FLP_TYPE_BIT = (1<<1), // adapter type is FLP
LOCATION_ADAPTER_GEOFENCE_TYPE_BIT = (1<<2) // adapter type is geo fence
} LocationAdapterTypeBits;
typedef struct {
// bit mask of the adpaters that we need to wait for the removeClientCompleteCallback
// before we invoke the registered locationApiDestroyCompleteCallback
LocationAdapterTypeMask waitAdapterMask;
locationApiDestroyCompleteCallback destroyCompleteCb;
} LocationAPIDestroyCbData;
// This is the map for the client that has requested destroy with
// destroy callback provided.
typedef std::map<LocationAPI*, LocationAPIDestroyCbData>
LocationClientDestroyCbMap;
typedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap; typedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap;
typedef struct { typedef struct {
LocationClientMap clientData; LocationClientMap clientData;
LocationClientDestroyCbMap destroyClientData;
LocationControlAPI* controlAPI; LocationControlAPI* controlAPI;
LocationControlCallbacks controlCallbacks; LocationControlCallbacks controlCallbacks;
GnssInterface* gnssInterface; GnssInterface* gnssInterface;
GeofenceInterface* geofenceInterface; GeofenceInterface* geofenceInterface;
FlpInterface* flpInterface; FlpInterface* flpInterface;
} LocationAPIData; } LocationAPIData;
static LocationAPIData gData = {}; static LocationAPIData gData = {};
static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER;
static bool gGnssLoadFailed = false; static bool gGnssLoadFailed = false;
@ -80,7 +102,8 @@ static bool isGeofenceClient(LocationCallbacks& locationCallbacks)
locationCallbacks.geofenceStatusCb != nullptr); locationCallbacks.geofenceStatusCb != nullptr);
} }
static void* loadLocationInterface(const char* library, const char* name) { static void* loadLocationInterface(const char* library, const char* name)
{
LOC_LOGD("%s]: loading %s::%s ...", __func__, library, name); LOC_LOGD("%s]: loading %s::%s ...", __func__, library, name);
if (NULL == library || NULL == name) { if (NULL == library || NULL == name) {
return NULL; return NULL;
@ -106,6 +129,46 @@ static void* loadLocationInterface(const char* library, const char* name) {
} }
} }
void onRemoveClientCompleteCb (
LocationAPI* client, LocationAdapterTypeMask adapterType)
{
bool invokeCallback = false;
locationApiDestroyCompleteCallback destroyCompleteCb;
LOC_LOGd("adatper type %x", adapterType);
pthread_mutex_lock(&gDataMutex);
auto it = gData.destroyClientData.find(client);
if (it != gData.destroyClientData.end()) {
it->second.waitAdapterMask &= ~adapterType;
if (it->second.waitAdapterMask == 0) {
invokeCallback = true;
destroyCompleteCb = it->second.destroyCompleteCb;
gData.destroyClientData.erase(it);
}
}
pthread_mutex_unlock(&gDataMutex);
if ((true == invokeCallback) && (nullptr != destroyCompleteCb)) {
LOC_LOGd("invoke client destroy cb");
(destroyCompleteCb) ();
LOC_LOGd("finish invoke client destroy cb");
}
}
void onGnssRemoveClientCompleteCb (LocationAPI* client)
{
onRemoveClientCompleteCb (client, LOCATION_ADAPTER_GNSS_TYPE_BIT);
}
void onFlpRemoveClientCompleteCb (LocationAPI* client)
{
onRemoveClientCompleteCb (client, LOCATION_ADAPTER_FLP_TYPE_BIT);
}
void onGeofenceRemoveClientCompleteCb (LocationAPI* client)
{
onRemoveClientCompleteCb (client, LOCATION_ADAPTER_GEOFENCE_TYPE_BIT);
}
LocationAPI* LocationAPI*
LocationAPI::createInstance(LocationCallbacks& locationCallbacks) LocationAPI::createInstance(LocationCallbacks& locationCallbacks)
{ {
@ -188,9 +251,66 @@ LocationAPI::createInstance(LocationCallbacks& locationCallbacks)
} }
void void
LocationAPI::destroy() LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb)
{ {
delete this; bool invokeDestroyCb = false;
pthread_mutex_lock(&gDataMutex);
auto it = gData.clientData.find(this);
if (it != gData.clientData.end()) {
bool removeFromGnssInf =
(isGnssClient(it->second) && NULL != gData.gnssInterface);
bool removeFromFlpInf =
(isFlpClient(it->second) && NULL != gData.flpInterface);
bool removeFromGeofenceInf =
(isGeofenceClient(it->second) && NULL != gData.geofenceInterface);
bool needToWait = (removeFromGnssInf || removeFromFlpInf || removeFromGeofenceInf);
LOC_LOGe("removeFromGnssInf: %d, removeFromFlpInf: %d, removeFromGeofenceInf: %d, need %d",
removeFromGnssInf, removeFromFlpInf, removeFromGeofenceInf, needToWait);
if ((NULL != destroyCompleteCb) && (true == needToWait)) {
LocationAPIDestroyCbData destroyCbData = {};
destroyCbData.destroyCompleteCb = destroyCompleteCb;
// record down from which adapter we need to wait for the destroy complete callback
// only when we have received all the needed callbacks from all the associated stacks,
// we shall notify the client.
destroyCbData.waitAdapterMask =
(removeFromGnssInf ? LOCATION_ADAPTER_GNSS_TYPE_BIT : 0);
destroyCbData.waitAdapterMask |=
(removeFromFlpInf ? LOCATION_ADAPTER_FLP_TYPE_BIT : 0);
destroyCbData.waitAdapterMask |=
(removeFromGeofenceInf ? LOCATION_ADAPTER_GEOFENCE_TYPE_BIT : 0);
gData.destroyClientData[this] = destroyCbData;
LOC_LOGe("destroy data stored in the map: 0x%x", destroyCbData.waitAdapterMask);
}
if (removeFromGnssInf) {
gData.gnssInterface->removeClient(it->first,
onGnssRemoveClientCompleteCb);
}
if (removeFromFlpInf) {
gData.flpInterface->removeClient(it->first,
onFlpRemoveClientCompleteCb);
}
if (removeFromGeofenceInf) {
gData.geofenceInterface->removeClient(it->first,
onGeofenceRemoveClientCompleteCb);
}
gData.clientData.erase(it);
if ((NULL != destroyCompleteCb) && (false == needToWait)) {
invokeDestroyCb = true;
}
} else {
LOC_LOGE("%s:%d]: Location API client %p not found in client data",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
if (invokeDestroyCb == true) {
(destroyCompleteCb) ();
}
} }
LocationAPI::LocationAPI() LocationAPI::LocationAPI()
@ -198,29 +318,9 @@ LocationAPI::LocationAPI()
LOC_LOGD("LOCATION API CONSTRUCTOR"); LOC_LOGD("LOCATION API CONSTRUCTOR");
} }
// private destructor
LocationAPI::~LocationAPI() LocationAPI::~LocationAPI()
{ {
LOC_LOGD("LOCATION API DESTRUCTOR");
pthread_mutex_lock(&gDataMutex);
auto it = gData.clientData.find(this);
if (it != gData.clientData.end()) {
if (isGnssClient(it->second) && NULL != gData.gnssInterface) {
gData.gnssInterface->removeClient(it->first);
}
if (isFlpClient(it->second) && NULL != gData.flpInterface) {
gData.flpInterface->removeClient(it->first);
}
if (isGeofenceClient(it->second) && NULL != gData.geofenceInterface) {
gData.geofenceInterface->removeClient(it->first);
}
gData.clientData.erase(it);
} else {
LOC_LOGE("%s:%d]: Location API client %p not found in client data",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
} }
void void

View file

@ -43,10 +43,14 @@ public:
of instances have been reached */ of instances have been reached */
static LocationAPI* createInstance(LocationCallbacks&); static LocationAPI* createInstance(LocationCallbacks&);
/* destroy/cleans up the instance, which should be called when LocationAPI object is /* destroy/cleans up the instance, which should be called when LocationControlAPI object is
no longer needed. LocationAPI* returned from createInstance will no longer valid no longer needed. LocationControlAPI* returned from createInstance will no longer valid
after destroy is called */ after destroy is called.
void destroy(); If the caller allocates the memory for LocationControlCallbacks used in
LocationControlAPI::createInstance, then the caller must ensure that the memory still remains
valid until destroyCompleteCb is invoked.
*/
void destroy(locationApiDestroyCompleteCallback destroyCompleteCb=nullptr);
/* updates/changes the callbacks that will be called. /* updates/changes the callbacks that will be called.
mandatory callbacks must be present for callbacks to be successfully updated mandatory callbacks must be present for callbacks to be successfully updated

View file

@ -1274,6 +1274,9 @@ typedef std::function<void(
LocationSystemInfo locationSystemInfo LocationSystemInfo locationSystemInfo
)> locationSystemInfoCallback; )> locationSystemInfoCallback;
typedef std::function<void(
)> locationApiDestroyCompleteCallback;
typedef struct { typedef struct {
size_t size; // set to sizeof(LocationCallbacks) size_t size; // set to sizeof(LocationCallbacks)
capabilitiesCallback capabilitiesCb; // mandatory capabilitiesCallback capabilitiesCb; // mandatory

View file

@ -46,12 +46,14 @@ typedef std::function<void(
uint64_t gnssEnergyConsumedFromFirstBoot uint64_t gnssEnergyConsumedFromFirstBoot
)> GnssEnergyConsumedCallback; )> GnssEnergyConsumedCallback;
typedef void (*removeClientCompleteCallback)(LocationAPI* client);
struct GnssInterface { struct GnssInterface {
size_t size; size_t size;
void (*initialize)(void); void (*initialize)(void);
void (*deinitialize)(void); void (*deinitialize)(void);
void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks); void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
void (*removeClient)(LocationAPI* client); void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb);
void (*requestCapabilities)(LocationAPI* client); void (*requestCapabilities)(LocationAPI* client);
uint32_t (*startTracking)(LocationAPI* client, TrackingOptions&); uint32_t (*startTracking)(LocationAPI* client, TrackingOptions&);
void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, TrackingOptions&); void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, TrackingOptions&);
@ -87,7 +89,7 @@ struct FlpInterface {
void (*initialize)(void); void (*initialize)(void);
void (*deinitialize)(void); void (*deinitialize)(void);
void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks); void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
void (*removeClient)(LocationAPI* client); void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb);
void (*requestCapabilities)(LocationAPI* client); void (*requestCapabilities)(LocationAPI* client);
uint32_t (*startTracking)(LocationAPI* client, TrackingOptions&); uint32_t (*startTracking)(LocationAPI* client, TrackingOptions&);
void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, TrackingOptions&); void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, TrackingOptions&);
@ -104,7 +106,7 @@ struct GeofenceInterface {
void (*initialize)(void); void (*initialize)(void);
void (*deinitialize)(void); void (*deinitialize)(void);
void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks); void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
void (*removeClient)(LocationAPI* client); void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb);
void (*requestCapabilities)(LocationAPI* client); void (*requestCapabilities)(LocationAPI* client);
uint32_t* (*addGeofences)(LocationAPI* client, size_t count, GeofenceOption*, GeofenceInfo*); uint32_t* (*addGeofences)(LocationAPI* client, size_t count, GeofenceOption*, GeofenceInfo*);
void (*removeGeofences)(LocationAPI* client, size_t count, uint32_t* ids); void (*removeGeofences)(LocationAPI* client, size_t count, uint32_t* ids);