19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//#define LOG_NDEBUG 0 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "AudioTrack-JNI" 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia#include "android_media_AudioTrack.h" 21071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia 22c81d31c3f801ba3d559a22c27b926ace38a7ab49Glenn Kasten#include <JNIHelp.h> 237ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi#include <JniConstants.h> 24ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h" 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 267ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi#include "ScopedBytes.h" 277ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 28c81d31c3f801ba3d559a22c27b926ace38a7ab49Glenn Kasten#include <utils/Log.h> 29c81d31c3f801ba3d559a22c27b926ace38a7ab49Glenn Kasten#include <media/AudioSystem.h> 30c81d31c3f801ba3d559a22c27b926ace38a7ab49Glenn Kasten#include <media/AudioTrack.h> 3137967d46f40c8c52c88ff8c011972a1489d465ecGlenn Kasten#include <audio_utils/primitives.h> 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 330795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian#include <binder/MemoryHeapBase.h> 340795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian#include <binder/MemoryBase.h> 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten#include "android_media_AudioFormat.h" 37bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent#include "android_media_AudioErrors.h" 382d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia#include "android_media_PlaybackParams.h" 394bcdba848449b33d7022de527c526943aff1f5fdEric Laurent#include "android_media_DeviceCallback.h" 40035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung#include "android_media_VolumeShaper.h" 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4285ea32b02a2b281ee5092ef8c31c44a0ba3452a4Ben Wagner#include <cinttypes> 4385ea32b02a2b281ee5092ef8c31c44a0ba3452a4Ben Wagner 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* const kClassPathName = "android/media/AudioTrack"; 50a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistatic const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes"; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 52a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistruct audio_track_fields_t { 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // these fields provide access from C++ to the... 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jmethodID postNativeEventInJava; //... event post callback method 5583b368505052f59616d29558e65e2250d01fd848Eric Laurent jfieldID nativeTrackInJavaObj; // stores in Java the native AudioTrack object 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID jniData; // stores in Java additional resources used by the native AudioTrack 57a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jfieldID fieldStreamType; // ... mStreamType field in the AudioTrack Java object 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 59a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistruct audio_attributes_fields_t { 60701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi jfieldID fieldUsage; // AudioAttributes.mUsage 61701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi jfieldID fieldContentType; // AudioAttributes.mContentType 62701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi jfieldID fieldFlags; // AudioAttributes.mFlags 63701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi jfieldID fieldFormattedTags;// AudioAttributes.mFormattedTags 64a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi}; 65a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistatic audio_track_fields_t javaAudioTrackFields; 66a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistatic audio_attributes_fields_t javaAudioAttrFields; 672d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jiastatic PlaybackParams::fields_t gPlaybackParamsFields; 68035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hungstatic VolumeShaperHelper::fields_t gVolumeShaperFields; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct audiotrack_callback_cookie { 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass audioTrack_class; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject audioTrack_ref; 73532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent bool busy; 74532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Condition cond; 75532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent}; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 773d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten// keep these values in sync with AudioTrack.java 783d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten#define MODE_STATIC 0 793d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten#define MODE_STREAM 1 803d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass AudioTrackJniStorage { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<MemoryHeapBase> mMemHeap; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<MemoryBase> mMemBase; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audiotrack_callback_cookie mCallbackData; 874bcdba848449b33d7022de527c526943aff1f5fdEric Laurent sp<JNIDeviceCallback> mDeviceCallback; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioTrackJniStorage() { 908a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi mCallbackData.audioTrack_class = 0; 918a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi mCallbackData.audioTrack_ref = 0; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ~AudioTrackJniStorage() { 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMemBase.clear(); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMemHeap.clear(); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool allocSharedMem(int sizeInBytes) { 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMemHeap = new MemoryHeapBase(sizeInBytes, 0, "AudioTrack Heap Base"); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMemHeap->getHeapID() < 0) { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMemBase = new MemoryBase(mMemHeap, 0, sizeInBytes); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 109532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic Mutex sLock; 110532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic SortedVector <audiotrack_callback_cookie *> sAudioTrackCallBackCookies; 111532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define DEFAULT_OUTPUT_SAMPLE_RATE 44100 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1150ca16ef3b8f42f74fdd3d32e7826f9df670bdf90Chih-Hung Hsieh#define AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM (-16) 1160ca16ef3b8f42f74fdd3d32e7826f9df670bdf90Chih-Hung Hsieh#define AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK (-17) 1170ca16ef3b8f42f74fdd3d32e7826f9df670bdf90Chih-Hung Hsieh#define AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT (-18) 1180ca16ef3b8f42f74fdd3d32e7826f9df670bdf90Chih-Hung Hsieh#define AUDIOTRACK_ERROR_SETUP_INVALIDSTREAMTYPE (-19) 1190ca16ef3b8f42f74fdd3d32e7826f9df670bdf90Chih-Hung Hsieh#define AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED (-20) 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 122e46a86fcb6a0849fc05c4cade6cb94aad0325295Glenn Kastenstatic void audioCallback(int event, void* user, void *info) { 123532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 124532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent audiotrack_callback_cookie *callbackInfo = (audiotrack_callback_cookie *)user; 125532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent { 126532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 127532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (sAudioTrackCallBackCookies.indexOf(callbackInfo) < 0) { 128532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return; 129532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 130532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent callbackInfo->busy = true; 131532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 132532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 1335b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten switch (event) { 1345b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten case AudioTrack::EVENT_MARKER: { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv *env = AndroidRuntime::getJNIEnv(); 136a667ff30e4fb6f741c2a930e7c31ef7e962d3b40Glenn Kasten if (user != NULL && env != NULL) { 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->CallStaticVoidMethod( 13818db49a46259020387c40fff36d92edc1087a366Glenn Kasten callbackInfo->audioTrack_class, 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.postNativeEventInJava, 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project callbackInfo->audioTrack_ref, event, 0,0, NULL); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1465b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten } break; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1485b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten case AudioTrack::EVENT_NEW_POS: { 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv *env = AndroidRuntime::getJNIEnv(); 150a667ff30e4fb6f741c2a930e7c31ef7e962d3b40Glenn Kasten if (user != NULL && env != NULL) { 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->CallStaticVoidMethod( 15218db49a46259020387c40fff36d92edc1087a366Glenn Kasten callbackInfo->audioTrack_class, 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.postNativeEventInJava, 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project callbackInfo->audioTrack_ref, event, 0,0, NULL); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1605b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten } break; 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1625b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten 163532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent { 164532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 165532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent callbackInfo->busy = false; 166532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent callbackInfo->cond.broadcast(); 167532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 172532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic sp<AudioTrack> getAudioTrack(JNIEnv* env, jobject thiz) 173532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent{ 174532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 175532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent AudioTrack* const at = 176075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat (AudioTrack*)env->GetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj); 177532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return sp<AudioTrack>(at); 178532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent} 179532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 180532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic sp<AudioTrack> setAudioTrack(JNIEnv* env, jobject thiz, const sp<AudioTrack>& at) 181532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent{ 182532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 183532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> old = 184075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat (AudioTrack*)env->GetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj); 185532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (at.get()) { 186b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian at->incStrong((void*)setAudioTrack); 187532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 188532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (old != 0) { 189b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian old->decStrong((void*)setAudioTrack); 190532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 191075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, (jlong)at.get()); 192532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return old; 193532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent} 194071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia 195071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia// ---------------------------------------------------------------------------- 196071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jiasp<AudioTrack> android_media_AudioTrack_getAudioTrack(JNIEnv* env, jobject audioTrackObj) { 197071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia return getAudioTrack(env, audioTrackObj); 198071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia} 199071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia 20030d794360f35592554403922bcc07835fea4737bAndy Hung// This function converts Java channel masks to a native channel mask. 20130d794360f35592554403922bcc07835fea4737bAndy Hung// validity should be checked with audio_is_output_channel(). 20230d794360f35592554403922bcc07835fea4737bAndy Hungstatic inline audio_channel_mask_t nativeChannelMaskFromJavaChannelMasks( 20330d794360f35592554403922bcc07835fea4737bAndy Hung jint channelPositionMask, jint channelIndexMask) 20430d794360f35592554403922bcc07835fea4737bAndy Hung{ 20530d794360f35592554403922bcc07835fea4737bAndy Hung if (channelIndexMask != 0) { // channel index mask takes priority 20630d794360f35592554403922bcc07835fea4737bAndy Hung // To convert to a native channel mask, the Java channel index mask 20730d794360f35592554403922bcc07835fea4737bAndy Hung // requires adding the index representation. 20830d794360f35592554403922bcc07835fea4737bAndy Hung return audio_channel_mask_from_representation_and_bits( 20930d794360f35592554403922bcc07835fea4737bAndy Hung AUDIO_CHANNEL_REPRESENTATION_INDEX, 21030d794360f35592554403922bcc07835fea4737bAndy Hung channelIndexMask); 21130d794360f35592554403922bcc07835fea4737bAndy Hung } 21230d794360f35592554403922bcc07835fea4737bAndy Hung // To convert to a native channel mask, the Java channel position mask 21330d794360f35592554403922bcc07835fea4737bAndy Hung // requires a shift by 2 to skip the two deprecated channel 21430d794360f35592554403922bcc07835fea4737bAndy Hung // configurations "default" and "mono". 21530d794360f35592554403922bcc07835fea4737bAndy Hung return (audio_channel_mask_t)(channelPositionMask >> 2); 21630d794360f35592554403922bcc07835fea4737bAndy Hung} 21730d794360f35592554403922bcc07835fea4737bAndy Hung 218532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent// ---------------------------------------------------------------------------- 219075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhatstatic jint 2209b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLeanandroid_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa, 2211cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten jintArray jSampleRate, jint channelPositionMask, jint channelIndexMask, 2229b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession, 2239b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean jlong nativeAudioTrack) { 224a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 2259b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d" 22685ea32b02a2b281ee5092ef8c31c44a0ba3452a4Ben Wagner "nativeAudioTrack=0x%" PRIX64, 2279b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes, 2289b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean nativeAudioTrack); 2291cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten 2309b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean sp<AudioTrack> lpTrack = 0; 2312fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent 2322fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent if (jSession == NULL) { 2333762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error creating AudioTrack: invalid session ID pointer"); 234bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint) AUDIO_JAVA_ERROR; 235619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent } 236619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent 2372fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent jint* nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); 2382fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent if (nSession == NULL) { 2393762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error creating AudioTrack: Error retrieving session id pointer"); 240bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint) AUDIO_JAVA_ERROR; 2412fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent } 24233b840444f5a481dd31e129079d3c0cf3acdf80eGlenn Kasten audio_session_t sessionId = (audio_session_t) nSession[0]; 2432fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); 2442fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent nSession = NULL; 2452fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent 2469b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean AudioTrackJniStorage* lpJniStorage = NULL; 24718db49a46259020387c40fff36d92edc1087a366Glenn Kasten 248a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi audio_attributes_t *paa = NULL; 24918db49a46259020387c40fff36d92edc1087a366Glenn Kasten 2509b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean jclass clazz = env->GetObjectClass(thiz); 2519b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean if (clazz == NULL) { 2529b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean ALOGE("Can't find %s when setting up callback.", kClassPathName); 2539b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED; 2549b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } 2559b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 2569b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // if we pass in an existing *Native* AudioTrack, we don't need to create/initialize one. 2579b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean if (nativeAudioTrack == 0) { 2589b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean if (jaa == 0) { 2599b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean ALOGE("Error creating AudioTrack: invalid audio attributes"); 2609b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean return (jint) AUDIO_JAVA_ERROR; 2619b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } 26218db49a46259020387c40fff36d92edc1087a366Glenn Kasten 2639b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean if (jSampleRate == 0) { 2649b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean ALOGE("Error creating AudioTrack: invalid sample rates"); 2659b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean return (jint) AUDIO_JAVA_ERROR; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26718db49a46259020387c40fff36d92edc1087a366Glenn Kasten 2689b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean int* sampleRates = env->GetIntArrayElements(jSampleRate, NULL); 2699b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean int sampleRateInHertz = sampleRates[0]; 2709b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean env->ReleaseIntArrayElements(jSampleRate, sampleRates, JNI_ABORT); 2713d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten 2729b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // Invalid channel representations are caught by !audio_is_output_channel() below. 2739b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean audio_channel_mask_t nativeChannelMask = nativeChannelMaskFromJavaChannelMasks( 2749b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean channelPositionMask, channelIndexMask); 2759b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean if (!audio_is_output_channel(nativeChannelMask)) { 2769b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean ALOGE("Error creating AudioTrack: invalid native channel mask %#x.", nativeChannelMask); 2779b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK; 2789b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2809b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean uint32_t channelCount = audio_channel_count_from_out_mask(nativeChannelMask); 2819b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 2829b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // check the format. 2839b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // This function was called from Java, so we compare the format against the Java constants 2849b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean audio_format_t format = audioFormatToNative(audioFormat); 2859b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean if (format == AUDIO_FORMAT_INVALID) { 2869b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean ALOGE("Error creating AudioTrack: unsupported audio format %d.", audioFormat); 2879b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT; 2889b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } 2899b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 2909b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // compute the frame count 2919b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean size_t frameCount; 2929b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean if (audio_is_linear_pcm(format)) { 2939b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean const size_t bytesPerSample = audio_bytes_per_sample(format); 2949b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean frameCount = buffSizeInBytes / (channelCount * bytesPerSample); 2959b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } else { 2969b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean frameCount = buffSizeInBytes; 2979b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } 2989b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 2999b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // create the native AudioTrack object 3009b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean lpTrack = new AudioTrack(); 3019b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 3029b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // read the AudioAttributes values 3039b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t)); 3049b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean const jstring jtags = 3059b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags); 3069b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean const char* tags = env->GetStringUTFChars(jtags, NULL); 3079b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it 3089b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1); 3099b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean env->ReleaseStringUTFChars(jtags, tags); 3109b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage); 3119b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean paa->content_type = 3129b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType); 3139b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags); 3149b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 3159b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean ALOGV("AudioTrack_setup for usage=%d content=%d flags=0x%#x tags=%s", 3169b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean paa->usage, paa->content_type, paa->flags, paa->tags); 3179b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 3189b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // initialize the callback information: 3199b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // this data will be passed with every AudioTrack callback 3209b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean lpJniStorage = new AudioTrackJniStorage(); 3219b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz); 3229b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // we use a weak reference so the AudioTrack object can be garbage collected. 3239b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this); 3249b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean lpJniStorage->mCallbackData.busy = false; 3259b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 3269b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // initialize the native AudioTrack object 3279b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean status_t status = NO_ERROR; 3289b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean switch (memoryMode) { 3299b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean case MODE_STREAM: 3309b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 3319b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean status = lpTrack->set( 3329b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument) 3339b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean sampleRateInHertz, 3349b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean format,// word length, PCM 3359b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean nativeChannelMask, 3369b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean frameCount, 3379b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean AUDIO_OUTPUT_FLAG_NONE, 3389b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user) 3399b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack 3409b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 0,// shared mem 3419b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean true,// thread can call Java 3429b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean sessionId,// audio session ID 3439b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean AudioTrack::TRANSFER_SYNC, 3449b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean NULL, // default offloadInfo 3459b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean -1, -1, // default uid, pid values 3469b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean paa); 3479b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean break; 3489b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 3499b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean case MODE_STATIC: 3509b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // AudioTrack is using shared memory 3519b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 3529b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) { 3539b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean ALOGE("Error creating AudioTrack in static mode: error creating mem heap base"); 3549b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean goto native_init_failure; 3559b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } 3569b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 3579b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean status = lpTrack->set( 3589b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument) 3599b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean sampleRateInHertz, 3609b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean format,// word length, PCM 3619b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean nativeChannelMask, 3629b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean frameCount, 3639b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean AUDIO_OUTPUT_FLAG_NONE, 3649b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)); 3659b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack 3669b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean lpJniStorage->mMemBase,// shared mem 3679b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean true,// thread can call Java 3689b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean sessionId,// audio session ID 3699b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean AudioTrack::TRANSFER_SHARED, 3709b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean NULL, // default offloadInfo 3719b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean -1, -1, // default uid, pid values 3729b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean paa); 3739b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean break; 3749b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 3759b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean default: 3769b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean ALOGE("Unknown mode %d", memoryMode); 3779b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean goto native_init_failure; 3789b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } 3799b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 3809b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean if (status != NO_ERROR) { 3819b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean ALOGE("Error %d initializing AudioTrack", status); 3829b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean goto native_init_failure; 3839b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } 3849b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } else { // end if (nativeAudioTrack == 0) 3859b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean lpTrack = (AudioTrack*)nativeAudioTrack; 3869b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // TODO: We need to find out which members of the Java AudioTrack might 3879b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // need to be initialized from the Native AudioTrack 3889b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // these are directly returned from getters: 3899b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // mSampleRate 3909b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // mAudioFormat 3919b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // mStreamType 3929b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // mChannelConfiguration 3939b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // mChannelCount 3949b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // mState (?) 3959b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // mPlayState (?) 3969b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // these may be used internally (Java AudioTrack.audioParamCheck(): 3979b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // mChannelMask 3989b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // mChannelIndexMask 3999b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // mDataLoadMode 4009b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 4019b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // initialize the callback information: 4029b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // this data will be passed with every AudioTrack callback 4039b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean lpJniStorage = new AudioTrackJniStorage(); 4049b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz); 4059b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // we use a weak reference so the AudioTrack object can be garbage collected. 4069b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this); 4079b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean lpJniStorage->mCallbackData.busy = false; 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4102fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); 4112fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent if (nSession == NULL) { 4123762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error creating AudioTrack: Error retrieving session id pointer"); 4132fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent goto native_init_failure; 4142fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent } 415619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent // read the audio session ID back from AudioTrack in case we create a new session 416619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent nSession[0] = lpTrack->getSessionId(); 417619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); 418619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent nSession = NULL; 419619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent 4201cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten { 4211cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten const jint elements[1] = { (jint) lpTrack->getSampleRate() }; 4221cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten env->SetIntArrayRegion(jSampleRate, 0, 1, elements); 4231cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten } 4241cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten 425532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent { // scope for the lock 426532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 427532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sAudioTrackCallBackCookies.add(&lpJniStorage->mCallbackData); 428532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 42918db49a46259020387c40fff36d92edc1087a366Glenn Kasten // save our newly created C++ AudioTrack in the "nativeTrackInJavaObj" field 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // of the Java object (in mNativeTrackInJavaObj) 431532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent setAudioTrack(env, thiz, lpTrack); 43218db49a46259020387c40fff36d92edc1087a366Glenn Kasten 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // save the JNI resources so we can free them later 434075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat //ALOGV("storing lpJniStorage: %x\n", (long)lpJniStorage); 435075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, javaAudioTrackFields.jniData, (jlong)lpJniStorage); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 437a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // since we had audio attributes, the stream type was derived from them during the 438a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // creation of the native AudioTrack: push the same value to the Java object 439a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi env->SetIntField(thiz, javaAudioTrackFields.fieldStreamType, (jint) lpTrack->streamType()); 4409b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean if (paa != NULL) { 4419b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean // audio attributes were copied in AudioTrack creation 4429b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean free(paa); 4439b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean paa = NULL; 4449b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } 445a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 446a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 447bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint) AUDIO_JAVA_SUCCESS; 44818db49a46259020387c40fff36d92edc1087a366Glenn Kasten 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // failures: 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnative_init_failure: 451a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi if (paa != NULL) { 452a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi free(paa); 453a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 454619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent if (nSession != NULL) { 455619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); 456619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent } 4578a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_class); 4588a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_ref); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete lpJniStorage; 460075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, javaAudioTrackFields.jniData, 0); 46118db49a46259020387c40fff36d92edc1087a366Glenn Kasten 46214d226a2cd7b39e17a3f0bfdab79e645f7146f53Glenn Kasten // lpTrack goes out of scope, so reference count drops to zero 463075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED; 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_start(JNIEnv *env, jobject thiz) 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 470532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 471532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for start()"); 4747070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 47621dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->start(); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_stop(JNIEnv *env, jobject thiz) 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 485532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 486532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for stop()"); 4897070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->stop(); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_pause(JNIEnv *env, jobject thiz) 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 500532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 501532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for pause()"); 5047070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->pause(); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_flush(JNIEnv *env, jobject thiz) 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 515532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 516532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for flush()"); 5197070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->flush(); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_set_volume(JNIEnv *env, jobject thiz, jfloat leftVol, jfloat rightVol ) 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 529532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 530532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setVolume()"); 5337070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->setVolume(leftVol, rightVol); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 54018db49a46259020387c40fff36d92edc1087a366Glenn Kasten 541532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent#define CALLBACK_COND_WAIT_TIMEOUT_MS 1000 542eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic void android_media_AudioTrack_release(JNIEnv *env, jobject thiz) { 543532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = setAudioTrack(env, thiz, 0); 544532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 545532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return; 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 547532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent //ALOGV("deleting lpTrack: %x\n", (int)lpTrack); 54818db49a46259020387c40fff36d92edc1087a366Glenn Kasten 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // delete the JNI data 550075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField( 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project thiz, javaAudioTrackFields.jniData); 552532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // reset the native resources in the Java object so any attempt to access 553532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // them after a call to release fails. 554075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, javaAudioTrackFields.jniData, 0); 555532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pJniStorage) { 557532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 558532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent audiotrack_callback_cookie *lpCookie = &pJniStorage->mCallbackData; 55971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block //ALOGV("deleting pJniStorage: %x\n", (int)pJniStorage); 560532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent while (lpCookie->busy) { 561532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpCookie->cond.waitRelative(sLock, 562532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) != 563532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent NO_ERROR) { 564532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent break; 565532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 566532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 567532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sAudioTrackCallBackCookies.remove(lpCookie); 568532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // delete global refs created in native_setup 569532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent env->DeleteGlobalRef(lpCookie->audioTrack_class); 570532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent env->DeleteGlobalRef(lpCookie->audioTrack_ref); 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete pJniStorage; 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 57518db49a46259020387c40fff36d92edc1087a366Glenn Kasten 576532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent// ---------------------------------------------------------------------------- 577eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic void android_media_AudioTrack_finalize(JNIEnv *env, jobject thiz) { 578eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi //ALOGV("android_media_AudioTrack_finalize jobject: %x\n", (int)thiz); 579eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi android_media_AudioTrack_release(env, thiz); 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5824aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung// overloaded JNI array helper functions (same as in android_media_AudioRecord) 5834aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline 5844aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungjbyte *envGetArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) { 5854aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return env->GetByteArrayElements(array, isCopy); 5864aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung} 5874aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung 5884aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline 5894aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungvoid envReleaseArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, jint mode) { 5904aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung env->ReleaseByteArrayElements(array, elems, mode); 5914aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung} 5924aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung 5934aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline 5944aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungjshort *envGetArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy) { 5954aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return env->GetShortArrayElements(array, isCopy); 5964aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung} 5974aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung 5984aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline 5994aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungvoid envReleaseArrayElements(JNIEnv *env, jshortArray array, jshort *elems, jint mode) { 6004aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung env->ReleaseShortArrayElements(array, elems, mode); 6014aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung} 6024aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung 6034aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline 6044aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungjfloat *envGetArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy) { 6054aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return env->GetFloatArrayElements(array, isCopy); 6064aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung} 6074aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung 6084aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline 6094aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungvoid envReleaseArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, jint mode) { 6104aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung env->ReleaseFloatArrayElements(array, elems, mode); 6114aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung} 6124aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung 613219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurentstatic inline 614219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurentjint interpretWriteSizeError(ssize_t writeSize) { 615219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent if (writeSize == WOULD_BLOCK) { 616219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent return (jint)0; 617219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent } else if (writeSize == NO_INIT) { 618219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent return AUDIO_JAVA_DEAD_OBJECT; 619219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent } else { 620219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent ALOGE("Error %zd during AudioTrack native read", writeSize); 621219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent return nativeToJavaStatus(writeSize); 622219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent } 623219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent} 624219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 6264aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungtemplate <typename T> 6274aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const T *data, 6284aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung jint offsetInSamples, jint sizeInSamples, bool blocking) { 62921dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // give the data to the native AudioTrack object (the data starts at the offset) 63021dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi ssize_t written = 0; 63121dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // regular write() or copy the data to the AudioTrack's shared memory? 6324aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung size_t sizeInBytes = sizeInSamples * sizeof(T); 633532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (track->sharedBuffer() == 0) { 6344aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung written = track->write(data + offsetInSamples, sizeInBytes, blocking); 6359b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten // for compatibility with earlier behavior of write(), return 0 in this case 6369b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten if (written == (ssize_t) WOULD_BLOCK) { 6379b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten written = 0; 6389b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten } 63921dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } else { 6402c0e17c029eccc06deb883d8d564a7e19d98f65eAndy Hung // writing to shared memory, check for capacity 6412c0e17c029eccc06deb883d8d564a7e19d98f65eAndy Hung if ((size_t)sizeInBytes > track->sharedBuffer()->size()) { 6422c0e17c029eccc06deb883d8d564a7e19d98f65eAndy Hung sizeInBytes = track->sharedBuffer()->size(); 64321dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } 6444aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung memcpy(track->sharedBuffer()->pointer(), data + offsetInSamples, sizeInBytes); 6452c0e17c029eccc06deb883d8d564a7e19d98f65eAndy Hung written = sizeInBytes; 64621dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } 647219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent if (written >= 0) { 6484aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return written / sizeof(T); 6494aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung } 650219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent return interpretWriteSizeError(written); 65121dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi} 65221dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi 65321dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi// ---------------------------------------------------------------------------- 6544aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungtemplate <typename T> 6554aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic jint android_media_AudioTrack_writeArray(JNIEnv *env, jobject thiz, 6564aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung T javaAudioData, 6574aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung jint offsetInSamples, jint sizeInSamples, 6584aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung jint javaAudioFormat, 6594aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung jboolean isWriteBlocking) { 6604aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung //ALOGV("android_media_AudioTrack_writeArray(offset=%d, sizeInSamples=%d) called", 6614aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung // offsetInSamples, sizeInSamples); 662532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lpTrack == NULL) { 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for write()"); 6664aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return (jint)AUDIO_JAVA_INVALID_OPERATION; 6674aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung } 6684aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung 6694aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung if (javaAudioData == NULL) { 6704aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung ALOGE("NULL java array of audio data to play"); 6714aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return (jint)AUDIO_JAVA_BAD_VALUE; 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 674421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such 675421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // a way that it becomes much more efficient. When doing so, we will have to prevent the 676421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // AudioSystem callback to be called while in critical section (in case of media server 677421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // process crash for instance) 6784aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung 6794aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung // get the pointer for the audio data from the java array 6804aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung auto cAudioData = envGetArrayElements(env, javaAudioData, NULL); 6814aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung if (cAudioData == NULL) { 6824aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung ALOGE("Error retrieving source of audio data to play"); 6834aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return (jint)AUDIO_JAVA_BAD_VALUE; // out of memory or no data to load 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6864aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung jint samplesWritten = writeToTrack(lpTrack, javaAudioFormat, cAudioData, 6874aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung offsetInSamples, sizeInSamples, isWriteBlocking == JNI_TRUE /* blocking */); 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6894aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung envReleaseArrayElements(env, javaAudioData, cAudioData, 0); 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6914aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung //ALOGV("write wrote %d (tried %d) samples in the native AudioTrack with offset %d", 6924aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung // (int)samplesWritten, (int)(sizeInSamples), (int)offsetInSamples); 6934aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return samplesWritten; 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 6977ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivistatic jint android_media_AudioTrack_write_native_bytes(JNIEnv *env, jobject thiz, 6985d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi jbyteArray javaBytes, jint byteOffset, jint sizeInBytes, 6997ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jint javaAudioFormat, jboolean isWriteBlocking) { 7007ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi //ALOGV("android_media_AudioTrack_write_native_bytes(offset=%d, sizeInBytes=%d) called", 7017ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi // offsetInBytes, sizeInBytes); 7027ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 7037ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi if (lpTrack == NULL) { 7047ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jniThrowException(env, "java/lang/IllegalStateException", 7057ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi "Unable to retrieve AudioTrack pointer for write()"); 7064aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return (jint)AUDIO_JAVA_INVALID_OPERATION; 7077ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 7087ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 7097ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi ScopedBytesRO bytes(env, javaBytes); 7107ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi if (bytes.get() == NULL) { 7117ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi ALOGE("Error retrieving source of audio data to play, can't play"); 712bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_BAD_VALUE; 7137ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 7147ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 7155d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi jint written = writeToTrack(lpTrack, javaAudioFormat, bytes.get(), byteOffset, 7167ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi sizeInBytes, isWriteBlocking == JNI_TRUE /* blocking */); 7177ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 7187ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi return written; 7197ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi} 7207ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 7217ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi// ---------------------------------------------------------------------------- 72210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burkstatic jint android_media_AudioTrack_get_buffer_size_frames(JNIEnv *env, jobject thiz) { 723532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 724532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 72610a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk "Unable to retrieve AudioTrack pointer for getBufferSizeInFrames()"); 727adfb7f62dda47100e1023503d3492e4894f832faPhil Burk return (jint)AUDIO_JAVA_ERROR; 728adfb7f62dda47100e1023503d3492e4894f832faPhil Burk } 729adfb7f62dda47100e1023503d3492e4894f832faPhil Burk 73010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk ssize_t result = lpTrack->getBufferSizeInFrames(); 73110a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk if (result < 0) { 73285ea32b02a2b281ee5092ef8c31c44a0ba3452a4Ben Wagner jniThrowExceptionFmt(env, "java/lang/IllegalStateException", 73385ea32b02a2b281ee5092ef8c31c44a0ba3452a4Ben Wagner "Internal error detected in getBufferSizeInFrames() = %zd", result); 73410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return (jint)AUDIO_JAVA_ERROR; 73510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk } 73610a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return (jint)result; 737adfb7f62dda47100e1023503d3492e4894f832faPhil Burk} 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 73910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk// ---------------------------------------------------------------------------- 74010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burkstatic jint android_media_AudioTrack_set_buffer_size_frames(JNIEnv *env, 74110a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk jobject thiz, jint bufferSizeInFrames) { 74210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 74310a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk if (lpTrack == NULL) { 74410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk jniThrowException(env, "java/lang/IllegalStateException", 74510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk "Unable to retrieve AudioTrack pointer for setBufferSizeInFrames()"); 74610a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return (jint)AUDIO_JAVA_ERROR; 74710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk } 74810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk // Value will be coerced into the valid range. 74910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk // But internal values are unsigned, size_t, so we need to clip 75010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk // against zero here where it is signed. 75110a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk if (bufferSizeInFrames < 0) { 75210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk bufferSizeInFrames = 0; 75310a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk } 75410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk ssize_t result = lpTrack->setBufferSizeInFrames(bufferSizeInFrames); 75510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk if (result < 0) { 75685ea32b02a2b281ee5092ef8c31c44a0ba3452a4Ben Wagner jniThrowExceptionFmt(env, "java/lang/IllegalStateException", 75785ea32b02a2b281ee5092ef8c31c44a0ba3452a4Ben Wagner "Internal error detected in setBufferSizeInFrames() = %zd", result); 75810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return (jint)AUDIO_JAVA_ERROR; 75910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk } 76010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return (jint)result; 76110a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk} 76210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk 76310a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk// ---------------------------------------------------------------------------- 76410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burkstatic jint android_media_AudioTrack_get_buffer_capacity_frames(JNIEnv *env, jobject thiz) { 76510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 76610a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk if (lpTrack == NULL) { 76710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk jniThrowException(env, "java/lang/IllegalStateException", 76810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk "Unable to retrieve AudioTrack pointer for getBufferCapacityInFrames()"); 76910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return (jint)AUDIO_JAVA_ERROR; 77010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk } 77110a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk 77210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return lpTrack->frameCount(); 77310a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk} 77477e01bd3ad92eb2290e942a58042e08683b5acafPhil Burk 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 77688e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurentstatic jint android_media_AudioTrack_set_playback_rate(JNIEnv *env, jobject thiz, 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint sampleRateInHz) { 778532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 779532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setSampleRate()"); 782bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 784bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus(lpTrack->setSampleRate(sampleRateInHz)); 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_playback_rate(JNIEnv *env, jobject thiz) { 790532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 791532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getSampleRate()"); 794bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 796532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint) lpTrack->getSampleRate(); 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 8012d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jiastatic void android_media_AudioTrack_set_playback_params(JNIEnv *env, jobject thiz, 8022d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia jobject params) { 803263b4c97823295c41900210515d0c769a236190cAndy Hung sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 804263b4c97823295c41900210515d0c769a236190cAndy Hung if (lpTrack == NULL) { 805263b4c97823295c41900210515d0c769a236190cAndy Hung jniThrowException(env, "java/lang/IllegalStateException", 806263b4c97823295c41900210515d0c769a236190cAndy Hung "AudioTrack not initialized"); 807263b4c97823295c41900210515d0c769a236190cAndy Hung return; 808263b4c97823295c41900210515d0c769a236190cAndy Hung } 809263b4c97823295c41900210515d0c769a236190cAndy Hung 810973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung PlaybackParams pbp; 811973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung pbp.fillFromJobject(env, gPlaybackParamsFields, params); 812fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung 8132d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia ALOGV("setPlaybackParams: %d:%f %d:%f %d:%u %d:%u", 814973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung pbp.speedSet, pbp.audioRate.mSpeed, 815973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung pbp.pitchSet, pbp.audioRate.mPitch, 816973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung pbp.audioFallbackModeSet, pbp.audioRate.mFallbackMode, 817973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung pbp.audioStretchModeSet, pbp.audioRate.mStretchMode); 818973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung 819973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung // to simulate partially set params, we do a read-modify-write. 820973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung // TODO: pass in the valid set mask into AudioTrack. 821973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung AudioPlaybackRate rate = lpTrack->getPlaybackRate(); 822973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung bool updatedRate = false; 823973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung if (pbp.speedSet) { 824973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung rate.mSpeed = pbp.audioRate.mSpeed; 825973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung updatedRate = true; 826973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung } 827973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung if (pbp.pitchSet) { 828973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung rate.mPitch = pbp.audioRate.mPitch; 829973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung updatedRate = true; 830973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung } 831973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung if (pbp.audioFallbackModeSet) { 832973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung rate.mFallbackMode = pbp.audioRate.mFallbackMode; 833973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung updatedRate = true; 834973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung } 835973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung if (pbp.audioStretchModeSet) { 836973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung rate.mStretchMode = pbp.audioRate.mStretchMode; 837973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung updatedRate = true; 838973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung } 839973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung if (updatedRate) { 840973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung if (lpTrack->setPlaybackRate(rate) != OK) { 841973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung jniThrowException(env, "java/lang/IllegalArgumentException", 842973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung "arguments out of range"); 843973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung } 844263b4c97823295c41900210515d0c769a236190cAndy Hung } 845263b4c97823295c41900210515d0c769a236190cAndy Hung} 846263b4c97823295c41900210515d0c769a236190cAndy Hung 847263b4c97823295c41900210515d0c769a236190cAndy Hung 848263b4c97823295c41900210515d0c769a236190cAndy Hung// ---------------------------------------------------------------------------- 8492d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jiastatic jobject android_media_AudioTrack_get_playback_params(JNIEnv *env, jobject thiz, 8502d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia jobject params) { 851263b4c97823295c41900210515d0c769a236190cAndy Hung sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 852263b4c97823295c41900210515d0c769a236190cAndy Hung if (lpTrack == NULL) { 853263b4c97823295c41900210515d0c769a236190cAndy Hung jniThrowException(env, "java/lang/IllegalStateException", 854263b4c97823295c41900210515d0c769a236190cAndy Hung "AudioTrack not initialized"); 855fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung return NULL; 856263b4c97823295c41900210515d0c769a236190cAndy Hung } 857263b4c97823295c41900210515d0c769a236190cAndy Hung 8582d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia PlaybackParams pbs; 859fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung pbs.audioRate = lpTrack->getPlaybackRate(); 860fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung pbs.speedSet = true; 861fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung pbs.pitchSet = true; 862fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung pbs.audioFallbackModeSet = true; 863fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung pbs.audioStretchModeSet = true; 8642d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia return pbs.asJobject(env, gPlaybackParamsFields); 865263b4c97823295c41900210515d0c769a236190cAndy Hung} 866263b4c97823295c41900210515d0c769a236190cAndy Hung 867263b4c97823295c41900210515d0c769a236190cAndy Hung 868263b4c97823295c41900210515d0c769a236190cAndy Hung// ---------------------------------------------------------------------------- 86918db49a46259020387c40fff36d92edc1087a366Glenn Kastenstatic jint android_media_AudioTrack_set_marker_pos(JNIEnv *env, jobject thiz, 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint markerPos) { 871532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 872532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setMarkerPosition()"); 875bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 877bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setMarkerPosition(markerPos) ); 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_marker_pos(JNIEnv *env, jobject thiz) { 883532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t markerPos = 0; 88518db49a46259020387c40fff36d92edc1087a366Glenn Kasten 886532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getMarkerPosition()"); 889bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 891532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpTrack->getMarkerPosition(&markerPos); 892532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint)markerPos; 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_set_pos_update_period(JNIEnv *env, jobject thiz, 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint period) { 899532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 900532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setPositionUpdatePeriod()"); 903bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 90418db49a46259020387c40fff36d92edc1087a366Glenn Kasten } 905bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setPositionUpdatePeriod(period) ); 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_pos_update_period(JNIEnv *env, jobject thiz) { 911532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t period = 0; 91318db49a46259020387c40fff36d92edc1087a366Glenn Kasten 914532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getPositionUpdatePeriod()"); 917bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 919532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpTrack->getPositionUpdatePeriod(&period); 920532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint)period; 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 92518db49a46259020387c40fff36d92edc1087a366Glenn Kastenstatic jint android_media_AudioTrack_set_position(JNIEnv *env, jobject thiz, 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint position) { 927532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 928532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setPosition()"); 931bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 933bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setPosition(position) ); 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_position(JNIEnv *env, jobject thiz) { 939532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t position = 0; 94118db49a46259020387c40fff36d92edc1087a366Glenn Kasten 942532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getPosition()"); 945bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 947532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpTrack->getPosition(&position); 948532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint)position; 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 95361dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodmanstatic jint android_media_AudioTrack_get_latency(JNIEnv *env, jobject thiz) { 95461dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 95561dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman 95661dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman if (lpTrack == NULL) { 95761dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman jniThrowException(env, "java/lang/IllegalStateException", 95861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman "Unable to retrieve AudioTrack pointer for latency()"); 959bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 96061dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman } 96161dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman return (jint)lpTrack->latency(); 96261dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman} 96361dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman 96403f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk// ---------------------------------------------------------------------------- 96503f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burkstatic jint android_media_AudioTrack_get_underrun_count(JNIEnv *env, jobject thiz) { 96603f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 96703f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk 96803f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk if (lpTrack == NULL) { 96903f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk jniThrowException(env, "java/lang/IllegalStateException", 97003f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk "Unable to retrieve AudioTrack pointer for getUnderrunCount()"); 97103f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk return (jint)AUDIO_JAVA_ERROR; 97203f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk } 97303f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk return (jint)lpTrack->getUnderrunCount(); 97403f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk} 97561dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman 97661dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman// ---------------------------------------------------------------------------- 977ebc2c14b0777042f2325d437078b0e7815129b75Andy Hungstatic jint android_media_AudioTrack_get_flags(JNIEnv *env, jobject thiz) { 978ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 979ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung 980ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung if (lpTrack == NULL) { 981ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung jniThrowException(env, "java/lang/IllegalStateException", 982ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung "Unable to retrieve AudioTrack pointer for getFlags()"); 983ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung return (jint)AUDIO_JAVA_ERROR; 984ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung } 985ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung return (jint)lpTrack->getFlags(); 986ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung} 987ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung 988ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung// ---------------------------------------------------------------------------- 989948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kastenstatic jint android_media_AudioTrack_get_timestamp(JNIEnv *env, jobject thiz, jlongArray jTimestamp) { 990948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 991948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 992948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten if (lpTrack == NULL) { 993948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten ALOGE("Unable to retrieve AudioTrack pointer for getTimestamp()"); 994bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 995948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten } 996948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten AudioTimestamp timestamp; 997948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten status_t status = lpTrack->getTimestamp(timestamp); 998948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten if (status == OK) { 999948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten jlong* nTimestamp = (jlong *) env->GetPrimitiveArrayCritical(jTimestamp, NULL); 1000948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten if (nTimestamp == NULL) { 1001948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten ALOGE("Unable to get array for getTimestamp()"); 1002bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 1003948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten } 1004948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten nTimestamp[0] = (jlong) timestamp.mPosition; 1005948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten nTimestamp[1] = (jlong) ((timestamp.mTime.tv_sec * 1000000000LL) + timestamp.mTime.tv_nsec); 1006948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten env->ReleasePrimitiveArrayCritical(jTimestamp, nTimestamp, 0); 1007948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten } 1008bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint) nativeToJavaStatus(status); 1009948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten} 1010948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 1011948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 1012948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten// ---------------------------------------------------------------------------- 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_set_loop(JNIEnv *env, jobject thiz, 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint loopStart, jint loopEnd, jint loopCount) { 1015532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 1016532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setLoop()"); 1019bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1021bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setLoop(loopStart, loopEnd, loopCount) ); 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_reload(JNIEnv *env, jobject thiz) { 1027532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 1028532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for reload()"); 1031bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1033bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->reload() ); 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_output_sample_rate(JNIEnv *env, jobject thiz, 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint javaStreamType) { 104085fbc871ded0f71f9638f85e7d2f03a35bf39ddaGlenn Kasten uint32_t afSamplingRate; 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // convert the stream type from Java to native value 1042eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi // FIXME: code duplication with android_media_AudioTrack_setup() 104324fc2fb1c541e954b83fd31ea9f786a5e9b45501Dima Zavin audio_stream_type_t nativeStreamType; 104429a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten switch (javaStreamType) { 104529a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_VOICE_CALL: 104629a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_SYSTEM: 104729a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_RING: 104829a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_MUSIC: 104929a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_ALARM: 105029a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_NOTIFICATION: 105129a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_BLUETOOTH_SCO: 105229a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_DTMF: 105329a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten nativeStreamType = (audio_stream_type_t) javaStreamType; 105429a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten break; 105529a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten default: 105624fc2fb1c541e954b83fd31ea9f786a5e9b45501Dima Zavin nativeStreamType = AUDIO_STREAM_DEFAULT; 105729a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten break; 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10608f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten status_t status = AudioSystem::getOutputSamplingRate(&afSamplingRate, nativeStreamType); 10618f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten if (status != NO_ERROR) { 10628f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten ALOGE("Error %d in AudioSystem::getOutputSamplingRate() for stream type %d " 10638f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten "in AudioTrack JNI", status, nativeStreamType); 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return DEFAULT_OUTPUT_SAMPLE_RATE; 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return afSamplingRate; 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// returns the minimum required size for the successful creation of a streaming AudioTrack 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// returns -1 if there was an error querying the hardware. 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thiz, 10755b8fd44365f03601aaba41879ac18e70ce814a0fGlenn Kasten jint sampleRateInHertz, jint channelCount, jint audioFormat) { 1076c3308074cd6f06bbb35c1999b5260f938742a9e7Chia-chi Yeh 1077659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten size_t frameCount; 1078659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten const status_t status = AudioTrack::getMinFrameCount(&frameCount, AUDIO_STREAM_DEFAULT, 1079659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten sampleRateInHertz); 1080659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten if (status != NO_ERROR) { 1081659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten ALOGE("AudioTrack::getMinFrameCount() for sample rate %d failed with status %d", 1082659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten sampleRateInHertz, status); 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1085fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten const audio_format_t format = audioFormatToNative(audioFormat); 108643f4b276a56e6fb5a3c9637c0e3a6865657e3be7Phil Burk if (audio_has_proportional_frames(format)) { 1087ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent const size_t bytesPerSample = audio_bytes_per_sample(format); 1088ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent return frameCount * channelCount * bytesPerSample; 1089ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent } else { 1090ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent return frameCount; 1091ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent } 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10947070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent// ---------------------------------------------------------------------------- 10953009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kastenstatic jint 10967070b36549d511d6627538c73dfbab23fbae5b43Eric Laurentandroid_media_AudioTrack_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level ) 10977070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent{ 1098532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 10997070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent if (lpTrack == NULL ) { 11007070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent jniThrowException(env, "java/lang/IllegalStateException", 11017070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent "Unable to retrieve AudioTrack pointer for setAuxEffectSendLevel()"); 11023009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten return -1; 11037070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent } 11047070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent 11053009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten status_t status = lpTrack->setAuxEffectSendLevel(level); 11063009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten if (status != NO_ERROR) { 11073009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten ALOGE("AudioTrack::setAuxEffectSendLevel() for level %g failed with status %d", 11083009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten level, status); 11093009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten } 11103009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten return (jint) status; 11117070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent} 11127070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent 11137070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent// ---------------------------------------------------------------------------- 11147070b36549d511d6627538c73dfbab23fbae5b43Eric Laurentstatic jint android_media_AudioTrack_attachAuxEffect(JNIEnv *env, jobject thiz, 11157070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent jint effectId) { 1116532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 1117532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 11187070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent jniThrowException(env, "java/lang/IllegalStateException", 11197070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent "Unable to retrieve AudioTrack pointer for attachAuxEffect()"); 1120bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 11217070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent } 1122bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->attachAuxEffect(effectId) ); 11237070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent} 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 112588e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLeanstatic jboolean android_media_AudioTrack_setOutputDevice( 112688e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean JNIEnv *env, jobject thiz, jint device_id) { 112788e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean 112888e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 1129cef696e8b464e6479ed352b3b490e41ee677bd91Paul McLean if (lpTrack == 0) { 1130cef696e8b464e6479ed352b3b490e41ee677bd91Paul McLean return false; 1131cef696e8b464e6479ed352b3b490e41ee677bd91Paul McLean } 113288e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean return lpTrack->setOutputDevice(device_id) == NO_ERROR; 113388e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean} 113488e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean 11354bcdba848449b33d7022de527c526943aff1f5fdEric Laurentstatic jint android_media_AudioTrack_getRoutedDeviceId( 11364bcdba848449b33d7022de527c526943aff1f5fdEric Laurent JNIEnv *env, jobject thiz) { 11374bcdba848449b33d7022de527c526943aff1f5fdEric Laurent 11384bcdba848449b33d7022de527c526943aff1f5fdEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 11394bcdba848449b33d7022de527c526943aff1f5fdEric Laurent if (lpTrack == NULL) { 11404bcdba848449b33d7022de527c526943aff1f5fdEric Laurent return 0; 11414bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 11424bcdba848449b33d7022de527c526943aff1f5fdEric Laurent return (jint)lpTrack->getRoutedDeviceId(); 11434bcdba848449b33d7022de527c526943aff1f5fdEric Laurent} 11444bcdba848449b33d7022de527c526943aff1f5fdEric Laurent 11454bcdba848449b33d7022de527c526943aff1f5fdEric Laurentstatic void android_media_AudioTrack_enableDeviceCallback( 11464bcdba848449b33d7022de527c526943aff1f5fdEric Laurent JNIEnv *env, jobject thiz) { 11474bcdba848449b33d7022de527c526943aff1f5fdEric Laurent 11484bcdba848449b33d7022de527c526943aff1f5fdEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 11494bcdba848449b33d7022de527c526943aff1f5fdEric Laurent if (lpTrack == NULL) { 11504bcdba848449b33d7022de527c526943aff1f5fdEric Laurent return; 11514bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 11524bcdba848449b33d7022de527c526943aff1f5fdEric Laurent AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField( 11534bcdba848449b33d7022de527c526943aff1f5fdEric Laurent thiz, javaAudioTrackFields.jniData); 11544bcdba848449b33d7022de527c526943aff1f5fdEric Laurent if (pJniStorage == NULL || pJniStorage->mDeviceCallback != 0) { 11554bcdba848449b33d7022de527c526943aff1f5fdEric Laurent return; 11564bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 11574bcdba848449b33d7022de527c526943aff1f5fdEric Laurent pJniStorage->mDeviceCallback = 11584bcdba848449b33d7022de527c526943aff1f5fdEric Laurent new JNIDeviceCallback(env, thiz, pJniStorage->mCallbackData.audioTrack_ref, 11594bcdba848449b33d7022de527c526943aff1f5fdEric Laurent javaAudioTrackFields.postNativeEventInJava); 11604bcdba848449b33d7022de527c526943aff1f5fdEric Laurent lpTrack->addAudioDeviceCallback(pJniStorage->mDeviceCallback); 11614bcdba848449b33d7022de527c526943aff1f5fdEric Laurent} 11624bcdba848449b33d7022de527c526943aff1f5fdEric Laurent 11634bcdba848449b33d7022de527c526943aff1f5fdEric Laurentstatic void android_media_AudioTrack_disableDeviceCallback( 11644bcdba848449b33d7022de527c526943aff1f5fdEric Laurent JNIEnv *env, jobject thiz) { 11654bcdba848449b33d7022de527c526943aff1f5fdEric Laurent 11664bcdba848449b33d7022de527c526943aff1f5fdEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 11674bcdba848449b33d7022de527c526943aff1f5fdEric Laurent if (lpTrack == NULL) { 11684bcdba848449b33d7022de527c526943aff1f5fdEric Laurent return; 11694bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 11704bcdba848449b33d7022de527c526943aff1f5fdEric Laurent AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField( 11714bcdba848449b33d7022de527c526943aff1f5fdEric Laurent thiz, javaAudioTrackFields.jniData); 11724bcdba848449b33d7022de527c526943aff1f5fdEric Laurent if (pJniStorage == NULL || pJniStorage->mDeviceCallback == 0) { 11734bcdba848449b33d7022de527c526943aff1f5fdEric Laurent return; 11744bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 11754bcdba848449b33d7022de527c526943aff1f5fdEric Laurent lpTrack->removeAudioDeviceCallback(pJniStorage->mDeviceCallback); 11764bcdba848449b33d7022de527c526943aff1f5fdEric Laurent pJniStorage->mDeviceCallback.clear(); 11774bcdba848449b33d7022de527c526943aff1f5fdEric Laurent} 11784bcdba848449b33d7022de527c526943aff1f5fdEric Laurent 1179bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kastenstatic jint android_media_AudioTrack_get_FCC_8(JNIEnv *env, jobject thiz) { 1180bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kasten return FCC_8; 1181bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kasten} 1182bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kasten 1183035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung// Pass through the arguments to the AudioFlinger track implementation. 1184035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hungstatic jint android_media_AudioTrack_apply_volume_shaper(JNIEnv *env, jobject thiz, 1185035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung jobject jconfig, jobject joperation) { 1186035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung // NOTE: hard code here to prevent platform issues. Must match VolumeShaper.java 1187035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung const int VOLUME_SHAPER_INVALID_OPERATION = -38; 1188035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung 1189035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 1190035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung if (lpTrack == nullptr) { 1191035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung return (jint)VOLUME_SHAPER_INVALID_OPERATION; 1192035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung } 1193035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung 1194035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung sp<VolumeShaper::Configuration> configuration; 1195035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung sp<VolumeShaper::Operation> operation; 1196035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung if (jconfig != nullptr) { 1197035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung configuration = VolumeShaperHelper::convertJobjectToConfiguration( 1198035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung env, gVolumeShaperFields, jconfig); 1199035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung ALOGV("applyVolumeShaper configuration: %s", configuration->toString().c_str()); 1200035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung } 1201035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung if (joperation != nullptr) { 1202035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung operation = VolumeShaperHelper::convertJobjectToOperation( 1203035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung env, gVolumeShaperFields, joperation); 1204035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung ALOGV("applyVolumeShaper operation: %s", operation->toString().c_str()); 1205035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung } 1206035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung VolumeShaper::Status status = lpTrack->applyVolumeShaper(configuration, operation); 1207035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung if (status == INVALID_OPERATION) { 1208035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung status = VOLUME_SHAPER_INVALID_OPERATION; 1209035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung } 1210035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung return (jint)status; // if status < 0 an error, else a VolumeShaper id 1211035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung} 1212035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung 1213035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung// Pass through the arguments to the AudioFlinger track implementation. 1214035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hungstatic jobject android_media_AudioTrack_get_volume_shaper_state(JNIEnv *env, jobject thiz, 1215035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung jint id) { 1216035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 1217035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung if (lpTrack == nullptr) { 1218035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung return (jobject)nullptr; 1219035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung } 1220035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung 1221035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung sp<VolumeShaper::State> state = lpTrack->getVolumeShaperState((int)id); 1222035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung if (state.get() == nullptr) { 1223035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung return (jobject)nullptr; 1224035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung } 1225035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung return VolumeShaperHelper::convertStateToJobject(env, gVolumeShaperFields, state); 1226035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung} 12274bcdba848449b33d7022de527c526943aff1f5fdEric Laurent 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 123076f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = { 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // name, signature, funcPtr 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_start", "()V", (void *)android_media_AudioTrack_start}, 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_stop", "()V", (void *)android_media_AudioTrack_stop}, 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_pause", "()V", (void *)android_media_AudioTrack_pause}, 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_flush", "()V", (void *)android_media_AudioTrack_flush}, 12369b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJ)I", 1237eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi (void *)android_media_AudioTrack_setup}, 1238eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi {"native_finalize", "()V", (void *)android_media_AudioTrack_finalize}, 1239eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi {"native_release", "()V", (void *)android_media_AudioTrack_release}, 12404aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung {"native_write_byte", "([BIIIZ)I",(void *)android_media_AudioTrack_writeArray<jbyteArray>}, 12417ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi {"native_write_native_bytes", 12425d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi "(Ljava/lang/Object;IIIZ)I", 12437ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi (void *)android_media_AudioTrack_write_native_bytes}, 12444aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung {"native_write_short", "([SIIIZ)I",(void *)android_media_AudioTrack_writeArray<jshortArray>}, 12454aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung {"native_write_float", "([FIIIZ)I",(void *)android_media_AudioTrack_writeArray<jfloatArray>}, 12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_setVolume", "(FF)V", (void *)android_media_AudioTrack_set_volume}, 124710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk {"native_get_buffer_size_frames", 124810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk "()I", (void *)android_media_AudioTrack_get_buffer_size_frames}, 124910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk {"native_set_buffer_size_frames", 125010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk "(I)I", (void *)android_media_AudioTrack_set_buffer_size_frames}, 125110a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk {"native_get_buffer_capacity_frames", 125210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk "()I", (void *)android_media_AudioTrack_get_buffer_capacity_frames}, 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_playback_rate", 125488e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent "(I)I", (void *)android_media_AudioTrack_set_playback_rate}, 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_playback_rate", 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "()I", (void *)android_media_AudioTrack_get_playback_rate}, 12572d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia {"native_set_playback_params", 12582d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia "(Landroid/media/PlaybackParams;)V", 12592d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia (void *)android_media_AudioTrack_set_playback_params}, 12602d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia {"native_get_playback_params", 12612d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia "()Landroid/media/PlaybackParams;", 12622d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia (void *)android_media_AudioTrack_get_playback_params}, 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_marker_pos","(I)I", (void *)android_media_AudioTrack_set_marker_pos}, 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_marker_pos","()I", (void *)android_media_AudioTrack_get_marker_pos}, 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_pos_update_period", 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "(I)I", (void *)android_media_AudioTrack_set_pos_update_period}, 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_pos_update_period", 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "()I", (void *)android_media_AudioTrack_get_pos_update_period}, 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_position", "(I)I", (void *)android_media_AudioTrack_set_position}, 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_position", "()I", (void *)android_media_AudioTrack_get_position}, 127161dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman {"native_get_latency", "()I", (void *)android_media_AudioTrack_get_latency}, 127203f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk {"native_get_underrun_count", "()I", (void *)android_media_AudioTrack_get_underrun_count}, 1273ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung {"native_get_flags", "()I", (void *)android_media_AudioTrack_get_flags}, 1274948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten {"native_get_timestamp", "([J)I", (void *)android_media_AudioTrack_get_timestamp}, 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_loop", "(III)I", (void *)android_media_AudioTrack_set_loop}, 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_reload_static", "()I", (void *)android_media_AudioTrack_reload}, 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_output_sample_rate", 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "(I)I", (void *)android_media_AudioTrack_get_output_sample_rate}, 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_min_buff_size", 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "(III)I", (void *)android_media_AudioTrack_get_min_buff_size}, 12817070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent {"native_setAuxEffectSendLevel", 12823009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten "(F)I", (void *)android_media_AudioTrack_setAuxEffectSendLevel}, 12837070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent {"native_attachAuxEffect", 12847070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent "(I)I", (void *)android_media_AudioTrack_attachAuxEffect}, 128588e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean {"native_setOutputDevice", "(I)Z", 128688e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean (void *)android_media_AudioTrack_setOutputDevice}, 12874bcdba848449b33d7022de527c526943aff1f5fdEric Laurent {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioTrack_getRoutedDeviceId}, 12884bcdba848449b33d7022de527c526943aff1f5fdEric Laurent {"native_enableDeviceCallback", "()V", (void *)android_media_AudioTrack_enableDeviceCallback}, 12894bcdba848449b33d7022de527c526943aff1f5fdEric Laurent {"native_disableDeviceCallback", "()V", (void *)android_media_AudioTrack_disableDeviceCallback}, 129025d3c7c49bafb22723138bfab2e315d2d0a926fbGlenn Kasten {"native_get_FCC_8", "()I", (void *)android_media_AudioTrack_get_FCC_8}, 1291035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung {"native_applyVolumeShaper", 1292035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung "(Landroid/media/VolumeShaper$Configuration;Landroid/media/VolumeShaper$Operation;)I", 1293035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung (void *)android_media_AudioTrack_apply_volume_shaper}, 1294035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung {"native_getVolumeShaperState", 1295035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung "(I)Landroid/media/VolumeShaper$State;", 1296035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung (void *)android_media_AudioTrack_get_volume_shaper_state}, 12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// field names found in android/media/AudioTrack.java 13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_POSTEVENT_CALLBACK_NAME "postEventFromNative" 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME "mNativeTrackInJavaObj" 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_JNIDATA_FIELD_NAME "mJniData" 1304a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi#define JAVA_STREAMTYPE_FIELD_NAME "mStreamType" 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// preconditions: 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// theClass is valid 13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool android_media_getIntConstantFromClass(JNIEnv* pEnv, jclass theClass, const char* className, 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* constName, int* constVal) { 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID javaConst = NULL; 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaConst = pEnv->GetStaticFieldID(theClass, constName, "I"); 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (javaConst != NULL) { 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *constVal = pEnv->GetStaticIntField(theClass, javaConst); 13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 13173762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find %s.%s", className, constName); 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_media_AudioTrack(JNIEnv *env) 13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1326931fde4291afb05fca3d23214d19a883782ed22bGlenn Kasten // must be first 1327931fde4291afb05fca3d23214d19a883782ed22bGlenn Kasten int res = RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); 1328931fde4291afb05fca3d23214d19a883782ed22bGlenn Kasten 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.nativeTrackInJavaObj = NULL; 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.postNativeEventInJava = NULL; 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the AudioTrack class 1333ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe jclass audioTrackClass = FindClassOrDie(env, kClassPathName); 13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the postEvent method 1336ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe javaAudioTrackFields.postNativeEventInJava = GetStaticMethodIDOrDie(env, 1337ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe audioTrackClass, JAVA_POSTEVENT_CALLBACK_NAME, 1338ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the variables fields 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // nativeTrackInJavaObj 1342ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe javaAudioTrackFields.nativeTrackInJavaObj = GetFieldIDOrDie(env, 1343ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe audioTrackClass, JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME, "J"); 1344a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // jniData 1345ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe javaAudioTrackFields.jniData = GetFieldIDOrDie(env, 1346ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe audioTrackClass, JAVA_JNIDATA_FIELD_NAME, "J"); 1347a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // fieldStreamType 1348ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe javaAudioTrackFields.fieldStreamType = GetFieldIDOrDie(env, 1349ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe audioTrackClass, JAVA_STREAMTYPE_FIELD_NAME, "I"); 1350a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 1351fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung env->DeleteLocalRef(audioTrackClass); 1352fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung 1353a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // Get the AudioAttributes class and fields 1354ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe jclass audioAttrClass = FindClassOrDie(env, kAudioAttributesClassPathName); 1355ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe javaAudioAttrFields.fieldUsage = GetFieldIDOrDie(env, audioAttrClass, "mUsage", "I"); 1356ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe javaAudioAttrFields.fieldContentType = GetFieldIDOrDie(env, 1357ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe audioAttrClass, "mContentType", "I"); 1358ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe javaAudioAttrFields.fieldFlags = GetFieldIDOrDie(env, audioAttrClass, "mFlags", "I"); 1359ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe javaAudioAttrFields.fieldFormattedTags = GetFieldIDOrDie(env, 1360ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe audioAttrClass, "mFormattedTags", "Ljava/lang/String;"); 1361ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe 1362fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung env->DeleteLocalRef(audioAttrClass); 1363fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung 13642d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia // initialize PlaybackParams field info 13652d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia gPlaybackParamsFields.init(env); 1366fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung 1367035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung gVolumeShaperFields.init(env); 1368931fde4291afb05fca3d23214d19a883782ed22bGlenn Kasten return res; 13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 1373