* Copyright (C) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "location_napi_adapter.h"
#include "location_log.h"
#include "location_napi_errcode.h"
#include "constant_definition.h"
#include "geofence_sdk.h"
#include "geofence_napi.h"
#include "geofence_async_context.h"
#include "beacon_fence_request.h"
#include "location_hiappevent.h"
#include <thread>
#include <chrono>
namespace OHOS {
namespace Location {
auto g_locatorClient = Locator::GetInstance();
auto g_geofenceClient = GeofenceManager::GetInstance();
auto g_hiAppEventClient = LocationHiAppEvent::GetInstance();
std::map<int, sptr<LocationGnssGeofenceCallbackNapi>> g_gnssGeofenceCallbackHostMap;
std::map<std::shared_ptr<BeaconFence>, sptr<LocationGnssGeofenceCallbackNapi>> g_beaconFenceRequestMap;
std::mutex g_gnssGeofenceCallbackHostMutex;
std::mutex g_beaconFenceRequestMutex;
napi_value GetLastLocation(napi_env env, napi_callback_info info)
{
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
auto asyncContext = new (std::nothrow) LocationAsyncContext(env);
NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
if (napi_create_string_latin1(env, "getLastLocation",
NAPI_AUTO_LENGTH, &asyncContext->resourceName) != napi_ok) {
GET_AND_THROW_LAST_ERROR(env);
delete asyncContext;
return nullptr;
}
asyncContext->beginTime = CommonUtils::GetCurrentTimeMilSec();
asyncContext->executeFunc = [&](void* data) -> void {
auto context = static_cast<LocationAsyncContext*>(data);
context->loc = g_locatorClient->IsLocationEnabled() ? g_locatorClient->GetCachedLocation() : nullptr;
if (context->loc != nullptr) {
context->errCode = SUCCESS;
} else {
context->errCode = LAST_KNOWN_LOCATION_ERROR;
}
};
asyncContext->completeFunc = [&](void* data) -> void {
auto context = static_cast<LocationAsyncContext*>(data);
NAPI_CALL_RETURN_VOID(context->env, napi_create_object(context->env, &context->result[PARAM1]));
g_hiAppEventClient->WriteEndEvent(
context->beginTime, context->errCode == ERRCODE_SUCCESS ? 0 : 1, context->errCode, "getLastLocation");
if (context->loc != nullptr) {
LocationToJs(context->env, context->loc, context->result[PARAM1]);
} else {
LBSLOGE(LOCATOR_STANDARD, "loc is nullptr!");
}
LBSLOGI(LOCATOR_STANDARD, "Push last location result to client");
};
size_t objectArgsNum = 0;
return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
}
napi_value IsLocationEnabled(napi_env env, napi_callback_info info)
{
LBSLOGI(LOCATOR_STANDARD, "IsLocationEnabled enter.");
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
#ifdef ENABLE_NAPI_MANAGER
napi_value res;
bool isEnabled = false;
int64_t beginTime = CommonUtils::GetCurrentTimeMilSec();
LocationErrCode errorCode = g_locatorClient->IsLocationEnabledV9(isEnabled);
if (errorCode != ERRCODE_SUCCESS) {
HandleSyncErrCode(env, errorCode);
return UndefinedNapiValue(env);
}
NAPI_CALL(env, napi_get_boolean(env, isEnabled, &res));
return res;
#else
auto asyncContext = new (std::nothrow) SwitchAsyncContext(env);
NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
if (napi_create_string_latin1(env, "isLocationEnabled", NAPI_AUTO_LENGTH,
&asyncContext->resourceName) != napi_ok) {
LBSLOGE(LOCATOR_STANDARD, "copy string failed");
}
asyncContext->executeFunc = [&](void* data) -> void {
auto context = static_cast<SwitchAsyncContext*>(data);
context->enable = g_locatorClient->IsLocationEnabled();
context->errCode = SUCCESS;
};
asyncContext->completeFunc = [&](void* data) -> void {
auto context = static_cast<SwitchAsyncContext*>(data);
NAPI_CALL_RETURN_VOID(context->env, napi_get_boolean(context->env, context->enable, &context->result[PARAM1]));
LBSLOGI(LOCATOR_STANDARD, "Push IsLocationEnabled result to client");
};
size_t objectArgsNum = 0;
return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
#endif
}
#ifdef ENABLE_NAPI_MANAGER
napi_value GetCurrentWifiBssidForLocating(napi_env env, napi_callback_info info)
{
LBSLOGI(LOCATOR_STANDARD, "GetCurrentWifiBssidForLocating called.");
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
napi_value res;
std::string bssid;
int64_t beginTime = CommonUtils::GetCurrentTimeMilSec();
LocationErrCode errorCode = g_locatorClient->GetCurrentWifiBssidForLocating(bssid);
g_hiAppEventClient->WriteEndEvent(
beginTime, errorCode == ERRCODE_SUCCESS ? 0 : 1, errorCode, "getCurrentWifiBssidForLocating");
if (errorCode != ERRCODE_SUCCESS) {
ThrowBusinessError(env, errorCode);
return UndefinedNapiValue(env);
}
NAPI_CALL(env, napi_create_string_utf8(env, bssid.c_str(), NAPI_AUTO_LENGTH, &res));
return res;
}
napi_value GetDistanceBetweenLocations(napi_env env, napi_callback_info info)
{
LBSLOGI(LOCATOR_STANDARD, "GetDistanceBetweenLocations called.");
LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
if (g_locatorClient == nullptr) {
HandleSyncErrCode(env, ERRCODE_SERVICE_UNAVAILABLE);
return UndefinedNapiValue(env);
}
if (argc != PARAM2) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
napi_valuetype valueType;
NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
napi_valuetype valueType1;
NAPI_CALL(env, napi_typeof(env, argv[1], &valueType1));
if (valueType != napi_object || valueType1 != napi_object) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
Location location1;
Location location2;
if (!JsObjToLocation(env, argv[0], location1) || !JsObjToLocation(env, argv[1], location2)) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
if (!location1.isValidLatitude(location1.GetLatitude()) || !location1.isValidLongitude(location1.GetLongitude()) ||
!location1.isValidLatitude(location2.GetLatitude()) || !location1.isValidLongitude(location2.GetLongitude())) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
napi_value res;
double distance;
int64_t beginTime = CommonUtils::GetCurrentTimeMilSec();
LocationErrCode errorCode = g_locatorClient->GetDistanceBetweenLocations(location1, location2, distance);
g_hiAppEventClient->WriteEndEvent(
beginTime, errorCode == ERRCODE_SUCCESS ? 0 : 1, errorCode, "getDistanceBetweenLocations");
if (errorCode != ERRCODE_SUCCESS) {
HandleSyncErrCode(env, errorCode);
return UndefinedNapiValue(env);
}
NAPI_CALL(env, napi_create_double(env, distance, &res));
return res;
}
#endif
napi_value IsGeoServiceAvailable(napi_env env, napi_callback_info info)
{
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
#ifdef ENABLE_NAPI_MANAGER
napi_value res;
bool isAvailable = false;
int64_t beginTime = CommonUtils::GetCurrentTimeMilSec();
LocationErrCode errorCode = g_locatorClient->IsGeoServiceAvailableV9(isAvailable);
g_hiAppEventClient->WriteEndEvent(
beginTime, errorCode == ERRCODE_SUCCESS ? 0 : 1, errorCode, "isGeoServiceAvailable");
if (errorCode != ERRCODE_SUCCESS) {
HandleSyncErrCode(env, errorCode);
return UndefinedNapiValue(env);
}
NAPI_CALL(env, napi_get_boolean(env, isAvailable, &res));
return res;
#else
auto asyncContext = new (std::nothrow) SwitchAsyncContext(env);
NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
NAPI_CALL(env,
napi_create_string_latin1(env, "isGeoServiceAvailable", NAPI_AUTO_LENGTH, &asyncContext->resourceName));
asyncContext->executeFunc = [&](void* data) -> void {
auto context = static_cast<SwitchAsyncContext*>(data);
bool isAvailable = g_locatorClient->IsGeoServiceAvailable();
context->enable = isAvailable;
context->errCode = SUCCESS;
};
asyncContext->completeFunc = [&](void* data) -> void {
auto context = static_cast<SwitchAsyncContext*>(data);
NAPI_CALL_RETURN_VOID(context->env, napi_get_boolean(context->env, context->enable, &context->result[PARAM1]));
LBSLOGI(LOCATOR_STANDARD, "Push isGeoServiceAvailable result to client");
};
size_t objectArgsNum = 0;
return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
#endif
}
void CreateReverseGeocodeAsyncContext(ReverseGeoCodeAsyncContext* asyncContext)
{
LBSLOGI(LOCATOR_STANDARD, "CreateReverseGeocodeAsyncContext called.");
asyncContext->executeFunc = [&](void* data) -> void {
auto context = static_cast<ReverseGeoCodeAsyncContext*>(data);
#ifdef ENABLE_NAPI_MANAGER
if (context->errCode != ERRCODE_SUCCESS) {
#else
if (context->errCode != SUCCESS) {
#endif
return;
}
#ifdef ENABLE_NAPI_MANAGER
bool isAvailable = false;
LocationErrCode errorCode = g_locatorClient->IsGeoServiceAvailableV9(isAvailable);
if (errorCode != ERRCODE_SUCCESS) {
context->errCode = errorCode;
return;
}
if (!isAvailable) {
context->errCode = ERRCODE_REVERSE_GEOCODING_FAIL;
return;
}
context->beginTime = CommonUtils::GetCurrentTimeMilSec();
errorCode = g_locatorClient->GetAddressByCoordinateV9(context->reverseGeoCodeRequest, context->replyList);
if (context->replyList.empty() || errorCode != ERRCODE_SUCCESS) {
context->errCode = errorCode;
}
#else
if (!g_locatorClient->IsGeoServiceAvailable()) {
context->errCode = REVERSE_GEOCODE_ERROR;
return;
}
g_locatorClient->GetAddressByCoordinate(context->reverseGeoCodeRequest, context->replyList);
if (context->replyList.empty()) {
context->errCode = REVERSE_GEOCODE_ERROR;
}
#endif
};
asyncContext->completeFunc = [&](void* data) -> void {
auto context = static_cast<ReverseGeoCodeAsyncContext*>(data);
if (context->errCode != SUCCESS) {
napi_create_array_with_length(context->env, 0, &context->result[PARAM1]);
return;
}
NAPI_CALL_RETURN_VOID(context->env,
napi_create_array_with_length(context->env, context->replyList.size(), &context->result[PARAM1]));
GeoAddressesToJsObj(context->env, context->replyList, context->result[PARAM1]);
};
}
void CreateGeocodeAsyncContext(GeoCodeAsyncContext* asyncContext)
{
LBSLOGI(LOCATOR_STANDARD, "CreateGeocodeAsyncContext called.");
asyncContext->executeFunc = [&](void* data) -> void {
auto context = static_cast<GeoCodeAsyncContext*>(data);
if (context->errCode != SUCCESS) {
return;
}
#ifdef ENABLE_NAPI_MANAGER
bool isAvailable = false;
LocationErrCode errorCode = g_locatorClient->IsGeoServiceAvailableV9(isAvailable);
if (errorCode != ERRCODE_SUCCESS) {
context->errCode = errorCode;
return;
}
if (!isAvailable) {
context->errCode = ERRCODE_GEOCODING_FAIL;
return;
}
errorCode = g_locatorClient->GetAddressByLocationNameV9(context->geoCodeRequest, context->replyList);
if (context->replyList.empty() || errorCode != ERRCODE_SUCCESS) {
context->errCode = errorCode;
}
#else
if (!g_locatorClient->IsGeoServiceAvailable()) {
context->errCode = GEOCODE_ERROR;
return;
}
g_locatorClient->GetAddressByLocationName(context->geoCodeRequest, context->replyList);
if (context->replyList.empty()) {
context->errCode = GEOCODE_ERROR;
}
#endif
};
asyncContext->completeFunc = [&](void* data) -> void {
auto context = static_cast<GeoCodeAsyncContext*>(data);
NAPI_CALL_RETURN_VOID(context->env,
napi_create_array_with_length(context->env, context->replyList.size(), &context->result[PARAM1]));
GeoAddressesToJsObj(context->env, context->replyList, context->result[PARAM1]);
LBSLOGI(LOCATOR_STANDARD, "Push GetAddressesFromLocationName result to client");
};
}
napi_value GetAddressesFromLocation(napi_env env, napi_callback_info info)
{
LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
#ifdef ENABLE_NAPI_MANAGER
if (argc < PARAM1 || argc > PARAM2 || (argc == PARAM2 && !CheckIfParamIsFunctionType(env, argv[1]))) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
#else
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
#endif
napi_valuetype valueType;
NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
#ifdef ENABLE_NAPI_MANAGER
if (valueType != napi_object) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
#else
NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type, object is expected for parameter 1.");
#endif
auto asyncContext = new ReverseGeoCodeAsyncContext(env);
asyncContext->reverseGeoCodeRequest = std::make_unique<ReverseGeoCodeRequest>();
if (napi_create_string_latin1(env, "getAddressesFromLocation",
NAPI_AUTO_LENGTH, &asyncContext->resourceName) != napi_ok) {
GET_AND_THROW_LAST_ERROR(env);
delete asyncContext;
return nullptr;
}
int ret = JsObjToReverseGeoCodeRequest(env, argv[0], asyncContext->reverseGeoCodeRequest);
asyncContext->errCode = (ret == SUCCESS) ? ERRCODE_SUCCESS : ERRCODE_INVALID_PARAM;
#ifdef ENABLE_NAPI_MANAGER
if (asyncContext->errCode != SUCCESS) {
int code = asyncContext->errCode;
delete asyncContext;
asyncContext = nullptr;
HandleSyncErrCode(env, code);
return UndefinedNapiValue(env);
}
#endif
CreateReverseGeocodeAsyncContext(asyncContext);
size_t objectArgsNum = 1;
return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
}
napi_value GetAddressesFromLocationName(napi_env env, napi_callback_info info)
{
LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
#ifdef ENABLE_NAPI_MANAGER
if (argc < PARAM1 || argc > PARAM2 || (argc == PARAM2 && !CheckIfParamIsFunctionType(env, argv[1]))) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
#else
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
#endif
napi_valuetype valueType;
NAPI_CALL(env, napi_typeof(env, argv[0], &valueType));
#ifdef ENABLE_NAPI_MANAGER
if (valueType != napi_object) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
#else
NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type, object is expected for parameter 1.");
#endif
auto asyncContext = new (std::nothrow) GeoCodeAsyncContext(env);
asyncContext->geoCodeRequest = std::make_unique<GeoCodeRequest>();
NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
if (napi_create_string_latin1(env, "GetAddressesFromLocationName",
NAPI_AUTO_LENGTH, &asyncContext->resourceName) != napi_ok) {
GET_AND_THROW_LAST_ERROR(env);
delete asyncContext;
return nullptr;
}
asyncContext->errCode = JsObjToGeoCodeRequest(env, argv[0], asyncContext->geoCodeRequest);
#ifdef ENABLE_NAPI_MANAGER
if (asyncContext->errCode == INPUT_PARAMS_ERROR) {
delete asyncContext;
asyncContext = nullptr;
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
#endif
asyncContext->beginTime = CommonUtils::GetCurrentTimeMilSec();
CreateGeocodeAsyncContext(asyncContext);
size_t objectArgsNum = 1;
return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
}
napi_value GetCachedGnssLocationsSize(napi_env env, napi_callback_info info)
{
LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
#ifdef ENABLE_NAPI_MANAGER
if (argc > PARAM1 || (argc == PARAM1 && !CheckIfParamIsFunctionType(env, argv[PARAM0]))) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
#endif
auto asyncContext = new (std::nothrow) CachedAsyncContext(env);
NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
if (napi_create_string_latin1(env, "GetCachedGnssLocationsSize",
NAPI_AUTO_LENGTH, &asyncContext->resourceName) != napi_ok) {
GET_AND_THROW_LAST_ERROR(env);
delete asyncContext;
return nullptr;
}
asyncContext->beginTime = CommonUtils::GetCurrentTimeMilSec();
SetExecuteFuncForGetCachedGnssLocationsSizeContext(asyncContext);
SetCompleteFuncForGetCachedGnssLocationsSizeContext(asyncContext);
return DoAsyncWork(env, asyncContext, argc, argv, 0);
}
void SetExecuteFuncForGetCachedGnssLocationsSizeContext(CachedAsyncContext* asyncContext)
{
asyncContext->executeFunc = [&](void* data) -> void {
auto context = static_cast<CachedAsyncContext*>(data);
#ifdef ENABLE_NAPI_MANAGER
LocationErrCode errorCode = CheckLocationSwitchState();
if (errorCode != ERRCODE_SUCCESS) {
context->errCode = errorCode;
return;
}
#endif
#ifdef ENABLE_NAPI_MANAGER
int size = -1;
g_locatorClient->GetCachedGnssLocationsSizeV9(size);
context->errCode = ERRCODE_NOT_SUPPORTED;
context->locationSize = size;
#else
context->locationSize = g_locatorClient->GetCachedGnssLocationsSize();
context->errCode = (context->locationSize >= 0) ? SUCCESS : NOT_SUPPORTED;
#endif
};
}
void SetCompleteFuncForGetCachedGnssLocationsSizeContext(CachedAsyncContext* asyncContext)
{
asyncContext->completeFunc = [&](void* data) -> void {
auto context = static_cast<CachedAsyncContext*>(data);
g_hiAppEventClient->WriteEndEvent(context->beginTime, context->errCode == ERRCODE_SUCCESS ? 0 : 1,
context->errCode, "getCachedGnssLocationsSize");
NAPI_CALL_RETURN_VOID(context->env,
napi_create_int32(context->env, context->locationSize, &context->result[PARAM1]));
LBSLOGI(LOCATOR_STANDARD, "Push GetCachedGnssLocationsSize result to client");
};
}
napi_value FlushCachedGnssLocations(napi_env env, napi_callback_info info)
{
LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
#ifdef ENABLE_NAPI_MANAGER
if (argc > PARAM1 || (argc == PARAM1 && !CheckIfParamIsFunctionType(env, argv[PARAM0]))) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
#endif
auto asyncContext = new CachedAsyncContext(env);
if (napi_create_string_latin1(env, "FlushCachedGnssLocations",
NAPI_AUTO_LENGTH, &asyncContext->resourceName) != napi_ok) {
GET_AND_THROW_LAST_ERROR(env);
delete asyncContext;
return nullptr;
}
asyncContext->beginTime = CommonUtils::GetCurrentTimeMilSec();
SetExecuteFuncForFlushCachedGnssLocationsContext(asyncContext);
SetCompleteFuncForFlushCachedGnssLocationsContext(asyncContext);
size_t objectArgsNum = 0;
return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
}
void SetExecuteFuncForFlushCachedGnssLocationsContext(CachedAsyncContext* asyncContext)
{
asyncContext->executeFunc = [&](void* data) -> void {
auto context = static_cast<CachedAsyncContext*>(data);
#ifdef ENABLE_NAPI_MANAGER
LocationErrCode errorCode = CheckLocationSwitchState();
if (errorCode != ERRCODE_SUCCESS) {
context->errCode = errorCode;
return;
}
g_locatorClient->FlushCachedGnssLocationsV9();
context->errCode = ERRCODE_NOT_SUPPORTED;
#else
if (g_locatorClient->IsLocationEnabled()) {
g_locatorClient->FlushCachedGnssLocations();
}
context->errCode = NOT_SUPPORTED;
#endif
};
}
void SetCompleteFuncForFlushCachedGnssLocationsContext(CachedAsyncContext* asyncContext)
{
asyncContext->completeFunc = [&](void* data) -> void {
auto context = static_cast<CachedAsyncContext*>(data);
#ifdef ENABLE_NAPI_MANAGER
g_hiAppEventClient->WriteEndEvent(context->beginTime, context->errCode == ERRCODE_SUCCESS ? 0 : 1,
context->errCode, "flushCachedGnssLocations");
NAPI_CALL_RETURN_VOID(context->env, napi_get_undefined(context->env, &context->result[PARAM1]));
#else
NAPI_CALL_RETURN_VOID(context->env,
napi_get_boolean(context->env, context->errCode == SUCCESS, &context->result[PARAM1]));
#endif
LBSLOGI(LOCATOR_STANDARD, "Push FlushCachedGnssLocations result to client");
};
}
#ifdef ENABLE_NAPI_MANAGER
napi_value GetIsoCountryCode(napi_env env, napi_callback_info info)
{
LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
LBSLOGI(LOCATOR_STANDARD, "GetIsoCountryCode_adapter");
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void *data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
NAPI_ASSERT(env, g_locatorClient != nullptr, "locator instance is null.");
if (argc > PARAM1 || (argc == PARAM1 && !CheckIfParamIsFunctionType(env, argv[PARAM0]))) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
CountryCodeContext *asyncContext = new (std::nothrow) CountryCodeContext(env);
NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
if (napi_create_string_latin1(env, "CountryCodeContext", NAPI_AUTO_LENGTH,
&asyncContext->resourceName) != napi_ok) {
LBSLOGE(LOCATOR_STANDARD, "copy string failed");
}
asyncContext->beginTime = CommonUtils::GetCurrentTimeMilSec();
SetExecuteFuncForCountryCodeContext(asyncContext);
SetCompleteFuncForCountryCodeContext(asyncContext);
size_t objectArgsNum = 0;
return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
}
void SetExecuteFuncForCountryCodeContext(CountryCodeContext* asyncContext)
{
asyncContext->executeFunc = [&](void *data) -> void {
if (data == nullptr) {
LBSLOGE(LOCATOR_STANDARD, "GetIsoCountryCode data == nullptr");
return;
}
CountryCodeContext *context = static_cast<CountryCodeContext*>(data);
std::shared_ptr<CountryCode> country = std::make_shared<CountryCode>();
LocationErrCode errorCode = g_locatorClient->GetIsoCountryCodeV9(country);
context->errCode = errorCode;
if (errorCode == ERRCODE_SUCCESS) {
context->country = country;
}
};
}
void SetCompleteFuncForCountryCodeContext(CountryCodeContext* asyncContext)
{
asyncContext->completeFunc = [&](void *data) -> void {
if (data == nullptr) {
LBSLOGE(LOCATOR_STANDARD, "GetIsoCountryCode data == nullptr");
return;
}
CountryCodeContext *context = static_cast<CountryCodeContext *>(data);
g_hiAppEventClient->WriteEndEvent(
context->beginTime, context->errCode == ERRCODE_SUCCESS ? 0 : 1, context->errCode, "getCountryCode");
NAPI_CALL_RETURN_VOID(context->env, napi_create_object(context->env, &context->result[PARAM1]));
if (context->country) {
CountryCodeToJs(context->env, context->country, context->result[PARAM1]);
} else {
LBSLOGE(LOCATOR_STANDARD, "country is nullptr!");
}
LBSLOGI(LOCATOR_STANDARD, "Push GetIsoCountryCode result to client, time = %{public}s",
std::to_string(CommonUtils::GetCurrentTimeMilSec()).c_str());
};
}
#endif
#ifdef ENABLE_NAPI_MANAGER
LocationErrCode CheckLocationSwitchState()
{
bool isEnabled = false;
LocationErrCode errorCode = g_locatorClient->IsLocationEnabledV9(isEnabled);
if (errorCode != ERRCODE_SUCCESS) {
return errorCode;
}
if (!isEnabled) {
return ERRCODE_SWITCH_OFF;
}
return ERRCODE_SUCCESS;
}
napi_value AddGnssGeofence(napi_env env, napi_callback_info info)
{
LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator ext SA failed");
if (argc > PARAM1) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
std::shared_ptr<GeofenceRequest> gnssGeofenceRequest = std::make_shared<GeofenceRequest>();
bool isValidParameter = ParseGnssGeofenceRequest(env, argv[0], gnssGeofenceRequest);
if (!isValidParameter) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
auto locationGnssGeofenceCallbackHost =
sptr<LocationGnssGeofenceCallbackNapi>(new LocationGnssGeofenceCallbackNapi());
JsObjToGeofenceTransitionCallback(env, argv[0], locationGnssGeofenceCallbackHost);
auto callbackPtr = sptr<IGnssGeofenceCallback>(locationGnssGeofenceCallbackHost);
gnssGeofenceRequest->SetGeofenceTransitionCallback(callbackPtr->AsObject());
auto asyncContext = new GnssGeofenceAsyncContext(env);
if (napi_create_string_latin1(env, "addGnssGeofence",
NAPI_AUTO_LENGTH, &asyncContext->resourceName) != napi_ok) {
GET_AND_THROW_LAST_ERROR(env);
delete asyncContext;
return nullptr;
}
asyncContext->callbackHost_ = locationGnssGeofenceCallbackHost;
asyncContext->request_ = gnssGeofenceRequest;
asyncContext->beginTime = CommonUtils::GetCurrentTimeMilSec();
SetExecuteFuncForAddGnssGeofenceContext(asyncContext);
SetCompleteFuncForAddGnssGeofenceContext(asyncContext);
return DoAsyncWork(env, asyncContext, argc, argv, 1);
}
void SetExecuteFuncForAddGnssGeofenceContext(GnssGeofenceAsyncContext* asyncContext)
{
LBSLOGI(LOCATOR_STANDARD, "SetExecuteFuncForAddGnssGeofenceContext called.");
asyncContext->executeFunc = [&](void* data) -> void {
if (data == nullptr) {
return;
}
auto context = static_cast<GnssGeofenceAsyncContext*>(data);
auto callbackHost = context->callbackHost_;
auto gnssGeofenceRequest = context->request_;
if (callbackHost != nullptr && gnssGeofenceRequest != nullptr) {
auto errCode = g_geofenceClient->AddGnssGeofence(gnssGeofenceRequest, callbackHost);
if (errCode != ERRCODE_SUCCESS) {
context->errCode = errCode;
}
}
};
}
void SetCompleteFuncForAddGnssGeofenceContext(GnssGeofenceAsyncContext* asyncContext)
{
asyncContext->completeFunc = [&](void* data) -> void {
if (data == nullptr) {
return;
}
auto context = static_cast<GnssGeofenceAsyncContext*>(data);
auto callbackHost = context->callbackHost_;
if (callbackHost != nullptr && context->errCode == ERRCODE_SUCCESS &&
callbackHost->GetGeofenceOperationType() == GnssGeofenceOperateType::GNSS_GEOFENCE_OPT_TYPE_ADD) {
LocationErrCode errCode = callbackHost->DealGeofenceOperationResult();
if (errCode == ERRCODE_SUCCESS) {
int fenceId = callbackHost->GetFenceId();
napi_create_object(context->env, &context->result[PARAM1]);
napi_create_int64(context->env, fenceId, &context->result[PARAM1]);
AddCallbackToGnssGeofenceCallbackHostMap(fenceId, callbackHost);
} else {
context->errCode = errCode;
}
}
};
}
napi_value RemoveGnssGeofence(napi_env env, napi_callback_info info)
{
LBSLOGI(LOCATOR_STANDARD, "RemoveGnssGeofence called.");
LBSLOGI(LOCATOR_STANDARD, "%{public}s called.", __func__);
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
if (argc > PARAM1) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
int fenceId = -1;
napi_valuetype valueType1;
NAPI_CALL(env, napi_typeof(env, argv[0], &valueType1));
if (valueType1 != napi_number) {
HandleSyncErrCode(env, ERRCODE_INVALID_PARAM);
return UndefinedNapiValue(env);
}
NAPI_CALL(env, napi_get_value_int32(env, argv[0], &fenceId));
auto asyncContext = new (std::nothrow) GnssGeofenceAsyncContext(env);
NAPI_ASSERT(env, asyncContext != nullptr, "asyncContext is null.");
asyncContext->fenceId_ = fenceId;
asyncContext->callbackHost_ = FindCallbackInGnssGeofenceCallbackHostMap(fenceId);
if (napi_create_string_latin1(env, "removeGnssGeofence",
NAPI_AUTO_LENGTH, &asyncContext->resourceName) != napi_ok) {
GET_AND_THROW_LAST_ERROR(env);
delete asyncContext;
return nullptr;
}
asyncContext->beginTime = CommonUtils::GetCurrentTimeMilSec();
SetExecuteFuncForRemoveGnssGeofenceContext(asyncContext);
SetCompleteFuncForRemoveGnssGeofenceContext(asyncContext);
size_t objectArgsNum = 1;
return DoAsyncWork(env, asyncContext, argc, argv, objectArgsNum);
}
void SetExecuteFuncForRemoveGnssGeofenceContext(GnssGeofenceAsyncContext* asyncContext)
{
LBSLOGI(LOCATOR_STANDARD, "SetExecuteFuncForRemoveGnssGeofenceContext called.");
asyncContext->executeFunc = [&](void* data) -> void {
auto context = static_cast<GnssGeofenceAsyncContext*>(data);
std::shared_ptr<GeofenceRequest> request = std::make_shared<GeofenceRequest>();
request->SetFenceId(context->fenceId_);
if (context->callbackHost_ == nullptr) {
context->errCode = ERRCODE_GEOFENCE_INCORRECT_ID;
return;
}
context->errCode = g_geofenceClient->RemoveGnssGeofence(request, context->callbackHost_);
auto callbackHost = context->callbackHost_;
if (callbackHost != nullptr) {
if (context->errCode != ERRCODE_SUCCESS) {
}
} else {
context->errCode = ERRCODE_GEOFENCE_INCORRECT_ID;
}
};
}
void SetCompleteFuncForRemoveGnssGeofenceContext(GnssGeofenceAsyncContext* asyncContext)
{
asyncContext->completeFunc = [&](void* data) -> void {
auto context = static_cast<GnssGeofenceAsyncContext*>(data);
auto callbackHost = context->callbackHost_;
if (callbackHost != nullptr && context->errCode == ERRCODE_SUCCESS &&
callbackHost->GetGeofenceOperationType() ==
GnssGeofenceOperateType::GNSS_GEOFENCE_OPT_TYPE_DELETE) {
LocationErrCode errCode = callbackHost->DealGeofenceOperationResult();
if (errCode == ERRCODE_SUCCESS) {
NAPI_CALL_RETURN_VOID(
context->env, napi_get_undefined(context->env, &context->result[PARAM1]));
RemoveCallbackToGnssGeofenceCallbackHostMap(context->fenceId_);
} else {
context->errCode = errCode;
}
}
g_hiAppEventClient->WriteEndEvent(
context->beginTime, context->errCode == ERRCODE_SUCCESS ? 0 : 1, context->errCode, "removeGnssGeofence");
LBSLOGI(LOCATOR_STANDARD, "Push RemoveGnssGeofence result to client");
};
}
napi_value GetGeofenceSupportedCoordTypes(napi_env env, napi_callback_info info)
{
size_t argc = MAXIMUM_JS_PARAMS;
napi_value argv[MAXIMUM_JS_PARAMS];
napi_value thisVar = nullptr;
void* data = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
NAPI_ASSERT(env, g_locatorClient != nullptr, "get locator SA failed");
std::vector<CoordinateSystemType> coordinateSystemTypes;
int64_t beginTime = CommonUtils::GetCurrentTimeMilSec();
LocationErrCode errorCode =
g_geofenceClient->GetGeofenceSupportedCoordTypes(coordinateSystemTypes);
g_hiAppEventClient->WriteEndEvent(
beginTime, errorCode == ERRCODE_SUCCESS ? 0 : 1, errorCode, "getGeofenceSupportedCoordTypes");
if (errorCode != ERRCODE_SUCCESS) {
HandleSyncErrCode(env, errorCode);
return UndefinedNapiValue(env);
}
napi_value res;
NAPI_CALL(env,
napi_create_array_with_length(env, coordinateSystemTypes.size(), &res));
uint32_t idx = 0;
for (auto iter = coordinateSystemTypes.begin(); iter != coordinateSystemTypes.end(); ++iter) {
auto coordType = *iter;
napi_value eachObj;
NAPI_CALL(env, napi_create_int32(env, static_cast<int>(coordType), &eachObj));
NAPI_CALL(env, napi_set_element(env, res, idx++, eachObj));
}
return res;
}
void AddCallbackToGnssGeofenceCallbackHostMap(int fenceId, sptr<LocationGnssGeofenceCallbackNapi> callbackHost)
{
std::unique_lock<std::mutex> lock(g_gnssGeofenceCallbackHostMutex);
g_gnssGeofenceCallbackHostMap.insert(std::make_pair(fenceId, callbackHost));
}
void RemoveCallbackToGnssGeofenceCallbackHostMap(int fenceId)
{
std::unique_lock<std::mutex> lock(g_gnssGeofenceCallbackHostMutex);
auto iterForDelete = g_gnssGeofenceCallbackHostMap.find(fenceId);
if (iterForDelete != g_gnssGeofenceCallbackHostMap.end()) {
g_gnssGeofenceCallbackHostMap.erase(iterForDelete);
}
}
sptr<LocationGnssGeofenceCallbackNapi> FindCallbackInGnssGeofenceCallbackHostMap(int fenceId)
{
std::unique_lock<std::mutex> lock(g_gnssGeofenceCallbackHostMutex);
auto iter = g_gnssGeofenceCallbackHostMap.find(fenceId);
if (iter != g_gnssGeofenceCallbackHostMap.end()) {
return iter->second;
}
return nullptr;
}
#endif
}
}