blob: 1f688e107fd1f1b02dcc4bc0a4a392d6f51c3f92 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16//#define LOG_NDEBUG 0
17
18#define LOG_TAG "AudioTrack-JNI"
19
Wei Jia071a8b72015-03-09 16:38:25 -070020#include "android_media_AudioTrack.h"
21
Glenn Kastenc81d31c2012-03-13 14:46:23 -070022#include <JNIHelp.h>
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -080023#include <JniConstants.h>
Andreas Gampeed6b9df2014-11-20 22:02:20 -080024#include "core_jni_helpers.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -080026#include "ScopedBytes.h"
27
Glenn Kastenc81d31c2012-03-13 14:46:23 -070028#include <utils/Log.h>
29#include <media/AudioSystem.h>
30#include <media/AudioTrack.h>
Glenn Kasten37967d42012-11-28 14:37:36 -080031#include <audio_utils/primitives.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032
Mathias Agopian07952722009-05-19 19:08:10 -070033#include <binder/MemoryHeapBase.h>
34#include <binder/MemoryBase.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035
Glenn Kastenfe834d32014-01-08 14:49:08 -080036#include "android_media_AudioFormat.h"
Eric Laurentbc11a692014-05-16 12:19:25 -070037#include "android_media_AudioErrors.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038
39// ----------------------------------------------------------------------------
40
41using namespace android;
42
43// ----------------------------------------------------------------------------
44static const char* const kClassPathName = "android/media/AudioTrack";
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -070045static const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -070047struct audio_track_fields_t {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048 // these fields provide access from C++ to the...
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 jmethodID postNativeEventInJava; //... event post callback method
Eric Laurent83b36852009-07-28 07:49:22 -070050 jfieldID nativeTrackInJavaObj; // stores in Java the native AudioTrack object
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051 jfieldID jniData; // stores in Java additional resources used by the native AudioTrack
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -070052 jfieldID fieldStreamType; // ... mStreamType field in the AudioTrack Java object
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053};
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -070054struct audio_attributes_fields_t {
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -070055 jfieldID fieldUsage; // AudioAttributes.mUsage
56 jfieldID fieldContentType; // AudioAttributes.mContentType
57 jfieldID fieldFlags; // AudioAttributes.mFlags
58 jfieldID fieldFormattedTags;// AudioAttributes.mFormattedTags
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -070059};
60static audio_track_fields_t javaAudioTrackFields;
61static audio_attributes_fields_t javaAudioAttrFields;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062
63struct audiotrack_callback_cookie {
64 jclass audioTrack_class;
65 jobject audioTrack_ref;
Eric Laurent532bc1c2012-04-20 12:45:03 -070066 bool busy;
67 Condition cond;
68};
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069
Glenn Kasten3d301cb2012-01-16 14:46:54 -080070// keep these values in sync with AudioTrack.java
71#define MODE_STATIC 0
72#define MODE_STREAM 1
73
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074// ----------------------------------------------------------------------------
75class AudioTrackJniStorage {
76 public:
77 sp<MemoryHeapBase> mMemHeap;
78 sp<MemoryBase> mMemBase;
79 audiotrack_callback_cookie mCallbackData;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080
81 AudioTrackJniStorage() {
Jean-Michel Trivi8a149682009-07-15 18:31:11 -070082 mCallbackData.audioTrack_class = 0;
83 mCallbackData.audioTrack_ref = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 }
85
86 ~AudioTrackJniStorage() {
87 mMemBase.clear();
88 mMemHeap.clear();
89 }
90
91 bool allocSharedMem(int sizeInBytes) {
92 mMemHeap = new MemoryHeapBase(sizeInBytes, 0, "AudioTrack Heap Base");
93 if (mMemHeap->getHeapID() < 0) {
94 return false;
95 }
96 mMemBase = new MemoryBase(mMemHeap, 0, sizeInBytes);
97 return true;
98 }
99};
100
Eric Laurent532bc1c2012-04-20 12:45:03 -0700101static Mutex sLock;
102static SortedVector <audiotrack_callback_cookie *> sAudioTrackCallBackCookies;
103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104// ----------------------------------------------------------------------------
105#define DEFAULT_OUTPUT_SAMPLE_RATE 44100
106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107#define AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM -16
Glenn Kastenfb2ab9e2011-12-12 09:05:55 -0800108#define AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK -17
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109#define AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT -18
110#define AUDIOTRACK_ERROR_SETUP_INVALIDSTREAMTYPE -19
111#define AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED -20
112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113// ----------------------------------------------------------------------------
Glenn Kastene46a86f2011-06-01 15:20:35 -0700114static void audioCallback(int event, void* user, void *info) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700115
116 audiotrack_callback_cookie *callbackInfo = (audiotrack_callback_cookie *)user;
117 {
118 Mutex::Autolock l(sLock);
119 if (sAudioTrackCallBackCookies.indexOf(callbackInfo) < 0) {
120 return;
121 }
122 callbackInfo->busy = true;
123 }
124
Glenn Kasten5b1576c2013-07-18 16:58:19 -0700125 switch (event) {
126 case AudioTrack::EVENT_MARKER: {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 JNIEnv *env = AndroidRuntime::getJNIEnv();
Glenn Kastena667ff32013-07-22 07:36:34 -0700128 if (user != NULL && env != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 env->CallStaticVoidMethod(
Glenn Kasten18db49a2012-03-12 16:29:55 -0700130 callbackInfo->audioTrack_class,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 javaAudioTrackFields.postNativeEventInJava,
132 callbackInfo->audioTrack_ref, event, 0,0, NULL);
133 if (env->ExceptionCheck()) {
134 env->ExceptionDescribe();
135 env->ExceptionClear();
136 }
137 }
Glenn Kasten5b1576c2013-07-18 16:58:19 -0700138 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139
Glenn Kasten5b1576c2013-07-18 16:58:19 -0700140 case AudioTrack::EVENT_NEW_POS: {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 JNIEnv *env = AndroidRuntime::getJNIEnv();
Glenn Kastena667ff32013-07-22 07:36:34 -0700142 if (user != NULL && env != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 env->CallStaticVoidMethod(
Glenn Kasten18db49a2012-03-12 16:29:55 -0700144 callbackInfo->audioTrack_class,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 javaAudioTrackFields.postNativeEventInJava,
146 callbackInfo->audioTrack_ref, event, 0,0, NULL);
147 if (env->ExceptionCheck()) {
148 env->ExceptionDescribe();
149 env->ExceptionClear();
150 }
151 }
Glenn Kasten5b1576c2013-07-18 16:58:19 -0700152 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 }
Glenn Kasten5b1576c2013-07-18 16:58:19 -0700154
Eric Laurent532bc1c2012-04-20 12:45:03 -0700155 {
156 Mutex::Autolock l(sLock);
157 callbackInfo->busy = false;
158 callbackInfo->cond.broadcast();
159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160}
161
162
163// ----------------------------------------------------------------------------
Eric Laurent532bc1c2012-04-20 12:45:03 -0700164static sp<AudioTrack> getAudioTrack(JNIEnv* env, jobject thiz)
165{
166 Mutex::Autolock l(sLock);
167 AudioTrack* const at =
Ashok Bhat075e9a12014-01-06 13:45:09 +0000168 (AudioTrack*)env->GetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj);
Eric Laurent532bc1c2012-04-20 12:45:03 -0700169 return sp<AudioTrack>(at);
170}
171
172static sp<AudioTrack> setAudioTrack(JNIEnv* env, jobject thiz, const sp<AudioTrack>& at)
173{
174 Mutex::Autolock l(sLock);
175 sp<AudioTrack> old =
Ashok Bhat075e9a12014-01-06 13:45:09 +0000176 (AudioTrack*)env->GetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj);
Eric Laurent532bc1c2012-04-20 12:45:03 -0700177 if (at.get()) {
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800178 at->incStrong((void*)setAudioTrack);
Eric Laurent532bc1c2012-04-20 12:45:03 -0700179 }
180 if (old != 0) {
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800181 old->decStrong((void*)setAudioTrack);
Eric Laurent532bc1c2012-04-20 12:45:03 -0700182 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000183 env->SetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, (jlong)at.get());
Eric Laurent532bc1c2012-04-20 12:45:03 -0700184 return old;
185}
Wei Jia071a8b72015-03-09 16:38:25 -0700186
187// ----------------------------------------------------------------------------
188sp<AudioTrack> android_media_AudioTrack_getAudioTrack(JNIEnv* env, jobject audioTrackObj) {
189 return getAudioTrack(env, audioTrackObj);
190}
191
Eric Laurent532bc1c2012-04-20 12:45:03 -0700192// ----------------------------------------------------------------------------
Ashok Bhat075e9a12014-01-06 13:45:09 +0000193static jint
Jean-Michel Trivieac84382014-02-04 14:50:40 -0800194android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700195 jobject jaa,
196 jint sampleRateInHertz, jint javaChannelMask,
197 jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession) {
198
Steve Block71f2cf12011-10-20 11:56:00 +0100199 ALOGV("sampleRate=%d, audioFormat(from Java)=%d, channel mask=%x, buffSize=%d",
Jean-Michel Trivid9ae1c52011-07-25 12:58:14 -0700200 sampleRateInHertz, audioFormat, javaChannelMask, buffSizeInBytes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700202 if (jaa == 0) {
203 ALOGE("Error creating AudioTrack: invalid audio attributes");
204 return (jint) AUDIO_JAVA_ERROR;
205 }
206
Andy Hunga9470c12015-01-29 17:16:03 -0800207 // Java channel masks don't map directly to the native definition for positional
208 // channel masks: it's a shift by 2 to skip the two deprecated channel
209 // configurations "default" and "mono".
210 // Invalid channel representations are caught by !audio_is_output_channel() below.
211 audio_channel_mask_t nativeChannelMask =
212 audio_channel_mask_get_representation(javaChannelMask)
213 == AUDIO_CHANNEL_REPRESENTATION_POSITION
214 ? javaChannelMask >> 2 : javaChannelMask;
Jean-Michel Trivid9ae1c52011-07-25 12:58:14 -0700215
216 if (!audio_is_output_channel(nativeChannelMask)) {
Glenn Kasten33c437d2013-07-18 17:04:21 -0700217 ALOGE("Error creating AudioTrack: invalid channel mask %#x.", javaChannelMask);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000218 return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 }
Jean-Michel Trivid9ae1c52011-07-25 12:58:14 -0700220
Eric Laurentdbf55662014-07-01 18:56:30 -0700221 uint32_t channelCount = audio_channel_count_from_out_mask(nativeChannelMask);
Glenn Kasten18db49a2012-03-12 16:29:55 -0700222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 // check the format.
224 // This function was called from Java, so we compare the format against the Java constants
Glenn Kastenfe834d32014-01-08 14:49:08 -0800225 audio_format_t format = audioFormatToNative(audioFormat);
226 if (format == AUDIO_FORMAT_INVALID) {
Glenn Kasten8f81d082012-11-28 14:37:48 -0800227 ALOGE("Error creating AudioTrack: unsupported audio format %d.", audioFormat);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000228 return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 }
230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 // compute the frame count
Eric Laurentff0d9f02014-06-09 17:23:02 -0700232 size_t frameCount;
233 if (audio_is_linear_pcm(format)) {
234 const size_t bytesPerSample = audio_bytes_per_sample(format);
235 frameCount = buffSizeInBytes / (channelCount * bytesPerSample);
236 } else {
237 frameCount = buffSizeInBytes;
238 }
Glenn Kasten18db49a2012-03-12 16:29:55 -0700239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 jclass clazz = env->GetObjectClass(thiz);
241 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000242 ALOGE("Can't find %s when setting up callback.", kClassPathName);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000243 return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 }
Eric Laurent2fb43ef2010-09-24 12:03:36 -0700245
246 if (jSession == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000247 ALOGE("Error creating AudioTrack: invalid session ID pointer");
Eric Laurentbc11a692014-05-16 12:19:25 -0700248 return (jint) AUDIO_JAVA_ERROR;
Eric Laurent619346f2010-06-21 09:27:30 -0700249 }
250
Eric Laurent2fb43ef2010-09-24 12:03:36 -0700251 jint* nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
252 if (nSession == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000253 ALOGE("Error creating AudioTrack: Error retrieving session id pointer");
Eric Laurentbc11a692014-05-16 12:19:25 -0700254 return (jint) AUDIO_JAVA_ERROR;
Eric Laurent2fb43ef2010-09-24 12:03:36 -0700255 }
256 int sessionId = nSession[0];
257 env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
258 nSession = NULL;
259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 // create the native AudioTrack object
Eric Laurent532bc1c2012-04-20 12:45:03 -0700261 sp<AudioTrack> lpTrack = new AudioTrack();
Glenn Kasten18db49a2012-03-12 16:29:55 -0700262
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700263 audio_attributes_t *paa = NULL;
264 // read the AudioAttributes values
265 paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
Jean-Michel Trivi701d6ff2014-07-16 07:51:22 -0700266 const jstring jtags =
267 (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700268 const char* tags = env->GetStringUTFChars(jtags, NULL);
269 // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
270 strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
271 env->ReleaseStringUTFChars(jtags, tags);
272 paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage);
273 paa->content_type =
274 (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
275 paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
276
277 ALOGV("AudioTrack_setup for usage=%d content=%d flags=0x%#x tags=%s",
278 paa->usage, paa->content_type, paa->flags, paa->tags);
279
Eric Laurent532bc1c2012-04-20 12:45:03 -0700280 // initialize the callback information:
281 // this data will be passed with every AudioTrack callback
282 AudioTrackJniStorage* lpJniStorage = new AudioTrackJniStorage();
Eric Laurent532bc1c2012-04-20 12:45:03 -0700283 lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz);
284 // we use a weak reference so the AudioTrack object can be garbage collected.
285 lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this);
286 lpJniStorage->mCallbackData.busy = false;
287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 // initialize the native AudioTrack object
Jean-Michel Trivi2defed92014-05-14 18:15:59 -0700289 status_t status = NO_ERROR;
Glenn Kasten3d301cb2012-01-16 14:46:54 -0800290 switch (memoryMode) {
291 case MODE_STREAM:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292
Glenn Kastenc5d14242014-03-28 16:19:52 -0700293 status = lpTrack->set(
Jean-Michel Trivic8d6b6f2014-07-28 09:52:14 -0700294 AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700295 sampleRateInHertz,
296 format,// word length, PCM
297 nativeChannelMask,
298 frameCount,
299 AUDIO_OUTPUT_FLAG_NONE,
300 audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
301 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
302 0,// shared mem
303 true,// thread can call Java
304 sessionId,// audio session ID
Jean-Michel Trivic8d6b6f2014-07-28 09:52:14 -0700305 AudioTrack::TRANSFER_SYNC,
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700306 NULL, // default offloadInfo
307 -1, -1, // default uid, pid values
308 paa);
Glenn Kasten3d301cb2012-01-16 14:46:54 -0800309 break;
Glenn Kasten18db49a2012-03-12 16:29:55 -0700310
Glenn Kasten3d301cb2012-01-16 14:46:54 -0800311 case MODE_STATIC:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 // AudioTrack is using shared memory
Glenn Kasten18db49a2012-03-12 16:29:55 -0700313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) {
Steve Block3762c312012-01-06 19:20:56 +0000315 ALOGE("Error creating AudioTrack in static mode: error creating mem heap base");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 goto native_init_failure;
317 }
Glenn Kasten18db49a2012-03-12 16:29:55 -0700318
Glenn Kastenc5d14242014-03-28 16:19:52 -0700319 status = lpTrack->set(
Jean-Michel Trivic8d6b6f2014-07-28 09:52:14 -0700320 AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700321 sampleRateInHertz,
322 format,// word length, PCM
323 nativeChannelMask,
324 frameCount,
325 AUDIO_OUTPUT_FLAG_NONE,
326 audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
327 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
328 lpJniStorage->mMemBase,// shared mem
329 true,// thread can call Java
330 sessionId,// audio session ID
Jean-Michel Trivic8d6b6f2014-07-28 09:52:14 -0700331 AudioTrack::TRANSFER_SHARED,
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700332 NULL, // default offloadInfo
333 -1, -1, // default uid, pid values
334 paa);
Glenn Kasten3d301cb2012-01-16 14:46:54 -0800335 break;
336
337 default:
338 ALOGE("Unknown mode %d", memoryMode);
339 goto native_init_failure;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 }
341
Glenn Kastenc5d14242014-03-28 16:19:52 -0700342 if (status != NO_ERROR) {
343 ALOGE("Error %d initializing AudioTrack", status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 goto native_init_failure;
345 }
346
Eric Laurent2fb43ef2010-09-24 12:03:36 -0700347 nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
348 if (nSession == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000349 ALOGE("Error creating AudioTrack: Error retrieving session id pointer");
Eric Laurent2fb43ef2010-09-24 12:03:36 -0700350 goto native_init_failure;
351 }
Eric Laurent619346f2010-06-21 09:27:30 -0700352 // read the audio session ID back from AudioTrack in case we create a new session
353 nSession[0] = lpTrack->getSessionId();
Eric Laurent619346f2010-06-21 09:27:30 -0700354 env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
355 nSession = NULL;
356
Eric Laurent532bc1c2012-04-20 12:45:03 -0700357 { // scope for the lock
358 Mutex::Autolock l(sLock);
359 sAudioTrackCallBackCookies.add(&lpJniStorage->mCallbackData);
360 }
Glenn Kasten18db49a2012-03-12 16:29:55 -0700361 // save our newly created C++ AudioTrack in the "nativeTrackInJavaObj" field
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 // of the Java object (in mNativeTrackInJavaObj)
Eric Laurent532bc1c2012-04-20 12:45:03 -0700363 setAudioTrack(env, thiz, lpTrack);
Glenn Kasten18db49a2012-03-12 16:29:55 -0700364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 // save the JNI resources so we can free them later
Ashok Bhat075e9a12014-01-06 13:45:09 +0000366 //ALOGV("storing lpJniStorage: %x\n", (long)lpJniStorage);
367 env->SetLongField(thiz, javaAudioTrackFields.jniData, (jlong)lpJniStorage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700369 // since we had audio attributes, the stream type was derived from them during the
370 // creation of the native AudioTrack: push the same value to the Java object
371 env->SetIntField(thiz, javaAudioTrackFields.fieldStreamType, (jint) lpTrack->streamType());
372 // audio attributes were copied in AudioTrack creation
373 free(paa);
374 paa = NULL;
375
376
Eric Laurentbc11a692014-05-16 12:19:25 -0700377 return (jint) AUDIO_JAVA_SUCCESS;
Glenn Kasten18db49a2012-03-12 16:29:55 -0700378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 // failures:
380native_init_failure:
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700381 if (paa != NULL) {
382 free(paa);
383 }
Eric Laurent619346f2010-06-21 09:27:30 -0700384 if (nSession != NULL) {
385 env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
386 }
Jean-Michel Trivi8a149682009-07-15 18:31:11 -0700387 env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_class);
388 env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 delete lpJniStorage;
Ashok Bhat075e9a12014-01-06 13:45:09 +0000390 env->SetLongField(thiz, javaAudioTrackFields.jniData, 0);
Glenn Kasten18db49a2012-03-12 16:29:55 -0700391
Ashok Bhat075e9a12014-01-06 13:45:09 +0000392 return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393}
394
395
396// ----------------------------------------------------------------------------
397static void
398android_media_AudioTrack_start(JNIEnv *env, jobject thiz)
399{
Eric Laurent532bc1c2012-04-20 12:45:03 -0700400 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
401 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 jniThrowException(env, "java/lang/IllegalStateException",
403 "Unable to retrieve AudioTrack pointer for start()");
Eric Laurent7070b362010-07-16 07:43:46 -0700404 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 }
Jean-Michel Trivi21dc0372009-05-08 16:06:34 -0700406
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 lpTrack->start();
408}
409
410
411// ----------------------------------------------------------------------------
412static void
413android_media_AudioTrack_stop(JNIEnv *env, jobject thiz)
414{
Eric Laurent532bc1c2012-04-20 12:45:03 -0700415 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
416 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 jniThrowException(env, "java/lang/IllegalStateException",
418 "Unable to retrieve AudioTrack pointer for stop()");
Eric Laurent7070b362010-07-16 07:43:46 -0700419 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 }
421
422 lpTrack->stop();
423}
424
425
426// ----------------------------------------------------------------------------
427static void
428android_media_AudioTrack_pause(JNIEnv *env, jobject thiz)
429{
Eric Laurent532bc1c2012-04-20 12:45:03 -0700430 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
431 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 jniThrowException(env, "java/lang/IllegalStateException",
433 "Unable to retrieve AudioTrack pointer for pause()");
Eric Laurent7070b362010-07-16 07:43:46 -0700434 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 }
436
437 lpTrack->pause();
438}
439
440
441// ----------------------------------------------------------------------------
442static void
443android_media_AudioTrack_flush(JNIEnv *env, jobject thiz)
444{
Eric Laurent532bc1c2012-04-20 12:45:03 -0700445 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
446 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 jniThrowException(env, "java/lang/IllegalStateException",
448 "Unable to retrieve AudioTrack pointer for flush()");
Eric Laurent7070b362010-07-16 07:43:46 -0700449 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 }
451
452 lpTrack->flush();
453}
454
455// ----------------------------------------------------------------------------
456static void
457android_media_AudioTrack_set_volume(JNIEnv *env, jobject thiz, jfloat leftVol, jfloat rightVol )
458{
Eric Laurent532bc1c2012-04-20 12:45:03 -0700459 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
460 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 jniThrowException(env, "java/lang/IllegalStateException",
462 "Unable to retrieve AudioTrack pointer for setVolume()");
Eric Laurent7070b362010-07-16 07:43:46 -0700463 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 }
465
466 lpTrack->setVolume(leftVol, rightVol);
467}
468
469// ----------------------------------------------------------------------------
Glenn Kasten18db49a2012-03-12 16:29:55 -0700470
Eric Laurent532bc1c2012-04-20 12:45:03 -0700471#define CALLBACK_COND_WAIT_TIMEOUT_MS 1000
Jean-Michel Trivieac84382014-02-04 14:50:40 -0800472static void android_media_AudioTrack_release(JNIEnv *env, jobject thiz) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700473 sp<AudioTrack> lpTrack = setAudioTrack(env, thiz, 0);
474 if (lpTrack == NULL) {
475 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 }
Eric Laurent532bc1c2012-04-20 12:45:03 -0700477 //ALOGV("deleting lpTrack: %x\n", (int)lpTrack);
478 lpTrack->stop();
Glenn Kasten18db49a2012-03-12 16:29:55 -0700479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 // delete the JNI data
Ashok Bhat075e9a12014-01-06 13:45:09 +0000481 AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 thiz, javaAudioTrackFields.jniData);
Eric Laurent532bc1c2012-04-20 12:45:03 -0700483 // reset the native resources in the Java object so any attempt to access
484 // them after a call to release fails.
Ashok Bhat075e9a12014-01-06 13:45:09 +0000485 env->SetLongField(thiz, javaAudioTrackFields.jniData, 0);
Eric Laurent532bc1c2012-04-20 12:45:03 -0700486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 if (pJniStorage) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700488 Mutex::Autolock l(sLock);
489 audiotrack_callback_cookie *lpCookie = &pJniStorage->mCallbackData;
Steve Block71f2cf12011-10-20 11:56:00 +0100490 //ALOGV("deleting pJniStorage: %x\n", (int)pJniStorage);
Eric Laurent532bc1c2012-04-20 12:45:03 -0700491 while (lpCookie->busy) {
492 if (lpCookie->cond.waitRelative(sLock,
493 milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) !=
494 NO_ERROR) {
495 break;
496 }
497 }
498 sAudioTrackCallBackCookies.remove(lpCookie);
499 // delete global refs created in native_setup
500 env->DeleteGlobalRef(lpCookie->audioTrack_class);
501 env->DeleteGlobalRef(lpCookie->audioTrack_ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 delete pJniStorage;
503 }
504}
505
Glenn Kasten18db49a2012-03-12 16:29:55 -0700506
Eric Laurent532bc1c2012-04-20 12:45:03 -0700507// ----------------------------------------------------------------------------
Jean-Michel Trivieac84382014-02-04 14:50:40 -0800508static void android_media_AudioTrack_finalize(JNIEnv *env, jobject thiz) {
509 //ALOGV("android_media_AudioTrack_finalize jobject: %x\n", (int)thiz);
510 android_media_AudioTrack_release(env, thiz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511}
512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513// ----------------------------------------------------------------------------
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -0800514jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const jbyte* data,
515 jint offsetInBytes, jint sizeInBytes, bool blocking = true) {
Jean-Michel Trivi21dc0372009-05-08 16:06:34 -0700516 // give the data to the native AudioTrack object (the data starts at the offset)
517 ssize_t written = 0;
518 // regular write() or copy the data to the AudioTrack's shared memory?
Eric Laurent532bc1c2012-04-20 12:45:03 -0700519 if (track->sharedBuffer() == 0) {
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -0800520 written = track->write(data + offsetInBytes, sizeInBytes, blocking);
Glenn Kasten9b53db32013-07-10 14:13:39 -0700521 // for compatibility with earlier behavior of write(), return 0 in this case
522 if (written == (ssize_t) WOULD_BLOCK) {
523 written = 0;
524 }
Jean-Michel Trivi21dc0372009-05-08 16:06:34 -0700525 } else {
Andy Hung2c0e17c2015-01-12 15:07:14 -0800526 // writing to shared memory, check for capacity
527 if ((size_t)sizeInBytes > track->sharedBuffer()->size()) {
528 sizeInBytes = track->sharedBuffer()->size();
Jean-Michel Trivi21dc0372009-05-08 16:06:34 -0700529 }
Andy Hung2c0e17c2015-01-12 15:07:14 -0800530 memcpy(track->sharedBuffer()->pointer(), data + offsetInBytes, sizeInBytes);
531 written = sizeInBytes;
Jean-Michel Trivi21dc0372009-05-08 16:06:34 -0700532 }
533 return written;
Jean-Michel Trivi21dc0372009-05-08 16:06:34 -0700534}
535
536// ----------------------------------------------------------------------------
Jean-Michel Trivieac84382014-02-04 14:50:40 -0800537static jint android_media_AudioTrack_write_byte(JNIEnv *env, jobject thiz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 jbyteArray javaAudioData,
539 jint offsetInBytes, jint sizeInBytes,
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -0800540 jint javaAudioFormat,
541 jboolean isWriteBlocking) {
Jean-Michel Trivieac84382014-02-04 14:50:40 -0800542 //ALOGV("android_media_AudioTrack_write_byte(offset=%d, sizeInBytes=%d) called",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 // offsetInBytes, sizeInBytes);
Eric Laurent532bc1c2012-04-20 12:45:03 -0700544 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 if (lpTrack == NULL) {
546 jniThrowException(env, "java/lang/IllegalStateException",
547 "Unable to retrieve AudioTrack pointer for write()");
Eric Laurent7070b362010-07-16 07:43:46 -0700548 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 }
550
551 // get the pointer for the audio data from the java array
Eric Laurent421ddc02011-03-07 14:52:59 -0800552 // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
553 // a way that it becomes much more efficient. When doing so, we will have to prevent the
554 // AudioSystem callback to be called while in critical section (in case of media server
555 // process crash for instance)
Eric Laurent532bc1c2012-04-20 12:45:03 -0700556 jbyte* cAudioData = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 if (javaAudioData) {
Eric Laurent421ddc02011-03-07 14:52:59 -0800558 cAudioData = (jbyte *)env->GetByteArrayElements(javaAudioData, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 if (cAudioData == NULL) {
Steve Block3762c312012-01-06 19:20:56 +0000560 ALOGE("Error retrieving source of audio data to play, can't play");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 return 0; // out of memory or no data to load
562 }
563 } else {
Steve Block3762c312012-01-06 19:20:56 +0000564 ALOGE("NULL java array of audio data to play, can't play");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 return 0;
566 }
567
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -0800568 jint written = writeToTrack(lpTrack, javaAudioFormat, cAudioData, offsetInBytes, sizeInBytes,
569 isWriteBlocking == JNI_TRUE /* blocking */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570
Eric Laurent421ddc02011-03-07 14:52:59 -0800571 env->ReleaseByteArrayElements(javaAudioData, cAudioData, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572
Steve Block71f2cf12011-10-20 11:56:00 +0100573 //ALOGV("write wrote %d (tried %d) bytes in the native AudioTrack with offset %d",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574 // (int)written, (int)(sizeInBytes), (int)offsetInBytes);
Jean-Michel Trivi21dc0372009-05-08 16:06:34 -0700575 return written;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576}
577
578
579// ----------------------------------------------------------------------------
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -0800580static jint android_media_AudioTrack_write_native_bytes(JNIEnv *env, jobject thiz,
Jean-Michel Trivi5d21f672014-03-20 17:02:31 -0700581 jbyteArray javaBytes, jint byteOffset, jint sizeInBytes,
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -0800582 jint javaAudioFormat, jboolean isWriteBlocking) {
583 //ALOGV("android_media_AudioTrack_write_native_bytes(offset=%d, sizeInBytes=%d) called",
584 // offsetInBytes, sizeInBytes);
585 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
586 if (lpTrack == NULL) {
587 jniThrowException(env, "java/lang/IllegalStateException",
588 "Unable to retrieve AudioTrack pointer for write()");
589 return 0;
590 }
591
592 ScopedBytesRO bytes(env, javaBytes);
593 if (bytes.get() == NULL) {
594 ALOGE("Error retrieving source of audio data to play, can't play");
Eric Laurentbc11a692014-05-16 12:19:25 -0700595 return (jint)AUDIO_JAVA_BAD_VALUE;
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -0800596 }
597
Jean-Michel Trivi5d21f672014-03-20 17:02:31 -0700598 jint written = writeToTrack(lpTrack, javaAudioFormat, bytes.get(), byteOffset,
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -0800599 sizeInBytes, isWriteBlocking == JNI_TRUE /* blocking */);
600
601 return written;
602}
603
604// ----------------------------------------------------------------------------
Jean-Michel Trivieac84382014-02-04 14:50:40 -0800605static jint android_media_AudioTrack_write_short(JNIEnv *env, jobject thiz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 jshortArray javaAudioData,
607 jint offsetInShorts, jint sizeInShorts,
608 jint javaAudioFormat) {
Eric Laurent3d4c6412014-04-30 11:59:21 -0700609
610 //ALOGV("android_media_AudioTrack_write_short(offset=%d, sizeInShorts=%d) called",
611 // offsetInShorts, sizeInShorts);
612 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
613 if (lpTrack == NULL) {
614 jniThrowException(env, "java/lang/IllegalStateException",
615 "Unable to retrieve AudioTrack pointer for write()");
616 return 0;
Glenn Kastenf7e0a3702013-07-10 14:03:03 -0700617 }
Eric Laurent3d4c6412014-04-30 11:59:21 -0700618
619 // get the pointer for the audio data from the java array
620 // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
621 // a way that it becomes much more efficient. When doing so, we will have to prevent the
622 // AudioSystem callback to be called while in critical section (in case of media server
623 // process crash for instance)
624 jshort* cAudioData = NULL;
625 if (javaAudioData) {
626 cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);
627 if (cAudioData == NULL) {
628 ALOGE("Error retrieving source of audio data to play, can't play");
629 return 0; // out of memory or no data to load
630 }
631 } else {
632 ALOGE("NULL java array of audio data to play, can't play");
633 return 0;
634 }
635 jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
636 offsetInShorts * sizeof(short), sizeInShorts * sizeof(short),
637 true /*blocking write, legacy behavior*/);
638 env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0);
639
640 if (written > 0) {
641 written /= sizeof(short);
642 }
643 //ALOGV("write wrote %d (tried %d) shorts in the native AudioTrack with offset %d",
644 // (int)written, (int)(sizeInShorts), (int)offsetInShorts);
645
Glenn Kastenf7e0a3702013-07-10 14:03:03 -0700646 return written;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647}
648
649
650// ----------------------------------------------------------------------------
Glenn Kasten54955e32014-04-30 18:03:15 -0700651static jint android_media_AudioTrack_write_float(JNIEnv *env, jobject thiz,
652 jfloatArray javaAudioData,
653 jint offsetInFloats, jint sizeInFloats,
654 jint javaAudioFormat,
655 jboolean isWriteBlocking) {
656
657 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
658 if (lpTrack == NULL) {
659 jniThrowException(env, "java/lang/IllegalStateException",
660 "Unable to retrieve AudioTrack pointer for write()");
661 return 0;
662 }
663
664 jfloat* cAudioData = NULL;
665 if (javaAudioData) {
666 cAudioData = (jfloat *)env->GetFloatArrayElements(javaAudioData, NULL);
667 if (cAudioData == NULL) {
668 ALOGE("Error retrieving source of audio data to play, can't play");
669 return 0; // out of memory or no data to load
670 }
671 } else {
672 ALOGE("NULL java array of audio data to play, can't play");
673 return 0;
674 }
675 jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
676 offsetInFloats * sizeof(float), sizeInFloats * sizeof(float),
677 isWriteBlocking == JNI_TRUE /* blocking */);
678 env->ReleaseFloatArrayElements(javaAudioData, cAudioData, 0);
679
680 if (written > 0) {
681 written /= sizeof(float);
682 }
683
684 return written;
685}
686
687
688// ----------------------------------------------------------------------------
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689static jint android_media_AudioTrack_get_native_frame_count(JNIEnv *env, jobject thiz) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700690 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
691 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 jniThrowException(env, "java/lang/IllegalStateException",
693 "Unable to retrieve AudioTrack pointer for frameCount()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700694 return (jint)AUDIO_JAVA_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 }
Eric Laurent532bc1c2012-04-20 12:45:03 -0700696
697 return lpTrack->frameCount();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698}
699
700
701// ----------------------------------------------------------------------------
Eric Laurent88e209d2009-07-07 07:10:45 -0700702static jint android_media_AudioTrack_set_playback_rate(JNIEnv *env, jobject thiz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 jint sampleRateInHz) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700704 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
705 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 jniThrowException(env, "java/lang/IllegalStateException",
707 "Unable to retrieve AudioTrack pointer for setSampleRate()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700708 return (jint)AUDIO_JAVA_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709 }
Eric Laurentbc11a692014-05-16 12:19:25 -0700710 return nativeToJavaStatus(lpTrack->setSampleRate(sampleRateInHz));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711}
712
713
714// ----------------------------------------------------------------------------
715static jint android_media_AudioTrack_get_playback_rate(JNIEnv *env, jobject thiz) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700716 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
717 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 jniThrowException(env, "java/lang/IllegalStateException",
719 "Unable to retrieve AudioTrack pointer for getSampleRate()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700720 return (jint)AUDIO_JAVA_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 }
Eric Laurent532bc1c2012-04-20 12:45:03 -0700722 return (jint) lpTrack->getSampleRate();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723}
724
725
726// ----------------------------------------------------------------------------
Glenn Kasten18db49a2012-03-12 16:29:55 -0700727static jint android_media_AudioTrack_set_marker_pos(JNIEnv *env, jobject thiz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 jint markerPos) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700729 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
730 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 jniThrowException(env, "java/lang/IllegalStateException",
732 "Unable to retrieve AudioTrack pointer for setMarkerPosition()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700733 return (jint)AUDIO_JAVA_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 }
Eric Laurentbc11a692014-05-16 12:19:25 -0700735 return nativeToJavaStatus( lpTrack->setMarkerPosition(markerPos) );
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736}
737
738
739// ----------------------------------------------------------------------------
740static jint android_media_AudioTrack_get_marker_pos(JNIEnv *env, jobject thiz) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700741 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800742 uint32_t markerPos = 0;
Glenn Kasten18db49a2012-03-12 16:29:55 -0700743
Eric Laurent532bc1c2012-04-20 12:45:03 -0700744 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 jniThrowException(env, "java/lang/IllegalStateException",
746 "Unable to retrieve AudioTrack pointer for getMarkerPosition()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700747 return (jint)AUDIO_JAVA_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 }
Eric Laurent532bc1c2012-04-20 12:45:03 -0700749 lpTrack->getMarkerPosition(&markerPos);
750 return (jint)markerPos;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800751}
752
753
754// ----------------------------------------------------------------------------
755static jint android_media_AudioTrack_set_pos_update_period(JNIEnv *env, jobject thiz,
756 jint period) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700757 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
758 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 jniThrowException(env, "java/lang/IllegalStateException",
760 "Unable to retrieve AudioTrack pointer for setPositionUpdatePeriod()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700761 return (jint)AUDIO_JAVA_ERROR;
Glenn Kasten18db49a2012-03-12 16:29:55 -0700762 }
Eric Laurentbc11a692014-05-16 12:19:25 -0700763 return nativeToJavaStatus( lpTrack->setPositionUpdatePeriod(period) );
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764}
765
766
767// ----------------------------------------------------------------------------
768static jint android_media_AudioTrack_get_pos_update_period(JNIEnv *env, jobject thiz) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700769 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 uint32_t period = 0;
Glenn Kasten18db49a2012-03-12 16:29:55 -0700771
Eric Laurent532bc1c2012-04-20 12:45:03 -0700772 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 jniThrowException(env, "java/lang/IllegalStateException",
774 "Unable to retrieve AudioTrack pointer for getPositionUpdatePeriod()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700775 return (jint)AUDIO_JAVA_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 }
Eric Laurent532bc1c2012-04-20 12:45:03 -0700777 lpTrack->getPositionUpdatePeriod(&period);
778 return (jint)period;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779}
780
781
782// ----------------------------------------------------------------------------
Glenn Kasten18db49a2012-03-12 16:29:55 -0700783static jint android_media_AudioTrack_set_position(JNIEnv *env, jobject thiz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 jint position) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700785 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
786 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 jniThrowException(env, "java/lang/IllegalStateException",
788 "Unable to retrieve AudioTrack pointer for setPosition()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700789 return (jint)AUDIO_JAVA_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 }
Eric Laurentbc11a692014-05-16 12:19:25 -0700791 return nativeToJavaStatus( lpTrack->setPosition(position) );
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792}
793
794
795// ----------------------------------------------------------------------------
796static jint android_media_AudioTrack_get_position(JNIEnv *env, jobject thiz) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700797 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 uint32_t position = 0;
Glenn Kasten18db49a2012-03-12 16:29:55 -0700799
Eric Laurent532bc1c2012-04-20 12:45:03 -0700800 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 jniThrowException(env, "java/lang/IllegalStateException",
802 "Unable to retrieve AudioTrack pointer for getPosition()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700803 return (jint)AUDIO_JAVA_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 }
Eric Laurent532bc1c2012-04-20 12:45:03 -0700805 lpTrack->getPosition(&position);
806 return (jint)position;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807}
808
809
810// ----------------------------------------------------------------------------
Oliver Woodman61dcdf32013-06-26 12:43:36 +0100811static jint android_media_AudioTrack_get_latency(JNIEnv *env, jobject thiz) {
812 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
813
814 if (lpTrack == NULL) {
815 jniThrowException(env, "java/lang/IllegalStateException",
816 "Unable to retrieve AudioTrack pointer for latency()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700817 return (jint)AUDIO_JAVA_ERROR;
Oliver Woodman61dcdf32013-06-26 12:43:36 +0100818 }
819 return (jint)lpTrack->latency();
820}
821
822
823// ----------------------------------------------------------------------------
Glenn Kasten948c2e62013-09-04 13:51:29 -0700824static jint android_media_AudioTrack_get_timestamp(JNIEnv *env, jobject thiz, jlongArray jTimestamp) {
825 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
826
827 if (lpTrack == NULL) {
828 ALOGE("Unable to retrieve AudioTrack pointer for getTimestamp()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700829 return (jint)AUDIO_JAVA_ERROR;
Glenn Kasten948c2e62013-09-04 13:51:29 -0700830 }
831 AudioTimestamp timestamp;
832 status_t status = lpTrack->getTimestamp(timestamp);
833 if (status == OK) {
834 jlong* nTimestamp = (jlong *) env->GetPrimitiveArrayCritical(jTimestamp, NULL);
835 if (nTimestamp == NULL) {
836 ALOGE("Unable to get array for getTimestamp()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700837 return (jint)AUDIO_JAVA_ERROR;
Glenn Kasten948c2e62013-09-04 13:51:29 -0700838 }
839 nTimestamp[0] = (jlong) timestamp.mPosition;
840 nTimestamp[1] = (jlong) ((timestamp.mTime.tv_sec * 1000000000LL) + timestamp.mTime.tv_nsec);
841 env->ReleasePrimitiveArrayCritical(jTimestamp, nTimestamp, 0);
842 }
Eric Laurentbc11a692014-05-16 12:19:25 -0700843 return (jint) nativeToJavaStatus(status);
Glenn Kasten948c2e62013-09-04 13:51:29 -0700844}
845
846
847// ----------------------------------------------------------------------------
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848static jint android_media_AudioTrack_set_loop(JNIEnv *env, jobject thiz,
849 jint loopStart, jint loopEnd, jint loopCount) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700850 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
851 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 jniThrowException(env, "java/lang/IllegalStateException",
853 "Unable to retrieve AudioTrack pointer for setLoop()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700854 return (jint)AUDIO_JAVA_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 }
Eric Laurentbc11a692014-05-16 12:19:25 -0700856 return nativeToJavaStatus( lpTrack->setLoop(loopStart, loopEnd, loopCount) );
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857}
858
859
860// ----------------------------------------------------------------------------
861static jint android_media_AudioTrack_reload(JNIEnv *env, jobject thiz) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700862 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
863 if (lpTrack == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 jniThrowException(env, "java/lang/IllegalStateException",
865 "Unable to retrieve AudioTrack pointer for reload()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700866 return (jint)AUDIO_JAVA_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 }
Eric Laurentbc11a692014-05-16 12:19:25 -0700868 return nativeToJavaStatus( lpTrack->reload() );
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869}
870
871
872// ----------------------------------------------------------------------------
873static jint android_media_AudioTrack_get_output_sample_rate(JNIEnv *env, jobject thiz,
874 jint javaStreamType) {
Glenn Kasten85fbc872012-11-14 13:21:09 -0800875 uint32_t afSamplingRate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 // convert the stream type from Java to native value
Jean-Michel Trivieac84382014-02-04 14:50:40 -0800877 // FIXME: code duplication with android_media_AudioTrack_setup()
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700878 audio_stream_type_t nativeStreamType;
Glenn Kasten29a09092012-01-16 14:37:12 -0800879 switch (javaStreamType) {
880 case AUDIO_STREAM_VOICE_CALL:
881 case AUDIO_STREAM_SYSTEM:
882 case AUDIO_STREAM_RING:
883 case AUDIO_STREAM_MUSIC:
884 case AUDIO_STREAM_ALARM:
885 case AUDIO_STREAM_NOTIFICATION:
886 case AUDIO_STREAM_BLUETOOTH_SCO:
887 case AUDIO_STREAM_DTMF:
888 nativeStreamType = (audio_stream_type_t) javaStreamType;
889 break;
890 default:
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700891 nativeStreamType = AUDIO_STREAM_DEFAULT;
Glenn Kasten29a09092012-01-16 14:37:12 -0800892 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 }
894
Glenn Kasten8f81d082012-11-28 14:37:48 -0800895 status_t status = AudioSystem::getOutputSamplingRate(&afSamplingRate, nativeStreamType);
896 if (status != NO_ERROR) {
897 ALOGE("Error %d in AudioSystem::getOutputSamplingRate() for stream type %d "
898 "in AudioTrack JNI", status, nativeStreamType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 return DEFAULT_OUTPUT_SAMPLE_RATE;
900 } else {
901 return afSamplingRate;
902 }
903}
904
905
906// ----------------------------------------------------------------------------
907// returns the minimum required size for the successful creation of a streaming AudioTrack
908// returns -1 if there was an error querying the hardware.
909static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thiz,
Glenn Kasten5b8fd442013-11-14 09:44:14 -0800910 jint sampleRateInHertz, jint channelCount, jint audioFormat) {
Chia-chi Yehc3308072010-08-19 17:14:36 +0800911
Glenn Kasten659a9712014-01-08 11:38:33 -0800912 size_t frameCount;
913 const status_t status = AudioTrack::getMinFrameCount(&frameCount, AUDIO_STREAM_DEFAULT,
914 sampleRateInHertz);
915 if (status != NO_ERROR) {
916 ALOGE("AudioTrack::getMinFrameCount() for sample rate %d failed with status %d",
917 sampleRateInHertz, status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 return -1;
919 }
Glenn Kastenfe834d32014-01-08 14:49:08 -0800920 const audio_format_t format = audioFormatToNative(audioFormat);
Eric Laurentff0d9f02014-06-09 17:23:02 -0700921 if (audio_is_linear_pcm(format)) {
922 const size_t bytesPerSample = audio_bytes_per_sample(format);
923 return frameCount * channelCount * bytesPerSample;
924 } else {
925 return frameCount;
926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927}
928
Eric Laurent7070b362010-07-16 07:43:46 -0700929// ----------------------------------------------------------------------------
Glenn Kasten3009f0b2014-03-28 16:02:26 -0700930static jint
Eric Laurent7070b362010-07-16 07:43:46 -0700931android_media_AudioTrack_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level )
932{
Eric Laurent532bc1c2012-04-20 12:45:03 -0700933 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
Eric Laurent7070b362010-07-16 07:43:46 -0700934 if (lpTrack == NULL ) {
935 jniThrowException(env, "java/lang/IllegalStateException",
936 "Unable to retrieve AudioTrack pointer for setAuxEffectSendLevel()");
Glenn Kasten3009f0b2014-03-28 16:02:26 -0700937 return -1;
Eric Laurent7070b362010-07-16 07:43:46 -0700938 }
939
Glenn Kasten3009f0b2014-03-28 16:02:26 -0700940 status_t status = lpTrack->setAuxEffectSendLevel(level);
941 if (status != NO_ERROR) {
942 ALOGE("AudioTrack::setAuxEffectSendLevel() for level %g failed with status %d",
943 level, status);
944 }
945 return (jint) status;
Eric Laurent7070b362010-07-16 07:43:46 -0700946}
947
948// ----------------------------------------------------------------------------
949static jint android_media_AudioTrack_attachAuxEffect(JNIEnv *env, jobject thiz,
950 jint effectId) {
Eric Laurent532bc1c2012-04-20 12:45:03 -0700951 sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
952 if (lpTrack == NULL) {
Eric Laurent7070b362010-07-16 07:43:46 -0700953 jniThrowException(env, "java/lang/IllegalStateException",
954 "Unable to retrieve AudioTrack pointer for attachAuxEffect()");
Eric Laurentbc11a692014-05-16 12:19:25 -0700955 return (jint)AUDIO_JAVA_ERROR;
Eric Laurent7070b362010-07-16 07:43:46 -0700956 }
Eric Laurentbc11a692014-05-16 12:19:25 -0700957 return nativeToJavaStatus( lpTrack->attachAuxEffect(effectId) );
Eric Laurent7070b362010-07-16 07:43:46 -0700958}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959
960// ----------------------------------------------------------------------------
961// ----------------------------------------------------------------------------
962static JNINativeMethod gMethods[] = {
963 // name, signature, funcPtr
964 {"native_start", "()V", (void *)android_media_AudioTrack_start},
965 {"native_stop", "()V", (void *)android_media_AudioTrack_stop},
966 {"native_pause", "()V", (void *)android_media_AudioTrack_pause},
967 {"native_flush", "()V", (void *)android_media_AudioTrack_flush},
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -0700968 {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;IIIII[I)I",
Jean-Michel Trivieac84382014-02-04 14:50:40 -0800969 (void *)android_media_AudioTrack_setup},
970 {"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
971 {"native_release", "()V", (void *)android_media_AudioTrack_release},
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -0800972 {"native_write_byte", "([BIIIZ)I",(void *)android_media_AudioTrack_write_byte},
973 {"native_write_native_bytes",
Jean-Michel Trivi5d21f672014-03-20 17:02:31 -0700974 "(Ljava/lang/Object;IIIZ)I",
Jean-Michel Trivi7ca04522014-02-07 09:39:34 -0800975 (void *)android_media_AudioTrack_write_native_bytes},
Jean-Michel Trivieac84382014-02-04 14:50:40 -0800976 {"native_write_short", "([SIII)I", (void *)android_media_AudioTrack_write_short},
Glenn Kasten54955e32014-04-30 18:03:15 -0700977 {"native_write_float", "([FIIIZ)I",(void *)android_media_AudioTrack_write_float},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 {"native_setVolume", "(FF)V", (void *)android_media_AudioTrack_set_volume},
979 {"native_get_native_frame_count",
980 "()I", (void *)android_media_AudioTrack_get_native_frame_count},
981 {"native_set_playback_rate",
Eric Laurent88e209d2009-07-07 07:10:45 -0700982 "(I)I", (void *)android_media_AudioTrack_set_playback_rate},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 {"native_get_playback_rate",
984 "()I", (void *)android_media_AudioTrack_get_playback_rate},
985 {"native_set_marker_pos","(I)I", (void *)android_media_AudioTrack_set_marker_pos},
986 {"native_get_marker_pos","()I", (void *)android_media_AudioTrack_get_marker_pos},
987 {"native_set_pos_update_period",
988 "(I)I", (void *)android_media_AudioTrack_set_pos_update_period},
989 {"native_get_pos_update_period",
990 "()I", (void *)android_media_AudioTrack_get_pos_update_period},
991 {"native_set_position", "(I)I", (void *)android_media_AudioTrack_set_position},
992 {"native_get_position", "()I", (void *)android_media_AudioTrack_get_position},
Oliver Woodman61dcdf32013-06-26 12:43:36 +0100993 {"native_get_latency", "()I", (void *)android_media_AudioTrack_get_latency},
Glenn Kasten948c2e62013-09-04 13:51:29 -0700994 {"native_get_timestamp", "([J)I", (void *)android_media_AudioTrack_get_timestamp},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 {"native_set_loop", "(III)I", (void *)android_media_AudioTrack_set_loop},
996 {"native_reload_static", "()I", (void *)android_media_AudioTrack_reload},
997 {"native_get_output_sample_rate",
998 "(I)I", (void *)android_media_AudioTrack_get_output_sample_rate},
999 {"native_get_min_buff_size",
1000 "(III)I", (void *)android_media_AudioTrack_get_min_buff_size},
Eric Laurent7070b362010-07-16 07:43:46 -07001001 {"native_setAuxEffectSendLevel",
Glenn Kasten3009f0b2014-03-28 16:02:26 -07001002 "(F)I", (void *)android_media_AudioTrack_setAuxEffectSendLevel},
Eric Laurent7070b362010-07-16 07:43:46 -07001003 {"native_attachAuxEffect",
1004 "(I)I", (void *)android_media_AudioTrack_attachAuxEffect},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005};
1006
1007
1008// field names found in android/media/AudioTrack.java
1009#define JAVA_POSTEVENT_CALLBACK_NAME "postEventFromNative"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010#define JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME "mNativeTrackInJavaObj"
1011#define JAVA_JNIDATA_FIELD_NAME "mJniData"
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -07001012#define JAVA_STREAMTYPE_FIELD_NAME "mStreamType"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014// ----------------------------------------------------------------------------
1015// preconditions:
1016// theClass is valid
1017bool android_media_getIntConstantFromClass(JNIEnv* pEnv, jclass theClass, const char* className,
1018 const char* constName, int* constVal) {
1019 jfieldID javaConst = NULL;
1020 javaConst = pEnv->GetStaticFieldID(theClass, constName, "I");
1021 if (javaConst != NULL) {
1022 *constVal = pEnv->GetStaticIntField(theClass, javaConst);
1023 return true;
1024 } else {
Steve Block3762c312012-01-06 19:20:56 +00001025 ALOGE("Can't find %s.%s", className, constName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 return false;
1027 }
1028}
1029
1030
1031// ----------------------------------------------------------------------------
1032int register_android_media_AudioTrack(JNIEnv *env)
1033{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 javaAudioTrackFields.nativeTrackInJavaObj = NULL;
1035 javaAudioTrackFields.postNativeEventInJava = NULL;
1036
1037 // Get the AudioTrack class
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001038 jclass audioTrackClass = FindClassOrDie(env, kClassPathName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039
1040 // Get the postEvent method
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001041 javaAudioTrackFields.postNativeEventInJava = GetStaticMethodIDOrDie(env,
1042 audioTrackClass, JAVA_POSTEVENT_CALLBACK_NAME,
1043 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044
1045 // Get the variables fields
1046 // nativeTrackInJavaObj
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001047 javaAudioTrackFields.nativeTrackInJavaObj = GetFieldIDOrDie(env,
1048 audioTrackClass, JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME, "J");
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -07001049 // jniData
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001050 javaAudioTrackFields.jniData = GetFieldIDOrDie(env,
1051 audioTrackClass, JAVA_JNIDATA_FIELD_NAME, "J");
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -07001052 // fieldStreamType
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001053 javaAudioTrackFields.fieldStreamType = GetFieldIDOrDie(env,
1054 audioTrackClass, JAVA_STREAMTYPE_FIELD_NAME, "I");
Jean-Michel Trivia1d80e32014-06-18 08:18:41 -07001055
1056 // Get the AudioAttributes class and fields
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001057 jclass audioAttrClass = FindClassOrDie(env, kAudioAttributesClassPathName);
1058 javaAudioAttrFields.fieldUsage = GetFieldIDOrDie(env, audioAttrClass, "mUsage", "I");
1059 javaAudioAttrFields.fieldContentType = GetFieldIDOrDie(env,
1060 audioAttrClass, "mContentType", "I");
1061 javaAudioAttrFields.fieldFlags = GetFieldIDOrDie(env, audioAttrClass, "mFlags", "I");
1062 javaAudioAttrFields.fieldFormattedTags = GetFieldIDOrDie(env,
1063 audioAttrClass, "mFormattedTags", "Ljava/lang/String;");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001065 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066}
1067
1068
1069// ----------------------------------------------------------------------------