• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 <if_system_ability_manager.h>
17 #include <iservice_registry.h>
18 
19 #include "message_parcel_warp.h"
20 #include "pasteboard_client_death_observer_stub.h"
21 #include "pasteboard_error.h"
22 #include "pasteboard_hilog.h"
23 #include "pasteboard_load_callback.h"
24 #include "pasteboard_service_loader.h"
25 #include "system_ability_definition.h"
26 
27 namespace OHOS {
28 namespace MiscServices {
29 
30 constexpr int32_t LOADSA_TIMEOUT_MS = 4000;
31 constexpr int64_t MIN_ASHMEM_DATA_SIZE = 32 * 1024; // 32K
32 sptr<IPasteboardService> PasteboardServiceLoader::pasteboardServiceProxy_;
33 std::condition_variable PasteboardServiceLoader::proxyConVar_;
34 PasteboardServiceLoader::StaticDestroyMonitor PasteboardServiceLoader::staticDestroyMonitor_;
35 sptr<IRemoteObject> clientDeathObserverPtr_;
36 std::mutex PasteboardServiceLoader::instanceLock_;
37 
PasteboardServiceLoader()38 PasteboardServiceLoader::PasteboardServiceLoader()
39 {
40 }
41 
~PasteboardServiceLoader()42 PasteboardServiceLoader::~PasteboardServiceLoader()
43 {
44     if (staticDestroyMonitor_.IsDestroyed()) {
45         return;
46     }
47     auto pasteboardServiceProxy = GetPasteboardServiceProxy();
48     if (pasteboardServiceProxy == nullptr) {
49         return;
50     }
51     auto remoteObject = pasteboardServiceProxy->AsObject();
52     if (remoteObject == nullptr) {
53         return;
54     }
55     remoteObject->RemoveDeathRecipient(deathRecipient_);
56 }
57 
CleanupResource()58 void PasteboardServiceLoader::CleanupResource()
59 {
60     if (staticDestroyMonitor_.IsDestroyed()) {
61         return;
62     }
63     auto pasteboardServiceProxy = GetPasteboardService();
64     if (pasteboardServiceProxy == nullptr) {
65         return;
66     }
67     auto remoteObject = pasteboardServiceProxy->AsObject();
68     if (remoteObject == nullptr) {
69         return;
70     }
71     remoteObject->RemoveDeathRecipient(deathRecipient_);
72 }
73 
CleanUp()74 extern "C" __attribute__((destructor)) void CleanUp()
75 {
76     PasteboardServiceLoader::GetInstance().CleanupResource();
77 }
78 
GetInstance()79 PasteboardServiceLoader &PasteboardServiceLoader::GetInstance()
80 {
81     static PasteboardServiceLoader serviceLoader;
82     return serviceLoader;
83 }
84 
GetPasteboardService()85 sptr<IPasteboardService> PasteboardServiceLoader::GetPasteboardService()
86 {
87     std::unique_lock<std::mutex> lock(instanceLock_);
88     if (pasteboardServiceProxy_ != nullptr) {
89         return pasteboardServiceProxy_;
90     }
91     if (constructing_) {
92         auto waitStatus = proxyConVar_.wait_for(lock, std::chrono::milliseconds(LOADSA_TIMEOUT_MS), [this]() {
93             return pasteboardServiceProxy_ != nullptr;
94         });
95         PASTEBOARD_CHECK_AND_RETURN_RET_LOGI(waitStatus, nullptr, PASTEBOARD_MODULE_CLIENT, "Load SA timeout");
96         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Getting PasteboardServiceProxy succeeded.");
97         return pasteboardServiceProxy_;
98     }
99     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "GetPasteboardService start.");
100     sptr<ISystemAbilityManager> saMgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
101     if (saMgrProxy == nullptr) {
102         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Get SystemAbilityManager failed.");
103         pasteboardServiceProxy_ = nullptr;
104         return nullptr;
105     }
106     sptr<IRemoteObject> remoteObject = saMgrProxy->CheckSystemAbility(PASTEBOARD_SERVICE_ID);
107     if (remoteObject != nullptr) {
108         PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "Get PasteboardServiceProxy succeed.");
109         SetPasteboardServiceProxy(remoteObject);
110         return pasteboardServiceProxy_;
111     }
112     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "remoteObject is null.");
113     sptr<PasteboardLoadCallback> loadCallback = new PasteboardLoadCallback();
114     PASTEBOARD_CHECK_AND_RETURN_RET_LOGI(loadCallback != nullptr, nullptr, PASTEBOARD_MODULE_CLIENT, "loadCb is null");
115     int32_t ret = saMgrProxy->LoadSystemAbility(PASTEBOARD_SERVICE_ID, loadCallback);
116     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(ret == ERR_OK, nullptr, PASTEBOARD_MODULE_CLIENT, "Failed to load SA");
117     constructing_ = true;
118     auto waitStatus = proxyConVar_.wait_for(lock, std::chrono::milliseconds(LOADSA_TIMEOUT_MS), [this]() {
119         return pasteboardServiceProxy_ != nullptr;
120     });
121     constructing_ = false;
122     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(waitStatus, nullptr, PASTEBOARD_MODULE_CLIENT, "Load SA timeout");
123     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "Getting PasteboardServiceProxy succeeded.");
124     return pasteboardServiceProxy_;
125 }
126 
GetPasteboardServiceProxy()127 sptr<IPasteboardService> PasteboardServiceLoader::GetPasteboardServiceProxy()
128 {
129     std::lock_guard<std::mutex> lock(instanceLock_);
130     return pasteboardServiceProxy_;
131 }
132 
ClearPasteboardServiceProxy()133 void PasteboardServiceLoader::ClearPasteboardServiceProxy()
134 {
135     std::lock_guard<std::mutex> lock(instanceLock_);
136     pasteboardServiceProxy_ = nullptr;
137 }
138 
SetPasteboardServiceProxy(const sptr<IRemoteObject> & remoteObject)139 void PasteboardServiceLoader::SetPasteboardServiceProxy(const sptr<IRemoteObject> &remoteObject)
140 {
141     PASTEBOARD_CHECK_AND_RETURN_LOGE(remoteObject != nullptr, PASTEBOARD_MODULE_CLIENT, "remoteObject is null.");
142     if (deathRecipient_ == nullptr) {
143         deathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new PasteboardSaDeathRecipient());
144     }
145     PASTEBOARD_CHECK_AND_RETURN_LOGE(
146         deathRecipient_ != nullptr, PASTEBOARD_MODULE_CLIENT, "deathRecipient_ is null.");
147     if (!remoteObject->AddDeathRecipient(deathRecipient_)) {
148         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "AddDeathRecipient failed.");
149         deathRecipient_ = nullptr;
150         return;
151     }
152     pasteboardServiceProxy_ = iface_cast<IPasteboardService>(remoteObject);
153     if (clientDeathObserverPtr_ == nullptr) {
154         clientDeathObserverPtr_ = sptr<PasteboardClientDeathObserverStub>::MakeSptr();
155     }
156     if (clientDeathObserverPtr_ == nullptr) {
157         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "clientDeathObserverPtr_ is null.");
158         remoteObject->RemoveDeathRecipient(deathRecipient_);
159         deathRecipient_ = nullptr;
160         return;
161     }
162     auto ret = pasteboardServiceProxy_->RegisterClientDeathObserver(clientDeathObserverPtr_);
163     if (ret != ERR_OK) {
164         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "RegisterClientDeathObserver failed.");
165         remoteObject->RemoveDeathRecipient(deathRecipient_);
166         deathRecipient_ = nullptr;
167         clientDeathObserverPtr_ = nullptr;
168     }
169 }
170 
ReleaseDeathRecipient()171 void PasteboardServiceLoader::ReleaseDeathRecipient()
172 {
173     std::lock_guard<std::mutex> lock(instanceLock_);
174     PASTEBOARD_CHECK_AND_RETURN_LOGE(deathRecipient_ != nullptr, PASTEBOARD_MODULE_CLIENT, "deathRecipient is null.");
175     bool notNull = pasteboardServiceProxy_ != nullptr && pasteboardServiceProxy_->AsObject() != nullptr;
176     PASTEBOARD_CHECK_AND_RETURN_LOGE(notNull, PASTEBOARD_MODULE_CLIENT, "pasteboardServiceProxy is null.");
177     pasteboardServiceProxy_->AsObject()->RemoveDeathRecipient(deathRecipient_);
178     deathRecipient_ = nullptr;
179     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "ReleaseDeathRecipient end.");
180 }
181 
GetRecordValueByType(uint32_t dataId,uint32_t recordId,PasteDataEntry & value)182 int32_t PasteboardServiceLoader::GetRecordValueByType(uint32_t dataId, uint32_t recordId, PasteDataEntry &value)
183 {
184     auto proxyService = GetPasteboardService();
185     PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(proxyService != nullptr,
186         static_cast<int32_t>(PasteboardError::OBTAIN_SERVER_SA_ERROR),
187         PASTEBOARD_MODULE_CLIENT, "proxyService is nullptr");
188     std::vector<uint8_t> sendTLV(0);
189     if (!value.Encode(sendTLV)) {
190         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "fail encode entry value");
191         return static_cast<int32_t>(PasteboardError::SERIALIZATION_ERROR);
192     }
193     int fd = -1;
194     int64_t tlvSize = static_cast<int64_t>(sendTLV.size());
195     MessageParcelWarp messageData;
196     MessageParcel parcelData;
197     if (tlvSize > MIN_ASHMEM_DATA_SIZE) {
198         if (!messageData.WriteRawData(parcelData, sendTLV.data(), sendTLV.size())) {
199             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "WriteRawData Failed, size:%{public}" PRId64, tlvSize);
200             return static_cast<int32_t>(PasteboardError::SERIALIZATION_ERROR);
201         }
202         fd = messageData.GetWriteDataFd();
203         std::vector<uint8_t>().swap(sendTLV);
204     } else {
205         fd = messageData.CreateTmpFd();
206         PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(fd >= 0, static_cast<int32_t>(PasteboardError::SERIALIZATION_ERROR),
207             PASTEBOARD_MODULE_CLIENT, "CreateTmpFd failed:%{public}d", fd);
208     }
209     int32_t ret = proxyService->GetRecordValueByType(dataId, recordId, tlvSize, sendTLV, fd);
210     if (ret != ERR_OK) {
211         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "GetRecordValueByType failed, ret:%{public}d", ret);
212         return ret;
213     }
214 
215     return ProcessPasteData(value, tlvSize, fd, sendTLV);
216 }
217 
ProcessPasteData(PasteDataEntry & data,int64_t rawDataSize,int fd,const std::vector<uint8_t> & recvTLV)218 int32_t PasteboardServiceLoader::ProcessPasteData(PasteDataEntry &data, int64_t rawDataSize, int fd,
219     const std::vector<uint8_t> &recvTLV)
220 {
221     int32_t ret = static_cast<int32_t>(PasteboardError::DESERIALIZATION_ERROR);
222     if (fd < 0) {
223         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "fail fd:%{public}d", fd);
224         return ret;
225     }
226     MessageParcelWarp messageReply;
227     if (rawDataSize <= 0 || rawDataSize > messageReply.GetRawDataSize()) {
228         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Invalid raw data size:%{public}" PRId64, rawDataSize);
229         close(fd);
230         return ret;
231     }
232     bool result = false;
233     MessageParcel parcelData;
234     PasteDataEntry entryValue;
235     if (rawDataSize > MIN_ASHMEM_DATA_SIZE) {
236         parcelData.WriteInt64(rawDataSize);
237         parcelData.WriteFileDescriptor(fd);
238         close(fd);
239         const uint8_t *rawData =
240             reinterpret_cast<const uint8_t *>(messageReply.ReadRawData(parcelData, static_cast<size_t>(rawDataSize)));
241         if (rawData == nullptr) {
242             PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "mmap failed, size=%{public}" PRId64, rawDataSize);
243             return ret;
244         }
245         std::vector<uint8_t> pasteDataTlv(rawData, rawData + rawDataSize);
246         result = entryValue.Decode(pasteDataTlv);
247     } else {
248         result = entryValue.Decode(recvTLV);
249         close(fd);
250     }
251     if (!result) {
252         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Failed to decode pastedata in TLV");
253         return ret;
254     }
255     data = std::move(entryValue);
256     return static_cast<int32_t>(PasteboardError::E_OK);
257 }
258 
LoadSystemAbilitySuccess(const sptr<IRemoteObject> & remoteObject)259 void PasteboardServiceLoader::LoadSystemAbilitySuccess(const sptr<IRemoteObject> &remoteObject)
260 {
261     std::lock_guard<std::mutex> lock(instanceLock_);
262     SetPasteboardServiceProxy(remoteObject);
263     proxyConVar_.notify_all();
264 }
265 
LoadSystemAbilityFail()266 void PasteboardServiceLoader::LoadSystemAbilityFail()
267 {
268     std::lock_guard<std::mutex> lock(instanceLock_);
269     pasteboardServiceProxy_ = nullptr;
270     proxyConVar_.notify_all();
271 }
272 
OnRemoteSaDied(const wptr<IRemoteObject> & remote)273 void PasteboardServiceLoader::OnRemoteSaDied(const wptr<IRemoteObject> &remote)
274 {
275     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "OnRemoteSaDied start.");
276     std::lock_guard<std::mutex> lock(instanceLock_);
277     pasteboardServiceProxy_ = nullptr;
278 }
279 
PasteboardSaDeathRecipient()280 PasteboardSaDeathRecipient::PasteboardSaDeathRecipient() {}
281 
OnRemoteDied(const wptr<IRemoteObject> & object)282 void PasteboardSaDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
283 {
284     PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "PasteboardSaDeathRecipient on remote systemAbility died.");
285     PasteboardServiceLoader::GetInstance().OnRemoteSaDied(object);
286 }
287 } // namespace MiscServices
288 } // namespace OHOS