• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ffi_remote_data.h"
17 
18 #include <cinttypes>
19 
20 #include "hilog/log_cpp.h"
21 
22 using namespace OHOS::FFI;
23 using namespace OHOS;
24 using namespace OHOS::HiviewDFX;
25 
26 namespace {
27 constexpr HiLogLabel LABEL = { LOG_CORE, 0xD003901, "CJ-FFIBindNative" };
28 } // namespace
29 
GetInstance()30 FFIDataManager* FFIDataManager::GetInstance()
31 {
32     static FFIDataManager singleton;
33     return &singleton;
34 }
35 
StoreFFIData(const sptr<FFIData> & data)36 void FFIDataManager::StoreFFIData(const sptr<FFIData>& data)
37 {
38     std::lock_guard<std::mutex> lock(mtx);
39     int64_t id = data->GetID();
40     // 0 represents invalid status
41     if (id == 0) {
42         HiLog::Fatal(LABEL, "FFIData store invalid key");
43         return;
44     }
45     HiLog::Info(LABEL, "FFIData store_ key put in: %{public}" PRId64, id);
46     ffiDataStore_[id] = data;
47 }
48 
StoreRemoteData(const sptr<RemoteData> & data)49 void FFIDataManager::StoreRemoteData(const sptr<RemoteData>& data)
50 {
51     std::lock_guard<std::mutex> lock(mtx);
52     remoteDataStore_[data->GetID()] = data;
53 }
54 
NewFFIDataId()55 int64_t FFIDataManager::NewFFIDataId()
56 {
57     std::lock_guard<std::mutex> lock(mtx);
58     if (static_cast<int64_t>(ffiDataStore_.size()) >= maxCapacity) {
59         HiLog::Fatal(LABEL, "FFIData store_ over max capacity: %{public}" PRId64, maxCapacity);
60         // 0 represents invalid status in CJ RemoteData, will be handled by CJ Exception
61         return 0;
62     }
63     // When ffiDataId over uint64 max value, resetTime will be increased with 1.
64     auto resetTimes = FFIDataIdSafeIncrease();
65     auto resetTimeUpperBound = 2;
66     while ((ffiDataStore_.find(curFFIDataId_) != ffiDataStore_.end()) && resetTimes < resetTimeUpperBound) {
67         resetTimes += FFIDataIdSafeIncrease();
68     }
69     // It means there is no one available id, When resetTimes come to UpperBound 2.
70     if (resetTimes >= resetTimeUpperBound) {
71         HiLog::Fatal(LABEL, "FFIData id run out");
72         // 0 represents invalid status in CJ RemoteData, will be handled by CJ Exception
73         return 0;
74     }
75     HiLog::Info(LABEL, "FFIDataManager new ID : %{public}" PRId64 ", cache size: %{public}zu", curFFIDataId_,
76         ffiDataStore_.size());
77     return curFFIDataId_;
78 }
79 
FFIDataIdSafeIncrease()80 int FFIDataManager::FFIDataIdSafeIncrease()
81 {
82     curFFIDataId_++;
83     if (curFFIDataId_ >= static_cast<uint64_t>(maxId)) {
84         HiLog::Warn(LABEL, "FFIData id: %{public}" PRId64 " over max %{public}" PRId64 ", reset to 0", curFFIDataId_,
85             maxCapacity);
86         curFFIDataId_ = 1;
87         return 1;
88     }
89     return 0;
90 }
91 
RemoteData(int64_t id)92 RemoteData::RemoteData(int64_t id) : id_(id), isValid_(id != 0)
93 {
94     HiLog::Debug(LABEL, "RemoteData constructed: %{public}" PRId64 ".", id_);
95 }
96 
~RemoteData()97 RemoteData::~RemoteData()
98 {
99     HiLog::Debug(LABEL, "RemoteData destructed: %{public}" PRId64 ".", id_);
100     auto cjFunc = CJFFIFnInvoker::GetInstance()->GetCJFuncs().atCOHOSFFIReleaseFFIData;
101     if (!cjFunc) {
102         HiLog::Error(LABEL, "Failed to invoke CJ function: FFIReleaseFFIData!");
103         return;
104     }
105     cjFunc(GetID());
106     isValid_ = false;
107 }
108 
~CJLambdaRemoteData()109 CJLambdaRemoteData::~CJLambdaRemoteData()
110 {
111     auto manager = FFIDataManager::GetInstance();
112     manager->RemoveRemoteData(GetID());
113 }
114 
GetID() const115 int64_t RemoteData::GetID() const
116 {
117     if (!isValid_) {
118         HiLog::Error(LABEL, "RemoteData::GetID error, remote data invalid: %{public}" PRId64 ".", id_);
119     }
120     return id_;
121 }
122 
~FFIData()123 FFIData::~FFIData()
124 {
125     auto cjFunc = CJFFIFnInvoker::GetInstance()->GetCJFuncs().atCOHOSFFIReleaseRemoteData;
126     if (!cjFunc) {
127         HiLog::Error(LABEL, "Failed to invoke CJ function: FFIReleaseRemoteData!");
128         return;
129     }
130     cjFunc(GetID());
131 }
132