blob: 9c9ce64c5733e11527d4d7013a90b0e36b3c4bbc [file] [log] [blame]
Mike Lockwood5ed68d22010-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"
18#include "utils/Log.h"
19
20#include "MtpClient.h"
21#include "MtpCursor.h"
22#include "MtpDevice.h"
23#include "MtpDeviceInfo.h"
24#include "MtpObjectInfo.h"
25#include "MtpStorageInfo.h"
26
27#include "binder/CursorWindow.h"
28
29namespace android {
30
31/* Device Column IDs */
32#define DEVICE_ROW_ID 1
33#define DEVICE_MANUFACTURER 2
34#define DEVICE_MODEL 3
35
36/* Storage Column IDs */
37#define STORAGE_ROW_ID 101
38#define STORAGE_IDENTIFIER 102
39#define STORAGE_DESCRIPTION 103
40
41/* Object Column IDs */
42#define OBJECT_ROW_ID 201
43#define OBJECT_NAME 202
44
45MtpCursor::MtpCursor(MtpClient* client, int queryType, int deviceID,
46 int storageID, int objectID, int columnCount, int* columns)
47 : mClient(client),
48 mQueryType(queryType),
49 mDeviceID(deviceID),
50 mStorageID(storageID),
51 mQbjectID(objectID),
52 mColumnCount(columnCount),
53 mColumns(NULL)
54{
55 if (columns) {
56 mColumns = new int[columnCount];
57 memcpy(mColumns, columns, columnCount * sizeof(int));
58 }
59}
60
61MtpCursor::~MtpCursor() {
62 delete[] mColumns;
63}
64
65int MtpCursor::fillWindow(CursorWindow* window, int startPos) {
66 LOGD("MtpCursor::fillWindow mQueryType: %d\n", mQueryType);
67
68 switch (mQueryType) {
69 case DEVICE:
70 return fillDevices(window, startPos);
71 case DEVICE_ID:
72 return fillDevice(window, startPos);
73 case STORAGE:
74 return fillStorages(window, startPos);
75 case STORAGE_ID:
76 return fillStorage(window, startPos);
77 case OBJECT:
78 return fillObjects(window, 0, startPos);
79 case OBJECT_ID:
80 return fillObject(window, startPos);
81 case STORAGE_CHILDREN:
82 return fillObjects(window, -1, startPos);
83 case OBJECT_CHILDREN:
84 return fillObjects(window, mQbjectID, startPos);
85 default:
86 LOGE("MtpCursor::fillWindow: unknown query type %d\n", mQueryType);
87 return 0;
88 }
89}
90
91int MtpCursor::fillDevices(CursorWindow* window, int startPos) {
92 int count = 0;
93 MtpDeviceList& deviceList = mClient->getDeviceList();
94 for (int i = 0; i < deviceList.size(); i++) {
95 MtpDevice* device = deviceList[i];
96 if (fillDevice(window, device, startPos)) {
97 count++;
98 startPos++;
99 } else {
100 break;
101 }
102 }
103 return count;
104}
105
106int MtpCursor::fillDevice(CursorWindow* window, int startPos) {
107 MtpDevice* device = mClient->getDevice(mDeviceID);
108 if (device && fillDevice(window, device, startPos))
109 return 1;
110 else
111 return 0;
112}
113
114int MtpCursor::fillStorages(CursorWindow* window, int startPos) {
115 int count = 0;
116 MtpDevice* device = mClient->getDevice(mDeviceID);
117 if (!device)
118 return 0;
119 MtpStorageIDList* storageIDs = device->getStorageIDs();
120 if (!storageIDs)
121 return 0;
122
123 for (int i = 0; i < storageIDs->size(); i++) {
124 MtpStorageID storageID = (*storageIDs)[i];
125 if (fillStorage(window, device, storageID, startPos)) {
126 count++;
127 startPos++;
128 } else {
129 break;
130 }
131 }
132 delete storageIDs;
133 return count;
134}
135
136int MtpCursor::fillStorage(CursorWindow* window, int startPos) {
137 MtpDevice* device = mClient->getDevice(mDeviceID);
138 if (device && fillStorage(window, device, mStorageID, startPos))
139 return 1;
140 else
141 return 0;
142}
143
144int MtpCursor::fillObjects(CursorWindow* window, int parent, int startPos) {
145 int count = 0;
146 MtpDevice* device = mClient->getDevice(mDeviceID);
147 if (!device)
148 return 0;
149 MtpObjectHandleList* handles = device->getObjectHandles(mStorageID, 0, parent);
150 if (!handles)
151 return 0;
152
153 for (int i = 0; i < handles->size(); i++) {
154 MtpObjectHandle handle = (*handles)[i];
155 if (fillObject(window, device, handle, startPos)) {
156 count++;
157 startPos++;
158 } else {
159 break;
160 }
161 }
162 delete handles;
163 return count;
164}
165
166int MtpCursor::fillObject(CursorWindow* window, int startPos) {
167 MtpDevice* device = mClient->getDevice(mDeviceID);
168 if (device && fillObject(window, device, mQbjectID, startPos))
169 return 1;
170 else
171 return 0;
172}
173
174bool MtpCursor::fillDevice(CursorWindow* window, MtpDevice* device, int row) {
175 MtpDeviceInfo* deviceInfo = device->getDeviceInfo();
176 if (!deviceInfo)
177 return false;
178 if (!prepareRow(window))
179 return false;
180
181 for (int i = 0; i < mColumnCount; i++) {
182 switch (mColumns[i]) {
183 case DEVICE_ROW_ID:
184 if (!putLong(window, device->getID(), row, i))
185 return false;
186 break;
187 case DEVICE_MANUFACTURER:
188 if (!putString(window, deviceInfo->mManufacturer, row, i))
189 return false;
190 break;
191 case DEVICE_MODEL:
192 if (!putString(window, deviceInfo->mModel, row, i))
193 return false;
194 break;
195 default:
196 LOGE("fillDevice: unknown column %d\n", mColumns[i]);
197 return false;
198 }
199 }
200
201 return true;
202}
203
204bool MtpCursor::fillStorage(CursorWindow* window, MtpDevice* device,
205 MtpStorageID storageID, int row) {
206
207LOGD("fillStorage %d\n", storageID);
208
209 MtpStorageInfo* storageInfo = device->getStorageInfo(storageID);
210 if (!storageInfo)
211 return false;
212 if (!prepareRow(window)) {
213 delete storageInfo;
214 return false;
215 }
216
217 const char* text;
218 for (int i = 0; i < mColumnCount; i++) {
219 switch (mColumns[i]) {
220 case STORAGE_ROW_ID:
221 if (!putLong(window, storageID, row, i))
222 goto fail;
223 break;
224 case STORAGE_IDENTIFIER:
225 text = storageInfo->mVolumeIdentifier;
226 if (!text || !text[0])
227 text = "Camera Storage";
228 if (!putString(window, text, row, i))
229 goto fail;
230 break;
231 case STORAGE_DESCRIPTION:
232 text = storageInfo->mStorageDescription;
233 if (!text || !text[0])
234 text = "Storage Description";
235 if (!putString(window, text, row, i))
236 goto fail;
237 break;
238 default:
239 LOGE("fillStorage: unknown column %d\n", mColumns[i]);
240 goto fail;
241 }
242 }
243
244 delete storageInfo;
245 return true;
246
247fail:
248 delete storageInfo;
249 return false;
250}
251
252bool MtpCursor::fillObject(CursorWindow* window, MtpDevice* device,
253 MtpObjectHandle objectID, int row) {
254
255LOGD("fillObject %d\n", objectID);
256
257 MtpObjectInfo* objectInfo = device->getObjectInfo(objectID);
258 if (!objectInfo)
259 return false;
260 if (!prepareRow(window)) {
261 delete objectInfo;
262 return false;
263 }
264
265 for (int i = 0; i < mColumnCount; i++) {
266 switch (mColumns[i]) {
267 case OBJECT_ROW_ID:
268 if (!putLong(window, objectID, row, i))
269 goto fail;
270 break;
271 case OBJECT_NAME:
272 if (!putString(window, objectInfo->mName, row, i))
273 goto fail;
274 break;
275 default:
276 LOGE("fillStorage: unknown column %d\n", mColumns[i]);
277 goto fail;
278 }
279 }
280
281 delete objectInfo;
282 return true;
283
284fail:
285 delete objectInfo;
286 return false;
287}
288
289bool MtpCursor::prepareRow(CursorWindow* window) {
290 if (!window->setNumColumns(mColumnCount)) {
291 LOGE("Failed to change column count from %d to %d", window->getNumColumns(), mColumnCount);
292 return false;
293 }
294 field_slot_t * fieldDir = window->allocRow();
295 if (!fieldDir) {
296 LOGE("Failed allocating fieldDir");
297 return false;
298 }
299 return true;
300}
301
302
303bool MtpCursor::putLong(CursorWindow* window, int value, int row, int column) {
304
305 if (!window->putLong(row, column, value)) {
306 window->freeLastRow();
307 LOGE("Failed allocating space for a long in column %d", column);
308 return false;
309 }
310 return true;
311}
312
313bool MtpCursor::putString(CursorWindow* window, const char* text, int row, int column) {
314 int size = strlen(text) + 1;
315 int offset = window->alloc(size);
316 if (!offset) {
317 window->freeLastRow();
318 LOGE("Failed allocating %u bytes for text/blob %s", size, text);
319 return false;
320 }
321 window->copyIn(offset, (const uint8_t*)text, size);
322
323 // This must be updated after the call to alloc(), since that
324 // may move the field around in the window
325 field_slot_t * fieldSlot = window->getFieldSlot(row, column);
326 fieldSlot->type = FIELD_TYPE_STRING;
327 fieldSlot->data.buffer.offset = offset;
328 fieldSlot->data.buffer.size = size;
329 return true;
330}
331
332} // namespace android