MtpObjectHandleList* MtpStorage::getObjectList(MtpStorageID storageID, MtpObjectHandle parent) { MTPD("MtpStorage::getObjectList, parent: %u\n", parent); //append object id (numerical #s) of database to int array MtpObjectHandleList* list = new MtpObjectHandleList(); if (parent == MTP_PARENT_ROOT) { MTPD("parent == MTP_PARENT_ROOT\n"); parent = 0; } if (mtpmap.find(parent) == mtpmap.end()) { MTPE("parent handle not found, returning empty list\n"); return list; } Tree* tree = mtpmap[parent]; if (!tree->wasAlreadyRead()) { std::string path = getNodePath(tree); MTPD("reading directory on demand for tree %p (%u), path: %s\n", tree, tree->Mtpid(), path.c_str()); readDir(path, tree); } mtpmap[parent]->getmtpids(list); MTPD("returning %u objects in %s.\n", list->size(), tree->getName().c_str()); return list; }
MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) { JNIEnv* env = AndroidRuntime::getJNIEnv(); jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences, (jint)handle); if (!array) return NULL; MtpObjectHandleList* list = new MtpObjectHandleList(); jint* handles = env->GetIntArrayElements(array, 0); jsize length = env->GetArrayLength(array); for (int i = 0; i < length; i++) list->push(handles[i]); env->ReleaseIntArrayElements(array, handles, 0); env->DeleteLocalRef(array); checkAndClearExceptionFromCallback(env, __FUNCTION__); return list; }
static jintArray android_mtp_MtpDevice_get_object_handles(JNIEnv *env, jobject thiz, jint storageID, jint format, jint objectID) { MtpDevice* device = get_device_from_object(env, thiz); if (!device) return NULL; MtpObjectHandleList* handles = device->getObjectHandles(storageID, format, objectID); if (!handles) return NULL; int length = handles->size(); jintArray array = env->NewIntArray(length); // FIXME is this cast safe? env->SetIntArrayRegion(array, 0, length, (const jint *)handles->array()); delete handles; return array; }
int MtpStorage::getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet) { MTPD("MtpStorage::getObjectPropertyList handle: %u, format: %x, property: %x\n", handle, format, property); if (groupCode != 0) { MTPE("getObjectPropertyList: groupCode unsupported\n"); return -1; // TODO: RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED } // TODO: support all the special stuff, like: // handle == 0 -> all objects at the root level // handle == 0xffffffff -> all objects (on all storages? how could we support that?) // format == 0 -> all formats, otherwise filter by ObjectFormatCode // property == 0xffffffff -> all properties except those with group code 0xffffffff // if property == 0 then use groupCode // groupCode == 0 -> return Specification_By_Group_Unsupported // depth == 0xffffffff -> all objects incl. and below handle std::vector<PropEntry> results; if (handle == 0xffffffff) { // TODO: all object on all storages (needs a different design, result packet needs to be built by server instead of storage) } else if (handle == 0) { // all objects at the root level Tree* root = mtpmap[0]; MtpObjectHandleList list; root->getmtpids(&list); for (MtpObjectHandleList::iterator it = list.begin(); it != list.end(); ++it) { Node* node = root->findNode(*it); if (!node) { MTPE("BUG: node not found for root entry with handle %u\n", *it); break; } queryNodeProperties(results, node, property, groupCode, mStorageID); } } else { // single object Node* node = findNode(handle); if (!node) { // Item is not on this storage device return -1; } queryNodeProperties(results, node, property, groupCode, mStorageID); } MTPD("count: %u\n", results.size()); packet.putUInt32(results.size()); for (size_t i = 0; i < results.size(); ++i) { PropEntry& p = results[i]; MTPD("handle: %u, propertyCode: %x = %s, datatype: %x, value: %llu\n", p.handle, p.property, MtpDebug::getObjectPropCodeName(p.property), p.datatype, p.intvalue); packet.putUInt32(p.handle); packet.putUInt16(p.property); packet.putUInt16(p.datatype); switch (p.datatype) { case MTP_TYPE_INT8: MTPD("MTP_TYPE_INT8\n"); packet.putInt8(p.intvalue); break; case MTP_TYPE_UINT8: MTPD("MTP_TYPE_UINT8\n"); packet.putUInt8(p.intvalue); break; case MTP_TYPE_INT16: MTPD("MTP_TYPE_INT16\n"); packet.putInt16(p.intvalue); break; case MTP_TYPE_UINT16: MTPD("MTP_TYPE_UINT16\n"); packet.putUInt16(p.intvalue); break; case MTP_TYPE_INT32: MTPD("MTP_TYPE_INT32\n"); packet.putInt32(p.intvalue); break; case MTP_TYPE_UINT32: MTPD("MTP_TYPE_UINT32\n"); packet.putUInt32(p.intvalue); break; case MTP_TYPE_INT64: MTPD("MTP_TYPE_INT64\n"); packet.putInt64(p.intvalue); break; case MTP_TYPE_UINT64: MTPD("MTP_TYPE_UINT64\n"); packet.putUInt64(p.intvalue); break; case MTP_TYPE_INT128: MTPD("MTP_TYPE_INT128\n"); packet.putInt128(p.intvalue); break; case MTP_TYPE_UINT128: MTPD("MTP_TYPE_UINT128\n"); packet.putUInt128(p.intvalue); break; case MTP_TYPE_STR: MTPD("MTP_TYPE_STR: %s\n", p.strvalue.c_str()); packet.putString(p.strvalue.c_str()); break; default: MTPE("bad or unsupported data type: %x in MyMtpDatabase::getObjectPropertyList", p.datatype); break; } } return 0; }