* Copyright (C) 2024 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 "geofence_request.h"
#include <parcel.h>
#include "common_utils.h"
#ifdef NOTIFICATION_ENABLE
#include "notification_request.h"
#endif
#include "want_agent.h"
#include "want_agent_helper.h"
namespace OHOS {
namespace Location {
GeofenceRequest::GeofenceRequest()
{
callback_ = nullptr;
scenario_ = -1;
fenceId_ = -1;
uid_ = 0;
appAliveStatus_ = true;
loiterTimeMs_ = 0;
wantAgent_ = nullptr;
pid_ = 0;
tokenId_ = 0;
tokenIdEx_ = 0;
firstTokenId_ = 0;
}
GeofenceRequest::GeofenceRequest(GeofenceRequest& geofenceRequest)
{
this->SetGeofence(geofenceRequest.GetGeofence());
this->SetScenario(geofenceRequest.GetScenario());
this->SetWantAgent(geofenceRequest.GetWantAgent());
this->SetGeofenceTransitionEventList(geofenceRequest.GetGeofenceTransitionEventList());
#ifdef NOTIFICATION_ENABLE
this->SetNotificationRequestList(geofenceRequest.GetNotificationRequestList());
#endif
this->SetGeofenceTransitionCallback(geofenceRequest.GetGeofenceTransitionCallback());
this->SetFenceId(geofenceRequest.GetFenceId());
this->SetBundleName(geofenceRequest.GetBundleName());
this->SetLoiterTimeMs(geofenceRequest.GetLoiterTimeMs());
this->SetFenceExtensionAbilityName(geofenceRequest.GetFenceExtensionAbilityName());
}
GeofenceRequest::~GeofenceRequest() {}
GeoFence GeofenceRequest::GetGeofence()
{
return geofence_;
}
void GeofenceRequest::SetGeofence(GeoFence geofence)
{
geofence_ = geofence;
}
int GeofenceRequest::GetScenario()
{
return scenario_;
}
void GeofenceRequest::SetScenario(int scenario)
{
scenario_ = scenario;
}
int GeofenceRequest::GetLoiterTimeMs()
{
return loiterTimeMs_;
}
void GeofenceRequest::SetLoiterTimeMs(int loiterTimeMs)
{
loiterTimeMs_ = loiterTimeMs;
}
void GeofenceRequest::SetWantAgent(const std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> wantAgent)
{
wantAgent_ = wantAgent;
}
std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> GeofenceRequest::GetWantAgent()
{
return wantAgent_;
}
std::vector<GeofenceTransitionEvent> GeofenceRequest::GetGeofenceTransitionEventList()
{
std::unique_lock<std::mutex> lock(geofenceRequestMutex_);
return transitionStatusList_;
}
void GeofenceRequest::SetGeofenceTransitionEvent(GeofenceTransitionEvent status)
{
std::unique_lock<std::mutex> lock(geofenceRequestMutex_);
transitionStatusList_.push_back(status);
}
void GeofenceRequest::SetGeofenceTransitionEventList(std::vector<GeofenceTransitionEvent> statusList)
{
std::unique_lock<std::mutex> lock(geofenceRequestMutex_);
for (auto it = statusList.begin(); it != statusList.end(); ++it) {
transitionStatusList_.push_back(*it);
}
}
#ifdef NOTIFICATION_ENABLE
std::vector<std::shared_ptr<OHOS::Notification::NotificationRequest>> GeofenceRequest::GetNotificationRequestList()
{
std::unique_lock<std::mutex> lock(geofenceRequestMutex_);
return notificationRequestList_;
}
void GeofenceRequest::SetNotificationRequest(std::shared_ptr<OHOS::Notification::NotificationRequest> request)
{
std::unique_lock<std::mutex> lock(geofenceRequestMutex_);
notificationRequestList_.push_back(request);
}
void GeofenceRequest::SetNotificationRequestList(
std::vector<std::shared_ptr<OHOS::Notification::NotificationRequest>> requestList)
{
std::unique_lock<std::mutex> lock(geofenceRequestMutex_);
for (auto it = requestList.begin(); it != requestList.end(); ++it) {
notificationRequestList_.push_back(*it);
}
}
#endif
void GeofenceRequest::SetGeofenceTransitionCallback(const sptr<IRemoteObject>& callback)
{
callback_ = callback;
}
sptr<IRemoteObject> GeofenceRequest::GetGeofenceTransitionCallback()
{
return callback_;
}
int GeofenceRequest::GetFenceId()
{
return fenceId_;
}
void GeofenceRequest::SetFenceId(int fenceId)
{
fenceId_ = fenceId;
}
const std::string& GeofenceRequest::GetBundleName()
{
return bundleName_;
}
void GeofenceRequest::SetBundleName(const std::string& bundleName)
{
bundleName_ = bundleName;
}
const std::string& GeofenceRequest::GetFenceExtensionAbilityName()
{
return fenceExtensionAbilityName_;
}
void GeofenceRequest::SetFenceExtensionAbilityName(const std::string& fenceExtensionAbilityName)
{
fenceExtensionAbilityName_ = fenceExtensionAbilityName;
}
int32_t GeofenceRequest::GetUid()
{
return uid_;
}
void GeofenceRequest::SetUid(int32_t uid)
{
uid_ = uid;
}
int32_t GeofenceRequest::GetPid()
{
return pid_;
}
void GeofenceRequest::SetPid(int32_t pid)
{
pid_ = pid;
}
uint32_t GeofenceRequest::GetTokenId()
{
return tokenId_;
}
void GeofenceRequest::SetTokenId(uint32_t tokenId)
{
tokenId_ = tokenId;
}
uint32_t GeofenceRequest::GetTokenIdEx()
{
return tokenIdEx_;
}
void GeofenceRequest::SetTokenIdEx(uint32_t tokenIdEx)
{
tokenIdEx_ = tokenIdEx;
}
uint32_t GeofenceRequest::GetFirstTokenId()
{
return firstTokenId_;
}
void GeofenceRequest::SetFirstTokenId(uint32_t firstTokenId)
{
firstTokenId_ = firstTokenId;
}
bool GeofenceRequest::GetAppAliveStatus()
{
return appAliveStatus_;
}
int64_t GeofenceRequest::GetRequestExpirationTimeStamp()
{
return requestExpirationTimeStamp_;
}
void GeofenceRequest::SetRequestExpirationTimeStamp(int64_t requestExpirationTimeStamp)
{
requestExpirationTimeStamp_ = requestExpirationTimeStamp;
}
void GeofenceRequest::SetAppAliveStatus(bool appAliveStatus)
{
appAliveStatus_ = appAliveStatus;
}
void GeofenceRequest::SetTransitionCallbackDeathRecipient(const sptr<IRemoteObject::DeathRecipient>& deathRecipient)
{
transitionCallbackDeathRecipient_ = deathRecipient;
}
sptr<IRemoteObject::DeathRecipient> GeofenceRequest::GetTransitionCallbackRecipient()
{
return transitionCallbackDeathRecipient_;
}
void GeofenceRequest::ReadFromParcel(Parcel& data)
{
std::unique_lock<std::mutex> lock(geofenceRequestMutex_);
fenceId_ = data.ReadInt32();
scenario_ = data.ReadInt32();
loiterTimeMs_ = data.ReadInt32();
geofence_.latitude = data.ReadDouble();
geofence_.longitude = data.ReadDouble();
geofence_.radius = data.ReadDouble();
geofence_.expiration = data.ReadDouble();
geofence_.coordinateSystemType = static_cast<CoordinateSystemType>(data.ReadInt32());
int monitorGeofenceTransitionSize = data.ReadInt32();
if (monitorGeofenceTransitionSize > MAX_TRANSITION_SIZE) {
LBSLOGE(LOCATOR, "fence transition list size should not be greater than 3");
return;
}
for (int i = 0; i < monitorGeofenceTransitionSize; i++) {
transitionStatusList_.push_back(static_cast<GeofenceTransitionEvent>(data.ReadInt32()));
}
#ifdef NOTIFICATION_ENABLE
int requestSize = data.ReadInt32();
if (requestSize > MAX_NOTIFICATION_REQUEST_LIST_SIZE) {
LBSLOGE(LOCATOR, "request size should not be greater than 3");
return;
}
for (int i = 0; i < requestSize; i++) {
std::shared_ptr<OHOS::Notification::NotificationRequest> request(
OHOS::Notification::NotificationRequest::Unmarshalling(data));
if (request != nullptr) {
notificationRequestList_.push_back(request);
}
}
#endif
callback_ = data.ReadObject<IRemoteObject>();
data.ReadString(fenceExtensionAbilityName_);
ReadAppInfo(data);
AbilityRuntime::WantAgent::WantAgent* wantAgentData =
AbilityRuntime::WantAgent::WantAgent::Unmarshalling(data);
if (wantAgentData == nullptr) {
return;
}
std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> wantAgent =
std::make_shared<AbilityRuntime::WantAgent::WantAgent>(*wantAgentData);
if (wantAgent != nullptr) {
wantAgent_ = wantAgent;
}
delete wantAgentData;
wantAgentData = nullptr;
}
void GeofenceRequest::ReadAppInfo(Parcel& data)
{
data.ReadString(bundleName_);
uid_ = data.ReadInt32();
pid_ = data.ReadInt32();
tokenId_ = data.ReadUint32();
tokenIdEx_ = data.ReadUint32();
firstTokenId_ = data.ReadUint32();
}
bool GeofenceRequest::Marshalling(Parcel& parcel) const
{
std::unique_lock<std::mutex> lock(geofenceRequestMutex_);
parcel.WriteInt32(fenceId_);
parcel.WriteInt32(scenario_);
parcel.WriteInt32(loiterTimeMs_);
parcel.WriteDouble(geofence_.latitude);
parcel.WriteDouble(geofence_.longitude);
parcel.WriteDouble(geofence_.radius);
parcel.WriteDouble(geofence_.expiration);
parcel.WriteInt32(static_cast<int>(geofence_.coordinateSystemType));
if (transitionStatusList_.size() > MAX_TRANSITION_SIZE) {
LBSLOGE(LOCATOR, "fence transition list size should not be greater than 3");
return false;
}
parcel.WriteInt32(transitionStatusList_.size());
for (size_t i = 0; i < transitionStatusList_.size(); i++) {
parcel.WriteInt32(static_cast<int>(transitionStatusList_[i]));
}
#ifdef NOTIFICATION_ENABLE
parcel.WriteInt32(notificationRequestList_.size());
if (notificationRequestList_.size() > MAX_NOTIFICATION_REQUEST_LIST_SIZE) {
LBSLOGE(LOCATOR, "request size should not be greater than 3");
return false;
}
for (size_t i = 0; i < notificationRequestList_.size(); i++) {
if (notificationRequestList_[i] != nullptr) {
notificationRequestList_[i]->Marshalling(parcel);
}
}
#endif
parcel.WriteRemoteObject(callback_);
parcel.WriteString(fenceExtensionAbilityName_);
parcel.WriteString(bundleName_);
parcel.WriteInt32(uid_);
parcel.WriteInt32(pid_);
parcel.WriteUint32(tokenId_);
parcel.WriteUint32(tokenIdEx_);
parcel.WriteUint32(firstTokenId_);
if (wantAgent_ != nullptr) {
wantAgent_->Marshalling(parcel);
}
return true;
}
std::shared_ptr<GeofenceRequest> GeofenceRequest::UnmarshallingShared(Parcel& parcel)
{
std::shared_ptr<GeofenceRequest> geofenceRequest = std::make_shared<GeofenceRequest>();
geofenceRequest->ReadFromParcel(parcel);
return geofenceRequest;
}
GeofenceRequest* GeofenceRequest::Unmarshalling(Parcel& parcel)
{
auto geofenceRequest = new GeofenceRequest();
geofenceRequest->ReadFromParcel(parcel);
return geofenceRequest;
}
bool GeofenceRequest::ToJson(nlohmann::json &jsonObject)
{
jsonObject["transitionStatusList"] = transitionStatusList_;
#ifdef NOTIFICATION_ENABLE
nlohmann::json notificationArr = nlohmann::json::array();
for (auto notificationRequest : notificationRequestList_) {
if (notificationRequest != nullptr) {
nlohmann::json jsonObj;
notificationRequest->ToJson(jsonObj);
notificationArr.emplace_back(jsonObj);
}
}
jsonObject["notificationRequestList"] = notificationArr;
#endif
nlohmann::json jsonGeofenceObj;
jsonGeofenceObj["latitude"] = geofence_.latitude;
jsonGeofenceObj["longitude"] = geofence_.longitude;
jsonGeofenceObj["radius"] = geofence_.radius;
jsonGeofenceObj["expiration"] = geofence_.expiration;
jsonGeofenceObj["coordinateSystemType"] = geofence_.coordinateSystemType;
jsonObject["geofence"] = jsonGeofenceObj;
jsonObject["scenario"] = scenario_;
jsonObject["loiterTimeMs"] = loiterTimeMs_;
jsonObject["fenceId"] = fenceId_;
jsonObject["uid"] = uid_;
jsonObject["pid"] = pid_;
jsonObject["tokenId"] = tokenId_;
jsonObject["tokenIdEx"] = tokenIdEx_;
jsonObject["firstTokenId"] = firstTokenId_;
jsonObject["wantAgent"] = wantAgent_ ? AbilityRuntime::WantAgent::WantAgentHelper::ToString(wantAgent_) : "";
jsonObject["bundleName"] = bundleName_;
jsonObject["fenceExtensionAbilityName"] = fenceExtensionAbilityName_;
jsonObject["appAliveStatus"] = appAliveStatus_;
jsonObject["requestExpirationTimeStamp"] = requestExpirationTimeStamp_;
return true;
}
void GeofenceRequest::ConvertGeoFenceInfo(const nlohmann::json &geofenceObj, GeoFence& geofence)
{
if (geofenceObj.find("latitude") != geofenceObj.cend() && geofenceObj.at("latitude").is_number()) {
geofence.latitude = geofenceObj.at("latitude").get<double>();
}
if (geofenceObj.find("longitude") != geofenceObj.cend() && geofenceObj.at("longitude").is_number()) {
geofence.longitude = geofenceObj.at("longitude").get<double>();
}
if (geofenceObj.find("radius") != geofenceObj.cend() && geofenceObj.at("radius").is_number()) {
geofence.radius = geofenceObj.at("radius").get<double>();
}
if (geofenceObj.find("expiration") != geofenceObj.cend() && geofenceObj.at("expiration").is_number()) {
geofence.expiration = geofenceObj.at("expiration").get<double>();
}
if (geofenceObj.find("coordinateSystemType") != geofenceObj.cend() &&
geofenceObj.at("coordinateSystemType").is_number_integer()) {
geofence.coordinateSystemType = geofenceObj.at("coordinateSystemType");
}
}
void GeofenceRequest::ConvertTransitionEventInfo(std::shared_ptr<GeofenceRequest>& request,
const nlohmann::json &jsonObject)
{
if (jsonObject.find("transitionStatusList") != jsonObject.cend() &&
jsonObject.at("transitionStatusList").is_array()) {
for (const auto& elem : jsonObject.at("transitionStatusList")) {
if (elem.is_number_integer()) {
request->transitionStatusList_.emplace_back(elem.get<GeofenceTransitionEvent>());
}
}
}
}
void GeofenceRequest::ConvertNotificationInfo(std::shared_ptr<GeofenceRequest>& request,
const nlohmann::json &jsonObject)
{
#ifdef NOTIFICATION_ENABLE
if (jsonObject.find("notificationRequestList") != jsonObject.cend()) {
auto notificationArray = jsonObject.at("notificationRequestList");
for (auto ¬ificationJson : notificationArray) {
OHOS::Notification::NotificationRequest *notification =
OHOS::Notification::NotificationRequest::FromJson(notificationJson);
if (notification == nullptr) {
continue;
}
auto notificationPtr = std::make_shared<OHOS::Notification::NotificationRequest>(*notification);
if (notificationPtr != nullptr) {
request->SetNotificationRequest(notificationPtr);
}
delete notification;
}
}
#endif
}
void GeofenceRequest::ConvertWantAgentInfo(std::shared_ptr<GeofenceRequest>& request,
const nlohmann::json &jsonObject)
{
if (jsonObject.find("wantAgent") != jsonObject.cend() && jsonObject.at("wantAgent").is_string()) {
auto wantAgentValue = jsonObject.at("wantAgent").get<std::string>();
auto wantAgent = AbilityRuntime::WantAgent::WantAgentHelper::FromString(wantAgentValue);
if (wantAgent != nullptr) {
AbilityRuntime::WantAgent::WantAgentConstant::OperationType operationType =
AbilityRuntime::WantAgent::WantAgentHelper::GetType(wantAgent);
std::shared_ptr<AAFwk::Want> want = OHOS::AbilityRuntime::WantAgent::WantAgentHelper::GetWant(wantAgent);
std::vector<std::shared_ptr<AAFwk::Want>> wants;
wants.push_back(want);
std::vector<OHOS::AbilityRuntime::WantAgent::WantAgentConstant::Flags> flags;
flags.push_back(OHOS::AbilityRuntime::WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG);
AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo(
0, operationType, flags, wants, nullptr);
request->wantAgent_ = AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo);
}
}
}
void GeofenceRequest::ConvertGeofenceRequestInfo(std::shared_ptr<GeofenceRequest>& request,
const nlohmann::json &jsonObject)
{
if (jsonObject.find("scenario") != jsonObject.cend() && jsonObject.at("scenario").is_number()) {
request->scenario_ = jsonObject.at("scenario").get<int>();
}
if (jsonObject.find("loiterTimeMs") != jsonObject.cend() && jsonObject.at("loiterTimeMs").is_number()) {
request->loiterTimeMs_ = jsonObject.at("loiterTimeMs").get<int>();
}
if (jsonObject.find("fenceId") != jsonObject.cend() && jsonObject.at("fenceId").is_number()) {
request->fenceId_ = jsonObject.at("fenceId").get<int>();
}
if (jsonObject.find("uid") != jsonObject.cend() && jsonObject.at("uid").is_number()) {
request->uid_ = jsonObject.at("uid").get<int32_t>();
}
if (jsonObject.find("bundleName") != jsonObject.cend() && jsonObject.at("bundleName").is_string()) {
request->bundleName_ = jsonObject.at("bundleName").get<std::string>();
}
if (jsonObject.find("fenceExtensionAbilityName") != jsonObject.cend() &&
jsonObject.at("fenceExtensionAbilityName").is_string()) {
request->fenceExtensionAbilityName_ = jsonObject.at("fenceExtensionAbilityName").get<std::string>();
}
if (jsonObject.find("appAliveStatus") != jsonObject.cend() && jsonObject.at("appAliveStatus").is_boolean()) {
request->appAliveStatus_ = jsonObject.at("appAliveStatus").get<bool>();
}
if (jsonObject.find("requestExpirationTimeStamp") != jsonObject.cend() &&
jsonObject.at("requestExpirationTimeStamp").is_number()) {
request->requestExpirationTimeStamp_ = jsonObject.at("requestExpirationTimeStamp").get<int64_t>();
}
ConvertGeofenceRequestInfoExt(request, jsonObject);
}
void GeofenceRequest::ConvertGeofenceRequestInfoExt(std::shared_ptr<GeofenceRequest>& request,
const nlohmann::json &jsonObject)
{
if (jsonObject.find("pid") != jsonObject.cend() && jsonObject.at("pid").is_number()) {
request->pid_ = jsonObject.at("pid").get<int32_t>();
}
if (jsonObject.find("tokenId") != jsonObject.cend() && jsonObject.at("tokenId").is_number()) {
request->tokenId_ = jsonObject.at("tokenId").get<uint32_t>();
}
if (jsonObject.find("tokenIdEx") != jsonObject.cend() && jsonObject.at("tokenIdEx").is_number()) {
request->tokenIdEx_ = jsonObject.at("tokenIdEx").get<uint32_t>();
}
if (jsonObject.find("firstTokenId") != jsonObject.cend() && jsonObject.at("firstTokenId").is_number()) {
request->firstTokenId_ = jsonObject.at("firstTokenId").get<uint32_t>();
}
}
std::shared_ptr<GeofenceRequest> GeofenceRequest::FromJson(const nlohmann::json &jsonObject)
{
if (jsonObject.is_null() || !jsonObject.is_object()) {
LBSLOGE(LOCATOR, "Invalid JSON object.");
return nullptr;
}
auto request = std::make_shared<GeofenceRequest>();
if (request == nullptr) {
LBSLOGE(LOCATOR, "Failed to create request instance");
return nullptr;
}
ConvertTransitionEventInfo(request, jsonObject);
ConvertNotificationInfo(request, jsonObject);
ConvertWantAgentInfo(request, jsonObject);
if (jsonObject.find("geofence") != jsonObject.cend()) {
auto geofenceObj = jsonObject.at("geofence");
if (!geofenceObj.is_null()) {
ConvertGeoFenceInfo(geofenceObj, request->geofence_);
}
}
ConvertGeofenceRequestInfo(request, jsonObject);
return request;
}
bool GeofenceRequest::IsTokenIdValid()
{
if (pid_ == 0 && tokenId_ == 0 && tokenIdEx_ == 0 && firstTokenId_ == 0) {
LBSLOGI(GNSS, "App TokenId InValid.");
return false;
}
return true;
}
}
}