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