* Copyright (C) 2026 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 "fusion_fence_request.h"
#include <parcel.h>
#include "location_log.h"
namespace OHOS {
namespace Location {
bool FusionFencePoint::Marshalling(Parcel& parcel) const
{
return parcel.WriteDouble(latitude) && parcel.WriteDouble(longitude);
}
bool FusionFencePoint::ReadFromParcel(Parcel& parcel)
{
latitude = parcel.ReadDouble();
longitude = parcel.ReadDouble();
return true;
}
bool FusionFenceCellInfo::Marshalling(Parcel& parcel) const
{
return parcel.WriteInt64(timeSinceBoot) &&
parcel.WriteInt64(cellId) &&
parcel.WriteInt32(lac) &&
parcel.WriteInt32(mcc) &&
parcel.WriteInt32(mnc) &&
parcel.WriteInt32(rat) &&
parcel.WriteInt32(signalIntensity) &&
parcel.WriteInt32(arfcn) &&
parcel.WriteInt32(pci) &&
parcel.WriteInt32(tac) &&
parcel.WriteInt32(static_cast<int32_t>(additionsMap.size())) &&
[this, &parcel]() {
for (const auto& [key, value] : additionsMap) {
if (!parcel.WriteString(key) || !parcel.WriteString(value)) {
return false;
}
}
return true;
}();
}
bool FusionFenceCellInfo::ReadFromParcel(Parcel& parcel)
{
timeSinceBoot = parcel.ReadInt64();
cellId = parcel.ReadInt64();
lac = parcel.ReadInt32();
mcc = parcel.ReadInt32();
mnc = parcel.ReadInt32();
rat = parcel.ReadInt32();
signalIntensity = parcel.ReadInt32();
arfcn = parcel.ReadInt32();
pci = parcel.ReadInt32();
tac = parcel.ReadInt32();
int32_t mapSize = parcel.ReadInt32();
constexpr int32_t MAX_ADDITIONS_MAP_SIZE = 100;
if (mapSize > MAX_ADDITIONS_MAP_SIZE) {
mapSize = MAX_ADDITIONS_MAP_SIZE;
}
for (int32_t i = 0; i < mapSize; i++) {
std::string key = parcel.ReadString();
std::string value = parcel.ReadString();
additionsMap[key] = value;
}
return true;
}
bool FusionFenceCell::Marshalling(Parcel& parcel) const
{
if (!parcel.WriteInt32(static_cast<int32_t>(cellInfos.size()))) {
return false;
}
for (const auto& cellInfo : cellInfos) {
if (!cellInfo.Marshalling(parcel)) {
return false;
}
}
return true;
}
bool FusionFenceCell::ReadFromParcel(Parcel& parcel)
{
int32_t size = parcel.ReadInt32();
constexpr int32_t MAX_CELL_FENCES_COUNT = 1000;
if (size > MAX_CELL_FENCES_COUNT) {
LBSLOGE(FUSION_FENCE, "cellInfos size %{public}d exceeds max %{public}d", size, MAX_CELL_FENCES_COUNT);
return false;
}
for (int32_t i = 0; i < size; i++) {
FusionFenceCellInfo cellInfo;
if (!cellInfo.ReadFromParcel(parcel)) {
return false;
}
cellInfos.push_back(cellInfo);
}
return true;
}
bool WirelessSignalFeature::Marshalling(Parcel& parcel) const
{
if (!parcel.WriteInt32(rssiAvg)) {
return false;
}
if (!parcel.WriteDouble(rssiStandardDeviation)) {
return false;
}
if (!parcel.WriteInt32(static_cast<int32_t>(mac.size()))) {
return false;
}
for (const auto& macAddr : mac) {
if (!parcel.WriteString(macAddr)) {
return false;
}
}
return true;
}
bool WirelessSignalFeature::ReadFromParcel(Parcel& parcel)
{
rssiAvg = parcel.ReadInt32();
rssiStandardDeviation = parcel.ReadDouble();
int32_t macSize = parcel.ReadInt32();
constexpr int32_t MAX_MAC_SIZE = 150;
if (macSize > MAX_MAC_SIZE) {
LBSLOGE(FUSION_FENCE, "mac size %{public}d exceeds max %{public}d", macSize, MAX_MAC_SIZE);
return false;
}
for (int32_t i = 0; i < macSize; i++) {
mac.push_back(parcel.ReadString());
}
return true;
}
bool FusionFenceWifi::Marshalling(Parcel& parcel) const
{
if (!parcel.WriteInt32(static_cast<int32_t>(type))) {
return false;
}
if (!parcel.WriteInt32(static_cast<int32_t>(wifiFeatures.size()))) {
return false;
}
for (const auto& feature : wifiFeatures) {
if (!feature.Marshalling(parcel)) {
return false;
}
}
return true;
}
bool FusionFenceWifi::ReadFromParcel(Parcel& parcel)
{
type = static_cast<WifiFingerprintType>(parcel.ReadInt32());
int32_t size = parcel.ReadInt32();
constexpr int32_t MAX_WIFI_FEATURES_COUNT = 150;
if (size > MAX_WIFI_FEATURES_COUNT) {
LBSLOGE(FUSION_FENCE, "wifiFeatures size %{public}d exceeds max %{public}d", size, MAX_WIFI_FEATURES_COUNT);
return false;
}
for (int32_t i = 0; i < size; i++) {
WirelessSignalFeature feature;
if (!feature.ReadFromParcel(parcel)) {
return false;
}
wifiFeatures.push_back(feature);
}
return true;
}
bool FusionFenceGnss::Marshalling(Parcel& parcel) const
{
if (!parcel.WriteInt32(static_cast<int32_t>(gnssFenceType))) {
return false;
}
if (circularFence != nullptr) {
if (!parcel.WriteInt32(1) || !circularFence->Marshalling(parcel)) {
return false;
}
} else {
if (!parcel.WriteInt32(0)) {
return false;
}
}
if (!parcel.WriteInt32(static_cast<int32_t>(polygon.size()))) {
return false;
}
for (const auto& point : polygon) {
if (!point.Marshalling(parcel)) {
return false;
}
}
return true;
}
bool FusionFenceGnss::ReadFromParcel(Parcel& parcel)
{
gnssFenceType = static_cast<GnssFenceType>(parcel.ReadInt32());
int32_t hasCircular = parcel.ReadInt32();
if (hasCircular == 1) {
circularFence = Geofence::UnmarshallingMakeUnique(parcel);
if (circularFence == nullptr) {
LBSLOGE(FUSION_FENCE, "FusionFenceGnss::ReadFromParcel: circularFence unmarshalling failed");
return false;
}
}
int32_t polygonSize = parcel.ReadInt32();
constexpr int32_t MAX_POLYGON_POINTS_COUNT = 10;
if (polygonSize > MAX_POLYGON_POINTS_COUNT) {
LBSLOGE(FUSION_FENCE, "polygon size %{public}d exceeds max %{public}d", polygonSize, MAX_POLYGON_POINTS_COUNT);
return false;
}
for (int32_t i = 0; i < polygonSize; i++) {
FusionFencePoint point;
if (!point.ReadFromParcel(parcel)) {
return false;
}
polygon.push_back(point);
}
return true;
}
bool FusionFenceTransition::Marshalling(Parcel& parcel) const
{
return parcel.WriteString(identifier) &&
parcel.WriteInt32(static_cast<int32_t>(scene)) &&
parcel.WriteInt32(static_cast<int32_t>(transitionEvent));
}
bool FusionFenceTransition::ReadFromParcel(Parcel& parcel)
{
identifier = parcel.ReadString();
scene = static_cast<FusionFenceScene>(parcel.ReadInt32());
transitionEvent = static_cast<GeofenceTransitionEvent>(parcel.ReadInt32());
return true;
}
FusionFenceTransition* FusionFenceTransition::Unmarshalling(Parcel& parcel)
{
FusionFenceTransition* transition = new FusionFenceTransition();
if (!transition->ReadFromParcel(parcel)) {
delete transition;
return nullptr;
}
return transition;
}
FusionFenceRequest::FusionFenceRequest()
{
fenceType_ = 0;
poiLocation_ = {0.0, 0.0};
monitorTransitionEvents_ = 0;
loiterTimeMs_ = 0;
expirationMs_ = 0;
transitionCallback_ = nullptr;
uid_ = 0;
pid_ = 0;
tokenId_ = 0;
tokenIdEx_ = 0;
firstTokenId_ = 0;
}
FusionFenceRequest::FusionFenceRequest(const FusionFenceRequest& request)
{
identifier_ = request.identifier_;
scene_ = request.scene_;
fenceType_ = request.fenceType_;
poiType_ = request.poiType_;
poiLocation_ = request.poiLocation_;
monitorTransitionEvents_ = request.monitorTransitionEvents_;
loiterTimeMs_ = request.loiterTimeMs_;
gnssFences_ = request.gnssFences_;
cellFences_ = request.cellFences_;
wifiFences_ = request.wifiFences_;
expirationMs_ = request.expirationMs_;
transitionCallback_ = request.transitionCallback_;
bundleName_ = request.bundleName_;
uid_ = request.uid_;
pid_ = request.pid_;
tokenId_ = request.tokenId_;
tokenIdEx_ = request.tokenIdEx_;
firstTokenId_ = request.firstTokenId_;
}
FusionFenceRequest::~FusionFenceRequest() {}
std::string FusionFenceRequest::GetIdentifier() const
{
return identifier_;
}
void FusionFenceRequest::SetIdentifier(const std::string& identifier)
{
identifier_ = identifier;
}
FusionFenceScene FusionFenceRequest::GetScene() const
{
return scene_;
}
void FusionFenceRequest::SetScene(FusionFenceScene scene)
{
scene_ = scene;
}
int32_t FusionFenceRequest::GetFenceType() const
{
return fenceType_;
}
void FusionFenceRequest::SetFenceType(int32_t fenceType)
{
fenceType_ = fenceType;
}
std::string FusionFenceRequest::GetPoiType() const
{
return poiType_;
}
void FusionFenceRequest::SetPoiType(const std::string& poiType)
{
poiType_ = poiType;
}
FusionFencePoint FusionFenceRequest::GetPoiLocation() const
{
return poiLocation_;
}
void FusionFenceRequest::SetPoiLocation(const FusionFencePoint& poiLocation)
{
poiLocation_ = poiLocation;
}
int32_t FusionFenceRequest::GetMonitorTransitionEvents() const
{
return monitorTransitionEvents_;
}
void FusionFenceRequest::SetMonitorTransitionEvents(int32_t monitorTransitionEvents)
{
monitorTransitionEvents_ = monitorTransitionEvents;
}
int64_t FusionFenceRequest::GetLoiterTimeMs() const
{
return loiterTimeMs_;
}
void FusionFenceRequest::SetLoiterTimeMs(int64_t loiterTimeMs)
{
loiterTimeMs_ = loiterTimeMs;
}
const std::vector<std::shared_ptr<FusionFenceGnss>>& FusionFenceRequest::GetGnssFences() const
{
return gnssFences_;
}
void FusionFenceRequest::SetGnssFences(const std::vector<std::shared_ptr<FusionFenceGnss>>& gnssFences)
{
gnssFences_ = gnssFences;
}
const std::vector<std::shared_ptr<FusionFenceCell>>& FusionFenceRequest::GetCellFences() const
{
return cellFences_;
}
void FusionFenceRequest::SetCellFences(const std::vector<std::shared_ptr<FusionFenceCell>>& cellFences)
{
cellFences_ = cellFences;
}
const std::vector<std::shared_ptr<FusionFenceWifi>>& FusionFenceRequest::GetWifiFences() const
{
return wifiFences_;
}
void FusionFenceRequest::SetWifiFences(const std::vector<std::shared_ptr<FusionFenceWifi>>& wifiFences)
{
wifiFences_ = wifiFences;
}
int64_t FusionFenceRequest::GetExpirationMs() const
{
return expirationMs_;
}
void FusionFenceRequest::SetExpirationMs(int64_t expirationMs)
{
expirationMs_ = expirationMs;
}
sptr<IRemoteObject> FusionFenceRequest::GetTransitionCallback()
{
return transitionCallback_;
}
void FusionFenceRequest::SetTransitionCallback(sptr<IRemoteObject> callback)
{
transitionCallback_ = callback;
}
std::string FusionFenceRequest::GetBundleName() const
{
return bundleName_;
}
void FusionFenceRequest::SetBundleName(const std::string& bundleName)
{
bundleName_ = bundleName;
}
int32_t FusionFenceRequest::GetUid() const
{
return uid_;
}
void FusionFenceRequest::SetUid(int32_t uid)
{
uid_ = uid;
}
int32_t FusionFenceRequest::GetPid() const
{
return pid_;
}
void FusionFenceRequest::SetPid(int32_t pid)
{
pid_ = pid;
}
int64_t FusionFenceRequest::GetTokenId() const
{
return tokenId_;
}
void FusionFenceRequest::SetTokenId(int64_t tokenId)
{
tokenId_ = tokenId;
}
int64_t FusionFenceRequest::GetTokenIdEx() const
{
return tokenIdEx_;
}
void FusionFenceRequest::SetTokenIdEx(int64_t tokenIdEx)
{
tokenIdEx_ = tokenIdEx;
}
int64_t FusionFenceRequest::GetFirstTokenId() const
{
return firstTokenId_;
}
void FusionFenceRequest::SetFirstTokenId(int64_t firstTokenId)
{
firstTokenId_ = firstTokenId;
}
template<typename T>
static bool MarshallingFenceArray(Parcel& parcel, const std::vector<std::shared_ptr<T>>& fences)
{
if (!parcel.WriteInt32(static_cast<int32_t>(fences.size()))) {
return false;
}
for (const auto& fence : fences) {
int32_t hasFence = (fence != nullptr) ? 1 : 0;
if (!parcel.WriteInt32(hasFence)) {
return false;
}
if (fence != nullptr && !fence->Marshalling(parcel)) {
return false;
}
}
return true;
}
template<typename T>
static bool ReadFromParcelFenceArray(Parcel& parcel, std::vector<std::shared_ptr<T>>& fences)
{
int32_t fenceSize = parcel.ReadInt32();
constexpr int32_t MAX_FENCE_ARRAY_SIZE = 30;
if (fenceSize > MAX_FENCE_ARRAY_SIZE) {
LBSLOGE(FUSION_FENCE, "fence array size %{public}d exceeds max %{public}d", fenceSize, MAX_FENCE_ARRAY_SIZE);
return false;
}
for (int32_t i = 0; i < fenceSize; i++) {
int32_t hasFence = parcel.ReadInt32();
if (hasFence == 1) {
auto fence = std::make_shared<T>();
if (!fence->ReadFromParcel(parcel)) {
LBSLOGE(FUSION_FENCE, "fence ReadFromParcel failed at index %{public}d", i);
return false;
}
fences.push_back(fence);
}
}
return true;
}
static bool MarshallingBasicFields(Parcel& parcel, const FusionFenceRequest& request)
{
return parcel.WriteString(request.GetIdentifier()) &&
parcel.WriteInt32(static_cast<int32_t>(request.GetScene())) &&
parcel.WriteInt32(request.GetFenceType()) &&
parcel.WriteString(request.GetPoiType()) &&
request.GetPoiLocation().Marshalling(parcel) &&
parcel.WriteInt32(request.GetMonitorTransitionEvents()) &&
parcel.WriteInt64(request.GetLoiterTimeMs());
}
bool FusionFenceRequest::Marshalling(Parcel& parcel) const
{
return MarshallingBasicFields(parcel, *this) &&
MarshallingFenceArray(parcel, gnssFences_) &&
MarshallingFenceArray(parcel, cellFences_) &&
MarshallingFenceArray(parcel, wifiFences_) &&
parcel.WriteInt64(expirationMs_) &&
parcel.WriteRemoteObject(transitionCallback_);
}
static bool ReadFromParcelBasicFields(Parcel& parcel, FusionFenceRequest& request)
{
request.SetIdentifier(parcel.ReadString());
request.SetScene(static_cast<FusionFenceScene>(parcel.ReadInt32()));
request.SetFenceType(parcel.ReadInt32());
request.SetPoiType(parcel.ReadString());
FusionFencePoint poiLocation;
poiLocation.ReadFromParcel(parcel);
request.SetPoiLocation(poiLocation);
request.SetMonitorTransitionEvents(parcel.ReadInt32());
request.SetLoiterTimeMs(parcel.ReadInt64());
return true;
}
bool FusionFenceRequest::ReadFromParcel(Parcel& parcel)
{
if (!ReadFromParcelBasicFields(parcel, *this)) {
return false;
}
if (!ReadFromParcelFenceArray(parcel, gnssFences_)) {
return false;
}
if (!ReadFromParcelFenceArray(parcel, cellFences_)) {
return false;
}
if (!ReadFromParcelFenceArray(parcel, wifiFences_)) {
return false;
}
expirationMs_ = parcel.ReadInt64();
transitionCallback_ = parcel.ReadObject<IRemoteObject>();
return true;
}
FusionFenceRequest* FusionFenceRequest::Unmarshalling(Parcel& parcel)
{
FusionFenceRequest* request = new FusionFenceRequest();
if (!request->ReadFromParcel(parcel)) {
delete request;
return nullptr;
}
return request;
}
}
}