* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define MLOG_TAG "MtpOperationUtils"
#include "mtp_operation_utils.h"
#include <cinttypes>
#include <sys/time.h>
#include "ability_manager_client.h"
#ifdef HAS_BATTERY_MANAGER_PART
#include "battery_srv_client.h"
#endif
#include "directory_ex.h"
#include "iservice_registry.h"
#include "media_log.h"
#include "media_mtp_utils.h"
#include "mtp_dfx_reporter.h"
#include "mtp_manager.h"
#include "mtp_packet_tools.h"
#include "mtp_operation_context.h"
#include "mtp_ptp_proxy.h"
#include "mtp_storage_manager.h"
#include "mtp_store_observer.h"
#include "payload_data/resp_common_data.h"
#include "payload_data/close_session_data.h"
#include "payload_data/copy_object_data.h"
#include "payload_data/get_device_info_data.h"
#include "payload_data/get_device_prop_desc_data.h"
#include "payload_data/get_device_prop_value_data.h"
#include "payload_data/get_num_objects_data.h"
#include "payload_data/get_object_data.h"
#include "payload_data/get_object_handles_data.h"
#include "payload_data/get_object_info_data.h"
#include "payload_data/get_object_prop_list_data.h"
#include "payload_data/get_object_prop_desc_data.h"
#include "payload_data/get_object_prop_value_data.h"
#include "payload_data/get_object_props_supported_data.h"
#include "payload_data/get_object_references_data.h"
#include "payload_data/get_partial_object_data.h"
#include "payload_data/get_storage_info_data.h"
#include "payload_data/get_storage_ids_data.h"
#include "payload_data/get_thumb_data.h"
#include "payload_data/object_event_data.h"
#include "payload_data/open_session_data.h"
#include "payload_data/send_object_info_data.h"
#include "payload_data/set_object_references_data.h"
#include "parameters.h"
using namespace std;
namespace OHOS {
namespace Media {
#ifdef HAS_BATTERY_MANAGER_PART
static constexpr int MAX_BATTERY = 100;
static constexpr int ERROR_BATTERY = -1;
#endif
static constexpr int EMPTY_BATTERY = 0;
static constexpr int STORAGE_MANAGER_UID = 5003;
static constexpr int RECEVIE_OBJECT_CANCELLED = -20;
static constexpr int RECEVIE_OBJECT_FAILED = -17;
const std::string PUBLIC_DOC = "/storage/media/local/files/Docs";
static constexpr uint32_t HEADER_LEN = 12;
static constexpr uint32_t READ_LEN = 1024;
static constexpr uint32_t SEND_OBJECT_FILE_MAX_SIZE = 0xFFFFFFFF;
constexpr int32_t PATH_TIMEVAL_MAX = 2;
static bool g_isDevicePropSet = false;
MtpOperationUtils::MtpOperationUtils(const shared_ptr<MtpOperationContext> &context, bool isInit) : context_(context)
{
if (isInit) {
auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
CHECK_AND_RETURN_LOG(saManager != nullptr, "GetSystemAbilityManager failed, saManager is null");
auto token = saManager->GetSystemAbility(STORAGE_MANAGER_UID);
MtpPtpProxy::GetInstance().Init(token, context);
g_isDevicePropSet = false;
}
}
MtpOperationUtils::~MtpOperationUtils()
{
}
uint16_t MtpOperationUtils::GetDeviceInfo(shared_ptr<PayloadData> &data, uint16_t containerType, int &errorCode)
{
if (containerType != DATA_CONTAINER_TYPE) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
shared_ptr<GetDeviceInfoData> getDeviceInfoData = make_shared<GetDeviceInfoData>();
getDeviceInfoData->SetManufacturer(GetPropertyInner("const.product.manufacturer",
DEFAULT_PRODUCT_MANUFACTURER));
getDeviceInfoData->SetModel(GetPropertyInner("const.product.model", DEFAULT_PRODUCT_MODEL));
getDeviceInfoData->SetVersion(GetPropertyInner("const.product.software.version",
DEFAULT_PRODUCT_SOFTWARE_VERSION));
getDeviceInfoData->SetSerialNum(GetPropertyInner("ohos.boot.sn", "0"));
data = getDeviceInfoData;
errorCode = MTP_SUCCESS;
return MTP_OK_CODE;
}
uint16_t MtpOperationUtils::GetNumObjects(shared_ptr<PayloadData> &data)
{
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, CheckErrorCode(MTP_ERROR_CONTEXT_IS_NULL),
"GetNumObjects context_ is null");
CHECK_AND_RETURN_RET(MtpStorageManager::GetInstance()->HasStorage(context_->storageID),
MTP_INVALID_STORAGEID_CODE);
shared_ptr<GetNumObjectsData> getNumObjects = make_shared<GetNumObjectsData>();
data = getNumObjects;
return CheckErrorCode(MTP_SUCCESS);
}
uint16_t MtpOperationUtils::HasStorage(int &errorCode)
{
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, MTP_ERROR_CONTEXT_IS_NULL,
"GetObjectHandles context_ is null");
CHECK_AND_RETURN_RET_LOG(context_->sessionOpen != false, MTP_ERROR_SESSION_NOT_OPEN,
"GetObjectHandles session not open");
CHECK_AND_RETURN_RET_LOG(MtpStorageManager::GetInstance()->HasStorage(context_->storageID),
MTP_ERROR_INVALID_STORAGE_ID, "GetObjectHandles no this storage");
return MTP_SUCCESS;
}
uint16_t MtpOperationUtils::GetObjectHandles(shared_ptr<PayloadData> &data, uint16_t containerType, int &errorCode)
{
if (containerType != DATA_CONTAINER_TYPE) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
uint16_t ret = HasStorage(errorCode);
CHECK_AND_RETURN_RET(ret == MTP_SUCCESS, CheckErrorCode(ret));
bool isMac = (context_->parent == 0 && !g_isDevicePropSet) ? true : false;
if (context_->parent == MTP_ALL_HANDLE_ID) {
context_->parent = 0;
}
shared_ptr<UInt32List> objectHandles = make_shared<UInt32List>();
errorCode = MtpPtpProxy::GetInstance().GetHandles(context_, objectHandles, isMac);
CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS,
CheckErrorCode(errorCode), "GetObjectHandles GetHandles fail!");
shared_ptr<GetObjectHandlesData> getObjectHandles = make_shared<GetObjectHandlesData>();
getObjectHandles->SetObjectHandles(objectHandles);
data = getObjectHandles;
errorCode = MTP_SUCCESS;
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::GetObjectInfo(shared_ptr<PayloadData> &data, uint16_t containerType, int &errorCode)
{
if (containerType != DATA_CONTAINER_TYPE) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
uint16_t ret = HasStorage(errorCode);
CHECK_AND_RETURN_RET(errorCode == MTP_SUCCESS, CheckErrorCode(ret));
shared_ptr<ObjectInfo> objectInfo = make_shared<ObjectInfo>(context_->handle);
errorCode = MtpPtpProxy::GetInstance().GetObjectInfo(context_, objectInfo);
CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS,
CheckErrorCode(errorCode), "GetObjectHandles GetObjectInfo fail!");
shared_ptr<GetObjectInfoData> getObjectInfo = make_shared<GetObjectInfoData>();
getObjectInfo->SetObjectInfo(objectInfo);
data = getObjectInfo;
errorCode = MTP_SUCCESS;
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::GetObjectPropDesc(shared_ptr<PayloadData> &data, uint16_t containerType, int &errorCode)
{
if (containerType != DATA_CONTAINER_TYPE) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, CheckErrorCode(MTP_ERROR_CONTEXT_IS_NULL),
"GetObjectPropDesc context_ is null");
data = make_shared<GetObjectPropDescData>(context_);
errorCode = MTP_SUCCESS;
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::GetObjectPropValue(shared_ptr<PayloadData> &data, uint16_t containerType, int &errorCode)
{
if (containerType != DATA_CONTAINER_TYPE) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, CheckErrorCode(MTP_ERROR_CONTEXT_IS_NULL),
"GetObjectPropValue context_ is null");
int type = MTP_TYPE_UNDEFINED_CODE;
uint64_t int64Value = 0;
uint128_t int128Value = {0};
string strValue;
errorCode = MtpPtpProxy::GetInstance().GetObjectPropValue(context_, int64Value, int128Value, strValue);
shared_ptr<GetObjectPropValueData> getObjectPropValue = make_shared<GetObjectPropValueData>(context_);
type = MtpPacketTool::GetObjectPropTypeByPropCode(context_->property);
getObjectPropValue->SetPropValue(type, int64Value, int128Value, strValue);
data = getObjectPropValue;
errorCode = MTP_SUCCESS;
return CheckErrorCode(errorCode);
}
void MtpOperationUtils::DoSetObjectPropValue(int &errorCode)
{
if (context_ == nullptr) {
MEDIA_ERR_LOG("SetObjectPropValue context_ is null");
errorCode = MTP_ERROR_CONTEXT_IS_NULL;
return;
}
errorCode = MtpPtpProxy::GetInstance().SetObjectPropValue(context_);
SendEventPacket(context_->handle, MTP_EVENT_OBJECT_ADDED_CODE);
}
void MtpOperationUtils::SendEventPacket(uint32_t objectHandle, uint16_t eventCode)
{
CHECK_AND_RETURN_LOG(context_ != nullptr, "SendEventPacket context_ is null");
EventMtp event;
event.length = MTP_CONTAINER_HEADER_SIZE + sizeof(objectHandle);
vector<uint8_t> outBuffer;
MtpPacketTool::PutUInt32(outBuffer, event.length);
MtpPacketTool::PutUInt16(outBuffer, EVENT_CONTAINER_TYPE);
MtpPacketTool::PutUInt16(outBuffer, eventCode);
MtpPacketTool::PutUInt32(outBuffer, context_->transactionID);
MtpPacketTool::PutUInt32(outBuffer, objectHandle);
event.data = outBuffer;
CHECK_AND_RETURN_LOG(context_->mtpDriver != nullptr, "SendEventPacket mtpDriver is null");
auto startTime = std::chrono::high_resolution_clock::now();
int32_t result = context_->mtpDriver->WriteEvent(event);
auto endTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<uint16_t, std::milli> duration =
std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
MtpDfxReporter::GetInstance().DoSendResponseResultDfxReporter(eventCode, result,
duration.count(), OperateMode::writemode);
}
uint16_t MtpOperationUtils::GetObjectPropList(shared_ptr<PayloadData> &data,
uint16_t containerType, int &errorCode)
{
if (containerType != DATA_CONTAINER_TYPE) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, CheckErrorCode(MTP_ERROR_CONTEXT_IS_NULL),
"GetObjectPropList context_ is null");
shared_ptr<vector<Property>> props = make_shared<vector<Property>>();
errorCode = MtpPtpProxy::GetInstance().GetObjectPropList(context_, props);
CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, CheckErrorCode(errorCode), "GetObjectPropList fail!");
shared_ptr<GetObjectPropListData> getObjectPropList = make_shared<GetObjectPropListData>(context_);
getObjectPropList->SetProps(props);
data = getObjectPropList;
errorCode = MTP_SUCCESS;
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::GetObjectReferences(shared_ptr<PayloadData> &data, uint16_t containerType, int &errorCode)
{
if (containerType != DATA_CONTAINER_TYPE) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
uint16_t ret = HasStorage(errorCode);
CHECK_AND_RETURN_RET(ret == MTP_SUCCESS, CheckErrorCode(ret));
shared_ptr<UInt32List> objectHandles = nullptr;
shared_ptr<GetObjectReferencesData> getObjectReferences = make_shared<GetObjectReferencesData>(context_);
getObjectReferences->SetObjectHandles(objectHandles);
data = getObjectReferences;
errorCode = MTP_SUCCESS;
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::SetObjectReferences(shared_ptr<PayloadData> &data)
{
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, CheckErrorCode(MTP_ERROR_CONTEXT_IS_NULL),
"SetObjectReferences context_ is null");
uint16_t result = MTP_INVALID_OBJECTPROP_FORMAT_CODE;
shared_ptr<SetObjectReferencesData> setObjectReferences = make_shared<SetObjectReferencesData>(context_);
setObjectReferences->SetResult(result);
data = setObjectReferences;
return CheckErrorCode(MTP_SUCCESS);
}
uint16_t MtpOperationUtils::GetObjectDataDeal()
{
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, MTP_ERROR_CONTEXT_IS_NULL, "GetObjectDataDeal context_ is null");
int fd = 0;
int errorCode = 0;
if (MtpManager::GetInstance().IsMtpMode() && !MtpPtpProxy::GetInstance().IsMtpExistObject(context_)) {
SendEventPacket(context_->handle, MTP_EVENT_OBJECT_REMOVED_CODE);
return MTP_INVALID_OBJECTHANDLE_CODE;
}
errorCode = MtpPtpProxy::GetInstance().GetReadFd(context_, fd);
CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, errorCode, "GetObjectDataDeal GetFd fail!");
MtpFileRange object;
object.fd = fd;
struct stat sstat;
int result = fstat(object.fd, &sstat);
PreDealFd(result < 0, fd);
CHECK_AND_RETURN_RET_LOG(result == MTP_SUCCESS, MTP_ERROR_INCOMPLETE_TRANSFER,
"GetObjectDataDeal fstat error = %{public}d", errno);
object.offset = static_cast<loff_t>(context_->offset);
if (context_->length == 0 || context_->length == MTP_ALL_HANDLE_ID) {
object.length = sstat.st_size;
} else {
if (context_->offset > static_cast<uint64_t>(sstat.st_size)) {
context_->length = 0;
MEDIA_WARN_LOG("GetObjectDataDeal offset is larger than file size, set length to 0");
} else if (context_->offset + context_->length > static_cast<uint64_t>(sstat.st_size)) {
context_->length = static_cast<uint32_t>(static_cast<uint64_t>(sstat.st_size) - context_->offset);
}
object.length = context_->length;
}
object.command = context_->operationCode;
object.transaction_id = context_->transactionID;
result = context_->mtpDriver->SendObj(object);
PreDealFd(result < 0, fd);
CHECK_AND_RETURN_RET_LOG(result >= 0, MTP_ERROR_INCOMPLETE_TRANSFER,
"GetObjectDataDeal SendObj error!");
int32_t ret = MtpPtpProxy::GetInstance().CloseReadFd(context_, fd);
CHECK_AND_RETURN_RET_LOG(ret == MTP_SUCCESS, E_ERR, "DealFd CloseFd fail!");
return MTP_SUCCESS;
}
uint16_t MtpOperationUtils::GetObject(shared_ptr<PayloadData> &data, int errorCode)
{
data = make_shared<GetObjectData>();
return CheckErrorCode(errorCode);
}
void MtpOperationUtils::ModifyObjectInfo()
{
CHECK_AND_RETURN_LOG(context_ != nullptr, "DoRecevieSendObject context_ is null");
std::tm tmCreated = {};
std::tm tmModified = {};
std::istringstream created(context_->created);
std::istringstream modified(context_->modified);
created >> std::get_time(&tmCreated, "%Y%m%dT%H%M%S");
modified >> std::get_time(&tmModified, "%Y%m%dT%H%M%S");
bool cond = (created.fail() || modified.fail());
CHECK_AND_RETURN_LOG(!cond, "get_time failed");
std::string path;
MtpPtpProxy::GetInstance().GetModifyObjectInfoPathById(context_->handle, path);
struct timeval times[PATH_TIMEVAL_MAX] = { { 0, 0 }, { 0, 0 } };
times[0].tv_sec = mktime(&tmCreated);
times[1].tv_sec = mktime(&tmModified);
if (utimes(path.c_str(), times) != 0) {
MEDIA_WARN_LOG("utimes path:%{public}s failed", path.c_str());
}
}
int32_t MtpOperationUtils::DoRecevieSendObject()
{
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, MTP_INVALID_PARAMETER_CODE, "DoRecevieSendObject context_ is null");
vector<uint8_t> dataBuffer;
uint32_t temp = READ_LEN;
int errorCode = context_->mtpDriver->Read(dataBuffer, temp);
CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, errorCode, "DoRecevieSendObject Read error!");
int fd = 0;
errorCode = MtpPtpProxy::GetInstance().GetWriteFd(context_, fd);
CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, errorCode, "DoRecevieSendObject GetFd fail!");
uint32_t initialData = dataBuffer.size() < HEADER_LEN ? 0 : dataBuffer.size() - HEADER_LEN;
errorCode = write(fd, &dataBuffer[HEADER_LEN], initialData);
PreDealFd(errorCode < 0, fd);
CHECK_AND_RETURN_RET_LOG(errorCode >= 0, MTP_ERROR_RESPONSE_GENERAL,
"DoRecevieSendObject write error = %{public}d", errno);
MtpFileRange object;
object.fd = fd;
object.offset = initialData;
if (context_->sendObjectFileSize == SEND_OBJECT_FILE_MAX_SIZE) {
object.length = SEND_OBJECT_FILE_MAX_SIZE;
} else {
object.length = static_cast<int64_t>(context_->sendObjectFileSize) - static_cast<int64_t>(initialData);
}
errorCode = RecevieSendObject(object, fd);
CHECK_AND_RETURN_RET_LOG(errorCode != MTP_ERROR_TRANSFER_CANCELLED, MTP_ERROR_TRANSFER_CANCELLED,
"DoRecevieSendObject ReceiveObj Cancelled = %{public}d", MTP_ERROR_TRANSFER_CANCELLED);
CHECK_AND_RETURN_RET_LOG(errorCode != MTP_ERROR_TRANSFER_FAILED, MTP_ERROR_TRANSFER_FAILED,
"DoRecevieSendObject ReceiveObj Failed = %{public}d", MTP_ERROR_TRANSFER_FAILED);
CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, MTP_ERROR_RESPONSE_GENERAL,
"DoRecevieSendObject ReceiveObj fail errorCode = %{public}d", errorCode);
ModifyObjectInfo();
errorCode = fsync(fd);
PreDealFd(errorCode != MTP_SUCCESS, fd);
CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, MTP_ERROR_RESPONSE_GENERAL,
"DoRecevieSendObject fsync eroor = %{public}d", errno);
struct stat sstat;
errorCode = fstat(fd, &sstat);
PreDealFd(errorCode != MTP_SUCCESS, fd);
CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, MTP_ERROR_RESPONSE_GENERAL,
"DoRecevieSendObject fstat error = %{public}d", errno);
errorCode = MtpPtpProxy::GetInstance().CloseWriteFd(context_, fd);
CHECK_AND_RETURN_RET_LOG(errorCode == MTP_SUCCESS, errorCode, "DoRecevieSendObject CloseFd fail!");
return MTP_SUCCESS;
}
int32_t MtpOperationUtils::RecevieSendObject(MtpFileRange &object, int fd)
{
MEDIA_DEBUG_LOG("RecevieSendObject begin");
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, MTP_INVALID_PARAMETER_CODE, "DoRecevieSendObject context_ is null");
CHECK_AND_RETURN_RET_LOG(context_->mtpDriver != nullptr, MTP_INVALID_PARAMETER_CODE,
"DoRecevieSendObject context_->mtpDriver is null");
int32_t errorCode = context_->mtpDriver->ReceiveObj(object);
bool cond = (errorCode != RECEVIE_OBJECT_CANCELLED && errorCode != RECEVIE_OBJECT_FAILED);
CHECK_AND_RETURN_RET(!cond, errorCode);
PreDealFd(errorCode != MTP_SUCCESS, fd);
string filePath("");
if (MtpManager::GetInstance().IsMtpMode()) {
MtpPtpProxy::GetInstance().GetMtpPathById(context_->handle, filePath);
CHECK_AND_RETURN_RET_LOG(!filePath.empty(), MTP_ERROR_TRANSFER_CANCELLED,
"File path is invalid!");
int ret = unlink(filePath.c_str());
CHECK_AND_RETURN_RET_LOG(ret == 0, MTP_ERROR_TRANSFER_CANCELLED, "unlink file fail");
}
MtpPtpProxy::GetInstance().DeleteCanceledObject(filePath, context_->handle);
CHECK_AND_RETURN_RET(errorCode != RECEVIE_OBJECT_FAILED, MTP_ERROR_TRANSFER_FAILED);
return MTP_ERROR_TRANSFER_CANCELLED;
}
void MtpOperationUtils::PreDealFd(const bool deal, const int fd)
{
if (!deal || fd <= 0) {
return;
}
int32_t ret = MtpPtpProxy::GetInstance().CloseReadFd(context_, fd);
CHECK_AND_PRINT_LOG(ret == MTP_SUCCESS, "DealFd CloseFd fail!");
}
uint16_t MtpOperationUtils::GetThumb(shared_ptr<PayloadData> &data, uint16_t containerType, int &errorCode)
{
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, MTP_INVALID_PARAMETER_CODE, "DoRecevieSendObject context_ is null");
if (containerType != DATA_CONTAINER_TYPE) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
uint16_t ret = HasStorage(errorCode);
CHECK_AND_RETURN_RET(ret == MTP_SUCCESS, CheckErrorCode(ret));
shared_ptr<UInt8List> thumb = make_shared<UInt8List>();
errorCode = MtpPtpProxy::GetInstance().GetThumb(context_, thumb);
if (errorCode != MTP_SUCCESS) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
shared_ptr<GetThumbData> getThumb = make_shared<GetThumbData>();
getThumb->SetThumb(thumb);
data = getThumb;
errorCode = MTP_SUCCESS;
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::SendObjectInfo(shared_ptr<PayloadData> &data, int &errorCode)
{
if (context_ == nullptr) {
MEDIA_ERR_LOG("MtpOperationUtils::SendObjectInfo param is null");
data = make_shared<RespCommonData>();
return CheckErrorCode(MTP_ERROR_CONTEXT_IS_NULL);
}
auto manager = MtpStorageManager::GetInstance();
CHECK_AND_RETURN_RET_LOG(manager != nullptr, MTP_INVALID_PARAMETER_CODE, "MtpStorageManager instance is nullptr");
if (static_cast<int64_t>(context_->sendObjectFileSize) + READ_LEN > manager->GetFreeSize()) {
data = make_shared<RespCommonData>();
MEDIA_DEBUG_LOG("SendObjectInfo run out of memory, sendObjectFileSize %{public}d",
context_->sendObjectFileSize);
MEDIA_DEBUG_LOG("SendObjectInfo run out of memory, FreeSpaceInBytes %{public}"
PRId64, manager->GetFreeSize());
return MTP_STORE_FULL_CODE;
}
uint32_t storageID = 0;
uint32_t parent = 0;
uint32_t handle = 0;
errorCode = MtpPtpProxy::GetInstance().SendObjectInfo(context_, storageID, parent, handle);
if (errorCode != MTP_SUCCESS) {
MEDIA_ERR_LOG("MtpOperationUtils::SendObjectInfo fail!");
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
context_->handle = handle;
shared_ptr<SendObjectInfoData> sendObjectInfo = make_shared<SendObjectInfoData>();
sendObjectInfo->SetSetParam(storageID, parent, handle);
data = sendObjectInfo;
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::GetRespCommonData(shared_ptr<PayloadData> &data, int errorCode)
{
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::GetPartialObject(shared_ptr<PayloadData> &data)
{
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, CheckErrorCode(MTP_ERROR_CONTEXT_IS_NULL),
"GetPartialObject context_ is null");
shared_ptr<GetPartialObjectData> getPartialObject = make_shared<GetPartialObjectData>(context_);
getPartialObject->SetLength(context_->length);
data = getPartialObject;
return MTP_OK_CODE;
}
uint16_t MtpOperationUtils::GetObjectPropsSupported(shared_ptr<PayloadData> &data)
{
CHECK_AND_RETURN_RET_LOG(context_ != nullptr, CheckErrorCode(MTP_ERROR_CONTEXT_IS_NULL),
"GetObjectPropsSupported context_ is null");
data = make_shared<GetObjectPropsSupportedData>(context_);
return MTP_OK_CODE;
}
uint16_t MtpOperationUtils::DeleteObject(shared_ptr<PayloadData> &data, int &errorCode)
{
if (context_ == nullptr) {
errorCode = MTP_ERROR_CONTEXT_IS_NULL;
} else {
MEDIA_ERR_LOG("MtpOperationUtils::DeleteObject format=%{public}u", context_->format);
errorCode = MtpPtpProxy::GetInstance().DeleteObject(context_);
}
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::MoveObject(shared_ptr<PayloadData> &data, int &errorCode)
{
bool cond = (context_ == nullptr);
CHECK_AND_RETURN_RET_LOG(!cond, CheckErrorCode(MTP_ERROR_CONTEXT_IS_NULL), "param is null");
uint32_t repeatHandle = 0;
errorCode = MtpPtpProxy::GetInstance().MoveObject(context_, repeatHandle);
data = make_shared<RespCommonData>();
if (repeatHandle != 0) {
SendEventPacket(repeatHandle, MTP_EVENT_OBJECT_REMOVED_CODE);
MEDIA_INFO_LOG("MTP:Send Event MTP_EVENT_OBJECT_REMOVED_CODE,repeatHandle[%{public}d]", repeatHandle);
}
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::CopyObject(shared_ptr<PayloadData> &data, int &errorCode)
{
if (context_ == nullptr) {
MEDIA_ERR_LOG("param is null");
data = make_shared<RespCommonData>();
return CheckErrorCode(MTP_ERROR_CONTEXT_IS_NULL);
}
uint32_t objectHandle = 0;
uint32_t oldHandle = 0;
MtpPtpProxy::GetInstance().CopyObject(context_, objectHandle, oldHandle);
shared_ptr<CopyObjectData> copyObject = make_shared<CopyObjectData>();
copyObject->SetObjectHandle(objectHandle);
data = copyObject;
if (oldHandle != 0) {
SendEventPacket(oldHandle, MTP_EVENT_OBJECT_REMOVED_CODE);
MEDIA_INFO_LOG("MTP:Send Event MTP_EVENT_OBJECT_REMOVED_CODE,oldHandle[%{public}d]", oldHandle);
}
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::GetStorageIDs(shared_ptr<PayloadData> &data, uint16_t containerType, int &errorCode)
{
if (containerType != DATA_CONTAINER_TYPE || context_ == nullptr) {
data = make_shared<RespCommonData>();
return CheckErrorCode(MTP_ERROR_CONTEXT_IS_NULL);
}
CHECK_AND_RETURN_RET_LOG(context_->sessionOpen != false, CheckErrorCode(MTP_ERROR_SESSION_NOT_OPEN),
"session isn't open");
auto manager = MtpStorageManager::GetInstance();
CHECK_AND_RETURN_RET_LOG(manager != nullptr, MTP_PARAMETER_NOT_SUPPORTED_CODE,
"MtpStorageManager instance is nullptr");
if (MtpManager::GetInstance().IsMtpMode()) {
MtpStoreObserver::AttachContext(context_);
MtpPtpProxy::GetInstance().GetMtpStorageIds();
} else {
auto storage = make_shared<Storage>();
CHECK_AND_RETURN_RET_LOG(storage != nullptr, E_ERR, "storage is nullptr");
storage->SetStorageID(DEFAULT_STORAGE_ID);
storage->SetStorageType(MTP_STORAGE_FIXEDRAM);
storage->SetFilesystemType(MTP_FILESYSTEM_GENERICHIERARCHICAL);
storage->SetAccessCapability(MTP_ACCESS_READ_WRITE);
storage->SetMaxCapacity(manager->GetTotalSize(PUBLIC_DOC));
storage->SetFreeSpaceInBytes(manager->GetFreeSize(PUBLIC_DOC));
storage->SetFreeSpaceInObjects(0);
storage->SetStorageDescription(manager->GetStorageDescription(MTP_STORAGE_FIXEDRAM));
manager->AddStorage(storage);
}
shared_ptr<GetStorageIdsData> getStorageIdsData = make_shared<GetStorageIdsData>();
getStorageIdsData->SetStorages(manager->GetStorages());
data = getStorageIdsData;
errorCode = MTP_SUCCESS;
return CheckErrorCode(errorCode);
}
uint16_t MtpOperationUtils::GetStorageInfo(shared_ptr<PayloadData> &data, uint16_t containerType, int &errorCode)
{
if (containerType != DATA_CONTAINER_TYPE) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
CHECK_AND_RETURN_RET_LOG(context_->sessionOpen != false, CheckErrorCode(MTP_ERROR_SESSION_NOT_OPEN),
"session isn't open error");
shared_ptr<Storage> storage = MtpStorageManager::GetInstance()->GetStorage(context_->storageInfoID);
CHECK_AND_RETURN_RET_LOG(storage != nullptr, CheckErrorCode(MTP_ERROR_INVALID_STORAGE_ID),
"invalid storage id error");
shared_ptr<GetStorageInfoData> getStorageInfoData = make_shared<GetStorageInfoData>();
getStorageInfoData->SetStorage(storage);
data = getStorageInfoData;
errorCode = MTP_SUCCESS;
return MTP_OK_CODE;
}
uint16_t MtpOperationUtils::GetOpenSession(shared_ptr<PayloadData> &data, int errorCode)
{
shared_ptr<OpenSessionData> openSessionData = make_shared<OpenSessionData>(context_);
uint16_t respCode = CheckErrorCode(errorCode);
if (respCode == MTP_SESSION_ALREADY_OPEN_CODE) {
openSessionData->SetSessionId(context_->sessionID);
}
if (respCode == MTP_OK_CODE) {
context_->sessionOpen = true;
}
data = openSessionData;
return respCode;
}
uint16_t MtpOperationUtils::CheckErrorCode(int errorCode)
{
switch (errorCode) {
case MTP_ERROR_PACKET_INCORRECT:
return MTP_INVALID_PARAMETER_CODE;
case MTP_ERROR_SESSION_ALREADY_OPEN:
return MTP_SESSION_ALREADY_OPEN_CODE;
case MTP_ERROR_NO_THIS_FILE:
return MTP_INVALID_OBJECTHANDLE_CODE;
case MTP_ERROR_INCOMPLETE_TRANSFER:
return MTP_INCOMPLETE_TRANSFER_CODE;
case MTP_ERROR_SESSION_NOT_OPEN:
return MTP_SESSION_NOT_OPEN_CODE;
case MTP_ERROR_INVALID_STORAGE_ID:
return MTP_INVALID_STORAGEID_CODE;
case MTP_ERROR_INVALID_OBJECTHANDLE:
return MTP_INVALID_OBJECTHANDLE_CODE;
case MTP_ERROR_DEVICEPROP_NOT_SUPPORTED:
return MTP_DEVICEPROP_NOT_SUPPORTED_CODE;
case MTP_ERROR_STORE_NOT_AVAILABLE:
return MTP_STORE_NOT_AVAILABLE_CODE;
case MTP_ERROR_INVALID_PARENTOBJECT:
return MTP_INVALID_PARENTOBJECT_CODE;
case MTP_ERROR_PARAMETER_NOT_SUPPORTED:
return MTP_PARAMETER_NOT_SUPPORTED_CODE;
case MTP_ERROR_INVALID_OBJECTPROP_VALUE:
return MTP_INVALID_OBJECTPROP_VALUE_CODE;
case MTP_ERROR_INVALID_OBJECTPROP_FORMAT:
return MTP_INVALID_OBJECTPROP_FORMAT_CODE;
case MTP_ERROR_INVALID_OBJECTPROPCODE:
return MTP_INVALID_OBJECTPROPCODE_CODE;
case MTP_ERROR_ACCESS_DENIED:
return MTP_ACCESS_DENIED_CODE;
case MTP_ERROR_SPECIFICATION_BY_GROUP_UNSUPPORTED:
return MTP_SPECIFICATION_BY_GROUP_UNSUPPORTED_CODE;
case MTP_ERROR_SPECIFICATION_BY_DEPTH_UNSUPPORTED:
return MTP_SPECIFICATION_BY_DEPTH_UNSUPPORTED_CODE;
case MTP_ERROR_TRANSFER_FAILED:
return MTP_STORE_FULL_CODE;
default:
return MTP_OK_CODE;
}
}
uint16_t MtpOperationUtils::GetCloseSession(shared_ptr<PayloadData> &data)
{
data = make_shared<CloseSessionData>(context_);
return MTP_OK_CODE;
}
uint16_t MtpOperationUtils::GetPropDesc(shared_ptr<PayloadData> &data, uint16_t containerType, int &errorCode)
{
if (containerType != DATA_CONTAINER_TYPE) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
shared_ptr<GetDevicePropDescData> devicePropDescData = make_shared<GetDevicePropDescData>();
shared_ptr<Property> property = nullptr;
switch (context_->property) {
case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER_CODE:
property = make_shared<Property>(context_->property, MTP_DEVICE_PROP_DESC_TYPE_STR, true);
break;
case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME_CODE:
property = make_shared<Property>(context_->property, MTP_DEVICE_PROP_DESC_TYPE_STR, true);
property->currentValue->str_ = make_shared<string>(GetPropertyInner("const.product.name",
DEFAULT_PRODUCT_NAME));
break;
case MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO_CODE:
property = make_shared<Property>(context_->property, MTP_DEVICE_PROP_DESC_TYPE_STR, true);
break;
case MTP_DEVICE_PROPERTY_IMAGE_SIZE_CODE:
property = make_shared<Property>(context_->property, MTP_DEVICE_PROP_DESC_TYPE_STR, true);
break;
case MTP_DEVICE_PROPERTY_BATTERY_LEVEL_CODE:
property = make_shared<Property>(context_->property, MTP_DEVICE_PROP_DESC_TYPE_UINT8);
property->currentValue->bin_.ui8 = (uint8_t)MtpOperationUtils::GetBatteryLevel();
property->SetFormRange(BATTERY_LEVEL_MIN, BATTERY_LEVEL_MAX, BATTERY_LEVEL_STEP);
break;
case MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE_CODE:
property = make_shared<Property>(context_->property, MTP_DEVICE_PROP_DESC_TYPE_UINT32);
break;
default:
MEDIA_INFO_LOG("property do not find");
break;
}
devicePropDescData->SetProperty(property);
data = devicePropDescData;
errorCode = MTP_SUCCESS;
return MTP_OK_CODE;
}
uint16_t MtpOperationUtils::GetPropValue(shared_ptr<PayloadData> &data, uint16_t containerType, int &errorCode)
{
if (containerType != DATA_CONTAINER_TYPE) {
data = make_shared<RespCommonData>();
return CheckErrorCode(errorCode);
}
shared_ptr<GetDevicePropValueData> devicePropValueData = make_shared<GetDevicePropValueData>();
shared_ptr<Property::Value> value = make_shared<Property::Value>();
uint16_t valueType = MTP_DEVICE_PROP_DESC_TYPE_UNDEFINED;
switch (context_->property) {
case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER_CODE:
valueType = MTP_DEVICE_PROP_DESC_TYPE_STR;
value->str_ = make_shared<string>("");
break;
case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME_CODE:
valueType = MTP_DEVICE_PROP_DESC_TYPE_STR;
value->str_ = make_shared<string>(GetPropertyInner("const.product.name", DEFAULT_PRODUCT_NAME));
break;
case MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO_CODE:
valueType = MTP_DEVICE_PROP_DESC_TYPE_STR;
value->str_ = make_shared<string>("");
break;
case MTP_DEVICE_PROPERTY_IMAGE_SIZE_CODE:
valueType = MTP_DEVICE_PROP_DESC_TYPE_STR;
value->str_ = make_shared<string>("");
break;
case MTP_DEVICE_PROPERTY_BATTERY_LEVEL_CODE:
valueType = MTP_DEVICE_PROP_DESC_TYPE_UINT8;
value->bin_.ui8 = (uint8_t)MtpOperationUtils::GetBatteryLevel();
break;
case MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE_CODE:
valueType = MTP_DEVICE_PROP_DESC_TYPE_UINT32;
value->bin_.ui32 = MTP_PERCEIVED_DEVICE_TYPE_GENERIC;
break;
default:
MEDIA_INFO_LOG("property do not find");
break;
}
devicePropValueData->SetValue(valueType, value);
data = devicePropValueData;
errorCode = MTP_SUCCESS;
return MTP_OK_CODE;
}
uint16_t MtpOperationUtils::SetDevicePropValueResp(shared_ptr<PayloadData> &data)
{
data = make_shared<RespCommonData>();
return MTP_OK_CODE;
}
uint16_t MtpOperationUtils::ResetDevicePropResp(shared_ptr<PayloadData> &data)
{
CHECK_AND_PRINT_LOG(SetPropertyInner("const.product.name", DEFAULT_PRODUCT_NAME), "SetPropertyInner fail");
data = make_shared<RespCommonData>();
return MTP_OK_CODE;
}
uint16_t MtpOperationUtils::ObjectEvent(shared_ptr<PayloadData> &data, const int32_t payload)
{
std::shared_ptr<ObjectEventData> eventData = make_shared<ObjectEventData>();
eventData->SetPayload(payload);
data = eventData;
return MTP_OK_CODE;
}
uint16_t MtpOperationUtils::GetPathByHandle(const uint32_t &handle, string &path, string &realPath)
{
MtpPtpProxy::GetInstance().GetPathByHandle(handle, path, realPath);
return MTP_OK_CODE;
}
int32_t MtpOperationUtils::GetHandleByPaths(string path, uint32_t &handle)
{
CHECK_AND_RETURN_RET(!path.empty(), MTP_UNDEFINED_CODE);
if (path.back() == '/') {
path.pop_back();
}
return MtpPtpProxy::GetInstance().GetIdByPath(path, handle);
}
bool MtpOperationUtils::TryAddExternalStorage(const std::string &fsUuid, uint32_t &storageId)
{
CHECK_AND_RETURN_RET(!MtpManager::GetInstance().IsMtpMode(),
MtpPtpProxy::GetInstance().MtpTryAddExternalStorage(fsUuid, storageId));
return false;
}
bool MtpOperationUtils::TryRemoveExternalStorage(const std::string &fsUuid, uint32_t &storageId)
{
CHECK_AND_RETURN_RET(!MtpManager::GetInstance().IsMtpMode(),
MtpPtpProxy::GetInstance().MtpTryRemoveExternalStorage(fsUuid, storageId));
return false;
}
int32_t MtpOperationUtils::GetBatteryLevel()
{
#ifdef HAS_BATTERY_MANAGER_PART
auto &batterySrvClient = PowerMgr::BatterySrvClient::GetInstance();
int32_t capacity = batterySrvClient.GetCapacity();
bool cond = (capacity > MAX_BATTERY || capacity < EMPTY_BATTERY);
CHECK_AND_RETURN_RET(!cond, ERROR_BATTERY);
return capacity;
#else
return EMPTY_BATTERY;
#endif
}
std::string MtpOperationUtils::GetPropertyInner(const std::string &property, const std::string &defValue)
{
return OHOS::system::GetParameter(property, defValue);
}
bool MtpOperationUtils::SetPropertyInner(const std::string &property, const std::string &defValue)
{
return OHOS::system::SetParameter(property, defValue);
}
void MtpOperationUtils::SetIsDevicePropSet()
{
g_isDevicePropSet = true;
}
}
}