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 #define MLOG_TAG "MtpOperation"
16 #include "mtp_operation.h"
17 #include <algorithm>
18 #include "header_data.h"
19 #include "medialibrary_tracer.h"
20 #include "media_log.h"
21 #include "media_mtp_utils.h"
22 #include "mtp_constants.h"
23 #include "mtp_dfx_reporter.h"
24 #include "mtp_packet.h"
25 #include "mtp_packet_tools.h"
26 #include "mtp_operation_context.h"
27 #include "mtp_operation_utils.h"
28 #include "mtp_storage_manager.h"
29 #include "packet_payload_factory.h"
30 #include "parameters.h"
31 #include "payload_data/get_device_info_data.h"
32 #include "payload_data.h"
33 #include "payload_data/send_object_info_data.h"
34 #include "payload_data/set_object_prop_value_data.h"
35 #include "storage.h"
36
37 using namespace std;
38 namespace OHOS {
39 namespace Media {
40 constexpr const char *MTP_DISABLE = "persist.edm.mtp_server_disable";
MtpOperation(void)41 MtpOperation::MtpOperation(void)
42 {
43 Init();
44 }
45
Init()46 void MtpOperation::Init()
47 {
48 mtpContextPtr_ = make_shared<MtpOperationContext>();
49 mtpContextPtr_->indata = false;
50
51 mtpDriver_ = make_shared<MtpDriver>();
52 mtpContextPtr_->mtpDriver = mtpDriver_;
53
54 requestPacketPtr_ = make_shared<MtpPacket>(mtpContextPtr_, mtpDriver_);
55 dataPacketPtr_ = make_shared<MtpPacket>(mtpContextPtr_, mtpDriver_);
56 responsePacketPtr_ = make_shared<MtpPacket>(mtpContextPtr_, mtpDriver_);
57
58 operationUtils_ = make_shared<MtpOperationUtils>(mtpContextPtr_, true);
59 responseCode_ = MTP_UNDEFINED_CODE;
60 }
61
Stop()62 void MtpOperation::Stop()
63 {
64 CHECK_AND_RETURN_LOG(requestPacketPtr_ != nullptr, "requestPacketPtr_ is null");
65 requestPacketPtr_->Stop();
66 }
67
Execute()68 int32_t MtpOperation::Execute()
69 {
70 MediaLibraryTracer tracer;
71 tracer.Start("MtpOperation::Execute");
72 // 判断param, disable == true, 直接给Initiator返回error_dode
73 std::string param(MTP_DISABLE);
74 bool mtpDisable = system::GetBoolParameter(param, false);
75 int errorCode = 0;
76 if (mtpDisable) {
77 SendMakeResponsePacket(errorCode);
78 MEDIA_INFO_LOG("MTP is disable");
79 return errorCode;
80 }
81 ResetOperation();
82 ReceiveRequestPacket(errorCode);
83 CHECK_AND_RETURN_RET_LOG(mtpContextPtr_ != nullptr, errorCode, "mtpContextPtr_ is null");
84 if (mtpContextPtr_->operationCode == 0) {
85 MEDIA_DEBUG_LOG("operationCode is 0, read error, no need to send response");
86 return errorCode;
87 }
88 if (errorCode != MTP_SUCCESS) {
89 SendMakeResponsePacket(errorCode);
90 MEDIA_ERR_LOG("MtpOperation::Execute Out ReceiveRequestPacket fail err: %{public}d", errorCode);
91 return errorCode;
92 }
93
94 DealRequest(mtpContextPtr_->operationCode, errorCode);
95 if (errorCode != MTP_SUCCESS) {
96 SendMakeResponsePacket(errorCode);
97 MEDIA_ERR_LOG("MtpOperation::Execute Out DealRequest fail err: %{public}d", errorCode);
98 return errorCode;
99 }
100
101 if (MtpPacket::IsNeedDataPhase(mtpContextPtr_->operationCode)) {
102 if (MtpPacket::IsI2R(mtpContextPtr_->operationCode)) {
103 ReceiveI2Rdata(errorCode);
104 } else {
105 SendR2Idata(errorCode);
106 }
107 }
108 if (errorCode == MTP_ERROR_TRANSFER_CANCELLED) {
109 MEDIA_INFO_LOG("File transfer canceled");
110 return errorCode;
111 }
112
113 SendMakeResponsePacket(errorCode);
114 return errorCode;
115 }
116
ReceiveRequestPacket(int & errorCode)117 void MtpOperation::ReceiveRequestPacket(int &errorCode)
118 {
119 shared_ptr<HeaderData> headerData = make_shared<HeaderData>(mtpContextPtr_);
120 requestPacketPtr_->Init(headerData);
121 errorCode = requestPacketPtr_->Read();
122 CHECK_AND_RETURN_LOG(errorCode == MTP_SUCCESS, "requestPacket Read fail err: %{public}d", errorCode);
123 errorCode = requestPacketPtr_->Parser();
124 CHECK_AND_RETURN_LOG(errorCode == MTP_SUCCESS, "requestPacket Parser fail err: %{public}d", errorCode);
125 }
126
SendMakeResponsePacket(int & errorCode)127 void MtpOperation::SendMakeResponsePacket(int &errorCode)
128 {
129 CHECK_AND_RETURN_LOG(responsePacketPtr_ != nullptr, "responsePacketPtr_ is null");
130 responsePacketPtr_->Reset();
131 CHECK_AND_RETURN_LOG(mtpContextPtr_ != nullptr, "mtpContextPtr_ is null");
132 GetPayloadData(mtpContextPtr_, dataPayloadData_, RESPONSE_CONTAINER_TYPE, errorCode);
133 if (mtpContextPtr_->operationCode != 0) {
134 MEDIA_INFO_LOG("operation = [0x%{public}x : %{public}s ]", mtpContextPtr_->operationCode,
135 MtpPacketTool::GetOperationName(mtpContextPtr_->operationCode).c_str());
136 }
137 MtpDfxReporter::GetInstance().DoOperationResultStatistics(mtpContextPtr_->operationCode, responseCode_);
138 shared_ptr<HeaderData> responseHeaderData = make_shared<HeaderData>(
139 RESPONSE_CONTAINER_TYPE, responseCode_, mtpContextPtr_->transactionID);
140
141 responsePacketPtr_->Init(responseHeaderData, dataPayloadData_);
142 errorCode = responsePacketPtr_->Maker(false);
143 CHECK_AND_RETURN_LOG(errorCode == MTP_SUCCESS, "responsePacket Maker fail err: %{public}d", errorCode);
144 int32_t result = 0;
145 auto startTime = std::chrono::high_resolution_clock::now();
146 errorCode = responsePacketPtr_->Write(result);
147 auto endTime = std::chrono::high_resolution_clock::now();
148 std::chrono::duration<uint16_t, std::milli> duration =
149 std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
150 MtpDfxReporter::GetInstance().DoSendResponseResultDfxReporter(mtpContextPtr_->operationCode, result,
151 duration.count(), OperateMode::writemode);
152 CHECK_AND_RETURN_LOG(errorCode == MTP_SUCCESS, "responsePacket Write fail err: %{public}d", errorCode);
153 }
154
SendObjectData(int & errorCode)155 void MtpOperation::SendObjectData(int &errorCode)
156 {
157 errorCode = operationUtils_->GetObjectDataDeal();
158 }
159
RecevieObjectData(int & errorCode)160 void MtpOperation::RecevieObjectData(int &errorCode)
161 {
162 errorCode = operationUtils_->DoRecevieSendObject();
163 }
164
ReceiveI2Rdata(int & errorCode)165 void MtpOperation::ReceiveI2Rdata(int &errorCode)
166 {
167 if (mtpContextPtr_->operationCode == MTP_OPERATION_SEND_OBJECT_CODE) {
168 MEDIA_INFO_LOG("ReceiveI2Rdata RecevieObjectData");
169 RecevieObjectData(errorCode);
170 return;
171 }
172 mtpContextPtr_->indata = true;
173
174 errorCode = dataPacketPtr_->Read();
175 CHECK_AND_RETURN_LOG(errorCode == MTP_SUCCESS, "dataPacket Read fail err: %{public}d", errorCode);
176 errorCode = dataPacketPtr_->Parser();
177 CHECK_AND_RETURN_LOG(errorCode == MTP_SUCCESS, "dataPacket Parser fail err: %{public}d", errorCode);
178
179 if (mtpContextPtr_->operationCode == MTP_OPERATION_SET_OBJECT_PROP_VALUE_CODE) {
180 MEDIA_INFO_LOG("ReceiveI2Rdata DoSetObjectPropValue");
181 operationUtils_->DoSetObjectPropValue(errorCode);
182 }
183 }
184
SendR2Idata(int & errorCode)185 void MtpOperation::SendR2Idata(int &errorCode)
186 {
187 if (mtpContextPtr_->operationCode == MTP_OPERATION_GET_OBJECT_CODE ||
188 mtpContextPtr_->operationCode == MTP_OPERATION_GET_PARTIAL_OBJECT_CODE) {
189 SendObjectData(errorCode);
190 return;
191 }
192
193 responseCode_ = GetPayloadData(mtpContextPtr_, dataPayloadData_, DATA_CONTAINER_TYPE, errorCode);
194 MEDIA_INFO_LOG("operation = [0x%{public}x : %{public}s ]", mtpContextPtr_->operationCode,
195 MtpPacketTool::GetOperationName(mtpContextPtr_->operationCode).c_str());
196 CHECK_AND_RETURN_LOG(errorCode == MTP_SUCCESS, "GetPayloadData fail err: %{public}d", errorCode);
197 shared_ptr<HeaderData> dataHeaderData = make_shared<HeaderData>(
198 DATA_CONTAINER_TYPE, mtpContextPtr_->operationCode, mtpContextPtr_->transactionID);
199 dataPacketPtr_->Init(dataHeaderData, dataPayloadData_);
200 errorCode = dataPacketPtr_->Maker(true);
201 CHECK_AND_RETURN_LOG(errorCode == MTP_SUCCESS, "dataPacket Maker fail err: %{public}d", errorCode);
202 int32_t result = 0;
203 auto startTime = std::chrono::high_resolution_clock::now();
204 errorCode = dataPacketPtr_->Write(result);
205 auto endTime = std::chrono::high_resolution_clock::now();
206 std::chrono::duration<uint16_t, std::milli> duration =
207 std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
208 MtpDfxReporter::GetInstance().DoSendResponseResultDfxReporter(mtpContextPtr_->operationCode, result,
209 duration.count(), OperateMode::writemode);
210 CHECK_AND_RETURN_LOG(errorCode == MTP_SUCCESS, "dataPacket Write fail err: %{public}d", errorCode);
211 }
212
DealRequest(uint16_t operationCode,int & errorCode)213 void MtpOperation::DealRequest(uint16_t operationCode, int &errorCode)
214 {
215 switch (operationCode) {
216 case MTP_OPERATION_OPEN_SESSION_CODE:
217 if (!mtpContextPtr_->sessionOpen) {
218 mtpContextPtr_->sessionID = mtpContextPtr_->tempSessionID;
219 errorCode = MTP_SUCCESS;
220 } else {
221 errorCode = MTP_ERROR_SESSION_ALREADY_OPEN;
222 }
223 break;
224 default:
225 errorCode = MTP_SUCCESS;
226 break;
227 }
228 }
229
GetPayloadData(shared_ptr<MtpOperationContext> & context,shared_ptr<PayloadData> & data,uint16_t containerType,int & errorCode)230 uint16_t MtpOperation::GetPayloadData(shared_ptr<MtpOperationContext> &context, shared_ptr<PayloadData> &data,
231 uint16_t containerType, int &errorCode)
232 {
233 responseCode_ = MTP_UNDEFINED_CODE;
234 switch (context->operationCode) {
235 case MTP_OPERATION_GET_DEVICE_INFO_CODE:
236 responseCode_ = operationUtils_->GetDeviceInfo(data, containerType, errorCode);
237 break;
238 case MTP_OPERATION_OPEN_SESSION_CODE:
239 responseCode_ = operationUtils_->GetOpenSession(data, errorCode);
240 break;
241 case MTP_OPERATION_SET_DEVICE_PROP_VALUE_CODE:
242 responseCode_ = operationUtils_->SetDevicePropValueResp(data);
243 break;
244 default:
245 responseCode_ = GetPayloadDataSub(context, data, containerType, errorCode);
246 break;
247 }
248 return responseCode_;
249 }
250
GetPayloadDataSub(shared_ptr<MtpOperationContext> & context,shared_ptr<PayloadData> & data,uint16_t containerType,int & errorCode)251 uint16_t MtpOperation::GetPayloadDataSub(shared_ptr<MtpOperationContext> &context, shared_ptr<PayloadData> &data,
252 uint16_t containerType, int &errorCode)
253 {
254 responseCode_ = MTP_UNDEFINED_CODE;
255 switch (context->operationCode) {
256 case MTP_OPERATION_RESET_DEVICE_CODE:
257 case MTP_OPERATION_CLOSE_SESSION_CODE:
258 responseCode_ = operationUtils_->GetCloseSession(data);
259 break;
260 case MTP_OPERATION_GET_STORAGE_IDS_CODE:
261 responseCode_ = operationUtils_->GetStorageIDs(data, containerType, errorCode);
262 break;
263 case MTP_OPERATION_GET_STORAGE_INFO_CODE:
264 responseCode_ = operationUtils_->GetStorageInfo(data, containerType, errorCode);
265 break;
266 case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED_CODE:
267 responseCode_ = operationUtils_->GetObjectPropsSupported(data);
268 break;
269 case MTP_OPERATION_GET_OBJECT_HANDLES_CODE:
270 responseCode_ = operationUtils_->GetObjectHandles(data, containerType, errorCode);
271 break;
272 case MTP_OPERATION_GET_NUM_OBJECTS_CODE:
273 responseCode_ = operationUtils_->GetNumObjects(data);
274 break;
275 case MTP_OPERATION_GET_OBJECT_INFO_CODE:
276 responseCode_ = operationUtils_->GetObjectInfo(data, containerType, errorCode);
277 break;
278 case MTP_OPERATION_GET_OBJECT_PROP_DESC_CODE:
279 responseCode_ = operationUtils_->GetObjectPropDesc(data, containerType, errorCode);
280 break;
281 case MTP_OPERATION_GET_OBJECT_PROP_VALUE_CODE:
282 responseCode_ = operationUtils_->GetObjectPropValue(data, containerType, errorCode);
283 break;
284 case MTP_OPERATION_SET_OBJECT_PROP_VALUE_CODE:
285 responseCode_ = operationUtils_->GetRespCommonData(data, errorCode);
286 break;
287 case MTP_OPERATION_GET_OBJECT_PROP_LIST_CODE:
288 responseCode_ = operationUtils_->GetObjectPropList(data, containerType, errorCode);
289 break;
290 default:
291 responseCode_ = GetPayloadDataMore(context, data, containerType, errorCode);
292 break;
293 }
294 return responseCode_;
295 }
296
GetPayloadDataMore(shared_ptr<MtpOperationContext> & context,shared_ptr<PayloadData> & data,uint16_t containerType,int & errorCode)297 uint16_t MtpOperation::GetPayloadDataMore(shared_ptr<MtpOperationContext> &context, shared_ptr<PayloadData> &data,
298 uint16_t containerType, int &errorCode)
299 {
300 responseCode_ = MTP_UNDEFINED_CODE;
301 switch (context->operationCode) {
302 case MTP_OPERATION_GET_OBJECT_REFERENCES_CODE:
303 responseCode_ = operationUtils_->GetObjectReferences(data, containerType, errorCode);
304 break;
305 case MTP_OPERATION_SET_OBJECT_REFERENCES_CODE:
306 responseCode_ = operationUtils_->SetObjectReferences(data);
307 break;
308 case MTP_OPERATION_DELETE_OBJECT_CODE:
309 responseCode_ = operationUtils_->DeleteObject(data, errorCode);
310 break;
311 case MTP_OPERATION_MOVE_OBJECT_CODE:
312 responseCode_ = operationUtils_->MoveObject(data, errorCode);
313 break;
314 case MTP_OPERATION_COPY_OBJECT_CODE:
315 responseCode_ = operationUtils_->CopyObject(data, errorCode);
316 break;
317 case MTP_OPERATION_GET_DEVICE_PROP_DESC_CODE:
318 responseCode_ = operationUtils_->GetPropDesc(data, containerType, errorCode);
319 break;
320 case MTP_OPERATION_GET_DEVICE_PROP_VALUE_CODE:
321 responseCode_ = operationUtils_->GetPropValue(data, containerType, errorCode);
322 break;
323 case MTP_OPERATION_RESET_DEVICE_PROP_VALUE_CODE:
324 responseCode_ = operationUtils_->ResetDevicePropResp(data);
325 break;
326 case MTP_OPERATION_GET_OBJECT_CODE:
327 responseCode_ = operationUtils_->GetObject(data, errorCode);
328 break;
329 case MTP_OPERATION_SEND_OBJECT_CODE:
330 responseCode_ = operationUtils_->GetRespCommonData(data, errorCode);
331 break;
332 case MTP_OPERATION_GET_THUMB_CODE:
333 responseCode_ = operationUtils_->GetThumb(data, containerType, errorCode);
334 break;
335 case MTP_OPERATION_SEND_OBJECT_INFO_CODE:
336 responseCode_ = operationUtils_->SendObjectInfo(data, errorCode);
337 break;
338 case MTP_OPERATION_GET_PARTIAL_OBJECT_CODE:
339 responseCode_ = operationUtils_->GetPartialObject(data);
340 break;
341 default:
342 responseCode_ = operationUtils_->GetRespCommonData(data, errorCode);
343 break;
344 }
345 return responseCode_;
346 }
347
ResetOperation()348 void MtpOperation::ResetOperation()
349 {
350 if (requestPacketPtr_ != nullptr) {
351 requestPacketPtr_->Reset();
352 }
353 if (dataPacketPtr_ != nullptr) {
354 dataPacketPtr_->Reset();
355 }
356 if (responsePacketPtr_ != nullptr) {
357 responsePacketPtr_->Reset();
358 }
359 if (dataPayloadData_!= nullptr) {
360 dataPayloadData_ = nullptr;
361 }
362 if (mtpContextPtr_ != nullptr) {
363 mtpContextPtr_->operationCode = 0;
364 mtpContextPtr_->transactionID = 0;
365 mtpContextPtr_->indata = false;
366 }
367
368 responseCode_ = MTP_OK_CODE;
369 }
370
AddStorage(shared_ptr<Storage> & storage)371 void MtpOperation::AddStorage(shared_ptr<Storage> &storage)
372 {
373 auto mtpStorageManager = MtpStorageManager::GetInstance();
374 if (mtpStorageManager != nullptr) {
375 mtpStorageManager->AddStorage(storage);
376 }
377 }
378
RemoveStorage(std::shared_ptr<Storage> & storage)379 void MtpOperation::RemoveStorage(std::shared_ptr<Storage> &storage)
380 {
381 auto mtpStorageManager = MtpStorageManager::GetInstance();
382 if (mtpStorageManager != nullptr) {
383 mtpStorageManager->RemoveStorage(storage);
384 }
385 }
386 } // namespace Media
387 } // namespace OHOS