mediametadataretriever.cpp revision 89fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5
189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project/* 289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Copyright 2008, The Android Open Source Project 489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** you may not use this file except in compliance with the License. 789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** You may obtain a copy of the License at 889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** See the License for the specific language governing permissions and 1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** limitations under the License. 1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project*/ 1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//#define LOG_NDEBUG 0 1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LOG_TAG "MediaMetadataRetriever" 2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 2189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/IServiceManager.h> 2289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/IPCThreadState.h> 2389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/mediametadataretriever.h> 2489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/IMediaPlayerService.h> 2589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Log.h> 2689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <dlfcn.h> 2789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 2889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android { 2989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 3089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// client singleton for binder interface to service 3189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectMutex MediaMetadataRetriever::sServiceLock; 3289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectsp<IMediaPlayerService> MediaMetadataRetriever::sService; 3389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectsp<MediaMetadataRetriever::DeathNotifier> MediaMetadataRetriever::sDeathNotifier; 3489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 3589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectconst sp<IMediaPlayerService>& MediaMetadataRetriever::getService() 3689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 3789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project Mutex::Autolock lock(sServiceLock); 3889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (sService.get() == 0) { 3989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project sp<IServiceManager> sm = defaultServiceManager(); 4089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project sp<IBinder> binder; 4189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project do { 4289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project binder = sm->getService(String16("media.player")); 4389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (binder != 0) { 4489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project break; 4589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 4689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGW("MediaPlayerService not published, waiting..."); 4789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project usleep(500000); // 0.5 s 4889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } while(true); 4989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (sDeathNotifier == NULL) { 5089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project sDeathNotifier = new DeathNotifier(); 5189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 5289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project binder->linkToDeath(sDeathNotifier); 5389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project sService = interface_cast<IMediaPlayerService>(binder); 5489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 5589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE_IF(sService == 0, "no MediaPlayerService!?"); 5689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return sService; 5789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 5889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 5989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectMediaMetadataRetriever::MediaMetadataRetriever() 6089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 6189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGV("constructor"); 6289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project const sp<IMediaPlayerService>& service(getService()); 6389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (service == 0) { 6489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE("failed to obtain MediaMetadataRetrieverService"); 6589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return; 6689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 6789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project sp<IMediaMetadataRetriever> retriever(service->createMetadataRetriever(getpid())); 6889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (retriever == 0) { 6989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE("failed to create IMediaMetadataRetriever object from server"); 7089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 7189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mRetriever = retriever; 7289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 7389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 7489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectMediaMetadataRetriever::~MediaMetadataRetriever() 7589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 7689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGV("destructor"); 7789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project disconnect(); 7889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project IPCThreadState::self()->flushCommands(); 7989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 8089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 8189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid MediaMetadataRetriever::disconnect() 8289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 8389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGV("disconnect"); 8489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project sp<IMediaMetadataRetriever> retriever; 8589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project { 8689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project Mutex::Autolock _l(mLock); 8789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project retriever = mRetriever; 8889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mRetriever.clear(); 8989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 9089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (retriever != 0) { 9189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project retriever->disconnect(); 9289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 9389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 9489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MediaMetadataRetriever::setDataSource(const char* srcUrl) 9689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 9789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGV("setDataSource"); 9889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (mRetriever == 0) { 9989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE("retriever is not initialized"); 10089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return INVALID_OPERATION; 10189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 10289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (srcUrl == NULL) { 10389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE("data source is a null pointer"); 10489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return UNKNOWN_ERROR; 10589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 10689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGV("data source (%s)", srcUrl); 10789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return mRetriever->setDataSource(srcUrl); 10889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 10989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 11089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length) 11189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 11289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); 11389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (mRetriever == 0) { 11489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE("retriever is not initialized"); 11589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return INVALID_OPERATION; 11689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 11789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (fd < 0 || offset < 0 || length < 0) { 11889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE("Invalid negative argument"); 11989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return UNKNOWN_ERROR; 12089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 12189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return mRetriever->setDataSource(fd, offset, length); 12289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 12389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 12489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MediaMetadataRetriever::setMode(int mode) 12589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 12689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGV("setMode(%d)", mode); 12789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (mRetriever == 0) { 12889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE("retriever is not initialized"); 12989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return INVALID_OPERATION; 13089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 13189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return mRetriever->setMode(mode); 13289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 13389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 13489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t MediaMetadataRetriever::getMode(int* mode) 13589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 13689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGV("getMode"); 13789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (mRetriever == 0) { 13889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE("retriever is not initialized"); 13989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return INVALID_OPERATION; 14089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 14189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return mRetriever->getMode(mode); 14289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 14389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 14489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectsp<IMemory> MediaMetadataRetriever::captureFrame() 14589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 14689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGV("captureFrame"); 14789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (mRetriever == 0) { 14889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE("retriever is not initialized"); 14989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NULL; 15089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 15189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return mRetriever->captureFrame(); 15289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 15389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 15489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectconst char* MediaMetadataRetriever::extractMetadata(int keyCode) 15589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 15689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGV("extractMetadata(%d)", keyCode); 15789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (mRetriever == 0) { 15889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE("retriever is not initialized"); 15989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NULL; 16089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 16189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return mRetriever->extractMetadata(keyCode); 16289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 16389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 16489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectsp<IMemory> MediaMetadataRetriever::extractAlbumArt() 16589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 16689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGV("extractAlbumArt"); 16789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (mRetriever == 0) { 16889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGE("retriever is not initialized"); 16989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NULL; 17089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 17189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return mRetriever->extractAlbumArt(); 17289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 17389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 17489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid MediaMetadataRetriever::DeathNotifier::binderDied(const wp<IBinder>& who) { 17589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock); 17689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project MediaMetadataRetriever::sService.clear(); 17789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project LOGW("MediaMetadataRetriever server died!"); 17889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 17989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 18089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectMediaMetadataRetriever::DeathNotifier::~DeathNotifier() 18189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 18289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project Mutex::Autolock lock(sServiceLock); 18389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (sService != 0) { 18489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project sService->asBinder()->unlinkToDeath(this); 18589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 18689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 18789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 18889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}; // namespace android 189