audioinwrapper.cpp revision 15fc15883c8aee2b736e8cc9a31eef071908e4a0
14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*---------------------------------------------------------------------------* 24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * audioinwrapper.cpp * 34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * * 44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * Copyright 2007, 2008 Nuance Communciations, Inc. * 54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * * 64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the 'License'); * 74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * you may not use this file except in compliance with the License. * 84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * * 94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * You may obtain a copy of the License at * 104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 * 114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * * 124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software * 134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * distributed under the License is distributed on an 'AS IS' BASIS, * 144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * See the License for the specific language governing permissions and * 164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * limitations under the License. * 174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * * 184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *---------------------------------------------------------------------------*/ 194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 2115fc15883c8aee2b736e8cc9a31eef071908e4a0Sean McNeil#if defined(ANDROID) && (defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_4__)) 224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//#define USE_DEV_EAC_FILE 1 244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if defined(USE_DEV_EAC_FILE) 264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <fcntl.h> 274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define N_CHANNELS 1 284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else 294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <media/AudioRecord.h> 304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <media/AudioSystem.h> 314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectusing namespace android; 324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif 334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 3415fc15883c8aee2b736e8cc9a31eef071908e4a0Sean McNeil#endif // defined(ANDROID) && (defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_4__)) 354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "plog.h" 374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// #define SAVE_RAW_AUDIO 1 394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifdef SAVE_RAW_AUDIO 414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <sys/time.h> 424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include <stdio.h> 434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic FILE *audio_data; 464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic struct timeval buffer_save_audio; 474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif 484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectextern "C" 514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 5315fc15883c8aee2b736e8cc9a31eef071908e4a0Sean McNeil#if defined(ANDROID) && (defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_4__)) 544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if defined(USE_DEV_EAC_FILE) 564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int audiofd = -1; 574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else 584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic AudioRecord* record; 594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int sampleRate = 8000; 604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectstatic int numChannels = 1; 614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif 624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// called before AudioOpen 644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioSetInputFormat(int sample_rate, int channel_count) 654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if defined(USE_DEV_EAC_FILE) 674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return 0; 684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else 694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project sampleRate = sample_rate; 704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project numChannels = channel_count; 714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return 0; 724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif 734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioOpen(void) 764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if defined(USE_DEV_EAC_FILE) 784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project audiofd = open("/dev/eac", O_RDONLY, 0666); 794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project if (audiofd >= 0) { 804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project //fcntl(audiofd, F_SETFL, O_NONBLOCK); 814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project // possibly lame attempt to get Sooner audio input working 834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project struct { unsigned long param1, param2, param3; } params = { 11025, 0, 0 }; 844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project ioctl(audiofd, 317, ¶ms, sizeof(params)); 854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return audiofd; 884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else 894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project #ifdef SAVE_RAW_AUDIO 904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project char file_name [256]; 914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project gettimeofday ( &buffer_save_audio, NULL ); 934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project sprintf ( file_name, "data_%ld_%ld.raw", buffer_save_audio.tv_sec, buffer_save_audio.tv_usec ); 944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project audio_data = fopen ( file_name, "w" ); 954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project #endif 964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// TODO: get record buffer size from hardware. 974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project record = new android::AudioRecord( 984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project android::AudioRecord::DEFAULT_INPUT, sampleRate, 994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project android::AudioSystem::PCM_16_BIT, numChannels, 8*1024, 0); 1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project if (!record) return -1; 1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return record->start() == NO_ERROR ? 0 : -1; 1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif 1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioClose(void) 1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if defined(USE_DEV_EAC_FILE) 1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return close(audiofd); 1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else 1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project record->stop(); 1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project delete record; 1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project #ifdef SAVE_RAW_AUDIO 1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project fclose ( audio_data ); 1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project #endif 1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return 0; 1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif 1194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioRead(short *buffer, int frame_count) 1224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 1234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project int n; 1244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if defined(USE_DEV_EAC_FILE) 1254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project n = read(audiofd, buffer, frame_count*sizeof(short)*N_CHANNELS); 1264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project n /= sizeof(short)*N_CHANNELS; 1274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return n; 1284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else 1294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project int nreq = frame_count * sizeof(short); 1304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project n = record->read(buffer, nreq); 1314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project if (n > 0) { 1324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project if (n != nreq) { 1334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project PLogError ( "AudioRead error: not enough data %d vs %d\n", n, nreq ); 1344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 1354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project n /= sizeof(short); 1364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project } 1374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project #ifdef SAVE_RAW_AUDIO 1384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project if ( n > 0 ) 1394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project fwrite ( buffer, 2, n, audio_data ); 1404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project #endif 1414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return n; 1424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif 1434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioSetVolume(int stream_type, int volume) 1464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 1474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if defined(USE_DEV_EAC_FILE) 1484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return 0; 1494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else 1504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return AudioSystem::setStreamVolume(stream_type, (float)volume/100.0f); 1514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif 1524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioGetVolume(int stream_type) 1554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 1564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if defined(USE_DEV_EAC_FILE) 1574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return 0; 1584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else 1594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project float v = 0; 1604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project AudioSystem::getStreamVolume(stream_type, &v); 1614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return int(v * 100.0f); 1624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif 1634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else 1664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioOpen(void) 1684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 1694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return -1; 1704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioClose(void) 1734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 1744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return -1; 1754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioSetInputFormat(int sample_rate, int channel_count) 1784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 1794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return -1; 1804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioSetOutputFormat(int sample_rate, int channel_count) 1834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 1844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return -1; 1854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioRead(short *buffer, int frame_count) 1884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 1894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return -1; 1904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioWrite(short *buffer, int frame_count) 1934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 1944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return -1; 1954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 1964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 1974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioSetStreamType(int stream_type) 1984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 1994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return -1; 2004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 2014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 2024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioSetVolume(int stream_type, int volume) 2034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 2044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return -1; 2054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 2064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 2074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectint AudioGetVolume(int stream_type) 2084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project{ 2094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project return -1; 2104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} 2114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 2124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif 2134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project 2144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project} // extern "C" 215