blob: 2ec08a903a86ed1ae569b991bcad561d3f60c1a0 [file] [log] [blame]
Igor Murashkine7ee7632013-06-11 18:10:18 -07001/*
2**
3** Copyright 2013, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18// #define LOG_NDEBUG 0
19#define LOG_TAG "ICameraDeviceUser"
20#include <utils/Log.h>
21#include <stdint.h>
22#include <sys/types.h>
23#include <binder/Parcel.h>
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070024#include <camera/camera2/ICameraDeviceUser.h>
Igor Murashkine7ee7632013-06-11 18:10:18 -070025#include <gui/IGraphicBufferProducer.h>
26#include <gui/Surface.h>
27#include <camera/CameraMetadata.h>
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070028#include <camera/camera2/CaptureRequest.h>
Yin-Chia Yehb97babb2015-03-12 13:42:44 -070029#include <camera/camera2/OutputConfiguration.h>
Igor Murashkine7ee7632013-06-11 18:10:18 -070030
31namespace android {
32
33typedef Parcel::WritableBlob WritableBlob;
34typedef Parcel::ReadableBlob ReadableBlob;
35
36enum {
37 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
38 SUBMIT_REQUEST,
Jianing Weicb0652e2014-03-12 18:29:36 -070039 SUBMIT_REQUEST_LIST,
Igor Murashkine7ee7632013-06-11 18:10:18 -070040 CANCEL_REQUEST,
Ruben Brunk29478402014-05-22 13:09:57 -070041 BEGIN_CONFIGURE,
42 END_CONFIGURE,
Igor Murashkine7ee7632013-06-11 18:10:18 -070043 DELETE_STREAM,
44 CREATE_STREAM,
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -070045 CREATE_INPUT_STREAM,
46 GET_INPUT_SURFACE,
Igor Murashkine7ee7632013-06-11 18:10:18 -070047 CREATE_DEFAULT_REQUEST,
48 GET_CAMERA_INFO,
Zhijun He2ab500c2013-07-23 08:02:53 -070049 WAIT_UNTIL_IDLE,
Ruben Brunk29478402014-05-22 13:09:57 -070050 FLUSH
Igor Murashkine7ee7632013-06-11 18:10:18 -070051};
52
Igor Murashkin88aef232013-08-23 17:47:06 -070053namespace {
54 // Read empty strings without printing a false error message.
55 String16 readMaybeEmptyString16(const Parcel& parcel) {
56 size_t len;
57 const char16_t* str = parcel.readString16Inplace(&len);
58 if (str != NULL) {
59 return String16(str, len);
60 } else {
61 return String16();
62 }
63 }
64};
65
Igor Murashkine7ee7632013-06-11 18:10:18 -070066class BpCameraDeviceUser : public BpInterface<ICameraDeviceUser>
67{
68public:
69 BpCameraDeviceUser(const sp<IBinder>& impl)
70 : BpInterface<ICameraDeviceUser>(impl)
71 {
72 }
73
74 // disconnect from camera service
75 void disconnect()
76 {
77 ALOGV("disconnect");
78 Parcel data, reply;
79 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
80 remote()->transact(DISCONNECT, data, &reply);
81 reply.readExceptionCode();
82 }
83
Jianing Weicb0652e2014-03-12 18:29:36 -070084 virtual status_t submitRequest(sp<CaptureRequest> request, bool repeating,
85 int64_t *lastFrameNumber)
Igor Murashkine7ee7632013-06-11 18:10:18 -070086 {
87 Parcel data, reply;
88 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
89
90 // arg0 = CaptureRequest
91 if (request != 0) {
92 data.writeInt32(1);
93 request->writeToParcel(&data);
94 } else {
95 data.writeInt32(0);
96 }
97
98 // arg1 = streaming (bool)
Jianing Weicb0652e2014-03-12 18:29:36 -070099 data.writeInt32(repeating);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700100
101 remote()->transact(SUBMIT_REQUEST, data, &reply);
102
103 reply.readExceptionCode();
Jianing Weicb0652e2014-03-12 18:29:36 -0700104 status_t res = reply.readInt32();
105
106 status_t resFrameNumber = BAD_VALUE;
107 if (reply.readInt32() != 0) {
108 if (lastFrameNumber != NULL) {
109 resFrameNumber = reply.readInt64(lastFrameNumber);
110 }
111 }
112
John Lin19fa0fe2015-02-02 18:10:42 +0800113 if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700114 res = FAILED_TRANSACTION;
115 }
116 return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700117 }
118
Jianing Weicb0652e2014-03-12 18:29:36 -0700119 virtual status_t submitRequestList(List<sp<CaptureRequest> > requestList, bool repeating,
120 int64_t *lastFrameNumber)
121 {
122 Parcel data, reply;
123 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
124
125 data.writeInt32(requestList.size());
126
127 for (List<sp<CaptureRequest> >::iterator it = requestList.begin();
128 it != requestList.end(); ++it) {
129 sp<CaptureRequest> request = *it;
130 if (request != 0) {
131 data.writeInt32(1);
132 if (request->writeToParcel(&data) != OK) {
133 return BAD_VALUE;
134 }
135 } else {
136 data.writeInt32(0);
137 }
138 }
139
140 data.writeInt32(repeating);
141
142 remote()->transact(SUBMIT_REQUEST_LIST, data, &reply);
143
144 reply.readExceptionCode();
145 status_t res = reply.readInt32();
146
147 status_t resFrameNumber = BAD_VALUE;
148 if (reply.readInt32() != 0) {
149 if (lastFrameNumber != NULL) {
150 resFrameNumber = reply.readInt64(lastFrameNumber);
151 }
152 }
John Lin19fa0fe2015-02-02 18:10:42 +0800153 if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
Jianing Weicb0652e2014-03-12 18:29:36 -0700154 res = FAILED_TRANSACTION;
155 }
156 return res;
157 }
158
159 virtual status_t cancelRequest(int requestId, int64_t *lastFrameNumber)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700160 {
161 Parcel data, reply;
162 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
163 data.writeInt32(requestId);
164
165 remote()->transact(CANCEL_REQUEST, data, &reply);
166
167 reply.readExceptionCode();
Jianing Weicb0652e2014-03-12 18:29:36 -0700168 status_t res = reply.readInt32();
169
170 status_t resFrameNumber = BAD_VALUE;
171 if (reply.readInt32() != 0) {
172 if (lastFrameNumber != NULL) {
John Lin19fa0fe2015-02-02 18:10:42 +0800173 resFrameNumber = reply.readInt64(lastFrameNumber);
Jianing Weicb0652e2014-03-12 18:29:36 -0700174 }
175 }
176 if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
177 res = FAILED_TRANSACTION;
178 }
179 return res;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700180 }
181
Ruben Brunk29478402014-05-22 13:09:57 -0700182 virtual status_t beginConfigure()
183 {
184 ALOGV("beginConfigure");
185 Parcel data, reply;
186 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
187 remote()->transact(BEGIN_CONFIGURE, data, &reply);
188 reply.readExceptionCode();
189 return reply.readInt32();
190 }
191
192 virtual status_t endConfigure()
193 {
194 ALOGV("endConfigure");
195 Parcel data, reply;
196 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
197 remote()->transact(END_CONFIGURE, data, &reply);
198 reply.readExceptionCode();
199 return reply.readInt32();
200 }
201
Igor Murashkine7ee7632013-06-11 18:10:18 -0700202 virtual status_t deleteStream(int streamId)
203 {
204 Parcel data, reply;
205 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
206 data.writeInt32(streamId);
207
208 remote()->transact(DELETE_STREAM, data, &reply);
209
210 reply.readExceptionCode();
211 return reply.readInt32();
212 }
213
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700214 virtual status_t createStream(const OutputConfiguration& outputConfiguration)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700215 {
216 Parcel data, reply;
217 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700218 if (outputConfiguration.getGraphicBufferProducer() != NULL) {
219 data.writeInt32(1); // marker that OutputConfiguration is not null. Mimic aidl behavior
220 outputConfiguration.writeToParcel(data);
221 } else {
222 data.writeInt32(0);
223 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700224 remote()->transact(CREATE_STREAM, data, &reply);
225
226 reply.readExceptionCode();
227 return reply.readInt32();
228 }
229
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700230 virtual status_t createInputStream(int width, int height, int format)
231 {
232 Parcel data, reply;
233 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
234 data.writeInt32(width);
235 data.writeInt32(height);
236 data.writeInt32(format);
237
238 remote()->transact(CREATE_INPUT_STREAM, data, &reply);
239
240 reply.readExceptionCode();
241 return reply.readInt32();
242 }
243
244 // get the buffer producer of the input stream
245 virtual status_t getInputBufferProducer(
246 sp<IGraphicBufferProducer> *producer) {
247 if (producer == NULL) {
248 return BAD_VALUE;
249 }
250
251 Parcel data, reply;
252 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
253
254 remote()->transact(GET_INPUT_SURFACE, data, &reply);
255
256 reply.readExceptionCode();
257 status_t result = reply.readInt32() ;
258 if (result != OK) {
259 return result;
260 }
261
262 sp<IGraphicBufferProducer> bp = NULL;
263 if (reply.readInt32() != 0) {
264 String16 name = readMaybeEmptyString16(reply);
265 bp = interface_cast<IGraphicBufferProducer>(
266 reply.readStrongBinder());
267 }
268
269 *producer = bp;
270
271 return *producer == NULL ? INVALID_OPERATION : OK;
272 }
273
Igor Murashkine7ee7632013-06-11 18:10:18 -0700274 // Create a request object from a template.
275 virtual status_t createDefaultRequest(int templateId,
276 /*out*/
277 CameraMetadata* request)
278 {
279 Parcel data, reply;
280 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
281 data.writeInt32(templateId);
282 remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
283
284 reply.readExceptionCode();
285 status_t result = reply.readInt32();
286
287 CameraMetadata out;
288 if (reply.readInt32() != 0) {
289 out.readFromParcel(&reply);
290 }
291
292 if (request != NULL) {
293 request->swap(out);
294 }
295 return result;
296 }
297
298
Igor Murashkin099b4572013-07-12 17:52:16 -0700299 virtual status_t getCameraInfo(CameraMetadata* info)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700300 {
301 Parcel data, reply;
302 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
Igor Murashkine7ee7632013-06-11 18:10:18 -0700303 remote()->transact(GET_CAMERA_INFO, data, &reply);
304
Igor Murashkine7ee7632013-06-11 18:10:18 -0700305 reply.readExceptionCode();
306 status_t result = reply.readInt32();
307
Igor Murashkin099b4572013-07-12 17:52:16 -0700308 CameraMetadata out;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700309 if (reply.readInt32() != 0) {
Igor Murashkin099b4572013-07-12 17:52:16 -0700310 out.readFromParcel(&reply);
311 }
312
313 if (info != NULL) {
314 info->swap(out);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700315 }
316
317 return result;
318 }
319
Zhijun He2ab500c2013-07-23 08:02:53 -0700320 virtual status_t waitUntilIdle()
321 {
322 ALOGV("waitUntilIdle");
323 Parcel data, reply;
324 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
325 remote()->transact(WAIT_UNTIL_IDLE, data, &reply);
326 reply.readExceptionCode();
327 return reply.readInt32();
328 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700329
Jianing Weicb0652e2014-03-12 18:29:36 -0700330 virtual status_t flush(int64_t *lastFrameNumber)
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -0700331 {
332 ALOGV("flush");
333 Parcel data, reply;
334 data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
335 remote()->transact(FLUSH, data, &reply);
336 reply.readExceptionCode();
Jianing Weicb0652e2014-03-12 18:29:36 -0700337 status_t res = reply.readInt32();
338
339 status_t resFrameNumber = BAD_VALUE;
340 if (reply.readInt32() != 0) {
341 if (lastFrameNumber != NULL) {
John Lin19fa0fe2015-02-02 18:10:42 +0800342 resFrameNumber = reply.readInt64(lastFrameNumber);
Jianing Weicb0652e2014-03-12 18:29:36 -0700343 }
344 }
345 if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
346 res = FAILED_TRANSACTION;
347 }
348 return res;
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -0700349 }
350
Igor Murashkine7ee7632013-06-11 18:10:18 -0700351private:
352
353
354};
355
356IMPLEMENT_META_INTERFACE(CameraDeviceUser,
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -0700357 "android.hardware.camera2.ICameraDeviceUser");
Igor Murashkine7ee7632013-06-11 18:10:18 -0700358
359// ----------------------------------------------------------------------
360
361status_t BnCameraDeviceUser::onTransact(
362 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
363{
364 switch(code) {
365 case DISCONNECT: {
366 ALOGV("DISCONNECT");
367 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
368 disconnect();
369 reply->writeNoException();
370 return NO_ERROR;
371 } break;
372 case SUBMIT_REQUEST: {
373 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
374
375 // arg0 = request
376 sp<CaptureRequest> request;
377 if (data.readInt32() != 0) {
378 request = new CaptureRequest();
379 request->readFromParcel(const_cast<Parcel*>(&data));
380 }
381
382 // arg1 = streaming (bool)
Jianing Weicb0652e2014-03-12 18:29:36 -0700383 bool repeating = data.readInt32();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700384
385 // return code: requestId (int32)
386 reply->writeNoException();
Jianing Weicb0652e2014-03-12 18:29:36 -0700387 int64_t lastFrameNumber = -1;
388 reply->writeInt32(submitRequest(request, repeating, &lastFrameNumber));
389 reply->writeInt32(1);
390 reply->writeInt64(lastFrameNumber);
391
392 return NO_ERROR;
393 } break;
394 case SUBMIT_REQUEST_LIST: {
395 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
396
397 List<sp<CaptureRequest> > requestList;
398 int requestListSize = data.readInt32();
399 for (int i = 0; i < requestListSize; i++) {
400 if (data.readInt32() != 0) {
401 sp<CaptureRequest> request = new CaptureRequest();
402 if (request->readFromParcel(const_cast<Parcel*>(&data)) != OK) {
403 return BAD_VALUE;
404 }
405 requestList.push_back(request);
406 } else {
407 sp<CaptureRequest> request = 0;
408 requestList.push_back(request);
409 ALOGE("A request is missing. Sending in null request.");
410 }
411 }
412
413 bool repeating = data.readInt32();
414
415 reply->writeNoException();
416 int64_t lastFrameNumber = -1;
417 reply->writeInt32(submitRequestList(requestList, repeating, &lastFrameNumber));
418 reply->writeInt32(1);
419 reply->writeInt64(lastFrameNumber);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700420
421 return NO_ERROR;
422 } break;
423 case CANCEL_REQUEST: {
424 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
425 int requestId = data.readInt32();
426 reply->writeNoException();
Jianing Weicb0652e2014-03-12 18:29:36 -0700427 int64_t lastFrameNumber = -1;
428 reply->writeInt32(cancelRequest(requestId, &lastFrameNumber));
429 reply->writeInt32(1);
430 reply->writeInt64(lastFrameNumber);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700431 return NO_ERROR;
432 } break;
433 case DELETE_STREAM: {
434 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
435 int streamId = data.readInt32();
436 reply->writeNoException();
437 reply->writeInt32(deleteStream(streamId));
438 return NO_ERROR;
439 } break;
440 case CREATE_STREAM: {
441 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700442
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700443 status_t ret = BAD_VALUE;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700444 if (data.readInt32() != 0) {
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700445 OutputConfiguration outputConfiguration(data);
446 ret = createStream(outputConfiguration);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700447 } else {
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700448 ALOGE("%s: cannot take an empty OutputConfiguration", __FUNCTION__);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700449 }
450
Igor Murashkine7ee7632013-06-11 18:10:18 -0700451 reply->writeNoException();
452 ALOGV("%s: CREATE_STREAM: write noException", __FUNCTION__);
453 reply->writeInt32(ret);
454 ALOGV("%s: CREATE_STREAM: write ret = %d", __FUNCTION__, ret);
455
456 return NO_ERROR;
457 } break;
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700458 case CREATE_INPUT_STREAM: {
459 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
460 int width, height, format;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700461
Chien-Yu Chen618ff8a2015-03-13 11:27:17 -0700462 width = data.readInt32();
463 height = data.readInt32();
464 format = data.readInt32();
465 status_t ret = createInputStream(width, height, format);
466
467 reply->writeNoException();
468 reply->writeInt32(ret);
469 return NO_ERROR;
470
471 } break;
472 case GET_INPUT_SURFACE: {
473 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
474
475 sp<IGraphicBufferProducer> bp;
476 status_t ret = getInputBufferProducer(&bp);
477 sp<IBinder> b(IInterface::asBinder(ret == OK ? bp : NULL));
478
479 reply->writeNoException();
480 reply->writeInt32(ret);
481 reply->writeInt32(1);
482 reply->writeString16(String16("camera input")); // name of surface
483 reply->writeStrongBinder(b);
484
485 return NO_ERROR;
486 } break;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700487 case CREATE_DEFAULT_REQUEST: {
488 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
489
490 int templateId = data.readInt32();
491
492 CameraMetadata request;
493 status_t ret;
494 ret = createDefaultRequest(templateId, &request);
495
496 reply->writeNoException();
497 reply->writeInt32(ret);
498
Igor Murashkin099b4572013-07-12 17:52:16 -0700499 // out-variables are after exception and return value
Igor Murashkine7ee7632013-06-11 18:10:18 -0700500 reply->writeInt32(1); // to mark presence of metadata object
501 request.writeToParcel(const_cast<Parcel*>(reply));
502
503 return NO_ERROR;
504 } break;
505 case GET_CAMERA_INFO: {
506 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
507
Igor Murashkin099b4572013-07-12 17:52:16 -0700508 CameraMetadata info;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700509 status_t ret;
Igor Murashkin099b4572013-07-12 17:52:16 -0700510 ret = getCameraInfo(&info);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700511
512 reply->writeNoException();
513 reply->writeInt32(ret);
514
Igor Murashkin099b4572013-07-12 17:52:16 -0700515 // out-variables are after exception and return value
516 reply->writeInt32(1); // to mark presence of metadata object
517 info.writeToParcel(reply);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700518
519 return NO_ERROR;
520 } break;
Zhijun He2ab500c2013-07-23 08:02:53 -0700521 case WAIT_UNTIL_IDLE: {
522 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
523 reply->writeNoException();
524 reply->writeInt32(waitUntilIdle());
525 return NO_ERROR;
526 } break;
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -0700527 case FLUSH: {
528 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
529 reply->writeNoException();
Jianing Weicb0652e2014-03-12 18:29:36 -0700530 int64_t lastFrameNumber = -1;
531 reply->writeInt32(flush(&lastFrameNumber));
532 reply->writeInt32(1);
533 reply->writeInt64(lastFrameNumber);
Eino-Ville Talvalaabaa51d2013-08-14 11:37:00 -0700534 return NO_ERROR;
535 }
Ruben Brunkb2119af2014-05-09 19:57:56 -0700536 case BEGIN_CONFIGURE: {
537 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
538 reply->writeNoException();
539 reply->writeInt32(beginConfigure());
540 return NO_ERROR;
541 } break;
542 case END_CONFIGURE: {
543 CHECK_INTERFACE(ICameraDeviceUser, data, reply);
544 reply->writeNoException();
545 reply->writeInt32(endConfigure());
546 return NO_ERROR;
547 } break;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700548 default:
549 return BBinder::onTransact(code, data, reply, flags);
550 }
551}
552
553// ----------------------------------------------------------------------------
554
555}; // namespace android