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