• 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 using namespace std;
19 namespace OHOS {
20 namespace StorageDaemon {
21 constexpr int32_t SLEEP_TIME = 1;
22 constexpr int32_t MTP_VAL_LEN = 6;
23 constexpr int32_t MTP_TRUE_LEN = 5;
24 constexpr int32_t DETECT_CNT = 4;
25 
26 constexpr const char *MTP_ROOT_PATH = "/mnt/data/external/";
27 constexpr const char *SYS_PARAM_SERVICE_PERSIST_ENABLE = "persist.edm.mtp_client_disable";
28 constexpr const char *SYS_PARAM_SERVICE_ENTERPRISE_ENABLE = "const.edm.is_enterprise_device";
29 constexpr const char *KEY_CUST = "const.cust.custPath";
30 constexpr const char *CUST_HWIT = "hwit";
31 constexpr int32_t SYS_PARARMETER_SIZE = 256;
32 bool g_keepMonitoring = true;
33 
MtpDeviceMonitor()34 MtpDeviceMonitor::MtpDeviceMonitor() {}
35 
~MtpDeviceMonitor()36 MtpDeviceMonitor::~MtpDeviceMonitor()
37 {
38     LOGI("MtpDeviceMonitor Destructor.");
39     UmountAllMtpDevice();
40 }
41 
StartMonitor()42 void MtpDeviceMonitor::StartMonitor()
43 {
44     LOGI("MtpDeviceMonitor, start mtp device monitor.");
45     if (IsHwitDevice()) {
46         LOGE("the vendor country of device is hwit/cn.");
47         return;
48     }
49     std::thread([this]() { MonitorDevice(); }).detach();
50 }
51 
IsNeedDisableMtp()52 bool MtpDeviceMonitor::IsNeedDisableMtp()
53 {
54     char mtpEnterpriseEnable[MTP_VAL_LEN + 1] = {"false"};
55     int retEn = GetParameter(SYS_PARAM_SERVICE_ENTERPRISE_ENABLE, "", mtpEnterpriseEnable, MTP_VAL_LEN);
56     LOGI("GetParameter mtpEnterpriseEnable %{public}s, retEnterprise %{public}d", mtpEnterpriseEnable, retEn);
57     char mtpEnable[MTP_VAL_LEN + 1] = {"false"};
58     int ret = GetParameter(SYS_PARAM_SERVICE_PERSIST_ENABLE, "", mtpEnable, MTP_VAL_LEN);
59     LOGI("GetParameter mtpEnable %{public}s, ret %{public}d", mtpEnable, ret);
60     if (strncmp(mtpEnterpriseEnable, "true", MTP_TRUE_LEN) == 0 && strncmp(mtpEnable, "true", MTP_TRUE_LEN) == 0) {
61         return true;
62     }
63     return false;
64 }
65 
MountMtpDeviceByBroadcast()66 void MtpDeviceMonitor::MountMtpDeviceByBroadcast()
67 {
68     int rawDevSize = 0;
69     LIBMTP_raw_device_t *rawDevices = nullptr;
70     LIBMTP_error_number_t err = LIBMTP_Detect_Raw_Devices(&rawDevices, &rawDevSize);
71     if ((err == LIBMTP_ERROR_NO_DEVICE_ATTACHED) || (rawDevices == nullptr) || (rawDevSize <= 0)) {
72         if (rawDevices != nullptr) {
73             free(static_cast<void *>(rawDevices));
74         }
75         return;
76     }
77 
78     std::vector<MtpDeviceInfo> devInfos;
79     for (int index = 0; index < rawDevSize; ++index) {
80         LIBMTP_raw_device_t *rawDevice = &rawDevices[index];
81         if (rawDevice == nullptr) {
82             LOGE("MonitorDevice: rawDevice is nullptr.");
83             continue;
84         }
85         std::vector<std::string> cmd = {
86             "cat",
87             "/proc/sys/kernel/random/uuid",
88         };
89         std::vector<std::string> uuids;
90         ForkExec(cmd, &uuids);
91 
92         MtpDeviceInfo devInfo;
93         devInfo.uuid = uuids.front();
94         devInfo.devNum = rawDevice->devnum;
95         devInfo.busLocation = rawDevice->bus_location;
96         devInfo.vendor = rawDevice->device_entry.vendor;
97         devInfo.product = rawDevice->device_entry.product;
98         devInfo.vendorId = rawDevice->device_entry.vendor_id;
99         devInfo.productId = rawDevice->device_entry.product_id;
100         devInfo.id = "mtp-" + std::to_string(devInfo.vendorId) + "-" + std::to_string(devInfo.productId);
101         devInfo.path = std::string(MTP_ROOT_PATH) + devInfo.id;
102         devInfos.push_back(devInfo);
103         LOGI("Detect new mtp device: id=%{public}s, vendor=%{public}s, product=%{public}s, devNum=%{public}d",
104             (devInfo.id).c_str(), (devInfo.vendor).c_str(), (devInfo.product).c_str(), devInfo.devNum);
105     }
106     MountMtpDevice(devInfos);
107     free(static_cast<void *>(rawDevices));
108 }
109 
MonitorDevice()110 void MtpDeviceMonitor::MonitorDevice()
111 {
112     LOGI("MonitorDevice: mtp device monitor thread begin.");
113     int32_t cnt = DETECT_CNT;
114     while (cnt > 0) {
115         MountMtpDeviceByBroadcast();
116         cnt--;
117         sleep(SLEEP_TIME);
118     }
119     RegisterMTPParamListener();
120     while (g_keepMonitoring) {
121         sleep(SLEEP_TIME);
122         UsbEventSubscriber::SubscribeCommonEvent();
123     }
124     RemoveMTPParamListener();
125     LOGI("MonitorDevice: mtp device monitor thread end.");
126 }
127 
MountMtpDevice(const std::vector<MtpDeviceInfo> & monitorDevices)128 void MtpDeviceMonitor::MountMtpDevice(const std::vector<MtpDeviceInfo> &monitorDevices)
129 {
130     if (IsNeedDisableMtp()) {
131         LOGE("This device cannot support MTP.");
132         return;
133     }
134     LOGI("MountMtpDevice: start mount mtp device.");
135     for (auto device : monitorDevices) {
136         if (HasMounted(device)) {
137             LOGI("MountMtpDevice: mtp device has mounted.");
138             continue;
139         }
140 
141         if (lastestMtpDevList_.size() > 0) {
142             LOGW("Multiple devices detected. Only one device is supported. Ignoring additional devices.");
143             return;
144         }
145         int32_t ret = DelayedSingleton<MtpDeviceManager>::GetInstance()->MountDevice(device);
146         if (ret == E_OK) {
147             lastestMtpDevList_.push_back(device);
148         } else if (ret == E_MTP_PREPARE_DIR_ERR) {
149             LOGE("MountMtpDevice: /mnt/data/external director not ready.");
150         }
151     }
152 }
153 
HasMounted(const MtpDeviceInfo & device)154 bool MtpDeviceMonitor::HasMounted(const MtpDeviceInfo &device)
155 {
156     std::lock_guard<std::mutex> lock(listMutex_);
157     for (auto iter = lastestMtpDevList_.begin(); iter != lastestMtpDevList_.end(); iter++) {
158         if (iter != lastestMtpDevList_.end() && (iter->id == device.id)) {
159             return true;
160         }
161     }
162     return false;
163 }
164 
UmountAllMtpDevice()165 void MtpDeviceMonitor::UmountAllMtpDevice()
166 {
167     std::lock_guard<std::mutex> lock(listMutex_);
168     for (auto iter = lastestMtpDevList_.begin(); iter != lastestMtpDevList_.end(); iter++) {
169         int32_t ret = DelayedSingleton<MtpDeviceManager>::GetInstance()->UmountDevice(*iter, true, false);
170         if (ret != E_OK) {
171             LOGE("UmountAllMtpDevice: umount mtp device failed, path=%{public}s", (iter->path).c_str());
172         }
173     }
174     lastestMtpDevList_.clear();
175 }
176 
UmountDetachedMtpDevice(uint8_t devNum,uint32_t busLoc)177 void MtpDeviceMonitor::UmountDetachedMtpDevice(uint8_t devNum, uint32_t busLoc)
178 {
179     std::lock_guard<std::mutex> lock(listMutex_);
180     LOGI("MtpDeviceMonitor::Umount detached mtp device, devNum=%{public}d, busLoc=%{public}d.", devNum, busLoc);
181 
182     for (auto iter = lastestMtpDevList_.begin(); iter != lastestMtpDevList_.end();) {
183         LOGI("Mtp device mount path=%{public}s is not exist or removed, umount it.", (iter->path).c_str());
184         int32_t ret = DelayedSingleton<MtpDeviceManager>::GetInstance()->UmountDevice(*iter, true, true);
185         if (ret == E_OK) {
186             iter = lastestMtpDevList_.erase(iter);
187         } else {
188             LOGE("Umount mtp device failed, path=%{public}s", (iter->path).c_str());
189             iter++;
190         }
191     }
192 }
193 
Mount(const std::string & id)194 int32_t MtpDeviceMonitor::Mount(const std::string &id)
195 {
196     LOGI("MtpDeviceMonitor: start mount mtp device by id=%{public}s", id.c_str());
197     std::lock_guard<std::mutex> lock(listMutex_);
198     for (auto iter = lastestMtpDevList_.begin(); iter != lastestMtpDevList_.end(); iter++) {
199         if (iter->id != id) {
200             continue;
201         }
202         int32_t ret = DelayedSingleton<MtpDeviceManager>::GetInstance()->MountDevice(*iter);
203         if (ret != E_OK) {
204             LOGE("MountMtpDevice: mtp device mount failed.");
205         }
206         return ret;
207     }
208     LOGE("the volume id %{public}s does not exist.", id.c_str());
209     return E_NON_EXIST;
210 }
211 
Umount(const std::string & id)212 int32_t MtpDeviceMonitor::Umount(const std::string &id)
213 {
214     LOGI("MtpDeviceMonitor: start umount mtp device by id=%{public}s", id.c_str());
215     std::lock_guard<std::mutex> lock(listMutex_);
216     for (auto iter = lastestMtpDevList_.begin(); iter != lastestMtpDevList_.end(); iter++) {
217         if (iter->id != id) {
218             continue;
219         }
220         int32_t ret = DelayedSingleton<MtpDeviceManager>::GetInstance()->UmountDevice(*iter, true, false);
221         if (ret == E_OK) {
222             lastestMtpDevList_.erase(iter);
223         } else {
224             LOGE("Umount mtp device failed, path=%{public}s", (iter->path).c_str());
225         }
226         return ret;
227     }
228     LOGE("the volume id %{public}s does not exist.", id.c_str());
229     return E_NON_EXIST;
230 }
231 
RegisterMTPParamListener()232 void MtpDeviceMonitor::RegisterMTPParamListener()
233 {
234     LOGI("RegisterMTPParamListener");
235     WatchParameter(SYS_PARAM_SERVICE_PERSIST_ENABLE, OnMtpDisableParamChange, this);
236     WatchParameter(SYS_PARAM_SERVICE_ENTERPRISE_ENABLE, OnEnterpriseParamChange, this);
237 }
238 
RemoveMTPParamListener()239 void MtpDeviceMonitor::RemoveMTPParamListener()
240 {
241     LOGI("RemoveMTPParamListener");
242     RemoveParameterWatcher(SYS_PARAM_SERVICE_PERSIST_ENABLE, OnMtpDisableParamChange, this);
243     RemoveParameterWatcher(SYS_PARAM_SERVICE_ENTERPRISE_ENABLE, OnEnterpriseParamChange, this);
244 }
245 
OnMtpDisableParamChange(const char * key,const char * value,void * context)246 void MtpDeviceMonitor::OnMtpDisableParamChange(const char *key, const  char *value, void *context)
247 {
248     if (key == nullptr || value == nullptr || context == nullptr) {
249         LOGE("OnMtpDisableParamChange return invaild value");
250         return;
251     }
252     LOGI("OnMtpDisableParamChange key = %{public}s, value = %{public}s,",  key, value);
253     if (strcmp(key, SYS_PARAM_SERVICE_PERSIST_ENABLE) != 0) {
254         LOGE("event key mismatch");
255         return;
256     }
257     MtpDeviceMonitor* instance = reinterpret_cast<MtpDeviceMonitor*>(context);
258     if (instance->IsNeedDisableMtp()) {
259         LOGI("MTP disable parameter changed, unmount all mtp devices.");
260         instance->UmountAllMtpDevice();
261     }
262 }
263 
OnEnterpriseParamChange(const char * key,const char * value,void * context)264 void MtpDeviceMonitor::OnEnterpriseParamChange(const char *key, const  char *value, void *context)
265 {
266     if (key == nullptr || value == nullptr || context == nullptr) {
267         LOGE("OnEnterpriseParamChange return invaild value");
268         return;
269     }
270     LOGI("OnEnterpriseParamChange key = %{public}s, value = %{public}s,",  key, value);
271     if (strcmp(key, SYS_PARAM_SERVICE_ENTERPRISE_ENABLE) != 0) {
272         LOGE("event key mismatch");
273         return;
274     }
275     MtpDeviceMonitor* instance = reinterpret_cast<MtpDeviceMonitor*>(context);
276     if (instance->IsNeedDisableMtp()) {
277         LOGI("Enterprise device parameter changed, unmount all mtp devices.");
278         instance->UmountAllMtpDevice();
279     }
280 }
281 
IsHwitDevice()282 bool MtpDeviceMonitor::IsHwitDevice()
283 {
284     char param[SYS_PARARMETER_SIZE] = {0};
285     int errorCode = GetParameter(KEY_CUST, "", param, SYS_PARARMETER_SIZE);
286     if (errorCode <= 0) {
287         LOGE("get vendor country fail, errorCode:%{public}d", errorCode);
288         return false;
289     }
290     LOGI("vendor counry: %{public}s, errorCode: %{public}d", param, errorCode);
291     if (std::string(param).find(CUST_HWIT) != std::string::npos) {
292         return true;
293     }
294     return false;
295 }
296 }  // namespace StorageDaemon
297 }  // namespace OHOS