summaryrefslogtreecommitdiff
path: root/location/LocationAPI.cpp
diff options
context:
space:
mode:
authorWei Chen <weic@codeaurora.org>2018-11-15 09:41:26 -0800
committerWei Chen <weic@codeaurora.org>2018-11-27 17:07:19 -0800
commite232986d84deb7178d1a57cc7f1e4d24cbaeeb3c (patch)
tree882a2a704ea4d27c8a40f0f1b2d661e5c96b5087 /location/LocationAPI.cpp
parent9b0abcc59d3ea840c38b131d2c4d1c14028f29e1 (diff)
downloadgps-e232986d84deb7178d1a57cc7f1e4d24cbaeeb3c.tar.gz
GPS location API: support destroy with callback for completion
Support Location API destroy function with callback. Location API client that passes callback to Location API need to wait for the destroy complete callback to be invoked before releasing the memory that holds the callback Change-Id: I29b1c6d46feb79c789e6f1ec1500c941b022a3ac CRs-fixed: 2349398
Diffstat (limited to 'location/LocationAPI.cpp')
-rw-r--r--location/LocationAPI.cpp138
1 files changed, 119 insertions, 19 deletions
diff --git a/location/LocationAPI.cpp b/location/LocationAPI.cpp
index 9a67f39..4d859b3 100644
--- a/location/LocationAPI.cpp
+++ b/location/LocationAPI.cpp
@@ -36,15 +36,37 @@
#include <map>
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 struct {
LocationClientMap clientData;
+ LocationClientDestroyCbMap destroyClientData;
LocationControlAPI* controlAPI;
LocationControlCallbacks controlCallbacks;
GnssInterface* gnssInterface;
GeofenceInterface* geofenceInterface;
FlpInterface* flpInterface;
} LocationAPIData;
+
static LocationAPIData gData = {};
static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER;
static bool gGnssLoadFailed = false;
@@ -80,7 +102,8 @@ static bool isGeofenceClient(LocationCallbacks& locationCallbacks)
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);
if (NULL == library || NULL == name) {
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::createInstance(LocationCallbacks& locationCallbacks)
{
@@ -188,39 +251,76 @@ LocationAPI::createInstance(LocationCallbacks& locationCallbacks)
}
void
-LocationAPI::destroy()
+LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb)
{
- delete this;
-}
-
-LocationAPI::LocationAPI()
-{
- LOC_LOGD("LOCATION API CONSTRUCTOR");
-}
+ bool invokeDestroyCb = false;
-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);
+ 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 (isFlpClient(it->second) && NULL != gData.flpInterface) {
- gData.flpInterface->removeClient(it->first);
+
+ if (removeFromGnssInf) {
+ gData.gnssInterface->removeClient(it->first,
+ onGnssRemoveClientCompleteCb);
+ }
+ if (removeFromFlpInf) {
+ gData.flpInterface->removeClient(it->first,
+ onFlpRemoveClientCompleteCb);
}
- if (isGeofenceClient(it->second) && NULL != gData.geofenceInterface) {
- gData.geofenceInterface->removeClient(it->first);
+ 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()
+{
+ LOC_LOGD("LOCATION API CONSTRUCTOR");
+}
+
+// private destructor
+LocationAPI::~LocationAPI()
+{
}
void