blob: 4356a6f48e44c313fbb03e6e742a7aa6b9e66eec [file] [log] [blame]
Mike Lockwood90f48732010-06-05 22:45: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
17#define LOG_TAG "MtpProperty"
Mike Lockwood90f48732010-06-05 22:45:01 -040018
19#include "MtpDataPacket.h"
20#include "MtpProperty.h"
21#include "MtpStringBuffer.h"
22#include "MtpUtils.h"
23
24namespace android {
25
26MtpProperty::MtpProperty()
27 : mCode(0),
28 mType(0),
29 mWriteable(false),
30 mDefaultArrayLength(0),
31 mDefaultArrayValues(NULL),
32 mCurrentArrayLength(0),
33 mCurrentArrayValues(NULL),
Mike Lockwood97c8d902010-08-09 14:49:28 -040034 mGroupCode(0),
Mike Lockwood90f48732010-06-05 22:45:01 -040035 mFormFlag(kFormNone),
36 mEnumLength(0),
37 mEnumValues(NULL)
38{
Mike Lockwooda2a21282010-09-25 21:21:05 -040039 memset(&mDefaultValue, 0, sizeof(mDefaultValue));
40 memset(&mCurrentValue, 0, sizeof(mCurrentValue));
41 memset(&mMinimumValue, 0, sizeof(mMinimumValue));
42 memset(&mMaximumValue, 0, sizeof(mMaximumValue));
Mike Lockwood90f48732010-06-05 22:45:01 -040043}
44
Mike Lockwood767c5e42010-06-30 17:00:35 -040045MtpProperty::MtpProperty(MtpPropertyCode propCode,
46 MtpDataType type,
47 bool writeable,
48 int defaultValue)
49 : mCode(propCode),
50 mType(type),
51 mWriteable(writeable),
52 mDefaultArrayLength(0),
53 mDefaultArrayValues(NULL),
54 mCurrentArrayLength(0),
55 mCurrentArrayValues(NULL),
Mike Lockwood7d7fb632010-12-01 18:46:23 -050056 mGroupCode(0),
Mike Lockwood767c5e42010-06-30 17:00:35 -040057 mFormFlag(kFormNone),
58 mEnumLength(0),
59 mEnumValues(NULL)
60{
61 memset(&mDefaultValue, 0, sizeof(mDefaultValue));
62 memset(&mCurrentValue, 0, sizeof(mCurrentValue));
63 memset(&mMinimumValue, 0, sizeof(mMinimumValue));
64 memset(&mMaximumValue, 0, sizeof(mMaximumValue));
65
66 if (defaultValue) {
67 switch (type) {
68 case MTP_TYPE_INT8:
Mike Lockwooda2a21282010-09-25 21:21:05 -040069 mDefaultValue.u.i8 = defaultValue;
Mike Lockwood767c5e42010-06-30 17:00:35 -040070 break;
71 case MTP_TYPE_UINT8:
Mike Lockwooda2a21282010-09-25 21:21:05 -040072 mDefaultValue.u.u8 = defaultValue;
Mike Lockwood767c5e42010-06-30 17:00:35 -040073 break;
74 case MTP_TYPE_INT16:
Mike Lockwooda2a21282010-09-25 21:21:05 -040075 mDefaultValue.u.i16 = defaultValue;
Mike Lockwood767c5e42010-06-30 17:00:35 -040076 break;
77 case MTP_TYPE_UINT16:
Mike Lockwooda2a21282010-09-25 21:21:05 -040078 mDefaultValue.u.u16 = defaultValue;
Mike Lockwood767c5e42010-06-30 17:00:35 -040079 break;
80 case MTP_TYPE_INT32:
Mike Lockwooda2a21282010-09-25 21:21:05 -040081 mDefaultValue.u.i32 = defaultValue;
Mike Lockwood767c5e42010-06-30 17:00:35 -040082 break;
83 case MTP_TYPE_UINT32:
Mike Lockwooda2a21282010-09-25 21:21:05 -040084 mDefaultValue.u.u32 = defaultValue;
Mike Lockwood767c5e42010-06-30 17:00:35 -040085 break;
86 case MTP_TYPE_INT64:
Mike Lockwooda2a21282010-09-25 21:21:05 -040087 mDefaultValue.u.i64 = defaultValue;
Mike Lockwood767c5e42010-06-30 17:00:35 -040088 break;
89 case MTP_TYPE_UINT64:
Mike Lockwooda2a21282010-09-25 21:21:05 -040090 mDefaultValue.u.u64 = defaultValue;
Mike Lockwood767c5e42010-06-30 17:00:35 -040091 break;
92 default:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -040093 LOGE("unknown type %04X in MtpProperty::MtpProperty", type);
Mike Lockwood767c5e42010-06-30 17:00:35 -040094 }
95 }
96}
97
Mike Lockwood90f48732010-06-05 22:45:01 -040098MtpProperty::~MtpProperty() {
99 if (mType == MTP_TYPE_STR) {
100 // free all strings
101 free(mDefaultValue.str);
102 free(mCurrentValue.str);
103 free(mMinimumValue.str);
104 free(mMaximumValue.str);
105 if (mDefaultArrayValues) {
106 for (int i = 0; i < mDefaultArrayLength; i++)
107 free(mDefaultArrayValues[i].str);
108 }
109 if (mCurrentArrayValues) {
110 for (int i = 0; i < mCurrentArrayLength; i++)
111 free(mCurrentArrayValues[i].str);
112 }
113 if (mEnumValues) {
114 for (int i = 0; i < mEnumLength; i++)
115 free(mEnumValues[i].str);
116 }
117 }
118 delete[] mDefaultArrayValues;
119 delete[] mCurrentArrayValues;
120 delete[] mEnumValues;
121}
122
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400123void MtpProperty::read(MtpDataPacket& packet) {
Mike Lockwood564ff842010-09-25 08:37:59 -0400124 bool deviceProp = isDeviceProperty();
Mike Lockwood90f48732010-06-05 22:45:01 -0400125
126 mCode = packet.getUInt16();
127 mType = packet.getUInt16();
128 mWriteable = (packet.getUInt8() == 1);
129 switch (mType) {
130 case MTP_TYPE_AINT8:
131 case MTP_TYPE_AUINT8:
132 case MTP_TYPE_AINT16:
133 case MTP_TYPE_AUINT16:
134 case MTP_TYPE_AINT32:
135 case MTP_TYPE_AUINT32:
136 case MTP_TYPE_AINT64:
137 case MTP_TYPE_AUINT64:
138 case MTP_TYPE_AINT128:
139 case MTP_TYPE_AUINT128:
140 mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength);
Mike Lockwood564ff842010-09-25 08:37:59 -0400141 if (deviceProp)
142 mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
Mike Lockwood90f48732010-06-05 22:45:01 -0400143 break;
144 default:
145 readValue(packet, mDefaultValue);
Mike Lockwood564ff842010-09-25 08:37:59 -0400146 if (deviceProp)
Mike Lockwood767c5e42010-06-30 17:00:35 -0400147 readValue(packet, mCurrentValue);
Mike Lockwood90f48732010-06-05 22:45:01 -0400148 }
Mike Lockwood564ff842010-09-25 08:37:59 -0400149 if (!deviceProp)
150 mGroupCode = packet.getUInt32();
Mike Lockwood90f48732010-06-05 22:45:01 -0400151 mFormFlag = packet.getUInt8();
152
153 if (mFormFlag == kFormRange) {
154 readValue(packet, mMinimumValue);
155 readValue(packet, mMaximumValue);
156 readValue(packet, mStepSize);
157 } else if (mFormFlag == kFormEnum) {
158 mEnumLength = packet.getUInt16();
159 mEnumValues = new MtpPropertyValue[mEnumLength];
160 for (int i = 0; i < mEnumLength; i++)
161 readValue(packet, mEnumValues[i]);
162 }
163}
164
Mike Lockwood767c5e42010-06-30 17:00:35 -0400165void MtpProperty::write(MtpDataPacket& packet) {
Mike Lockwood564ff842010-09-25 08:37:59 -0400166 bool deviceProp = isDeviceProperty();
167
Mike Lockwood767c5e42010-06-30 17:00:35 -0400168 packet.putUInt16(mCode);
169 packet.putUInt16(mType);
170 packet.putUInt8(mWriteable ? 1 : 0);
171
172 switch (mType) {
173 case MTP_TYPE_AINT8:
174 case MTP_TYPE_AUINT8:
175 case MTP_TYPE_AINT16:
176 case MTP_TYPE_AUINT16:
177 case MTP_TYPE_AINT32:
178 case MTP_TYPE_AUINT32:
179 case MTP_TYPE_AINT64:
180 case MTP_TYPE_AUINT64:
181 case MTP_TYPE_AINT128:
182 case MTP_TYPE_AUINT128:
183 writeArrayValues(packet, mDefaultArrayValues, mDefaultArrayLength);
Mike Lockwood564ff842010-09-25 08:37:59 -0400184 if (deviceProp)
185 writeArrayValues(packet, mCurrentArrayValues, mCurrentArrayLength);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400186 break;
187 default:
188 writeValue(packet, mDefaultValue);
Mike Lockwood564ff842010-09-25 08:37:59 -0400189 if (deviceProp)
190 writeValue(packet, mCurrentValue);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400191 }
Mike Lockwood97c8d902010-08-09 14:49:28 -0400192 packet.putUInt32(mGroupCode);
Mike Lockwood564ff842010-09-25 08:37:59 -0400193 if (!deviceProp)
194 packet.putUInt8(mFormFlag);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400195 if (mFormFlag == kFormRange) {
196 writeValue(packet, mMinimumValue);
197 writeValue(packet, mMaximumValue);
198 writeValue(packet, mStepSize);
199 } else if (mFormFlag == kFormEnum) {
200 packet.putUInt16(mEnumLength);
201 for (int i = 0; i < mEnumLength; i++)
202 writeValue(packet, mEnumValues[i]);
203 }
204}
205
Mike Lockwooda2a21282010-09-25 21:21:05 -0400206void MtpProperty::setDefaultValue(const uint16_t* string) {
207 free(mDefaultValue.str);
208 if (string) {
209 MtpStringBuffer buffer(string);
210 mDefaultValue.str = strdup(buffer);
211 }
212 else
213 mDefaultValue.str = NULL;
214}
215
216void MtpProperty::setCurrentValue(const uint16_t* string) {
217 free(mCurrentValue.str);
218 if (string) {
219 MtpStringBuffer buffer(string);
220 mCurrentValue.str = strdup(buffer);
221 }
222 else
223 mCurrentValue.str = NULL;
224}
225
Mike Lockwood4a65e282010-11-10 12:48:39 -0500226void MtpProperty::setFormRange(int min, int max, int step) {
227 mFormFlag = kFormRange;
228 switch (mType) {
229 case MTP_TYPE_INT8:
230 mMinimumValue.u.i8 = min;
231 mMaximumValue.u.i8 = max;
232 mStepSize.u.i8 = step;
233 break;
234 case MTP_TYPE_UINT8:
235 mMinimumValue.u.u8 = min;
236 mMaximumValue.u.u8 = max;
237 mStepSize.u.u8 = step;
238 break;
239 case MTP_TYPE_INT16:
240 mMinimumValue.u.i16 = min;
241 mMaximumValue.u.i16 = max;
242 mStepSize.u.i16 = step;
243 break;
244 case MTP_TYPE_UINT16:
245 mMinimumValue.u.u16 = min;
246 mMaximumValue.u.u16 = max;
247 mStepSize.u.u16 = step;
248 break;
249 case MTP_TYPE_INT32:
250 mMinimumValue.u.i32 = min;
251 mMaximumValue.u.i32 = max;
252 mStepSize.u.i32 = step;
253 break;
254 case MTP_TYPE_UINT32:
255 mMinimumValue.u.u32 = min;
256 mMaximumValue.u.u32 = max;
257 mStepSize.u.u32 = step;
258 break;
259 case MTP_TYPE_INT64:
260 mMinimumValue.u.i64 = min;
261 mMaximumValue.u.i64 = max;
262 mStepSize.u.i64 = step;
263 break;
264 case MTP_TYPE_UINT64:
265 mMinimumValue.u.u64 = min;
266 mMaximumValue.u.u64 = max;
267 mStepSize.u.u64 = step;
268 break;
269 default:
270 LOGE("unsupported type for MtpProperty::setRange");
271 break;
272 }
273}
274
275void MtpProperty::setFormEnum(const int* values, int count) {
276 mFormFlag = kFormEnum;
277 delete[] mEnumValues;
278 mEnumValues = new MtpPropertyValue[count];
279 mEnumLength = count;
280
281 for (int i = 0; i < count; i++) {
282 int value = *values++;
283 switch (mType) {
284 case MTP_TYPE_INT8:
285 mEnumValues[i].u.i8 = value;
286 break;
287 case MTP_TYPE_UINT8:
288 mEnumValues[i].u.u8 = value;
289 break;
290 case MTP_TYPE_INT16:
291 mEnumValues[i].u.i16 = value;
292 break;
293 case MTP_TYPE_UINT16:
294 mEnumValues[i].u.u16 = value;
295 break;
296 case MTP_TYPE_INT32:
297 mEnumValues[i].u.i32 = value;
298 break;
299 case MTP_TYPE_UINT32:
300 mEnumValues[i].u.u32 = value;
301 break;
302 case MTP_TYPE_INT64:
303 mEnumValues[i].u.i64 = value;
304 break;
305 case MTP_TYPE_UINT64:
306 mEnumValues[i].u.u64 = value;
307 break;
308 default:
309 LOGE("unsupported type for MtpProperty::setEnum");
310 break;
311 }
312 }
313}
314
Mike Lockwood5b19af02010-11-23 18:38:55 -0500315void MtpProperty::setFormDateTime() {
316 mFormFlag = kFormDateTime;
317}
318
Mike Lockwood90f48732010-06-05 22:45:01 -0400319void MtpProperty::print() {
Mike Lockwood456d8e62010-07-27 11:50:34 -0400320 LOGV("MtpProperty %04X\n", mCode);
321 LOGV(" type %04X\n", mType);
322 LOGV(" writeable %s\n", (mWriteable ? "true" : "false"));
Mike Lockwood90f48732010-06-05 22:45:01 -0400323}
324
325void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400326 MtpStringBuffer stringBuffer;
327
Mike Lockwood90f48732010-06-05 22:45:01 -0400328 switch (mType) {
329 case MTP_TYPE_INT8:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400330 case MTP_TYPE_AINT8:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400331 value.u.i8 = packet.getInt8();
Mike Lockwood90f48732010-06-05 22:45:01 -0400332 break;
333 case MTP_TYPE_UINT8:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400334 case MTP_TYPE_AUINT8:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400335 value.u.u8 = packet.getUInt8();
Mike Lockwood90f48732010-06-05 22:45:01 -0400336 break;
337 case MTP_TYPE_INT16:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400338 case MTP_TYPE_AINT16:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400339 value.u.i16 = packet.getInt16();
Mike Lockwood90f48732010-06-05 22:45:01 -0400340 break;
341 case MTP_TYPE_UINT16:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400342 case MTP_TYPE_AUINT16:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400343 value.u.u16 = packet.getUInt16();
Mike Lockwood90f48732010-06-05 22:45:01 -0400344 break;
345 case MTP_TYPE_INT32:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400346 case MTP_TYPE_AINT32:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400347 value.u.i32 = packet.getInt32();
Mike Lockwood90f48732010-06-05 22:45:01 -0400348 break;
349 case MTP_TYPE_UINT32:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400350 case MTP_TYPE_AUINT32:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400351 value.u.u32 = packet.getUInt32();
Mike Lockwood90f48732010-06-05 22:45:01 -0400352 break;
353 case MTP_TYPE_INT64:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400354 case MTP_TYPE_AINT64:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400355 value.u.i64 = packet.getInt64();
Mike Lockwood90f48732010-06-05 22:45:01 -0400356 break;
357 case MTP_TYPE_UINT64:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400358 case MTP_TYPE_AUINT64:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400359 value.u.u64 = packet.getUInt64();
Mike Lockwood90f48732010-06-05 22:45:01 -0400360 break;
361 case MTP_TYPE_INT128:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400362 case MTP_TYPE_AINT128:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400363 packet.getInt128(value.u.i128);
Mike Lockwood90f48732010-06-05 22:45:01 -0400364 break;
365 case MTP_TYPE_UINT128:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400366 case MTP_TYPE_AUINT128:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400367 packet.getUInt128(value.u.u128);
Mike Lockwood90f48732010-06-05 22:45:01 -0400368 break;
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400369 case MTP_TYPE_STR:
370 packet.getString(stringBuffer);
371 value.str = strdup(stringBuffer);
372 break;
Mike Lockwood90f48732010-06-05 22:45:01 -0400373 default:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400374 LOGE("unknown type %04X in MtpProperty::readValue", mType);
Mike Lockwood90f48732010-06-05 22:45:01 -0400375 }
376}
377
Mike Lockwood767c5e42010-06-30 17:00:35 -0400378void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400379 MtpStringBuffer stringBuffer;
380
Mike Lockwood767c5e42010-06-30 17:00:35 -0400381 switch (mType) {
382 case MTP_TYPE_INT8:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400383 case MTP_TYPE_AINT8:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400384 packet.putInt8(value.u.i8);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400385 break;
386 case MTP_TYPE_UINT8:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400387 case MTP_TYPE_AUINT8:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400388 packet.putUInt8(value.u.u8);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400389 break;
390 case MTP_TYPE_INT16:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400391 case MTP_TYPE_AINT16:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400392 packet.putInt16(value.u.i16);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400393 break;
394 case MTP_TYPE_UINT16:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400395 case MTP_TYPE_AUINT16:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400396 packet.putUInt16(value.u.u16);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400397 break;
398 case MTP_TYPE_INT32:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400399 case MTP_TYPE_AINT32:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400400 packet.putInt32(value.u.i32);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400401 break;
402 case MTP_TYPE_UINT32:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400403 case MTP_TYPE_AUINT32:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400404 packet.putUInt32(value.u.u32);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400405 break;
406 case MTP_TYPE_INT64:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400407 case MTP_TYPE_AINT64:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400408 packet.putInt64(value.u.i64);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400409 break;
410 case MTP_TYPE_UINT64:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400411 case MTP_TYPE_AUINT64:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400412 packet.putUInt64(value.u.u64);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400413 break;
414 case MTP_TYPE_INT128:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400415 case MTP_TYPE_AINT128:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400416 packet.putInt128(value.u.i128);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400417 break;
418 case MTP_TYPE_UINT128:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400419 case MTP_TYPE_AUINT128:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400420 packet.putUInt128(value.u.u128);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400421 break;
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400422 case MTP_TYPE_STR:
423 if (value.str)
424 packet.putString(value.str);
425 else
426 packet.putEmptyString();
427 break;
Mike Lockwood767c5e42010-06-30 17:00:35 -0400428 default:
Mike Lockwood9bbc2ea2010-07-20 09:47:41 -0400429 LOGE("unknown type %04X in MtpProperty::writeValue", mType);
Mike Lockwood767c5e42010-06-30 17:00:35 -0400430 }
431}
432
Mike Lockwood90f48732010-06-05 22:45:01 -0400433MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& length) {
434 length = packet.getUInt32();
435 if (length == 0)
436 return NULL;
437 MtpPropertyValue* result = new MtpPropertyValue[length];
438 for (int i = 0; i < length; i++)
439 readValue(packet, result[i]);
440 return result;
441}
442
Mike Lockwood767c5e42010-06-30 17:00:35 -0400443void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, int length) {
444 packet.putUInt32(length);
445 for (int i = 0; i < length; i++)
446 writeValue(packet, values[i]);
447}
448
Mike Lockwood90f48732010-06-05 22:45:01 -0400449} // namespace android