• 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 "mtp/mtp_device_monitor.h"
17 
18 #include <cstdio>
19 #include <dirent.h>
20 #include <filesystem>
21 #include <iostream>
22 #include <libmtp.h>
23 #include "parameter.h"
24 #include "parameters.h"
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/xattr.h>
28 #include <unistd.h>
29 #include <thread>
30 #include "mtp/usb_event_subscriber.h"
31 #include "storage_service_errno.h"
32 #include "storage_service_log.h"
33 #include "utils/file_utils.h"
34 #include "usb_srv_client.h"
35 
36 using namespace std;
37 namespace OHOS {
38 namespace StorageDaemon {
39 constexpr int32_t SLEEP_TIME = 1;
40 constexpr int32_t MTP_VAL_LEN = 6;
41 constexpr int32_t MTP_TRUE_LEN = 5;
42 constexpr int32_t DETECT_CNT = 4;
43 constexpr int UPLOAD_RECORD_FALSE_LEN = 5;
44 constexpr int UPLOAD_RECORD_TRUE_LEN = 4;
45 
46 constexpr const char *MTP_ROOT_PATH = "/mnt/data/external/";
47 constexpr const char *SYS_PARAM_SERVICE_PERSIST_ENABLE = "persist.edm.mtp_client_disable";
48 constexpr const char *SYS_PARAM_SERVICE_ENTERPRISE_ENABLE = "const.edm.is_enterprise_device";
49 constexpr const char *KEY_CUST = "const.cust.custPath";
50 constexpr const char *CUST_HWIT = "hwit";
51 constexpr const char *IS_PYP_MODE = "user.isptpmode";
52 constexpr int32_t SYS_PARARMETER_SIZE = 256;
53 bool g_keepMonitoring = true;
54 
MtpDeviceMonitor()55 MtpDeviceMonitor::MtpDeviceMonitor() {}
56 
~MtpDeviceMonitor()57 MtpDeviceMonitor::~MtpDeviceMonitor()
58 {
59     LOGI("MtpDeviceMonitor Destructor.");
60     UmountAllMtpDevice();
61 }
62 
StartMonitor()63 void MtpDeviceMonitor::StartMonitor()
64 {
65     LOGI("MtpDeviceMonitor, start mtp device monitor.");
66     if (IsHwitDevice()) {
67         LOGE("the vendor country of device is hwit/cn.");
68         return;
69     }
70     std::thread([this]() { MonitorDevice(); }).detach();
71 }
72 
IsNeedDisableMtp()73 bool MtpDeviceMonitor::IsNeedDisableMtp()
74 {
75     char mtpEnterpriseEnable[MTP_VAL_LEN + 1] = {"false"};
76     int retEn = GetParameter(SYS_PARAM_SERVICE_ENTERPRISE_ENABLE, "", mtpEnterpriseEnable, MTP_VAL_LEN);
77     LOGI("GetParameter mtpEnterpriseEnable %{public}s, retEnterprise %{public}d", mtpEnterpriseEnable, retEn);
78     char mtpEnable[MTP_VAL_LEN + 1] = {"false"};
79     int ret = GetParameter(SYS_PARAM_SERVICE_PERSIST_ENABLE, "", mtpEnable, MTP_VAL_LEN);
80     LOGI("GetParameter mtpEnable %{public}s, ret %{public}d", mtpEnable, ret);
81     if (strncmp(mtpEnterpriseEnable, "true", MTP_TRUE_LEN) == 0 && strncmp(mtpEnable, "true", MTP_TRUE_LEN) == 0) {
82         return true;
83     }
84     return false;
85 }
86 
GetMtpDevices(std::vector<MtpDeviceInfo> & devInfos)87 int32_t MtpDeviceMonitor::GetMtpDevices(std::vector<MtpDeviceInfo> &devInfos)
88 {
89     int rawDevSize = 0;
90     LIBMTP_raw_device_t *rawDevices = nullptr;
91     LIBMTP_error_number_t err = LIBMTP_Detect_Raw_Devices(&rawDevices, &rawDevSize);
92     if ((err == LIBMTP_ERROR_NO_DEVICE_ATTACHED) || (rawDevices == nullptr) || (rawDevSize <= 0)) {
93         if (rawDevices != nullptr) {
94             free(static_cast<void *>(rawDevices));
95         }
96         return E_MTP_MOUNT_FAILED;
97     }
98 
99     for (int index = 0; index < rawDevSize; ++index) {
100         LIBMTP_raw_device_t *rawDevice = &rawDevices[index];
101         if (rawDevice == nullptr) {
102             LOGE("MonitorDevice: rawDevice is nullptr.");
103             continue;
104         }
105         std::vector<std::string> cmd = {
106             "cat",
107             "/proc/sys/kernel/random/uuid",
108         };
109         std::vector<std::string> uuids;
110         ForkExec(cmd, &uuids);
111 
112         MtpDeviceInfo devInfo;
113         devInfo.uuid = uuids.front();
114         devInfo.devNum = rawDevice->devnum;
115         devInfo.busLocation = rawDevice->bus_location;
116         devInfo.vendor = rawDevice->device_entry.vendor;
117         devInfo.product = rawDevice->device_entry.product;
118         devInfo.vendorId = rawDevice->device_entry.vendor_id;
119         devInfo.productId = rawDevice->device_entry.product_id;
120         devInfo.id = "mtp-" + std::to_string(devInfo.vendorId) + "-" + std::to_string(devInfo.productId);
121         devInfo.path = std::string(MTP_ROOT_PATH) + devInfo.id;
122         devInfos.push_back(devInfo);
123         LOGI("Detect new mtp device: id=%{public}s, vendor=%{public}s, product=%{public}s, devNum=%{public}d",
124             (devInfo.id).c_str(), (devInfo.vendor).c_str(), (devInfo.product).c_str(), devInfo.devNum);
125     }
126     free(static_cast<void *>(rawDevices));
127     return E_OK;
128 }
129 
MountMtpDeviceByBroadcast()130 void MtpDeviceMonitor::MountMtpDeviceByBroadcast()
131 {
132     std::vector<MtpDeviceInfo> devInfos;
133     int32_t ret = GetMtpDevices(devInfos);
134     if (ret != E_OK) {
135         LOGE("No MTP devices detected");
136         return;
137     }
138     ret = MountMtpDevice(devInfos);
139     if (ret != E_OK) {
140         LOGE("mount mtp device failed");
141         return;
142     }
143     bool isPtp = UsbEventSubscriber::IsPtpMode();
144 
145     for (const auto& devInfo : devInfos) {
146         const char* value = isPtp ? "true" : "false";
147         size_t len = isPtp ? UPLOAD_RECORD_TRUE_LEN : UPLOAD_RECORD_FALSE_LEN;
148         if (setxattr(devInfo.path.c_str(), IS_PYP_MODE, value, len, 0) == -1) {
149             LOGE("Failed to set xattr");
150         }
151     }
152 }
153 
MonitorDevice()154 void MtpDeviceMonitor::MonitorDevice()
155 {
156     LOGI("MonitorDevice: mtp device monitor thread begin.");
157     int32_t cnt = DETECT_CNT;
158     while (cnt > 0) {
159         bool hasMtp = false;
160         if (HasMTPDevice(hasMtp) != E_OK) {
161             cnt--;
162             sleep(SLEEP_TIME);
163             continue;
164         }
165         if (hasMtp) {
166             MountMtpDeviceByBroadcast();
167             break;
168         }
169         cnt--;
170         sleep(SLEEP_TIME);
171     }
172     RegisterMTPParamListener();
173     while (g_keepMonitoring) {
174         sleep(SLEEP_TIME);
175         UsbEventSubscriber::SubscribeCommonEvent();
176     }
177     RemoveMTPParamListener();
178     LOGI("MonitorDevice: mtp device monitor thread end.");
179 }
180 
MountMtpDevice(const std::vector<MtpDeviceInfo> & monitorDevices)181 int32_t MtpDeviceMonitor::MountMtpDevice(const std::vector<MtpDeviceInfo> &monitorDevices)
182 {
183     if (IsNeedDisableMtp()) {
184         LOGE("This device cannot support MTP.");
185         return E_MTP_MOUNT_FAILED;
186     }
187     LOGI("MountMtpDevice: start mount mtp device.");
188     for (auto device : monitorDevices) {
189         if (HasMounted(device)) {
190             LOGI("MountMtpDevice: mtp device has mounted.");
191             continue;
192         }
193 
194         if (lastestMtpDevList_.size() > 0) {
195             LOGW("Multiple devices detected. Only one device is supported. Ignoring additional devices.");
196             return E_MTP_MOUNT_FAILED;
197         }
198         int32_t ret = MtpDeviceManager::GetInstance().MountDevice(device);
199         if (ret == E_OK) {
200             lastestMtpDevList_.push_back(device);
201         } else if (ret == E_MTP_IS_MOUNTING) {
202             return E_OK;
203         } else {
204             return E_MTP_MOUNT_FAILED;
205         }
206     }
207     return E_OK;
208 }
209 
HasMounted(const MtpDeviceInfo & device)210 bool MtpDeviceMonitor::HasMounted(const MtpDeviceInfo &device)
211 {
212     std::lock_guard<std::mutex> lock(listMutex_);
213     for (auto iter = lastestMtpDevList_.begin(); iter != lastestMtpDevList_.end(); iter++) {
214         if (iter != lastestMtpDevList_.end() && (iter->id == device.id)) {
215             return true;
216         }
217     }
218     return false;
219 }
220 
UmountAllMtpDevice()221 void MtpDeviceMonitor::UmountAllMtpDevice()
222 {
223     std::lock_guard<std::mutex> lock(listMutex_);
224     for (auto iter = lastestMtpDevList_.begin(); iter != lastestMtpDevList_.end(); iter++) {
225         int32_t ret = MtpDeviceManager::GetInstance().UmountDevice(*iter, true, false);
226         if (ret != E_OK) {
227             LOGE("UmountAllMtpDevice: umount mtp device failed, path=%{public}s", (iter->path).c_str());
228         }
229     }
230     lastestMtpDevList_.clear();
231 }
232 
UmountDetachedMtpDevice(uint8_t devNum,uint32_t busLoc)233 void MtpDeviceMonitor::UmountDetachedMtpDevice(uint8_t devNum, uint32_t busLoc)
234 {
235     std::lock_guard<std::mutex> lock(listMutex_);
236     LOGI("MtpDeviceMonitor::Umount detached mtp device, devNum=%{public}d, busLoc=%{public}d.", devNum, busLoc);
237 
238     for (auto iter = lastestMtpDevList_.begin(); iter != lastestMtpDevList_.end();) {
239         LOGI("Mtp device mount path=%{public}s is not exist or removed, umount it.", (iter->path).c_str());
240         int32_t ret = MtpDeviceManager::GetInstance().UmountDevice(*iter, true, true);
241         if (ret == E_OK) {
242             iter = lastestMtpDevList_.erase(iter);
243         } else {
244             LOGE("Umount mtp device failed, path=%{public}s", (iter->path).c_str());
245             iter++;
246         }
247     }
248 }
249 
Mount(const std::string & id)250 int32_t MtpDeviceMonitor::Mount(const std::string &id)
251 {
252     LOGI("MtpDeviceMonitor: start mount mtp device by id=%{public}s", id.c_str());
253     std::lock_guard<std::mutex> lock(listMutex_);
254     for (auto iter = lastestMtpDevList_.begin(); iter != lastestMtpDevList_.end(); iter++) {
255         if (iter->id != id) {
256             continue;
257         }
258         int32_t ret = MtpDeviceManager::GetInstance().MountDevice(*iter);
259         if (ret != E_OK) {
260             LOGE("MountMtpDevice: mtp device mount failed.");
261         }
262         return ret;
263     }
264     LOGE("the volume id %{public}s does not exist.", id.c_str());
265     return E_NON_EXIST;
266 }
267 
Umount(const std::string & id)268 int32_t MtpDeviceMonitor::Umount(const std::string &id)
269 {
270     LOGI("MtpDeviceMonitor: start umount mtp device by id=%{public}s", id.c_str());
271     std::lock_guard<std::mutex> lock(listMutex_);
272     for (auto iter = lastestMtpDevList_.begin(); iter != lastestMtpDevList_.end(); iter++) {
273         if (iter->id != id) {
274             continue;
275         }
276         int32_t ret = MtpDeviceManager::GetInstance().UmountDevice(*iter, true, false);
277         if (ret == E_OK) {
278             lastestMtpDevList_.erase(iter);
279         } else {
280             LOGE("Umount mtp device failed, path=%{public}s", (iter->path).c_str());
281         }
282         return ret;
283     }
284     LOGE("the volume id %{public}s does not exist.", id.c_str());
285     return E_NON_EXIST;
286 }
287 
IsHwitDevice()288 bool MtpDeviceMonitor::IsHwitDevice()
289 {
290     char param[SYS_PARARMETER_SIZE] = {0};
291     int errorCode = GetParameter(KEY_CUST, "", param, SYS_PARARMETER_SIZE);
292     if (errorCode <= 0) {
293         LOGE("get vendor country fail, errorCode:%{public}d", errorCode);
294         return false;
295     }
296     LOGI("vendor counry: %{public}s, errorCode: %{public}d", param, errorCode);
297     if (std::string(param).find(CUST_HWIT) != std::string::npos) {
298         return true;
299     }
300     return false;
301 }
302 
RegisterMTPParamListener()303 void MtpDeviceMonitor::RegisterMTPParamListener()
304 {
305     LOGI("RegisterMTPParamListener");
306     WatchParameter(SYS_PARAM_SERVICE_PERSIST_ENABLE, OnMtpDisableParamChange, this);
307     WatchParameter(SYS_PARAM_SERVICE_ENTERPRISE_ENABLE, OnEnterpriseParamChange, this);
308 }
309 
RemoveMTPParamListener()310 void MtpDeviceMonitor::RemoveMTPParamListener()
311 {
312     LOGI("RemoveMTPParamListener");
313     RemoveParameterWatcher(SYS_PARAM_SERVICE_PERSIST_ENABLE, OnMtpDisableParamChange, this);
314     RemoveParameterWatcher(SYS_PARAM_SERVICE_ENTERPRISE_ENABLE, OnEnterpriseParamChange, this);
315 }
316 
OnMtpDisableParamChange(const char * key,const char * value,void * context)317 void MtpDeviceMonitor::OnMtpDisableParamChange(const char *key, const  char *value, void *context)
318 {
319     if (key == nullptr || value == nullptr || context == nullptr) {
320         LOGE("OnMtpDisableParamChange return invaild value");
321         return;
322     }
323     LOGI("OnMtpDisableParamChange key = %{public}s, value = %{public}s,",  key, value);
324     if (strcmp(key, SYS_PARAM_SERVICE_PERSIST_ENABLE) != 0) {
325         LOGE("event key mismatch");
326         return;
327     }
328     MtpDeviceMonitor* instance = reinterpret_cast<MtpDeviceMonitor*>(context);
329     if (instance == nullptr) {
330         LOGE("Converted context is null");
331         return;
332     }
333     if (instance->IsNeedDisableMtp()) {
334         LOGI("MTP disable parameter changed, unmount all mtp devices.");
335         instance->UmountAllMtpDevice();
336     }
337 }
338 
OnEnterpriseParamChange(const char * key,const char * value,void * context)339 void MtpDeviceMonitor::OnEnterpriseParamChange(const char *key, const  char *value, void *context)
340 {
341     if (key == nullptr || value == nullptr || context == nullptr) {
342         LOGE("OnEnterpriseParamChange return invaild value");
343         return;
344     }
345     LOGI("OnEnterpriseParamChange key = %{public}s, value = %{public}s,",  key, value);
346     if (strcmp(key, SYS_PARAM_SERVICE_ENTERPRISE_ENABLE) != 0) {
347         LOGE("event key mismatch");
348         return;
349     }
350     MtpDeviceMonitor* instance = reinterpret_cast<MtpDeviceMonitor*>(context);
351     if (instance == nullptr) {
352         LOGE("Converted context is null");
353         return;
354     }
355     if (instance->IsNeedDisableMtp()) {
356         LOGI("Enterprise device parameter changed, unmount all mtp devices.");
357         instance->UmountAllMtpDevice();
358     }
359 }
360 
HasMTPDevice(bool & hasMtp)361 int32_t MtpDeviceMonitor::HasMTPDevice(bool &hasMtp)
362 {
363     auto &usbSrvClient = OHOS::USB::UsbSrvClient::GetInstance();
364     std::vector<UsbDevice> deviceList;
365     int32_t ret = usbSrvClient.GetDevices(deviceList);
366     if (ret != E_OK) {
367         LOGE("USB GetDevices failed, ret is %{public}d.", ret);
368         return ret;
369     }
370     for (UsbDevice &dev : deviceList) {
371         uint8_t deviceClass = static_cast<uint8_t>(dev.GetClass());
372         uint16_t idVendor = static_cast<uint16_t>(dev.GetVendorId());
373         uint16_t idProduct = static_cast<uint16_t>(dev.GetProductId());
374         LOGI("device class is %{public}d, vendor id is %{public}d, product id is %{public}d.",
375              deviceClass, idVendor, idProduct);
376         if (LIBMTP_check_is_mtp_device(deviceClass, idVendor, idProduct)) {
377             LOGE("this is mtp device.");
378             hasMtp = true;
379             return E_OK;
380         }
381     }
382     LOGI("there has no mtp device.");
383     hasMtp = false;
384     return E_OK;
385 }
386 }  // namespace StorageDaemon
387 }  // namespace OHOS