NBAIO.cpp revision 51d53cd993043d9286e12cba884e6ee4d10b5fac
1010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten/* 2010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Copyright (C) 2012 The Android Open Source Project 3010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 4010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * you may not use this file except in compliance with the License. 6010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * You may obtain a copy of the License at 7010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 8010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 10010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Unless required by applicable law or agreed to in writing, software 11010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * See the License for the specific language governing permissions and 14010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * limitations under the License. 15010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten */ 16010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 17010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#define LOG_TAG "NBAIO" 18010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten//#define LOG_NDEBUG 0 19010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 20010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <utils/Log.h> 212dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <media/nbaio/NBAIO.h> 22010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 23010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastennamespace android { 24010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 2572e54af9fcdc4754914fe2bf8de699523538b315Glenn Kastensize_t Format_frameSize(const NBAIO_Format& format) 26010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 27b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return Format_channelCount(format) * sizeof(short); 28010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 29010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 3072e54af9fcdc4754914fe2bf8de699523538b315Glenn Kastensize_t Format_frameBitShift(const NBAIO_Format& format) 31010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 32b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten // sizeof(short) == 2, so frame size == 1 << channels 33b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return Format_channelCount(format); 34010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 35010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 3651d53cd993043d9286e12cba884e6ee4d10b5facGlenn Kastenconst NBAIO_Format Format_Invalid = { 0 }; 3751d53cd993043d9286e12cba884e6ee4d10b5facGlenn Kasten 38b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kastenenum { 39b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_8000, 40b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_11025, 41b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_16000, 42b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_22050, 43b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_24000, 44b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_32000, 45b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_44100, 46b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_48000, 47b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_SR_Mask = 7 48b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten}; 49b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten 50b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kastenenum { 51b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_C_1 = 0x08, 52b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_C_2 = 0x10, 53b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten Format_C_Mask = 0x18 54b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten}; 55b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten 5672e54af9fcdc4754914fe2bf8de699523538b315Glenn Kastenunsigned Format_sampleRate(const NBAIO_Format& format) 57010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 58b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten if (format == Format_Invalid) { 59b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return 0; 60b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten } 61b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten switch (format & Format_SR_Mask) { 62b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case Format_SR_8000: 63b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return 8000; 64b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case Format_SR_11025: 65b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return 11025; 66b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case Format_SR_16000: 67b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return 16000; 68b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case Format_SR_22050: 69b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return 22050; 70b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case Format_SR_24000: 71b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return 24000; 72b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case Format_SR_32000: 73b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return 32000; 74b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case Format_SR_44100: 75010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return 44100; 76b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case Format_SR_48000: 77010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return 48000; 78010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten default: 79010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return 0; 80010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 81010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 82010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 8372e54af9fcdc4754914fe2bf8de699523538b315Glenn Kastenunsigned Format_channelCount(const NBAIO_Format& format) 84010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 85b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten if (format == Format_Invalid) { 86b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return 0; 87b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten } 88b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten switch (format & Format_C_Mask) { 89b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case Format_C_1: 90010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return 1; 91b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case Format_C_2: 92010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return 2; 93010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten default: 94010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return 0; 95010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 96010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 97010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 98010662326b9c43c703725f933e95e0897f8a6bddGlenn KastenNBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount) 99010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 100b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten NBAIO_Format format; 101b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten switch (sampleRate) { 102b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case 8000: 103b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten format = Format_SR_8000; 104b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten break; 105b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case 11025: 106b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten format = Format_SR_11025; 107b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten break; 108b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case 16000: 109b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten format = Format_SR_16000; 110b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten break; 111b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case 22050: 112b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten format = Format_SR_22050; 113b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten break; 114b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case 24000: 115b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten format = Format_SR_24000; 116b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten break; 117b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case 32000: 118b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten format = Format_SR_32000; 119b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten break; 120b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case 44100: 121b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten format = Format_SR_44100; 122b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten break; 123b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case 48000: 124b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten format = Format_SR_48000; 125b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten break; 126b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten default: 127b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return Format_Invalid; 128b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten } 129b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten switch (channelCount) { 130b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case 1: 131b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten format |= Format_C_1; 132b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten break; 133b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten case 2: 134b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten format |= Format_C_2; 135b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten break; 136b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten default: 137b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return Format_Invalid; 138b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten } 139b64497eb8724c4c372fffdbf3ee30543432953c5Glenn Kasten return format; 140010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 141010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 142010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten// This is a default implementation; it is expected that subclasses will optimize this. 143010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block) 144010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 145010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (!mNegotiated) { 146010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return (ssize_t) NEGOTIATE; 147010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 148010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten static const size_t maxBlock = 32; 149010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t frameSize = Format_frameSize(mFormat); 150010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 151010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten // double guarantees alignment for stack similar to what malloc() gives for heap 152010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (block == 0 || block > maxBlock) { 153010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten block = maxBlock; 154010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 155010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 156010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t accumulator = 0; 157010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten while (accumulator < total) { 158010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t count = total - accumulator; 159010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (count > block) { 160010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten count = block; 161010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 162010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ssize_t ret = via(user, buffer, count); 163010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (ret > 0) { 164010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT((size_t) ret <= count); 165010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t maxRet = ret; 166010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ret = write(buffer, maxRet); 167010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (ret > 0) { 168010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT((size_t) ret <= maxRet); 169010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten accumulator += ret; 170010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten continue; 171010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 172010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 173010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return accumulator > 0 ? accumulator : ret; 174010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 175010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return accumulator; 176010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 177010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 178010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten// This is a default implementation; it is expected that subclasses will optimize this. 1792c3b2da3049627264b7c6b449a1622f002210f03John Grossmanssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user, 1802c3b2da3049627264b7c6b449a1622f002210f03John Grossman int64_t readPTS, size_t block) 181010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 182010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (!mNegotiated) { 183010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return (ssize_t) NEGOTIATE; 184010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 185010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten static const size_t maxBlock = 32; 186010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t frameSize = Format_frameSize(mFormat); 187010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 188010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten // double guarantees alignment for stack similar to what malloc() gives for heap 189010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (block == 0 || block > maxBlock) { 190010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten block = maxBlock; 191010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 192010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 193010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t accumulator = 0; 194010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten while (accumulator < total) { 195010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t count = total - accumulator; 196010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (count > block) { 197010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten count = block; 198010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 1992c3b2da3049627264b7c6b449a1622f002210f03John Grossman ssize_t ret = read(buffer, count, readPTS); 200010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (ret > 0) { 201010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT((size_t) ret <= count); 202010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t maxRet = ret; 2032c3b2da3049627264b7c6b449a1622f002210f03John Grossman ret = via(user, buffer, maxRet, readPTS); 204010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (ret > 0) { 205010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT((size_t) ret <= maxRet); 206010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten accumulator += ret; 207010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten continue; 208010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 209010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 210010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return accumulator > 0 ? accumulator : ret; 211010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 212010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return accumulator; 213010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 214010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 215010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten// Default implementation that only accepts my mFormat 216010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers, 217010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten NBAIO_Format counterOffers[], size_t& numCounterOffers) 218010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 219010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u", 220010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten offers, numOffers, counterOffers, numCounterOffers); 221010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (mFormat != Format_Invalid) { 222010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten for (size_t i = 0; i < numOffers; ++i) { 223010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (offers[i] == mFormat) { 224010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mNegotiated = true; 225010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return i; 226010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 227010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 228010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (numCounterOffers > 0) { 229010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten counterOffers[0] = mFormat; 230010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 231010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten numCounterOffers = 1; 232010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } else { 233010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten numCounterOffers = 0; 234010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 235010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return (ssize_t) NEGOTIATE; 236010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 237010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 238010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} // namespace android 239