1 /*
2 * Copyright (C) 2023-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 "file_access_service.h"
17
18 #include <cstddef>
19 #include <unistd.h>
20
21 #include "user_access_tracer.h"
22 #include "file_access_framework_errno.h"
23 #include "file_access_extension_info.h"
24 #include "hilog_wrapper.h"
25 #include "hitrace_meter.h"
26 #include "ipc_skeleton.h"
27 #include "system_ability_definition.h"
28 #include "iservice_registry.h"
29
30 using namespace std;
31 namespace OHOS {
32 namespace FileAccessFwk {
33 namespace {
34 auto pms = FileAccessService::GetInstance();
35 const bool G_REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(pms.GetRefPtr());
36 const std::string FILE_SCHEME = "file://";
37 }
38 sptr<FileAccessService> FileAccessService::instance_;
39 mutex FileAccessService::mutex_;
40
41 constexpr int32_t NOTIFY_MAX_NUM = 32;
42 constexpr int32_t NOTIFY_TIME_INTERVAL = 500;
43 constexpr int32_t MAX_WAIT_TIME = 20;
44 constexpr int32_t ONE_SECOND = 1 * 1000;
45 constexpr int32_t UNLOAD_SA_WAIT_TIME = 30;
46 std::vector<Uri> deviceUris(DEVICE_ROOTS.begin(), DEVICE_ROOTS.end());
47
GetInstance()48 sptr<FileAccessService> FileAccessService::GetInstance()
49 {
50 if (instance_ != nullptr) {
51 return instance_;
52 }
53
54 lock_guard<mutex> lock(mutex_);
55 if (instance_ == nullptr) {
56 instance_ = sptr(new FileAccessService());
57 if (instance_ == nullptr) {
58 HILOG_ERROR("GetInstance nullptr");
59 return instance_;
60 }
61 }
62 return instance_;
63 }
64
FileAccessService()65 FileAccessService::FileAccessService() : SystemAbility(FILE_ACCESS_SERVICE_ID, false)
66 {
67 }
68
OnStart()69 void FileAccessService::OnStart()
70 {
71 UserAccessTracer trace;
72 trace.Start("OnStart");
73 sptr<FileAccessService> service = FileAccessService::GetInstance();
74 service->Init();
75 if (!Publish(service)) {
76 HILOG_ERROR("OnStart register to system ability manager failed");
77 return;
78 }
79 ready_ = true;
80 return;
81 }
82
OnStop()83 void FileAccessService::OnStop()
84 {
85 UserAccessTracer trace;
86 trace.Start("OnStop");
87 if (!ready_) {
88 HILOG_ERROR("OnStop is not ready, nothing to do");
89 return;
90 }
91 ready_ = false;
92 }
93
Dump(int32_t fd,const vector<u16string> & args)94 int32_t FileAccessService::Dump(int32_t fd, const vector<u16string> &args)
95 {
96 return ERR_OK;
97 }
98
IsServiceReady() const99 bool FileAccessService::IsServiceReady() const
100 {
101 return ready_;
102 }
103
IsParentUri(const string & comparedUriStr,string & srcUriStr)104 static bool IsParentUri(const string &comparedUriStr, string &srcUriStr)
105 {
106 if ((comparedUriStr.empty()) || (srcUriStr.empty())) {
107 HILOG_ERROR("Uri is empty");
108 return false;
109 }
110 size_t slashIndex = srcUriStr.rfind("/");
111 if (slashIndex != string::npos) {
112 if (comparedUriStr.compare(srcUriStr.substr(0, slashIndex)) == 0) {
113 return true;
114 }
115 }
116 return false;
117 }
118
IsChildUri(const string & comparedUriStr,string & srcUriStr)119 static bool IsChildUri(const string &comparedUriStr, string &srcUriStr)
120 {
121 if ((comparedUriStr.empty()) || (srcUriStr.empty())) {
122 HILOG_ERROR("Uri is empty");
123 return false;
124 }
125 size_t slashIndex = comparedUriStr.rfind("/");
126 if (slashIndex != string::npos) {
127 if (srcUriStr.compare(comparedUriStr.substr(0, slashIndex)) == 0) {
128 return true;
129 }
130 }
131 return false;
132 }
133
Init()134 void FileAccessService::Init()
135 {
136 InitTimer();
137 if (extensionDeathRecipient_ == nullptr) {
138 extensionDeathRecipient_ = sptr(new ExtensionDeathRecipient());
139 }
140 if (observerDeathRecipient_ == nullptr) {
141 observerDeathRecipient_ = sptr(new ObserverDeathRecipient());
142 }
143 if (appDeathRecipient_ == nullptr) {
144 appDeathRecipient_ = sptr(new AppDeathRecipient());
145 }
146 }
147
GetBundleNameFromUri(Uri & uri,string & bundleName)148 static bool GetBundleNameFromUri(Uri &uri, string &bundleName)
149 {
150 string scheme = uri.GetScheme();
151 if (scheme != FILE_SCHEME_NAME) {
152 return false;
153 }
154 string path = "/" + uri.GetAuthority() + uri.GetPath();
155 if (path.size() == 0) {
156 HILOG_ERROR("Uri path error.");
157 return false;
158 }
159
160 if (path.front() != '/') {
161 HILOG_ERROR("Uri path format error.");
162 return false;
163 }
164
165 auto tmpPath = path.substr(1);
166 auto index = tmpPath.find_first_of("/");
167 bundleName = tmpPath.substr(0, index);
168 if (bundleName.compare(MEDIA_BNUDLE_NAME_ALIAS) == 0) {
169 bundleName = MEDIA_BNUDLE_NAME;
170 return true;
171 }
172 if (bundleName.compare(EXTERNAL_BNUDLE_NAME_ALIAS) == 0) {
173 bundleName = EXTERNAL_BNUDLE_NAME;
174 return true;
175 }
176 HILOG_ERROR("Uri-authority error.");
177 return false;
178 }
179
ConnectExtension(Uri & uri,const shared_ptr<ConnectExtensionInfo> & info)180 sptr<IFileAccessExtBase> FileAccessService::ConnectExtension(Uri &uri, const shared_ptr<ConnectExtensionInfo> &info)
181 {
182 string bundleName;
183 GetBundleNameFromUri(uri, bundleName);
184 auto curBundleExtProxy = FindExtProxyByBundleName(bundleName);
185 if (curBundleExtProxy != nullptr) {
186 return curBundleExtProxy;
187 }
188 sptr<IFileAccessExtBase> extensionProxy;
189 {
190 lock_guard<mutex> lock(mutex_);
191 int32_t ret = GetExtensionProxy(info, extensionProxy);
192 if (ret != ERR_OK || extensionProxy == nullptr) {
193 return nullptr;
194 }
195 auto object = extensionProxy->AsObject();
196 if (object) {
197 object->AddDeathRecipient(extensionDeathRecipient_);
198 }
199 }
200 AddExtProxyInfo(bundleName, extensionProxy);
201 return extensionProxy;
202 }
203
ResetProxy(const wptr<IRemoteObject> & remote)204 void FileAccessService::ResetProxy(const wptr<IRemoteObject> &remote)
205 {
206 HILOG_DEBUG("FileAccessService::ResetProxy start");
207 lock_guard<mutex> lock(mapMutex_);
208 if (remote != nullptr && extensionDeathRecipient_ != nullptr) {
209 for (auto iter = cMap_.begin(); iter != cMap_.end(); ++iter) {
210 if (iter->second == nullptr) {
211 HILOG_ERROR("iter->second is null or extensionDeathRecipient_ is null.");
212 continue;
213 }
214 auto proxyRemote = iter->second->AsObject();
215 if (proxyRemote != nullptr && proxyRemote == remote.promote()) {
216 proxyRemote->RemoveDeathRecipient(extensionDeathRecipient_);
217 cMap_.erase(iter->first);
218 }
219 }
220 } else {
221 HILOG_ERROR("FileAccessService::ResetProxy, proxy is null or extensionDeathRecipient_ is null.");
222 }
223 }
224
OnRemoteDied(const wptr<IRemoteObject> & remote)225 void FileAccessService::ExtensionDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
226 {
227 HILOG_ERROR("FileAccessService::ExtensionDeathRecipient::OnRemoteDied, remote obj died.");
228 if (remote == nullptr) {
229 HILOG_ERROR("remote is nullptr");
230 return;
231 }
232 FileAccessService::GetInstance()->ResetProxy(remote);
233 }
234
OnRemoteDied(const wptr<IRemoteObject> & remote)235 void FileAccessService::ObserverDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
236 {
237 HILOG_ERROR("FileAccessService::ObserverDeathRecipient::OnRemoteDied, remote obj died.");
238 if (remote == nullptr || remote.promote() == nullptr) {
239 return;
240 }
241 sptr<IFileAccessObserver> observer = iface_cast<IFileAccessObserver>(remote.promote());
242 if (observer == nullptr) {
243 HILOG_ERROR("convert promote failed");
244 return;
245 }
246 FileAccessService::GetInstance()->CleanRelativeObserver(observer);
247 }
248
CleanRelativeObserver(const sptr<IFileAccessObserver> & observer)249 void FileAccessService::CleanRelativeObserver(const sptr<IFileAccessObserver> &observer)
250 {
251 shared_ptr<ObserverContext> obsContext = make_shared<ObserverContext>(observer);
252 uint32_t code = obsManager_.getId([obsContext](const shared_ptr<ObserverContext> &afterContext) {
253 return obsContext->EqualTo(afterContext);
254 });
255 std::vector<Uri> uriLists = GetUriList(code);
256 for (size_t i = 0; i < uriLists.size(); ++i) {
257 UnregisterNotify(uriLists[i], observer);
258 }
259 }
260
GetUriList(uint32_t code)261 std::vector<Uri> FileAccessService::GetUriList(uint32_t code)
262 {
263 lock_guard<mutex> lock(nodeMutex_);
264 std::vector<Uri> uriList;
265 for (auto pair : relationshipMap_) {
266 auto codeList = pair.second->obsCodeList_;
267 auto haveCodeIter = find_if(codeList.begin(), codeList.end(),
268 [code](const uint32_t &listCode) { return code == listCode; });
269 if (haveCodeIter != codeList.end()) {
270 Uri uri(pair.first);
271 uriList.push_back(uri);
272 }
273 }
274 return uriList;
275 }
276
convertUris(Uri uri,std::vector<Uri> & uris)277 static void convertUris(Uri uri, std::vector<Uri> &uris)
278 {
279 std::string uriString = uri.ToString();
280 if (uriString == DEVICES_URI) {
281 auto uid = uriString.substr(0, uriString.find("file://"));
282 for (auto uirStr : DEVICE_ROOTS) {
283 uris.push_back(Uri(uid + uirStr));
284 }
285 } else {
286 uris.push_back(uri);
287 }
288 }
289
RegisterNotify(Uri uri,bool notifyForDescendants,const sptr<IFileAccessObserver> & observer,const std::shared_ptr<ConnectExtensionInfo> & info)290 int32_t FileAccessService::RegisterNotify(Uri uri, bool notifyForDescendants, const sptr<IFileAccessObserver> &observer,
291 const std::shared_ptr<ConnectExtensionInfo> &info)
292 {
293 std::vector<Uri> uris;
294 convertUris(uri, uris);
295 for (auto eachUri : uris) {
296 int ret = RegisterNotifyImpl(eachUri, notifyForDescendants, observer, info);
297 if (ret != ERR_OK) {
298 HILOG_ERROR("RegisterNotify error ret = %{public}d", ret);
299 return ret;
300 }
301 }
302 return ERR_OK;
303 }
304
OperateObsNode(Uri & uri,bool notifyForDescendants,uint32_t code,const std::shared_ptr<ConnectExtensionInfo> & info)305 int32_t FileAccessService::OperateObsNode(Uri &uri, bool notifyForDescendants, uint32_t code,
306 const std::shared_ptr<ConnectExtensionInfo> &info)
307 {
308 string uriStr = uri.ToString();
309 HILOG_INFO("OperateObsNode uriStr: %{public}s", uriStr.c_str());
310 {
311 lock_guard<mutex> lock(nodeMutex_);
312 auto iter = relationshipMap_.find(uriStr);
313 if (iter != relationshipMap_.end()) {
314 auto obsNode = iter->second;
315 // this node has this callback or not, if has this, unref manager.
316 auto haveCodeIter = find_if(obsNode->obsCodeList_.begin(), obsNode->obsCodeList_.end(),
317 [code](const uint32_t &listCode) { return code == listCode; });
318 if (haveCodeIter != obsNode->obsCodeList_.end()) {
319 if (obsManager_.get(code) != nullptr) {
320 obsManager_.get(code)->UnRef();
321 }
322 if (obsNode->needChildNote_ == notifyForDescendants) {
323 HILOG_DEBUG("Register same uri and same callback and same notifyForDescendants");
324 return ERR_OK;
325 }
326 // need modify obsNode notifyForDescendants
327 obsNode->needChildNote_ = notifyForDescendants;
328 HILOG_DEBUG("Register same uri and same callback but need modify notifyForDescendants");
329 return ERR_OK;
330 }
331 obsNode->obsCodeList_.push_back(code);
332 return ERR_OK;
333 }
334 }
335
336 auto extensionProxy = ConnectExtension(uri, info);
337 if (extensionProxy == nullptr) {
338 HILOG_ERROR("Creator get invalid fileExtProxy");
339 return E_CONNECT;
340 }
341 extensionProxy->StartWatcher(uri);
342 {
343 lock_guard<mutex> lock(nodeMutex_);
344 auto obsNode = make_shared<ObserverNode>(notifyForDescendants);
345 // add new node relations.
346 for (auto &[comUri, node] : relationshipMap_) {
347 if (IsParentUri(comUri, uriStr)) {
348 obsNode->parent_ = node;
349 node->children_.push_back(obsNode);
350 }
351 if (IsChildUri(comUri, uriStr)) {
352 obsNode->children_.push_back(node);
353 node->parent_ = obsNode;
354 }
355 }
356 // obsCodeList_ is to save callback number
357 obsNode->obsCodeList_.push_back(code);
358 relationshipMap_.insert(make_pair(uriStr, obsNode));
359 return ERR_OK;
360 }
361 }
362
RegisterNotifyImpl(Uri uri,bool notifyForDescendants,const sptr<IFileAccessObserver> & observer,const std::shared_ptr<ConnectExtensionInfo> & info)363 int32_t FileAccessService::RegisterNotifyImpl(Uri uri, bool notifyForDescendants,
364 const sptr<IFileAccessObserver> &observer, const std::shared_ptr<ConnectExtensionInfo> &info)
365 {
366 UserAccessTracer trace;
367 trace.Start("RegisterNotifyImpl");
368 // std::string token = IPCSkeleton::ResetCallingIdentity();
369 shared_ptr<ObserverContext> obsContext = make_shared<ObserverContext>(observer);
370 // find if obsManager_ has this callback.
371 uint32_t code = obsManager_.getId([obsContext](const shared_ptr<ObserverContext> &afterContext) {
372 return obsContext->EqualTo(afterContext);
373 });
374 if (code == HolderManager<shared_ptr<ObserverContext>>::CODE_CAN_NOT_FIND) {
375 // this is new callback, save this context
376 obsContext->Ref();
377 code = obsManager_.save(obsContext);
378 if (obsContext->obs_ == nullptr) {
379 return E_GETRESULT;
380 }
381 auto object = obsContext->obs_->AsObject();
382 object->AddDeathRecipient(observerDeathRecipient_);
383 } else {
384 // this callback is already in manager, add ref.
385 auto object = obsManager_.get(code);
386 if (object == nullptr) {
387 return E_GETRESULT;
388 }
389 object->Ref();
390 }
391 return OperateObsNode(uri, notifyForDescendants, code, info);
392 }
393
RemoveRelations(string & uriStr,shared_ptr<ObserverNode> obsNode)394 void FileAccessService::RemoveRelations(string &uriStr, shared_ptr<ObserverNode> obsNode)
395 {
396 lock_guard<mutex> lock(nodeMutex_);
397 for (auto &[comUri, node] : relationshipMap_) {
398 auto childrenIter = find_if(node->children_.begin(), node->children_.end(),
399 [obsNode](const shared_ptr<ObserverNode> &obsListNode) { return obsNode == obsListNode; });
400 if (childrenIter != node->children_.end()) {
401 node->children_.erase(childrenIter);
402 }
403 if (IsChildUri(comUri, uriStr)) {
404 node->parent_ = nullptr;
405 }
406 }
407 relationshipMap_.erase(uriStr);
408 }
409
FindUri(const string & uriStr,shared_ptr<ObserverNode> & outObsNode)410 int FileAccessService::FindUri(const string &uriStr, shared_ptr<ObserverNode> &outObsNode)
411 {
412 HILOG_INFO("uriStr: %{public}s", uriStr.c_str());
413 lock_guard<mutex> lock(nodeMutex_);
414 HILOG_DEBUG("FindUri start");
415 auto iter = relationshipMap_.find(uriStr);
416 if (iter == relationshipMap_.end()) {
417 HILOG_ERROR("Can not find uri");
418 return E_CAN_NOT_FIND_URI;
419 }
420 outObsNode = iter->second;
421 return ERR_OK;
422 }
423
CleanAllNotify(Uri uri,const std::shared_ptr<ConnectExtensionInfo> & info)424 int32_t FileAccessService::CleanAllNotify(Uri uri, const std::shared_ptr<ConnectExtensionInfo> &info)
425 {
426 std::vector<Uri> uris;
427 convertUris(uri, uris);
428 for (auto eachUri : uris) {
429 int ret = CleanAllNotifyImpl(eachUri, info);
430 if (ret != ERR_OK) {
431 HILOG_ERROR("CleanAllNotify error ret = %{public}d", ret);
432 return ret;
433 }
434 }
435 return ERR_OK;
436 }
437
CleanAllNotifyImpl(Uri uri,const std::shared_ptr<ConnectExtensionInfo> & info)438 int32_t FileAccessService::CleanAllNotifyImpl(Uri uri, const std::shared_ptr<ConnectExtensionInfo> &info)
439 {
440 UserAccessTracer trace;
441 trace.Start("CleanAllNotifyImpl");
442 string uriStr = uri.ToString();
443 shared_ptr<ObserverNode> obsNode;
444 if (FindUri(uriStr, obsNode) != ERR_OK) {
445 HILOG_ERROR("Can not find unregisterNotify uri");
446 return E_CAN_NOT_FIND_URI;
447 }
448 for (auto code : obsNode->obsCodeList_) {
449 auto context = obsManager_.get(code);
450 if (context == nullptr) {
451 continue;
452 }
453 context->UnRef();
454 if (!context->IsValid()) {
455 obsManager_.release(code);
456 }
457 }
458
459 size_t uriIndex = uriStr.find(FILE_SCHEME);
460 if (uriIndex == string::npos) {
461 HILOG_ERROR("Current uriStr can not find targetUri");
462 return ERR_URI;
463 }
464 Uri originalUri(uriStr.substr(uriIndex));
465 auto extensionProxy = ConnectExtension(originalUri, info);
466 if (extensionProxy == nullptr) {
467 HILOG_ERROR("Creator get invalid fileExtProxy");
468 return E_CONNECT;
469 }
470 extensionProxy->StopWatcher(originalUri);
471 RemoveRelations(uriStr, obsNode);
472 if (IsUnused() && unLoadTimer_) {
473 unLoadTimer_->reset();
474 }
475 return ERR_OK;
476 }
477
UnregisterNotify(Uri uri,const sptr<IFileAccessObserver> & observer,const std::shared_ptr<ConnectExtensionInfo> & info)478 int32_t FileAccessService::UnregisterNotify(Uri uri, const sptr<IFileAccessObserver> &observer,
479 const std::shared_ptr<ConnectExtensionInfo> &info)
480 {
481 std::vector<Uri> uris;
482 convertUris(uri, uris);
483 for (auto eachUri : uris) {
484 int ret = UnregisterNotifyImpl(eachUri, observer, info);
485 if (ret != ERR_OK) {
486 HILOG_ERROR("UnregisterNotify error ret = %{public}d", ret);
487 return ret;
488 }
489 }
490 if (IsUnused() && unLoadTimer_) {
491 unLoadTimer_->reset();
492 }
493 return ERR_OK;
494 }
495
UnregisterNotifyImpl(Uri uri,const sptr<IFileAccessObserver> & observer,const std::shared_ptr<ConnectExtensionInfo> & info)496 int32_t FileAccessService::UnregisterNotifyImpl(Uri uri, const sptr<IFileAccessObserver> &observer,
497 const std::shared_ptr<ConnectExtensionInfo> &info)
498 {
499 UserAccessTracer trace;
500 trace.Start("UnregisterNotifyImpl");
501 if (observer == nullptr) {
502 HILOG_ERROR("UnregisterNotify failed with invalid observer");
503 return E_IPCS;
504 }
505 if (observer->AsObject() == nullptr) {
506 HILOG_ERROR("UnregisterNotify failed with invalid observer");
507 return E_IPCS;
508 }
509 string uriStr = uri.ToString();
510 shared_ptr<ObserverNode> obsNode;
511 if (FindUri(uriStr, obsNode) != ERR_OK) {
512 HILOG_ERROR("Can not find unregisterNotify uri");
513 return E_CAN_NOT_FIND_URI;
514 }
515 // find if obsManager_ has this callback.
516 shared_ptr<ObserverContext> obsContext = make_shared<ObserverContext>(observer);
517 uint32_t code = obsManager_.getId([obsContext](const shared_ptr<ObserverContext> &afterContext) {
518 return obsContext->EqualTo(afterContext);
519 });
520 if (code == HolderManager<shared_ptr<ObserverContext>>::CODE_CAN_NOT_FIND) {
521 HILOG_ERROR("Can not find observer");
522 return E_CALLBACK_IS_NOT_REGISTER;
523 }
524 int32_t ret = obsNode->FindAndRmObsCodeByCode(code);
525 if (ret != ERR_OK) {
526 HILOG_ERROR("Can not find obsNode by code");
527 return ret;
528 }
529 auto object = obsManager_.get(code);
530 if (object == nullptr) {
531 HILOG_ERROR("Can not find obsNode by code");
532 return E_IPCS;
533 }
534 object->UnRef();
535 // node has other observers, do not need remove.
536 if (obsNode->CheckObsCodeListNotEmpty()) {
537 HILOG_DEBUG("Has code do not stopWatcher");
538 return ERR_OK;
539 }
540 // if data refcount is invalid, release this code.
541 if (!object->IsValid()) {
542 obsManager_.release(code);
543 }
544 return RmUriObsNodeRelations(uriStr, obsNode, info);
545 }
546
SendListNotify(string uriStr,NotifyType notifyType,const std::vector<uint32_t> & list)547 void FileAccessService::SendListNotify(string uriStr, NotifyType notifyType, const std::vector<uint32_t> &list)
548 {
549 if (onDemandTimer_ == nullptr) {
550 HILOG_ERROR("onDemandTimer_ is nullptr");
551 return;
552 }
553 onDemandTimer_->start();
554 for (uint32_t code : list) {
555 if (obsManager_.get(code) == nullptr) {
556 HILOG_ERROR("Failed to get obs code = %{private}ud", code);
557 continue;
558 }
559 auto context = obsManager_.get(code);
560 auto it = std::find(DEVICE_ROOTS.begin(), DEVICE_ROOTS.end(), uriStr);
561 if (it != DEVICE_ROOTS.end()) {
562 vector<string> uris = {uriStr};
563 NotifyMessage notifyMessage{notifyType, uris};
564 if (context->obs_) {
565 context->obs_->OnChange(notifyMessage);
566 }
567 continue;
568 }
569 lock_guard<mutex> lock(context->mapMutex_);
570 if (context->notifyMap_.find(notifyType) != context->notifyMap_.end()) {
571 context->notifyMap_[notifyType].push_back(uriStr);
572 } else {
573 vector<string> uris{uriStr};
574 context->notifyMap_.emplace(notifyType, uris);
575 }
576 if (context->notifyMap_[notifyType].size() >= NOTIFY_MAX_NUM) {
577 NotifyMessage notifyMessage;
578 notifyMessage.notifyType_ = notifyType;
579 notifyMessage.uris_ = context->notifyMap_[notifyType];
580 if (context->obs_) {
581 context->obs_->OnChange(notifyMessage);
582 }
583 context->notifyMap_.erase(notifyType);
584 }
585 }
586 }
587
OnChange(Uri uri,NotifyType notifyType)588 int32_t FileAccessService::OnChange(Uri uri, NotifyType notifyType)
589 {
590 UserAccessTracer trace;
591 trace.Start("OnChange");
592 string uriStr = uri.ToString();
593 shared_ptr<ObserverNode> node;
594 size_t uriIndex = uriStr.find(FILE_SCHEME);
595 if (uriIndex == string::npos) {
596 HILOG_ERROR("Current uriStr can not find targetUri");
597 return ERR_URI;
598 }
599 string uris = uriStr.substr(uriIndex);
600 HILOG_DEBUG("OnChange FindUri start");
601 //When the path is not found, search for its parent path
602 if (FindUri(uriStr, node) != ERR_OK) {
603 size_t slashIndex = uriStr.rfind("/");
604 if (slashIndex == string::npos) {
605 HILOG_ERROR("Do not have parent");
606 return E_DO_NOT_HAVE_PARENT;
607 }
608 string parentUri = uriStr.substr(0, slashIndex);
609 if (FindUri(parentUri, node) != ERR_OK) {
610 HILOG_DEBUG("Can not find onChange parent uri");
611 return ERR_OK;
612 }
613 if (!node->needChildNote_) {
614 HILOG_DEBUG("Do not need send onChange message");
615 return ERR_OK;
616 }
617 SendListNotify(uris, notifyType, node->obsCodeList_);
618 return ERR_OK;
619 }
620 HILOG_DEBUG("OnChange FindUri end");
621 SendListNotify(uris, notifyType, node->obsCodeList_);
622 if ((node->parent_ == nullptr) || (!node->parent_->needChildNote_)) {
623 HILOG_DEBUG("Do not need notify parent");
624 return ERR_OK;
625 }
626 SendListNotify(uris, notifyType, node->parent_->obsCodeList_);
627 return ERR_OK;
628 }
629
IsUnused()630 bool FileAccessService::IsUnused()
631 {
632 HILOG_INFO("IsUnused: obsManager_: %{public}d, appProxyMap_: %{public}d",
633 obsManager_.isEmpty(), appProxyMap_.empty());
634 return obsManager_.isEmpty() && appProxyMap_.empty();
635 }
636
InitTimer()637 void FileAccessService::InitTimer()
638 {
639 onDemandTimer_ = std::make_shared<OnDemandTimer>([this] {
640 lock_guard<mutex> lock(mutex_);
641 vector<shared_ptr<ObserverContext>> contexts;
642 FileAccessService::GetInstance()->obsManager_.getAll(contexts);
643 bool isMessage = false;
644 for (auto context : contexts) {
645 if (context == nullptr) {
646 continue;
647 }
648 if (!context->notifyMap_.size()) {
649 continue;
650 }
651 for (auto message : context->notifyMap_) {
652 NotifyMessage notifyMessage;
653 notifyMessage.notifyType_ = message.first;
654 notifyMessage.uris_ = message.second;
655 context->obs_->OnChange(notifyMessage);
656 }
657 context->notifyMap_.clear();
658 isMessage = true;
659 }
660 return isMessage;
661 }, NOTIFY_TIME_INTERVAL, MAX_WAIT_TIME);
662
663 unLoadTimer_ = std::make_shared<UnloadTimer>([this] {
664 if (!IsUnused()) {
665 return;
666 }
667 sptr<ISystemAbilityManager> saManager =
668 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
669 if (saManager == nullptr) {
670 HILOG_ERROR("UnloadSA, GetSystemAbilityManager is null.");
671 return;
672 }
673 int32_t result = saManager->UnloadSystemAbility(FILE_ACCESS_SERVICE_ID);
674 if (result != ERR_OK) {
675 HILOG_ERROR("UnloadSA, UnloadSystemAbility result: %{public}d", result);
676 return;
677 }
678 }, ONE_SECOND, UNLOAD_SA_WAIT_TIME);
679 unLoadTimer_->start();
680 }
681
ConnectFileExtAbility(const AAFwk::Want & want,const sptr<AAFwk::IAbilityConnection> & connection)682 int32_t FileAccessService::ConnectFileExtAbility(const AAFwk::Want &want,
683 const sptr<AAFwk::IAbilityConnection>& connection)
684 {
685 HILOG_INFO("ConnectFileExtAbility start");
686 if (connection == nullptr) {
687 HILOG_ERROR("connection is nullptr");
688 return E_CONNECT;
689 }
690
691 sptr<AgentFileAccessExtConnection> fileAccessExtConnection(
692 new(std::nothrow) AgentFileAccessExtConnection(connection));
693 if (fileAccessExtConnection == nullptr) {
694 HILOG_ERROR("new fileAccessExtConnection fail");
695 return E_CONNECT;
696 }
697
698 fileAccessExtConnection->ConnectFileExtAbility(want);
699 AddAppProxy(connection, fileAccessExtConnection);
700 return ERR_OK;
701 }
702
DisConnectFileExtAbility(const sptr<AAFwk::IAbilityConnection> & connection)703 int32_t FileAccessService::DisConnectFileExtAbility(const sptr<AAFwk::IAbilityConnection>& connection)
704 {
705 HILOG_INFO("ConnectFileExtAbility start");
706 if (connection == nullptr) {
707 HILOG_ERROR("connection is nullptr");
708 return E_CONNECT;
709 }
710 DisconnectAppProxy(connection);
711 RemoveAppProxy(connection);
712 return ERR_OK;
713 }
714
715
GetExtensionProxy(const std::shared_ptr<ConnectExtensionInfo> & info,sptr<IFileAccessExtBase> & extensionProxy)716 int32_t FileAccessService::GetExtensionProxy(const std::shared_ptr<ConnectExtensionInfo> &info,
717 sptr<IFileAccessExtBase> &extensionProxy)
718 {
719 sptr<FileAccessExtConnection> fileAccessExtConnection(new(std::nothrow) FileAccessExtConnection());
720 if (fileAccessExtConnection == nullptr) {
721 HILOG_ERROR("new fileAccessExtConnection fail");
722 return E_CONNECT;
723 }
724 if (info == nullptr || info->token == nullptr) {
725 HILOG_ERROR("ConnectExtensionInfo is invalid");
726 return E_CONNECT;
727 }
728 fileAccessExtConnection->ConnectFileExtAbility(info->want, info->token);
729 extensionProxy = fileAccessExtConnection->GetFileExtProxy();
730 if (extensionProxy == nullptr) {
731 HILOG_ERROR("extensionProxy is nullptr");
732 return E_CONNECT;
733 }
734 return ERR_OK;
735 }
736
RmUriObsNodeRelations(std::string & uriStr,std::shared_ptr<ObserverNode> & obsNode,const std::shared_ptr<ConnectExtensionInfo> & info)737 int32_t FileAccessService::RmUriObsNodeRelations(std::string &uriStr, std::shared_ptr<ObserverNode> &obsNode,
738 const std::shared_ptr<ConnectExtensionInfo> &info)
739 {
740 size_t uriIndex = uriStr.find(FILE_SCHEME);
741 if (uriIndex == string::npos) {
742 HILOG_ERROR("Current uriStr can not find targetUri");
743 return ERR_URI;
744 }
745 Uri originalUri(uriStr.substr(uriIndex));
746 auto extensionProxy = ConnectExtension(originalUri, info);
747 if (extensionProxy == nullptr) {
748 HILOG_ERROR("Creator get invalid fileExtProxy");
749 return E_CONNECT;
750 }
751 extensionProxy->StopWatcher(originalUri);
752 RemoveRelations(uriStr, obsNode);
753 return ERR_OK;
754 }
755
FindExtProxyByBundleName(std::string bundleName)756 sptr<IFileAccessExtBase> FileAccessService::FindExtProxyByBundleName(std::string bundleName)
757 {
758 lock_guard<mutex> lock(mapMutex_);
759 auto iterator = cMap_.find(bundleName);
760 if (iterator != cMap_.end()) {
761 return iterator->second;
762 }
763 return nullptr;
764 }
765
AddExtProxyInfo(std::string bundleName,sptr<IFileAccessExtBase> extProxy)766 void FileAccessService::AddExtProxyInfo(std::string bundleName, sptr<IFileAccessExtBase> extProxy)
767 {
768 lock_guard<mutex> lock(mapMutex_);
769 cMap_.emplace(bundleName, extProxy);
770 }
771
AddAppProxy(const sptr<AAFwk::IAbilityConnection> & connection,sptr<AgentFileAccessExtConnection> & value)772 void FileAccessService::AddAppProxy(const sptr<AAFwk::IAbilityConnection>& connection,
773 sptr<AgentFileAccessExtConnection>& value)
774 {
775 if (connection == nullptr || value == nullptr) {
776 HILOG_ERROR("key is null or value is null");
777 return;
778 }
779 size_t key = reinterpret_cast<size_t>(connection->AsObject().GetRefPtr());
780 HILOG_INFO("sa add key, %{public}zu", key);
781 lock_guard<mutex> lock(appProxyMutex_);
782 if (appProxyMap_.count(key)) {
783 HILOG_INFO("sa had proxy,needn't create connection");
784 return;
785 }
786 connection->AsObject()->AddDeathRecipient(appDeathRecipient_);
787 appProxyMap_[key] = value;
788 appConnection_[key] = connection;
789 HILOG_INFO("appProxyMap_ size: %{public}zu", appProxyMap_.size());
790 }
791
RemoveAppProxy(const sptr<AAFwk::IAbilityConnection> & connection)792 void FileAccessService::RemoveAppProxy(const sptr<AAFwk::IAbilityConnection>& connection)
793 {
794 if (connection == nullptr) {
795 HILOG_WARN("key is null");
796 return;
797 }
798 size_t key = reinterpret_cast<size_t>(connection->AsObject().GetRefPtr());
799 lock_guard<mutex> lock(appProxyMutex_);
800 if (appProxyMap_.find(key) == appProxyMap_.end()) {
801 HILOG_INFO("appProxyMap_ not key %{public}zu", key);
802 return;
803 }
804
805 appProxyMap_.erase(key);
806 appConnection_.erase(key);
807 HILOG_INFO("appProxyMap_ size: %{public}zu", appProxyMap_.size());
808 }
809
DisconnectAppProxy(const sptr<AAFwk::IAbilityConnection> & connection)810 void FileAccessService::DisconnectAppProxy(const sptr<AAFwk::IAbilityConnection>& connection)
811 {
812 size_t key = reinterpret_cast<size_t>(connection->AsObject().GetRefPtr());
813 lock_guard<mutex> lock(appProxyMutex_);
814 if (appProxyMap_.find(key) == appProxyMap_.end()) {
815 HILOG_WARN("appProxyMap_ not key: %{public}zu", key);
816 return;
817 }
818 HILOG_INFO("DisconnectAppProxy DisconnectFileExtAbility key: %{public}zu", key);
819 if (appProxyMap_[key] != nullptr) {
820 appProxyMap_[key]->DisconnectFileExtAbility();
821 }
822 }
823
OnRemoteDied(const wptr<IRemoteObject> & remote)824 void FileAccessService::AppDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
825 {
826 HILOG_INFO("FileAccessService::AppDeathRecipient::OnRemoteDied, remote obj died.");
827 if (remote == nullptr) {
828 HILOG_ERROR("remote is nullptr");
829 return;
830 }
831 auto remoteBroker = iface_cast<AAFwk::IAbilityConnection>(remote.promote());
832 size_t key = reinterpret_cast<size_t>(remoteBroker->AsObject().GetRefPtr());
833 HILOG_INFO("remote: %{public}zu", key);
834 FileAccessService::GetInstance()->RemoveAppProxy(remoteBroker);
835 }
836
837 } // namespace FileAccessFwk
838 } // namespace OHOS
839