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