void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) { MtpStringBuffer stringBuffer; switch (mType) { case MTP_TYPE_INT8: case MTP_TYPE_AINT8: packet.putInt8(value.u.i8); break; case MTP_TYPE_UINT8: case MTP_TYPE_AUINT8: packet.putUInt8(value.u.u8); break; case MTP_TYPE_INT16: case MTP_TYPE_AINT16: packet.putInt16(value.u.i16); break; case MTP_TYPE_UINT16: case MTP_TYPE_AUINT16: packet.putUInt16(value.u.u16); break; case MTP_TYPE_INT32: case MTP_TYPE_AINT32: packet.putInt32(value.u.i32); break; case MTP_TYPE_UINT32: case MTP_TYPE_AUINT32: packet.putUInt32(value.u.u32); break; case MTP_TYPE_INT64: case MTP_TYPE_AINT64: packet.putInt64(value.u.i64); break; case MTP_TYPE_UINT64: case MTP_TYPE_AUINT64: packet.putUInt64(value.u.u64); break; case MTP_TYPE_INT128: case MTP_TYPE_AINT128: packet.putInt128(value.u.i128); break; case MTP_TYPE_UINT128: case MTP_TYPE_AUINT128: packet.putUInt128(value.u.u128); break; case MTP_TYPE_STR: if (value.str) packet.putString(value.str); else packet.putEmptyString(); break; default: LOG(ERROR) << "unknown type " << std::hex << mType << std::dec << " in MtpProperty::writeValue"; } }
MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet) { JNIEnv* env = AndroidRuntime::getJNIEnv(); jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList, (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth); checkAndClearExceptionFromCallback(env, __FUNCTION__); if (!list) return MTP_RESPONSE_GENERAL_ERROR; int count = env->GetIntField(list, field_mCount); MtpResponseCode result = env->GetIntField(list, field_mResult); packet.putUInt32(count); if (count > 0) { jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles); jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes); jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes); jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues); jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues); jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0); jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0); jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0); jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL); for (int i = 0; i < count; i++) { packet.putUInt32(objectHandles[i]); packet.putUInt16(propertyCodes[i]); int type = dataTypes[i]; packet.putUInt16(type); switch (type) { case MTP_TYPE_INT8: packet.putInt8(longValues[i]); break; case MTP_TYPE_UINT8: packet.putUInt8(longValues[i]); break; case MTP_TYPE_INT16: packet.putInt16(longValues[i]); break; case MTP_TYPE_UINT16: packet.putUInt16(longValues[i]); break; case MTP_TYPE_INT32: packet.putInt32(longValues[i]); break; case MTP_TYPE_UINT32: packet.putUInt32(longValues[i]); break; case MTP_TYPE_INT64: packet.putInt64(longValues[i]); break; case MTP_TYPE_UINT64: packet.putUInt64(longValues[i]); break; case MTP_TYPE_INT128: packet.putInt128(longValues[i]); break; case MTP_TYPE_UINT128: packet.putUInt128(longValues[i]); break; case MTP_TYPE_STR: { jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i); const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL); if (valueStr) { packet.putString(valueStr); env->ReleaseStringUTFChars(value, valueStr); } else { packet.putEmptyString(); } env->DeleteLocalRef(value); break; } default: ALOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList"); break; } } env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0); env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0); env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0); if (longValues) env->ReleaseLongArrayElements(longValuesArray, longValues, 0); env->DeleteLocalRef(objectHandlesArray); env->DeleteLocalRef(propertyCodesArray); env->DeleteLocalRef(dataTypesArray); if (longValuesArray) env->DeleteLocalRef(longValuesArray); if (stringValuesArray) env->DeleteLocalRef(stringValuesArray); } env->DeleteLocalRef(list); checkAndClearExceptionFromCallback(env, __FUNCTION__); return result; }
MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle, MtpObjectProperty property, MtpDataPacket& packet) { JNIEnv* env = AndroidRuntime::getJNIEnv(); jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList, (jlong)handle, 0, (jlong)property, 0, 0); MtpResponseCode result = env->GetIntField(list, field_mResult); int count = env->GetIntField(list, field_mCount); if (result == MTP_RESPONSE_OK && count != 1) result = MTP_RESPONSE_GENERAL_ERROR; if (result == MTP_RESPONSE_OK) { jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles); jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes); jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes); jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues); jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues); jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0); jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0); jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0); jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL); int type = dataTypes[0]; jlong longValue = (longValues ? longValues[0] : 0); // special case date properties, which are strings to MTP // but stored internally as a uint64 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) { char date[20]; formatDateTime(longValue, date, sizeof(date)); packet.putString(date); goto out; } // release date is stored internally as just the year if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) { char date[20]; snprintf(date, sizeof(date), "%04" PRId64 "0101T000000", longValue); packet.putString(date); goto out; } switch (type) { case MTP_TYPE_INT8: packet.putInt8(longValue); break; case MTP_TYPE_UINT8: packet.putUInt8(longValue); break; case MTP_TYPE_INT16: packet.putInt16(longValue); break; case MTP_TYPE_UINT16: packet.putUInt16(longValue); break; case MTP_TYPE_INT32: packet.putInt32(longValue); break; case MTP_TYPE_UINT32: packet.putUInt32(longValue); break; case MTP_TYPE_INT64: packet.putInt64(longValue); break; case MTP_TYPE_UINT64: packet.putUInt64(longValue); break; case MTP_TYPE_INT128: packet.putInt128(longValue); break; case MTP_TYPE_UINT128: packet.putInt128(longValue); break; case MTP_TYPE_STR: { jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0); const char* str = (stringValue ? env->GetStringUTFChars(stringValue, NULL) : NULL); if (stringValue) { packet.putString(str); env->ReleaseStringUTFChars(stringValue, str); } else { packet.putEmptyString(); } env->DeleteLocalRef(stringValue); break; } default: ALOGE("unsupported type in getObjectPropertyValue\n"); result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT; } out: env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0); env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0); env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0); if (longValues) env->ReleaseLongArrayElements(longValuesArray, longValues, 0); env->DeleteLocalRef(objectHandlesArray); env->DeleteLocalRef(propertyCodesArray); env->DeleteLocalRef(dataTypesArray); if (longValuesArray) env->DeleteLocalRef(longValuesArray); if (stringValuesArray) env->DeleteLocalRef(stringValuesArray); } env->DeleteLocalRef(list); checkAndClearExceptionFromCallback(env, __FUNCTION__); return result; }