blob: 3ba07cc444fcb893dd6f756efebe4228b092b17b [file] [log] [blame]
Mike Lockwood755fd612010-05-25 19:08:48 -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
17#define LOG_TAG "MtpCursor"
Mike Lockwood755fd612010-05-25 19:08:48 -040018
Mike Lockwood3e6616d2010-06-29 18:11:52 -040019#include "MtpDebug.h"
Mike Lockwood755fd612010-05-25 19:08:48 -040020#include "MtpClient.h"
21#include "MtpCursor.h"
22#include "MtpDevice.h"
23#include "MtpDeviceInfo.h"
24#include "MtpObjectInfo.h"
25#include "MtpStorageInfo.h"
26
Mike Lockwood3e6616d2010-06-29 18:11:52 -040027
Mike Lockwood755fd612010-05-25 19:08:48 -040028#include "binder/CursorWindow.h"
29
30namespace android {
31
32/* Device Column IDs */
Mike Lockwoodf724eed2010-06-08 07:33:14 -040033/* These must match the values in MtpCursor.java */
Mike Lockwood755fd612010-05-25 19:08:48 -040034#define DEVICE_ROW_ID 1
35#define DEVICE_MANUFACTURER 2
36#define DEVICE_MODEL 3
37
38/* Storage Column IDs */
Mike Lockwoodf724eed2010-06-08 07:33:14 -040039/* These must match the values in MtpCursor.java */
Mike Lockwood755fd612010-05-25 19:08:48 -040040#define STORAGE_ROW_ID 101
41#define STORAGE_IDENTIFIER 102
42#define STORAGE_DESCRIPTION 103
43
44/* Object Column IDs */
Mike Lockwoodf724eed2010-06-08 07:33:14 -040045/* These must match the values in MtpCursor.java */
46#define OBJECT_ROW_ID 201
47#define OBJECT_STORAGE_ID 202
48#define OBJECT_FORMAT 203
49#define OBJECT_PROTECTION_STATUS 204
50#define OBJECT_SIZE 205
51#define OBJECT_THUMB_FORMAT 206
52#define OBJECT_THUMB_SIZE 207
53#define OBJECT_THUMB_WIDTH 208
54#define OBJECT_THUMB_HEIGHT 209
55#define OBJECT_IMAGE_WIDTH 210
56#define OBJECT_IMAGE_HEIGHT 211
57#define OBJECT_IMAGE_DEPTH 212
58#define OBJECT_PARENT 213
59#define OBJECT_ASSOCIATION_TYPE 214
60#define OBJECT_ASSOCIATION_DESC 215
61#define OBJECT_SEQUENCE_NUMBER 216
62#define OBJECT_NAME 217
63#define OBJECT_DATE_CREATED 218
64#define OBJECT_DATE_MODIFIED 219
65#define OBJECT_KEYWORDS 220
Mike Lockwooddda56862010-06-10 16:34:20 -040066#define OBJECT_THUMB 221
Mike Lockwood755fd612010-05-25 19:08:48 -040067
68MtpCursor::MtpCursor(MtpClient* client, int queryType, int deviceID,
69 int storageID, int objectID, int columnCount, int* columns)
70 : mClient(client),
71 mQueryType(queryType),
72 mDeviceID(deviceID),
73 mStorageID(storageID),
74 mQbjectID(objectID),
75 mColumnCount(columnCount),
76 mColumns(NULL)
77{
78 if (columns) {
79 mColumns = new int[columnCount];
80 memcpy(mColumns, columns, columnCount * sizeof(int));
81 }
82}
83
84MtpCursor::~MtpCursor() {
85 delete[] mColumns;
86}
87
88int MtpCursor::fillWindow(CursorWindow* window, int startPos) {
89 LOGD("MtpCursor::fillWindow mQueryType: %d\n", mQueryType);
90
91 switch (mQueryType) {
92 case DEVICE:
93 return fillDevices(window, startPos);
94 case DEVICE_ID:
95 return fillDevice(window, startPos);
96 case STORAGE:
97 return fillStorages(window, startPos);
98 case STORAGE_ID:
99 return fillStorage(window, startPos);
100 case OBJECT:
101 return fillObjects(window, 0, startPos);
102 case OBJECT_ID:
103 return fillObject(window, startPos);
104 case STORAGE_CHILDREN:
105 return fillObjects(window, -1, startPos);
106 case OBJECT_CHILDREN:
107 return fillObjects(window, mQbjectID, startPos);
108 default:
109 LOGE("MtpCursor::fillWindow: unknown query type %d\n", mQueryType);
110 return 0;
111 }
112}
113
114int MtpCursor::fillDevices(CursorWindow* window, int startPos) {
115 int count = 0;
116 MtpDeviceList& deviceList = mClient->getDeviceList();
117 for (int i = 0; i < deviceList.size(); i++) {
118 MtpDevice* device = deviceList[i];
119 if (fillDevice(window, device, startPos)) {
120 count++;
121 startPos++;
122 } else {
123 break;
124 }
125 }
126 return count;
127}
128
129int MtpCursor::fillDevice(CursorWindow* window, int startPos) {
130 MtpDevice* device = mClient->getDevice(mDeviceID);
131 if (device && fillDevice(window, device, startPos))
132 return 1;
133 else
134 return 0;
135}
136
137int MtpCursor::fillStorages(CursorWindow* window, int startPos) {
138 int count = 0;
139 MtpDevice* device = mClient->getDevice(mDeviceID);
140 if (!device)
141 return 0;
142 MtpStorageIDList* storageIDs = device->getStorageIDs();
143 if (!storageIDs)
144 return 0;
145
146 for (int i = 0; i < storageIDs->size(); i++) {
147 MtpStorageID storageID = (*storageIDs)[i];
148 if (fillStorage(window, device, storageID, startPos)) {
149 count++;
150 startPos++;
151 } else {
152 break;
153 }
154 }
155 delete storageIDs;
156 return count;
157}
158
159int MtpCursor::fillStorage(CursorWindow* window, int startPos) {
160 MtpDevice* device = mClient->getDevice(mDeviceID);
161 if (device && fillStorage(window, device, mStorageID, startPos))
162 return 1;
163 else
164 return 0;
165}
166
167int MtpCursor::fillObjects(CursorWindow* window, int parent, int startPos) {
168 int count = 0;
169 MtpDevice* device = mClient->getDevice(mDeviceID);
170 if (!device)
171 return 0;
172 MtpObjectHandleList* handles = device->getObjectHandles(mStorageID, 0, parent);
173 if (!handles)
174 return 0;
175
176 for (int i = 0; i < handles->size(); i++) {
177 MtpObjectHandle handle = (*handles)[i];
178 if (fillObject(window, device, handle, startPos)) {
179 count++;
180 startPos++;
181 } else {
182 break;
183 }
184 }
185 delete handles;
186 return count;
187}
188
189int MtpCursor::fillObject(CursorWindow* window, int startPos) {
190 MtpDevice* device = mClient->getDevice(mDeviceID);
191 if (device && fillObject(window, device, mQbjectID, startPos))
192 return 1;
193 else
194 return 0;
195}
196
197bool MtpCursor::fillDevice(CursorWindow* window, MtpDevice* device, int row) {
198 MtpDeviceInfo* deviceInfo = device->getDeviceInfo();
199 if (!deviceInfo)
200 return false;
201 if (!prepareRow(window))
202 return false;
203
204 for (int i = 0; i < mColumnCount; i++) {
205 switch (mColumns[i]) {
206 case DEVICE_ROW_ID:
207 if (!putLong(window, device->getID(), row, i))
208 return false;
209 break;
210 case DEVICE_MANUFACTURER:
211 if (!putString(window, deviceInfo->mManufacturer, row, i))
212 return false;
213 break;
214 case DEVICE_MODEL:
215 if (!putString(window, deviceInfo->mModel, row, i))
216 return false;
217 break;
218 default:
219 LOGE("fillDevice: unknown column %d\n", mColumns[i]);
220 return false;
221 }
222 }
223
224 return true;
225}
226
227bool MtpCursor::fillStorage(CursorWindow* window, MtpDevice* device,
228 MtpStorageID storageID, int row) {
229
230LOGD("fillStorage %d\n", storageID);
231
232 MtpStorageInfo* storageInfo = device->getStorageInfo(storageID);
233 if (!storageInfo)
234 return false;
235 if (!prepareRow(window)) {
236 delete storageInfo;
237 return false;
238 }
239
240 const char* text;
241 for (int i = 0; i < mColumnCount; i++) {
242 switch (mColumns[i]) {
243 case STORAGE_ROW_ID:
244 if (!putLong(window, storageID, row, i))
245 goto fail;
246 break;
247 case STORAGE_IDENTIFIER:
248 text = storageInfo->mVolumeIdentifier;
249 if (!text || !text[0])
250 text = "Camera Storage";
251 if (!putString(window, text, row, i))
252 goto fail;
253 break;
254 case STORAGE_DESCRIPTION:
255 text = storageInfo->mStorageDescription;
256 if (!text || !text[0])
257 text = "Storage Description";
258 if (!putString(window, text, row, i))
259 goto fail;
260 break;
261 default:
262 LOGE("fillStorage: unknown column %d\n", mColumns[i]);
263 goto fail;
264 }
265 }
266
267 delete storageInfo;
268 return true;
269
270fail:
271 delete storageInfo;
272 return false;
273}
274
275bool MtpCursor::fillObject(CursorWindow* window, MtpDevice* device,
276 MtpObjectHandle objectID, int row) {
277
Mike Lockwood755fd612010-05-25 19:08:48 -0400278 MtpObjectInfo* objectInfo = device->getObjectInfo(objectID);
279 if (!objectInfo)
280 return false;
Mike Lockwoodf724eed2010-06-08 07:33:14 -0400281 // objectInfo->print();
Mike Lockwood755fd612010-05-25 19:08:48 -0400282 if (!prepareRow(window)) {
283 delete objectInfo;
284 return false;
285 }
286
287 for (int i = 0; i < mColumnCount; i++) {
288 switch (mColumns[i]) {
289 case OBJECT_ROW_ID:
290 if (!putLong(window, objectID, row, i))
291 goto fail;
292 break;
Mike Lockwoodf724eed2010-06-08 07:33:14 -0400293 case OBJECT_STORAGE_ID:
294 if (!putLong(window, objectInfo->mStorageID, row, i))
295 goto fail;
296 break;
297 case OBJECT_FORMAT:
298 if (!putLong(window, objectInfo->mFormat, row, i))
299 goto fail;
300 break;
301 case OBJECT_PROTECTION_STATUS:
302 if (!putLong(window, objectInfo->mProtectionStatus, row, i))
303 goto fail;
304 break;
305 case OBJECT_SIZE:
306 if (!putLong(window, objectInfo->mCompressedSize, row, i))
307 goto fail;
308 break;
309 case OBJECT_THUMB_FORMAT:
310 if (!putLong(window, objectInfo->mThumbFormat, row, i))
311 goto fail;
312 break;
313 case OBJECT_THUMB_SIZE:
314 if (!putLong(window, objectInfo->mThumbCompressedSize, row, i))
315 goto fail;
316 break;
317 case OBJECT_THUMB_WIDTH:
318 if (!putLong(window, objectInfo->mThumbPixWidth, row, i))
319 goto fail;
320 break;
321 case OBJECT_THUMB_HEIGHT:
322 if (!putLong(window, objectInfo->mThumbPixHeight, row, i))
323 goto fail;
324 break;
325 case OBJECT_IMAGE_WIDTH:
326 if (!putLong(window, objectInfo->mImagePixWidth, row, i))
327 goto fail;
328 break;
329 case OBJECT_IMAGE_HEIGHT:
330 if (!putLong(window, objectInfo->mImagePixHeight, row, i))
331 goto fail;
332 break;
333 case OBJECT_IMAGE_DEPTH:
334 if (!putLong(window, objectInfo->mImagePixDepth, row, i))
335 goto fail;
336 break;
337 case OBJECT_PARENT:
338 if (!putLong(window, objectInfo->mParent, row, i))
339 goto fail;
340 break;
341 case OBJECT_ASSOCIATION_TYPE:
342 if (!putLong(window, objectInfo->mAssociationType, row, i))
343 goto fail;
344 break;
345 case OBJECT_ASSOCIATION_DESC:
346 if (!putLong(window, objectInfo->mAssociationDesc, row, i))
347 goto fail;
348 break;
349 case OBJECT_SEQUENCE_NUMBER:
350 if (!putLong(window, objectInfo->mSequenceNumber, row, i))
351 goto fail;
352 break;
Mike Lockwood755fd612010-05-25 19:08:48 -0400353 case OBJECT_NAME:
354 if (!putString(window, objectInfo->mName, row, i))
355 goto fail;
356 break;
Mike Lockwoodf724eed2010-06-08 07:33:14 -0400357 case OBJECT_DATE_CREATED:
358 if (!putLong(window, objectInfo->mDateCreated, row, i))
359 goto fail;
360 break;
361 case OBJECT_DATE_MODIFIED:
362 if (!putLong(window, objectInfo->mDateModified, row, i))
363 goto fail;
364 break;
365 case OBJECT_KEYWORDS:
366 if (!putString(window, objectInfo->mKeywords, row, i))
367 goto fail;
368 break;
Mike Lockwooddda56862010-06-10 16:34:20 -0400369 case OBJECT_THUMB:
Mike Lockwoodf78b26a2010-07-26 20:35:21 -0400370 if (!putThumbnail(window, objectID, objectInfo->mFormat, row, i))
Mike Lockwooddda56862010-06-10 16:34:20 -0400371 goto fail;
372 break;
Mike Lockwood755fd612010-05-25 19:08:48 -0400373 default:
374 LOGE("fillStorage: unknown column %d\n", mColumns[i]);
375 goto fail;
376 }
377 }
378
Mike Lockwoodf724eed2010-06-08 07:33:14 -0400379 delete objectInfo;
Mike Lockwood755fd612010-05-25 19:08:48 -0400380 return true;
381
382fail:
383 delete objectInfo;
384 return false;
385}
386
387bool MtpCursor::prepareRow(CursorWindow* window) {
388 if (!window->setNumColumns(mColumnCount)) {
389 LOGE("Failed to change column count from %d to %d", window->getNumColumns(), mColumnCount);
390 return false;
391 }
392 field_slot_t * fieldDir = window->allocRow();
393 if (!fieldDir) {
394 LOGE("Failed allocating fieldDir");
395 return false;
396 }
397 return true;
398}
399
400
401bool MtpCursor::putLong(CursorWindow* window, int value, int row, int column) {
402
403 if (!window->putLong(row, column, value)) {
404 window->freeLastRow();
405 LOGE("Failed allocating space for a long in column %d", column);
406 return false;
407 }
408 return true;
409}
410
411bool MtpCursor::putString(CursorWindow* window, const char* text, int row, int column) {
412 int size = strlen(text) + 1;
413 int offset = window->alloc(size);
414 if (!offset) {
415 window->freeLastRow();
416 LOGE("Failed allocating %u bytes for text/blob %s", size, text);
417 return false;
418 }
419 window->copyIn(offset, (const uint8_t*)text, size);
420
421 // This must be updated after the call to alloc(), since that
422 // may move the field around in the window
423 field_slot_t * fieldSlot = window->getFieldSlot(row, column);
424 fieldSlot->type = FIELD_TYPE_STRING;
425 fieldSlot->data.buffer.offset = offset;
426 fieldSlot->data.buffer.size = size;
427 return true;
428}
429
Mike Lockwoodf78b26a2010-07-26 20:35:21 -0400430bool MtpCursor::putThumbnail(CursorWindow* window, int objectID, int format, int row, int column) {
Mike Lockwooddda56862010-06-10 16:34:20 -0400431 MtpDevice* device = mClient->getDevice(mDeviceID);
Mike Lockwoodf78b26a2010-07-26 20:35:21 -0400432 void* thumbnail;
433 int size, offset;
434 if (format == MTP_FORMAT_ASSOCIATION) {
435 thumbnail = NULL;
436 size = offset = 0;
437 } else {
438 thumbnail = device->getThumbnail(objectID, size);
Mike Lockwooddda56862010-06-10 16:34:20 -0400439
Mike Lockwood456d8e62010-07-27 11:50:34 -0400440 LOGV("putThumbnail: %p, size: %d\n", thumbnail, size);
Mike Lockwoodf78b26a2010-07-26 20:35:21 -0400441 offset = window->alloc(size);
442 if (!offset) {
443 window->freeLastRow();
444 LOGE("Failed allocating %u bytes for thumbnail", size);
445 return false;
446 }
Mike Lockwooddda56862010-06-10 16:34:20 -0400447 }
Mike Lockwoodf78b26a2010-07-26 20:35:21 -0400448 if (thumbnail)
Mike Lockwooddda56862010-06-10 16:34:20 -0400449 window->copyIn(offset, (const uint8_t*)thumbnail, size);
450
451 // This must be updated after the call to alloc(), since that
452 // may move the field around in the window
453 field_slot_t * fieldSlot = window->getFieldSlot(row, column);
454 fieldSlot->type = FIELD_TYPE_BLOB;
455 fieldSlot->data.buffer.offset = offset;
456 fieldSlot->data.buffer.size = size;
457 return true;
458}
459
Mike Lockwood755fd612010-05-25 19:08:48 -0400460} // namespace android