blob: b5096fe7645daebefdf42cd655443ff314944b75 [file] [log] [blame]
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
17 */
18
19#include <utils/Log.h>
20
21#include <stdio.h>
22#include <assert.h>
23#include <limits.h>
24#include <unistd.h>
25#include <fcntl.h>
26#include <dirent.h>
27#include <errno.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <string>
31#include <map>
32#include <libgen.h>
33#include <cutils/properties.h>
34
35#include "MtpDatabase.h"
36#include "MtpStorage.h"
37#include "MtpDataPacket.h"
38#include "MtpObjectInfo.h"
39#include "MtpProperty.h"
40#include "MtpDebug.h"
41#include "MtpStringBuffer.h"
42#include "MtpUtils.h"
43#include "mtp.h"
44#include "mtp_MtpDatabase.hpp"
45#include "btree.hpp"
46
47MyMtpDatabase::MyMtpDatabase()
48{
49 storagenum = 0;
50 count = -1;
51}
52
53MyMtpDatabase::~MyMtpDatabase() {
54 std::map<int, MtpStorage*>::iterator i;
55 for (i = storagemap.begin(); i != storagemap.end(); i++) {
56 delete i->second;
57 }
58}
59
bigbiff bigbiff1812c892014-09-08 21:04:06 -040060int MyMtpDatabase::DEVICE_PROPERTIES[3] = {
61 MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
62 MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
63 MTP_DEVICE_PROPERTY_IMAGE_SIZE
64};
65
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -040066int MyMtpDatabase::FILE_PROPERTIES[10] = {
67 // NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES
68 // and IMAGE_PROPERTIES below
69 MTP_PROPERTY_STORAGE_ID,
70 MTP_PROPERTY_OBJECT_FORMAT,
71 MTP_PROPERTY_PROTECTION_STATUS,
72 MTP_PROPERTY_OBJECT_SIZE,
73 MTP_PROPERTY_OBJECT_FILE_NAME,
74 MTP_PROPERTY_DATE_MODIFIED,
75 MTP_PROPERTY_PARENT_OBJECT,
76 MTP_PROPERTY_PERSISTENT_UID,
77 MTP_PROPERTY_NAME,
78 MTP_PROPERTY_DATE_ADDED
79};
bigbiff bigbiff1812c892014-09-08 21:04:06 -040080
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -040081int MyMtpDatabase::AUDIO_PROPERTIES[19] = {
82 // NOTE must match FILE_PROPERTIES above
83 MTP_PROPERTY_STORAGE_ID,
84 MTP_PROPERTY_OBJECT_FORMAT,
85 MTP_PROPERTY_PROTECTION_STATUS,
86 MTP_PROPERTY_OBJECT_SIZE,
87 MTP_PROPERTY_OBJECT_FILE_NAME,
88 MTP_PROPERTY_DATE_MODIFIED,
89 MTP_PROPERTY_PARENT_OBJECT,
90 MTP_PROPERTY_PERSISTENT_UID,
91 MTP_PROPERTY_NAME,
92 MTP_PROPERTY_DISPLAY_NAME,
93 MTP_PROPERTY_DATE_ADDED,
94
95 // audio specific properties
96 MTP_PROPERTY_ARTIST,
97 MTP_PROPERTY_ALBUM_NAME,
98 MTP_PROPERTY_ALBUM_ARTIST,
99 MTP_PROPERTY_TRACK,
100 MTP_PROPERTY_ORIGINAL_RELEASE_DATE,
101 MTP_PROPERTY_DURATION,
102 MTP_PROPERTY_GENRE,
103 MTP_PROPERTY_COMPOSER
104};
105
106int MyMtpDatabase::VIDEO_PROPERTIES[15] = {
107 // NOTE must match FILE_PROPERTIES above
108 MTP_PROPERTY_STORAGE_ID,
109 MTP_PROPERTY_OBJECT_FORMAT,
110 MTP_PROPERTY_PROTECTION_STATUS,
111 MTP_PROPERTY_OBJECT_SIZE,
112 MTP_PROPERTY_OBJECT_FILE_NAME,
113 MTP_PROPERTY_DATE_MODIFIED,
114 MTP_PROPERTY_PARENT_OBJECT,
115 MTP_PROPERTY_PERSISTENT_UID,
116 MTP_PROPERTY_NAME,
117 MTP_PROPERTY_DISPLAY_NAME,
118 MTP_PROPERTY_DATE_ADDED,
119
120 // video specific properties
121 MTP_PROPERTY_ARTIST,
122 MTP_PROPERTY_ALBUM_NAME,
123 MTP_PROPERTY_DURATION,
124 MTP_PROPERTY_DESCRIPTION
125};
126
127int MyMtpDatabase::IMAGE_PROPERTIES[12] = {
128 // NOTE must match FILE_PROPERTIES above
129 MTP_PROPERTY_STORAGE_ID,
130 MTP_PROPERTY_OBJECT_FORMAT,
131 MTP_PROPERTY_PROTECTION_STATUS,
132 MTP_PROPERTY_OBJECT_SIZE,
133 MTP_PROPERTY_OBJECT_FILE_NAME,
134 MTP_PROPERTY_DATE_MODIFIED,
135 MTP_PROPERTY_PARENT_OBJECT,
136 MTP_PROPERTY_PERSISTENT_UID,
137 MTP_PROPERTY_NAME,
138 MTP_PROPERTY_DISPLAY_NAME,
139 MTP_PROPERTY_DATE_ADDED,
140
141 // image specific properties
142 MTP_PROPERTY_DESCRIPTION
143};
144
145int MyMtpDatabase::ALL_PROPERTIES[25] = {
146 // NOTE must match FILE_PROPERTIES above
147 MTP_PROPERTY_STORAGE_ID,
148 MTP_PROPERTY_OBJECT_FORMAT,
149 MTP_PROPERTY_PROTECTION_STATUS,
150 MTP_PROPERTY_OBJECT_SIZE,
151 MTP_PROPERTY_OBJECT_FILE_NAME,
152 MTP_PROPERTY_DATE_MODIFIED,
153 MTP_PROPERTY_PARENT_OBJECT,
154 MTP_PROPERTY_PERSISTENT_UID,
155 MTP_PROPERTY_NAME,
156 MTP_PROPERTY_DISPLAY_NAME,
157 MTP_PROPERTY_DATE_ADDED,
158
159 // image specific properties
160 MTP_PROPERTY_DESCRIPTION,
161
162 // audio specific properties
163 MTP_PROPERTY_ARTIST,
164 MTP_PROPERTY_ALBUM_NAME,
165 MTP_PROPERTY_ALBUM_ARTIST,
166 MTP_PROPERTY_TRACK,
167 MTP_PROPERTY_ORIGINAL_RELEASE_DATE,
168 MTP_PROPERTY_DURATION,
169 MTP_PROPERTY_GENRE,
170 MTP_PROPERTY_COMPOSER,
171
172 // video specific properties
173 MTP_PROPERTY_ARTIST,
174 MTP_PROPERTY_ALBUM_NAME,
175 MTP_PROPERTY_DURATION,
176 MTP_PROPERTY_DESCRIPTION,
177
178 // image specific properties
179 MTP_PROPERTY_DESCRIPTION
180};
181
182int MyMtpDatabase::SUPPORTED_PLAYBACK_FORMATS[26] = {
183 SUPPORTED_PLAYBACK_FORMAT_UNDEFINED,
184 SUPPORTED_PLAYBACK_FORMAT_ASSOCIATION,
185 SUPPORTED_PLAYBACK_FORMAT_TEXT,
186 SUPPORTED_PLAYBACK_FORMAT_HTML,
187 SUPPORTED_PLAYBACK_FORMAT_WAV,
188 SUPPORTED_PLAYBACK_FORMAT_MP3,
189 SUPPORTED_PLAYBACK_FORMAT_MPEG,
190 SUPPORTED_PLAYBACK_FORMAT_EXIF_JPEG,
191 SUPPORTED_PLAYBACK_FORMAT_TIFF_EP,
192 SUPPORTED_PLAYBACK_FORMAT_BMP,
193 SUPPORTED_PLAYBACK_FORMAT_GIF,
194 SUPPORTED_PLAYBACK_FORMAT_JFIF,
195 SUPPORTED_PLAYBACK_FORMAT_PNG,
196 SUPPORTED_PLAYBACK_FORMAT_TIFF,
197 SUPPORTED_PLAYBACK_FORMAT_WMA,
198 SUPPORTED_PLAYBACK_FORMAT_OGG,
199 SUPPORTED_PLAYBACK_FORMAT_AAC,
200 SUPPORTED_PLAYBACK_FORMAT_MP4_CONTAINER,
201 SUPPORTED_PLAYBACK_FORMAT_MP2,
202 SUPPORTED_PLAYBACK_FORMAT_3GP_CONTAINER,
203 SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_AV_PLAYLIST,
204 SUPPORTED_PLAYBACK_FORMAT_WPL_PLAYLIST,
205 SUPPORTED_PLAYBACK_FORMAT_M3U_PLAYLIST,
206 SUPPORTED_PLAYBACK_FORMAT_PLS_PLAYLIST,
207 SUPPORTED_PLAYBACK_FORMAT_XML_DOCUMENT,
208 SUPPORTED_PLAYBACK_FORMAT_FLAC
209};
210
211MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
212 MtpObjectFormat format,
213 MtpObjectHandle parent,
214 MtpStorageID storage,
215 uint64_t size,
216 time_t modified) {
217 MTPD("MyMtpDatabase::beginSendObject() which passes to MtpStorage.cpp\n");
218 return storagemap[storage]->beginSendObject(path, format, parent, storage, size, modified);
219}
220
221void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
222 MtpObjectFormat format, bool succeeded) {
223 MTPD("endSendObject() %s\n", path);
224 if (!succeeded) {
225 MTPE("endSendObject() failed, unlinking %s\n", path);
226 unlink(path);
227 }
228}
229
230void MyMtpDatabase::createDB(MtpStorage* storage, MtpStorageID storageID) {
231 storagemap[storageID] = storage;
232 storage->createDB();
233}
234
235MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
236 MtpObjectFormat format,
237 MtpObjectHandle parent) {
238 MTPD("storageID: %d\n", storageID);
239 MtpObjectHandleList* list = new MtpObjectHandleList();
240 list = storagemap[storageID]->getObjectList(storageID, parent);
241 MTPD("list: %d\n", list->size());
242 return list;
243}
244
245int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
246 MtpObjectFormat format,
247 MtpObjectHandle parent) {
248 MTPE("MyMtpDatabase::getNumObjects not implemented, returning 0\n");
249 int result = 0;
250 //get number of objects on filesystem storage
251 return result;
252}
253
254MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
255 // This function tells the host PC which file formats the device supports
256 int* formats;
257 MtpObjectFormatList* list = new MtpObjectFormatList();
258 formats = SUPPORTED_PLAYBACK_FORMATS;
259 int length = sizeof(formats)/ sizeof(int);
260 MTPD("MyMtpDatabase::getSupportedPlaybackFormats length: %i\n", length);
261 for (int i = 0; i < length; i++) {
262 MTPD("supported playback format: %d\n", formats[i]);
263 list->push(formats[i]);
264 }
265 return list;
266}
267
268MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
269 // Android OS implementation of this function returns NULL
270 // so we are not implementing this function either.
271 MTPD("MyMtpDatabase::getSupportedCaptureFormats returning NULL (This is what Android does as well).\n");
272 return NULL;
273}
274
275MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
276 int* properties;
277 MtpObjectPropertyList* list = new MtpObjectPropertyList();
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400278 int length = 0;
279 switch (format) {
280 case MTP_FORMAT_MP3:
281 case MTP_FORMAT_WAV:
282 case MTP_FORMAT_WMA:
283 case MTP_FORMAT_OGG:
284 case MTP_FORMAT_AAC:
285 properties = AUDIO_PROPERTIES;
286 length = sizeof(AUDIO_PROPERTIES) / sizeof(AUDIO_PROPERTIES[0]);
287 case MTP_FORMAT_MPEG:
288 case MTP_FORMAT_3GP_CONTAINER:
289 case MTP_FORMAT_WMV:
290 properties = VIDEO_PROPERTIES;
291 length = sizeof(VIDEO_PROPERTIES) / sizeof(VIDEO_PROPERTIES[0]);
292 case MTP_FORMAT_EXIF_JPEG:
293 case MTP_FORMAT_GIF:
294 case MTP_FORMAT_PNG:
295 case MTP_FORMAT_BMP:
296 properties = IMAGE_PROPERTIES;
297 length = sizeof(IMAGE_PROPERTIES) / sizeof(IMAGE_PROPERTIES[0]);
298 case 0:
299 properties = ALL_PROPERTIES;
300 length = sizeof(ALL_PROPERTIES) / sizeof(ALL_PROPERTIES[0]);
301 default:
302 properties = FILE_PROPERTIES;
303 length = sizeof(FILE_PROPERTIES) / sizeof(FILE_PROPERTIES[0]);
304 }
305 MTPD("MyMtpDatabase::getSupportedObjectProperties length is: %i, format: %x, sizeof: %i", length, format);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400306 for (int i = 0; i < length; i++) {
307 MTPD("supported object property: %x\n", properties[i]);
308 list->push(properties[i]);
309 }
310 return list;
311}
312
313MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400314 MtpDevicePropertyList* list = new MtpDevicePropertyList();
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400315 int length = sizeof(DEVICE_PROPERTIES) / sizeof(DEVICE_PROPERTIES[0]);
316 MTPD("MyMtpDatabase::getSupportedDeviceProperties length was: %i\n");
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400317 for (int i = 0; i < length; i++)
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400318 list->push(DEVICE_PROPERTIES[i]);
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400319 return list;
320}
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400321MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
322 MtpObjectProperty property,
323 MtpDataPacket& packet) {
324 MTPD("MyMtpDatabase::getObjectPropertyValue mtpid: %i, property: %x\n", handle, property);
325 int type;
Ethan Yonker5e083dc2014-09-03 14:46:41 -0500326 MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_HANDLE;
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400327 uint64_t longValue;
328 if (!getObjectPropertyInfo(property, type)) {
329 MTPE("MyMtpDatabase::setObjectPropertyValue returning MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED\n");
330 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
331 }
332 std::map<int, MtpStorage*>::iterator storit;
333 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
334 if (storit->second->getObjectPropertyValue(handle, property, longValue) == 0) {
335 result = MTP_RESPONSE_OK;
336 break;
337 }
338 }
339
Ethan Yonker5e083dc2014-09-03 14:46:41 -0500340 if (result != MTP_RESPONSE_OK) {
341 MTPE("MyMtpDatabase::setObjectPropertyValue unable to locate handle: %i\n", handle);
342 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
343 }
344
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400345 // special case date properties, which are strings to MTP
346 // but stored internally as a uint64
347 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
348 char date[20];
349 formatDateTime(longValue, date, sizeof(date));
350 packet.putString(date);
351 goto out;
352 }
353 // release date is stored internally as just the year
354 if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
355 char date[20];
356 snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
357 packet.putString(date);
358 goto out;
359 }
360
361 switch (type) {
362 case MTP_TYPE_INT8:
363 packet.putInt8(longValue);
364 break;
365 case MTP_TYPE_UINT8:
366 packet.putUInt8(longValue);
367 break;
368 case MTP_TYPE_INT16:
369 packet.putInt16(longValue);
370 break;
371 case MTP_TYPE_UINT16:
372 packet.putUInt16(longValue);
373 break;
374 case MTP_TYPE_INT32:
375 packet.putInt32(longValue);
376 break;
377 case MTP_TYPE_UINT32:
378 packet.putUInt32(longValue);
379 break;
380 case MTP_TYPE_INT64:
381 packet.putInt64(longValue);
382 break;
383 case MTP_TYPE_UINT64:
384 packet.putUInt64(longValue);
385 break;
386 case MTP_TYPE_INT128:
387 packet.putInt128(longValue);
388 break;
389 case MTP_TYPE_UINT128:
390 packet.putInt128(longValue);
391 break;
392 case MTP_TYPE_STR:
393 {
394 /*std::string stringValue = (string)stringValuesArray[0];
395 if (stringValue) {
396 const char* str = stringValue.c_str();
397 if (str == NULL) {
398 return MTP_RESPONSE_GENERAL_ERROR;
399 }
400 packet.putString(str);
401 } else {
402 packet.putEmptyString();
403 }*/
404 MTPE("STRING unsupported type in getObjectPropertyValue\n");
405 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
406 break;
407 }
408 default:
409 MTPE("unsupported type in getObjectPropertyValue\n");
410 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
411 }
412out:
413 return result;
414}
415
416MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
417 MtpObjectProperty property,
418 MtpDataPacket& packet) {
419 int type;
420 MTPD("MyMtpDatabase::setObjectPropertyValue start\n");
421 if (!getObjectPropertyInfo(property, type)) {
422 MTPE("MyMtpDatabase::setObjectPropertyValue returning MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED\n");
423 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
424 }
425 MTPD("MyMtpDatabase::setObjectPropertyValue continuing\n");
426 long longValue = 0;
427 std::string stringValue;
428
429 switch (type) {
430 case MTP_TYPE_INT8:
431 MTPD("int8\n");
432 longValue = packet.getInt8();
433 break;
434 case MTP_TYPE_UINT8:
435 MTPD("uint8\n");
436 longValue = packet.getUInt8();
437 break;
438 case MTP_TYPE_INT16:
439 MTPD("int16\n");
440 longValue = packet.getInt16();
441 break;
442 case MTP_TYPE_UINT16:
443 MTPD("uint16\n");
444 longValue = packet.getUInt16();
445 break;
446 case MTP_TYPE_INT32:
447 MTPD("int32\n");
448 longValue = packet.getInt32();
449 break;
450 case MTP_TYPE_UINT32:
451 MTPD("uint32\n");
452 longValue = packet.getUInt32();
453 break;
454 case MTP_TYPE_INT64:
455 MTPD("int64\n");
456 longValue = packet.getInt64();
457 break;
458 case MTP_TYPE_UINT64:
459 MTPD("uint64\n");
460 longValue = packet.getUInt64();
461 break;
462 case MTP_TYPE_STR:
463 {
464 MTPD("string\n");
465 MtpStringBuffer buffer;
466 packet.getString(buffer);
467 stringValue = (const char *)buffer;
468 break;
469 }
470 default:
471 MTPE("MyMtpDatabase::setObjectPropertyValue unsupported type %i in getObjectPropertyValue\n", type);
472 return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
473 }
474
475 int result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
476
477 switch (property) {
478 case MTP_PROPERTY_OBJECT_FILE_NAME:
479 {
480 MTPD("MyMtpDatabase::setObjectPropertyValue renaming file, handle: %d, new name: '%s'\n", handle, stringValue.c_str());
481 std::map<int, MtpStorage*>::iterator storit;
482 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
483 if (storit->second->renameObject(handle, stringValue) == 0) {
484 MTPD("MTP_RESPONSE_OK\n");
485 result = MTP_RESPONSE_OK;
486 break;
487 }
488 }
489 }
490 break;
491
492 default:
493 MTPE("MyMtpDatabase::setObjectPropertyValue property %x not supported.\n", property);
494 result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
495 }
496 MTPD("MyMtpDatabase::setObjectPropertyValue returning %d\n", result);
497 return result;
498}
499
500MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
501 MtpDataPacket& packet) {
502 int type, result = 0;
503 char prop_value[PROPERTY_VALUE_MAX];
504 MTPD("property %s\n",
505 MtpDebug::getDevicePropCodeName(property));
506 if (!getDevicePropertyInfo(property, type)) {
507 MTPE("MyMtpDatabase::getDevicePropertyValue MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED\n");
508 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
509 }
510 MTPD("property %s\n",
511 MtpDebug::getDevicePropCodeName(property));
512 MTPD("property %x\n", property);
513 MTPD("MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME %x\n", MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME);
514 switch (property) {
515 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
516 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
517 result = MTP_RESPONSE_OK;
518 break;
519 default:
520 {
521 MTPE("MyMtpDatabase::getDevicePropertyValue property %x not supported\n", property);
522 result = MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
523 break;
524 }
525 }
526
527 if (result != MTP_RESPONSE_OK) {
528 MTPD("MTP_REPONSE_OK NOT OK\n");
529 return result;
530 }
531
532 long longValue = 0;
533 property_get("ro.build.product", prop_value, "unknown manufacturer");
534 switch (type) {
535 case MTP_TYPE_INT8: {
536 MTPD("MTP_TYPE_INT8\n");
537 packet.putInt8(longValue);
538 break;
539 }
540 case MTP_TYPE_UINT8:
541 {
542 MTPD("MTP_TYPE_UINT8\n");
543 packet.putUInt8(longValue);
544 break;
545 }
546 case MTP_TYPE_INT16:
547 {
548 MTPD("MTP_TYPE_INT16\n");
549 packet.putInt16(longValue);
550 break;
551 }
552 case MTP_TYPE_UINT16:
553 {
554 MTPD("MTP_TYPE_UINT16\n");
555 packet.putUInt16(longValue);
556 break;
557 }
558 case MTP_TYPE_INT32:
559 {
560 MTPD("MTP_TYPE_INT32\n");
561 packet.putInt32(longValue);
562 break;
563 }
564 case MTP_TYPE_UINT32:
565 {
566 MTPD("MTP_TYPE_UINT32\n");
567 packet.putUInt32(longValue);
568 break;
569 }
570 case MTP_TYPE_INT64:
571 {
572 MTPD("MTP_TYPE_INT64\n");
573 packet.putInt64(longValue);
574 break;
575 }
576 case MTP_TYPE_UINT64:
577 {
578 MTPD("MTP_TYPE_UINT64\n");
579 packet.putUInt64(longValue);
580 break;
581 }
582 case MTP_TYPE_INT128:
583 {
584 MTPD("MTP_TYPE_INT128\n");
585 packet.putInt128(longValue);
586 break;
587 }
588 case MTP_TYPE_UINT128:
589 {
590 MTPD("MTP_TYPE_UINT128\n");
591 packet.putInt128(longValue);
592 break;
593 }
594 case MTP_TYPE_STR:
595 {
596 MTPD("MTP_TYPE_STR\n");
597 char* str = prop_value;
598 packet.putString(str);
599 break;
600 }
601 default:
602 MTPE("MyMtpDatabase::getDevicePropertyValue unsupported type %i in getDevicePropertyValue\n", type);
603 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
604 }
605
606 return MTP_RESPONSE_OK;
607}
608
609MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property, MtpDataPacket& packet) {
610 int type;
611 MTPE("MyMtpDatabase::setDevicePropertyValue not implemented, returning 0\n");
612 return 0;
613}
614
615MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
616 MTPE("MyMtpDatabase::resetDeviceProperty not implemented, returning -1\n");
617 return -1;
618}
619
620MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet) {
621 MTPD("getObjectPropertyList()\n");
622 MTPD("property: %x\n", property);
623 std::map<int, MtpStorage*>::iterator storit;
624 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
625 MTPD("MyMtpDatabase::getObjectPropertyList calling getObjectPropertyList\n");
626 if (storit->second->getObjectPropertyList(handle, format, property, groupCode, depth, packet) == 0) {
627 MTPD("MTP_RESPONSE_OK\n");
628 return MTP_RESPONSE_OK;
629 }
630 }
631 MTPE("MyMtpDatabase::getObjectPropertyList MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
632 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
633}
634
635MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, MtpObjectInfo& info) {
636 std::map<int, MtpStorage*>::iterator storit;
637 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
638 if (storit->second->getObjectInfo(handle, info) == 0) {
639 MTPD("MTP_RESPONSE_OK\n");
640 return MTP_RESPONSE_OK;
641 }
642 }
643 MTPE("MyMtpDatabase::getObjectInfo MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
644 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
645}
646
647void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
648 MtpString path;
649 int64_t length;
650 MtpObjectFormat format;
651 void* result = NULL;
652 outThumbSize = 0;
653 MTPE("MyMtpDatabase::getThumbnail not implemented, returning 0\n");
654 return 0;
655}
656
657MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle, MtpString& outFilePath, int64_t& outFileLength, MtpObjectFormat& outFormat) {
658 std::map<int, MtpStorage*>::iterator storit;
659 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
bigbiff bigbiff1812c892014-09-08 21:04:06 -0400660 MTPD("MyMtpDatabase::getObjectFilePath calling getObjectFilePath\n");
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400661 if (storit->second->getObjectFilePath(handle, outFilePath, outFileLength, outFormat) == 0) {
662 MTPD("MTP_RESPONSE_OK\n");
663 return MTP_RESPONSE_OK;
664 }
665 }
666 MTPE("MyMtpDatabase::getObjectFilePath MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
667 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
668}
669
670MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
671 MTPD("deleteFile\n");
672 std::map<int, MtpStorage*>::iterator storit;
673 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
674 if (storit->second->deleteFile(handle) == 0) {
675 MTPD("MTP_RESPONSE_OK\n");
676 return MTP_RESPONSE_OK;
677 }
678 }
679 MTPE("MyMtpDatabase::deleteFile MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
680 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
681}
682
683struct PropertyTableEntry {
684 MtpObjectProperty property;
685 int type;
686};
687
688static const PropertyTableEntry kObjectPropertyTable[] = {
689 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
690 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
691 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
692 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
693 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
694 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
695 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
696 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
697 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
698 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
699 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
700 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
701 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
702 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
703 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
704 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
705 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
706 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
707 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
708 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
709};
710
711static const PropertyTableEntry kDevicePropertyTable[] = {
712 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
713 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
714 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
715};
716
717bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
718 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
719 const PropertyTableEntry* entry = kObjectPropertyTable;
720 MTPD("MyMtpDatabase::getObjectPropertyInfo size is: %i\n", count);
721 for (int i = 0; i < count; i++, entry++) {
722 if (entry->property == property) {
723 type = entry->type;
724 return true;
725 }
726 }
727 return false;
728}
729
730bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
731 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
732 const PropertyTableEntry* entry = kDevicePropertyTable;
733 MTPD("MyMtpDatabase::getDevicePropertyInfo count is: %i\n", count);
734 for (int i = 0; i < count; i++, entry++) {
735 if (entry->property == property) {
736 type = entry->type;
737 MTPD("type: %x\n", type);
738 return true;
739 }
740 }
741 return false;
742}
743
744MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
745 // call function and place files with associated handles into int array
746 MTPD("MyMtpDatabase::getObjectReferences returning null, this seems to be what Android always does.\n");
747 MTPD("handle: %d\n", handle);
748 // Windows + Android seems to always return a NULL in this function, c == null path
749 // The way that this is handled in Android then is to do this:
750 return NULL;
751}
752
753MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
754 MtpObjectHandleList* references) {
755 int count = references->size();
756 MTPE("MyMtpDatabase::setObjectReferences not implemented, returning 0\n");
757 return 0;
758}
759
760MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
761 MtpObjectFormat format) {
762 MTPD("MyMtpDatabase::getObjectPropertyDesc start\n");
763 MtpProperty* result = NULL;
764 switch (property) {
765 case MTP_PROPERTY_OBJECT_FORMAT:
766 // use format as default value
767 MTPD("MyMtpDatabase::getObjectPropertyDesc format\n");
768 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
769 break;
770 case MTP_PROPERTY_PROTECTION_STATUS:
771 case MTP_PROPERTY_TRACK:
772 MTPD("MyMtpDatabase::getObjectPropertyDesc track\n");
773 result = new MtpProperty(property, MTP_TYPE_UINT16);
774 break;
775 case MTP_PROPERTY_STORAGE_ID:
776 case MTP_PROPERTY_PARENT_OBJECT:
777 case MTP_PROPERTY_DURATION:
778 MTPD("MyMtpDatabase::getObjectPropertyDesc duration\n");
779 result = new MtpProperty(property, MTP_TYPE_UINT32);
780 break;
781 case MTP_PROPERTY_OBJECT_SIZE:
782 MTPD("MyMtpDatabase::getObjectPropertyDesc size\n");
783 result = new MtpProperty(property, MTP_TYPE_UINT64);
784 break;
785 case MTP_PROPERTY_PERSISTENT_UID:
786 MTPD("MyMtpDatabase::getObjectPropertyDesc persistent uid\n");
787 result = new MtpProperty(property, MTP_TYPE_UINT128);
788 break;
789 case MTP_PROPERTY_NAME:
790 case MTP_PROPERTY_DISPLAY_NAME:
791 case MTP_PROPERTY_ARTIST:
792 case MTP_PROPERTY_ALBUM_NAME:
793 case MTP_PROPERTY_ALBUM_ARTIST:
794 case MTP_PROPERTY_GENRE:
795 case MTP_PROPERTY_COMPOSER:
796 case MTP_PROPERTY_DESCRIPTION:
797 MTPD("MyMtpDatabase::getObjectPropertyDesc description\n");
798 result = new MtpProperty(property, MTP_TYPE_STR);
799 break;
800 case MTP_PROPERTY_DATE_MODIFIED:
801 case MTP_PROPERTY_DATE_ADDED:
802 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
803 MTPD("MyMtpDatabase::getObjectPropertyDesc date\n");
804 result = new MtpProperty(property, MTP_TYPE_STR);
805 result->setFormDateTime();
806 break;
807 case MTP_PROPERTY_OBJECT_FILE_NAME:
808 MTPD("MyMtpDatabase::getObjectPropertyDesc file name\n");
809 // We allow renaming files and folders
810 result = new MtpProperty(property, MTP_TYPE_STR, true);
811 break;
812 }
813 return result;
814}
815
816MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
817 MtpProperty* result = NULL;
818 int ret;
819 bool writable = true;
820 switch (property) {
821 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
822 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
823 ret = MTP_RESPONSE_OK;
824 // fall through
825 case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
826 result = new MtpProperty(property, MTP_TYPE_STR, writable);
827 ret = MTP_RESPONSE_OK;
828
829 // get current value
830 if (ret == MTP_RESPONSE_OK) {
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -0400831 result->setCurrentValue('\0');
832 result->setDefaultValue('\0');
833 } else {
834 MTPE("unable to read device property, response: %04X", ret);
835 }
836 break;
837 default:
838 ret = MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
839 break;
840 }
841
842 return result;
843}
844
845void MyMtpDatabase::sessionStarted() {
846 MTPD("MyMtpDatabase::sessionStarted not implemented or does nothing, returning\n");
847 return;
848}
849
850void MyMtpDatabase::sessionEnded() {
851 MTPD("MyMtpDatabase::sessionEnded not implemented or does nothing, returning\n");
852 return;
853}
854
855// ----------------------------------------------------------------------------
856
857static void
858android_mtp_MtpDatabase_setup()
859{
860 MyMtpDatabase* database = new MyMtpDatabase();
861}
862
863static void
864android_mtp_MtpDatabase_finalize()
865{
866 return;
867}
868
869static std::string
870android_mtp_MtpPropertyGroup_format_date_time(long seconds)
871{
872 char date[20];
873 formatDateTime(seconds, date, sizeof(date));
874 return date;
875}
876
877void MyMtpDatabase::lockMutex(void) {
878 std::map<int, MtpStorage*>::iterator storit;
879 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
880 storit->second->lockMutex(0);
881 }
882}
883
884void MyMtpDatabase::unlockMutex(void) {
885 std::map<int, MtpStorage*>::iterator storit;
886 for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
887 storit->second->unlockMutex(0);
888 }
889}