• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 #include "mtp_file_observer.h"
16 #include <memory>
17 #include <securec.h>
18 #include <string>
19 #include <sys/inotify.h>
20 #include <unistd.h>
21 #include "media_log.h"
22 
23 using namespace std;
24 namespace OHOS {
25 namespace Media {
26 bool MtpFileObserver::isRunning_ = false;
27 int MtpFileObserver::inotifyFd_ = 0;
28 std::map<int, std::string> MtpFileObserver::watchMap_;
29 std::mutex MtpFileObserver::eventLock_;
30 const int BUF_SIZE = 1024;
31 #ifdef HAS_BATTERY_MANAGER_PART
32 const int LOW_BATTERY = 50;
33 #endif
SendEvent(const inotify_event & event,const std::string & path,const ContextSptr & context)34 void MtpFileObserver::SendEvent(const inotify_event &event, const std::string &path, const ContextSptr &context)
35 {
36     string fileName;
37     std::shared_ptr<MtpEvent> eventPtr = std::make_shared<OHOS::Media::MtpEvent>(context);
38     if ((event.mask & IN_CREATE) || (event.mask & IN_MOVED_TO)) {
39         fileName = path + "/" + event.name;
40         MEDIA_DEBUG_LOG("MtpFileObserver AddInotifyEvents create/MOVED_TO: path:%{private}s", fileName.c_str());
41         eventPtr->SendObjectAdded(fileName);
42     } else if ((event.mask & IN_DELETE) || (event.mask & IN_MOVED_FROM)) {
43         fileName = path + "/" + event.name;
44         MEDIA_DEBUG_LOG("MtpFileObserver AddInotifyEvents delete/MOVED_FROM: path:%{private}s", fileName.c_str());
45         eventPtr->SendObjectRemoved(fileName);
46     } else if (event.mask & IN_CLOSE_WRITE) {
47         fileName = path + "/" + event.name;
48         MEDIA_DEBUG_LOG("MtpFileObserver AddInotifyEvents IN_CLOSE_WRITE : path:%{private}s", fileName.c_str());
49         eventPtr->SendObjectInfoChanged(fileName);
50     }
51 }
52 
AddInotifyEvents(const int & inotifyFd,const ContextSptr & context)53 bool MtpFileObserver::AddInotifyEvents(const int &inotifyFd, const ContextSptr &context)
54 {
55     char eventBuf[BUF_SIZE] = {0};
56 
57     int ret = read(inotifyFd, eventBuf, sizeof(eventBuf));
58     if (ret < (int)sizeof(struct inotify_event)) {
59         MEDIA_ERR_LOG("MtpFileObserver AddInotifyEvents no event");
60         return false;
61     }
62 
63     struct inotify_event *positionEvent = (struct inotify_event *)eventBuf;
64     struct inotify_event *event;
65     while (ret >= (int)sizeof(struct inotify_event)) {
66         event = positionEvent;
67         if (event->len) {
68             bool isFind;
69             map<int, string>::iterator iter;
70             {
71                 lock_guard<mutex> lock(eventLock_);
72                 iter = watchMap_.find(event->wd);
73                 isFind = iter != watchMap_.end();
74             }
75             if (isFind) {
76                 string path = iter->second;
77                 SendEvent(*event, path, context);
78             }
79         }
80         positionEvent++;
81         ret -= (int)sizeof(struct inotify_event);
82     }
83     return true;
84 }
85 
SendBattery(const ContextSptr & context)86 void MtpFileObserver::SendBattery(const ContextSptr &context)
87 {
88 #ifdef HAS_BATTERY_MANAGER_PART
89     std::shared_ptr<MtpEvent> eventPtr = std::make_shared<OHOS::Media::MtpEvent>(context);
90     auto battery = make_shared<MtpOperationUtils>(context);
91     if (LOW_BATTERY >= battery->GetBatteryLevel()) {
92         eventPtr->SendDevicePropertyChanged();
93     }
94 #endif
95 }
96 
StopFileInotify()97 bool MtpFileObserver::StopFileInotify()
98 {
99     isRunning_ = false;
100     lock_guard<mutex> lock(eventLock_);
101     for (auto ret : watchMap_) {
102         if (inotify_rm_watch(inotifyFd_, ret.first) == -1) {
103             MEDIA_ERR_LOG("MtpFileObserver StopFileInotify inotify_rm_watch error");
104             return false;
105         }
106     }
107     close(inotifyFd_);
108     watchMap_.clear();
109     startThread_ = false;
110     inotifySuccess_ = false;
111     inotifyFd_ = 0;
112     return true;
113 }
114 
StartFileInotify()115 bool MtpFileObserver::StartFileInotify()
116 {
117     isRunning_ = true;
118     inotifyFd_ = inotify_init();
119     if (inotifyFd_ == -1) {
120         MEDIA_ERR_LOG("MtpFileObserver inotify_init false");
121         return false;
122     } else {
123         inotifySuccess_ = true;
124         return true;
125     }
126 }
127 
WatchPathThread(const ContextSptr & context)128 bool MtpFileObserver::WatchPathThread(const ContextSptr &context)
129 {
130     while (isRunning_) {
131         SendBattery(context);
132         size_t size;
133         {
134             lock_guard<mutex> lock(eventLock_);
135             size = watchMap_.size();
136         }
137         if (size > 0) {
138             AddInotifyEvents(inotifyFd_, context);
139         }
140     }
141     return true;
142 }
143 
AddFileInotify(const std::string & path,const std::string & realPath,const ContextSptr & context)144 void MtpFileObserver::AddFileInotify(const std::string &path, const std::string &realPath, const ContextSptr &context)
145 {
146     if (inotifySuccess_) {
147         lock_guard<mutex> lock(eventLock_);
148         if (!path.empty() && !realPath.empty()) {
149             int ret = inotify_add_watch(inotifyFd_, realPath.c_str(),
150                 IN_CLOSE_WRITE | IN_MOVED_FROM | IN_MOVED_TO | IN_CREATE | IN_DELETE);
151             watchMap_.insert(make_pair(ret, path));
152         }
153         if (!startThread_) {
154             std::thread watchThread([context] { context->WatchPathThread(); });
155             watchThread.detach();
156             startThread_ = true;
157         }
158     }
159 }
160 } // namespace Media
161 } // namespace OHOS
162