android_media_AudioTrack.cpp revision 973b8851eecbdcbab4992be01aaab568fd371a0a
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"
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* const kClassPathName = "android/media/AudioTrack";
47a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistatic const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes";
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
49a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistruct audio_track_fields_t {
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these fields provide access from C++ to the...
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jmethodID postNativeEventInJava; //... event post callback method
5283b368505052f59616d29558e65e2250d01fd848Eric Laurent    jfieldID  nativeTrackInJavaObj;  // stores in Java the native AudioTrack object
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID  jniData;      // stores in Java additional resources used by the native AudioTrack
54a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    jfieldID  fieldStreamType; // ... mStreamType field in the AudioTrack Java object
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
56a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistruct audio_attributes_fields_t {
57701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi    jfieldID  fieldUsage;        // AudioAttributes.mUsage
58701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi    jfieldID  fieldContentType;  // AudioAttributes.mContentType
59701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi    jfieldID  fieldFlags;        // AudioAttributes.mFlags
60701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi    jfieldID  fieldFormattedTags;// AudioAttributes.mFormattedTags
61a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi};
62a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistatic audio_track_fields_t      javaAudioTrackFields;
63a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistatic audio_attributes_fields_t javaAudioAttrFields;
642d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jiastatic PlaybackParams::fields_t gPlaybackParamsFields;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct audiotrack_callback_cookie {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass      audioTrack_class;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jobject     audioTrack_ref;
69532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    bool        busy;
70532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    Condition   cond;
71532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent};
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
733d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten// keep these values in sync with AudioTrack.java
743d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten#define MODE_STATIC 0
753d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten#define MODE_STREAM 1
763d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass AudioTrackJniStorage {
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public:
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sp<MemoryHeapBase>         mMemHeap;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sp<MemoryBase>             mMemBase;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        audiotrack_callback_cookie mCallbackData;
834bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        sp<JNIDeviceCallback>      mDeviceCallback;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AudioTrackJniStorage() {
868a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi        mCallbackData.audioTrack_class = 0;
878a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi        mCallbackData.audioTrack_ref = 0;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ~AudioTrackJniStorage() {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMemBase.clear();
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMemHeap.clear();
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool allocSharedMem(int sizeInBytes) {
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMemHeap = new MemoryHeapBase(sizeInBytes, 0, "AudioTrack Heap Base");
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mMemHeap->getHeapID() < 0) {
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMemBase = new MemoryBase(mMemHeap, 0, sizeInBytes);
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
105532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic Mutex sLock;
106532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic SortedVector <audiotrack_callback_cookie *> sAudioTrackCallBackCookies;
107532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define DEFAULT_OUTPUT_SAMPLE_RATE   44100
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM         -16
112fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten#define AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK  -17
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT       -18
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define AUDIOTRACK_ERROR_SETUP_INVALIDSTREAMTYPE   -19
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED    -20
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
118e46a86fcb6a0849fc05c4cade6cb94aad0325295Glenn Kastenstatic void audioCallback(int event, void* user, void *info) {
119532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent
120532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    audiotrack_callback_cookie *callbackInfo = (audiotrack_callback_cookie *)user;
121532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    {
122532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        Mutex::Autolock l(sLock);
123532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        if (sAudioTrackCallBackCookies.indexOf(callbackInfo) < 0) {
124532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent            return;
125532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        }
126532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        callbackInfo->busy = true;
127532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    }
128532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent
1295b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten    switch (event) {
1305b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten    case AudioTrack::EVENT_MARKER: {
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        JNIEnv *env = AndroidRuntime::getJNIEnv();
132a667ff30e4fb6f741c2a930e7c31ef7e962d3b40Glenn Kasten        if (user != NULL && env != NULL) {
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->CallStaticVoidMethod(
13418db49a46259020387c40fff36d92edc1087a366Glenn Kasten                callbackInfo->audioTrack_class,
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                javaAudioTrackFields.postNativeEventInJava,
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                callbackInfo->audioTrack_ref, event, 0,0, NULL);
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (env->ExceptionCheck()) {
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                env->ExceptionDescribe();
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                env->ExceptionClear();
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1425b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten        } break;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1445b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten    case AudioTrack::EVENT_NEW_POS: {
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        JNIEnv *env = AndroidRuntime::getJNIEnv();
146a667ff30e4fb6f741c2a930e7c31ef7e962d3b40Glenn Kasten        if (user != NULL && env != NULL) {
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            env->CallStaticVoidMethod(
14818db49a46259020387c40fff36d92edc1087a366Glenn Kasten                callbackInfo->audioTrack_class,
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                javaAudioTrackFields.postNativeEventInJava,
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                callbackInfo->audioTrack_ref, event, 0,0, NULL);
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (env->ExceptionCheck()) {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                env->ExceptionDescribe();
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                env->ExceptionClear();
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1565b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten        } break;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1585b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten
159532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    {
160532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        Mutex::Autolock l(sLock);
161532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        callbackInfo->busy = false;
162532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        callbackInfo->cond.broadcast();
163532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    }
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
168532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic sp<AudioTrack> getAudioTrack(JNIEnv* env, jobject thiz)
169532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent{
170532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    Mutex::Autolock l(sLock);
171532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    AudioTrack* const at =
172075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat            (AudioTrack*)env->GetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj);
173532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    return sp<AudioTrack>(at);
174532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent}
175532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent
176532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic sp<AudioTrack> setAudioTrack(JNIEnv* env, jobject thiz, const sp<AudioTrack>& at)
177532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent{
178532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    Mutex::Autolock l(sLock);
179532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> old =
180075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat            (AudioTrack*)env->GetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj);
181532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (at.get()) {
182b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian        at->incStrong((void*)setAudioTrack);
183532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    }
184532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (old != 0) {
185b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian        old->decStrong((void*)setAudioTrack);
186532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    }
187075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, (jlong)at.get());
188532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    return old;
189532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent}
190071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia
191071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia// ----------------------------------------------------------------------------
192071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jiasp<AudioTrack> android_media_AudioTrack_getAudioTrack(JNIEnv* env, jobject audioTrackObj) {
193071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia    return getAudioTrack(env, audioTrackObj);
194071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia}
195071a8b71d1212e218a3ebf7dbb8908a4acf5cf6dWei Jia
19630d794360f35592554403922bcc07835fea4737bAndy Hung// This function converts Java channel masks to a native channel mask.
19730d794360f35592554403922bcc07835fea4737bAndy Hung// validity should be checked with audio_is_output_channel().
19830d794360f35592554403922bcc07835fea4737bAndy Hungstatic inline audio_channel_mask_t nativeChannelMaskFromJavaChannelMasks(
19930d794360f35592554403922bcc07835fea4737bAndy Hung        jint channelPositionMask, jint channelIndexMask)
20030d794360f35592554403922bcc07835fea4737bAndy Hung{
20130d794360f35592554403922bcc07835fea4737bAndy Hung    if (channelIndexMask != 0) {  // channel index mask takes priority
20230d794360f35592554403922bcc07835fea4737bAndy Hung        // To convert to a native channel mask, the Java channel index mask
20330d794360f35592554403922bcc07835fea4737bAndy Hung        // requires adding the index representation.
20430d794360f35592554403922bcc07835fea4737bAndy Hung        return audio_channel_mask_from_representation_and_bits(
20530d794360f35592554403922bcc07835fea4737bAndy Hung                        AUDIO_CHANNEL_REPRESENTATION_INDEX,
20630d794360f35592554403922bcc07835fea4737bAndy Hung                        channelIndexMask);
20730d794360f35592554403922bcc07835fea4737bAndy Hung    }
20830d794360f35592554403922bcc07835fea4737bAndy Hung    // To convert to a native channel mask, the Java channel position mask
20930d794360f35592554403922bcc07835fea4737bAndy Hung    // requires a shift by 2 to skip the two deprecated channel
21030d794360f35592554403922bcc07835fea4737bAndy Hung    // configurations "default" and "mono".
21130d794360f35592554403922bcc07835fea4737bAndy Hung    return (audio_channel_mask_t)(channelPositionMask >> 2);
21230d794360f35592554403922bcc07835fea4737bAndy Hung}
21330d794360f35592554403922bcc07835fea4737bAndy Hung
214532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent// ----------------------------------------------------------------------------
215075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhatstatic jint
216eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Triviandroid_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
217a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        jobject jaa,
21830d794360f35592554403922bcc07835fea4737bAndy Hung        jint sampleRateInHertz, jint channelPositionMask, jint channelIndexMask,
219a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession) {
220a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi
22130d794360f35592554403922bcc07835fea4737bAndy Hung    ALOGV("sampleRate=%d, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d",
22230d794360f35592554403922bcc07835fea4737bAndy Hung        sampleRateInHertz, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes);
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
224a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    if (jaa == 0) {
225a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        ALOGE("Error creating AudioTrack: invalid audio attributes");
226a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        return (jint) AUDIO_JAVA_ERROR;
227a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    }
228a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi
229a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung    // Invalid channel representations are caught by !audio_is_output_channel() below.
23030d794360f35592554403922bcc07835fea4737bAndy Hung    audio_channel_mask_t nativeChannelMask = nativeChannelMaskFromJavaChannelMasks(
23130d794360f35592554403922bcc07835fea4737bAndy Hung            channelPositionMask, channelIndexMask);
232d9ae1c573e37e245c7f4f0480a8fa925e57bd49dJean-Michel Trivi    if (!audio_is_output_channel(nativeChannelMask)) {
23330d794360f35592554403922bcc07835fea4737bAndy Hung        ALOGE("Error creating AudioTrack: invalid native channel mask %#x.", nativeChannelMask);
234075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
236d9ae1c573e37e245c7f4f0480a8fa925e57bd49dJean-Michel Trivi
237dbf55665c5c4802cbfc56463198805be48ec75afEric Laurent    uint32_t channelCount = audio_channel_count_from_out_mask(nativeChannelMask);
23818db49a46259020387c40fff36d92edc1087a366Glenn Kasten
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // check the format.
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // This function was called from Java, so we compare the format against the Java constants
241fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten    audio_format_t format = audioFormatToNative(audioFormat);
242fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten    if (format == AUDIO_FORMAT_INVALID) {
2438f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten        ALOGE("Error creating AudioTrack: unsupported audio format %d.", audioFormat);
244075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // compute the frame count
248ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent    size_t frameCount;
249ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent    if (audio_is_linear_pcm(format)) {
250ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        const size_t bytesPerSample = audio_bytes_per_sample(format);
251ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        frameCount = buffSizeInBytes / (channelCount * bytesPerSample);
252ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent    } else {
253ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        frameCount = buffSizeInBytes;
254ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent    }
25518db49a46259020387c40fff36d92edc1087a366Glenn Kasten
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass clazz = env->GetObjectClass(thiz);
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (clazz == NULL) {
2583762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find %s when setting up callback.", kClassPathName);
259075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2612fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent
2622fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    if (jSession == NULL) {
2633762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Error creating AudioTrack: invalid session ID pointer");
264bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint) AUDIO_JAVA_ERROR;
265619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    }
266619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent
2672fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    jint* nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
2682fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    if (nSession == NULL) {
2693762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Error creating AudioTrack: Error retrieving session id pointer");
270bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint) AUDIO_JAVA_ERROR;
2712fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    }
2722fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    int sessionId = nSession[0];
2732fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
2742fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    nSession = NULL;
2752fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // create the native AudioTrack object
277532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = new AudioTrack();
27818db49a46259020387c40fff36d92edc1087a366Glenn Kasten
279a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    audio_attributes_t *paa = NULL;
280a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    // read the AudioAttributes values
281a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
282701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi    const jstring jtags =
283701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi            (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
284a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    const char* tags = env->GetStringUTFChars(jtags, NULL);
285a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
286a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
287a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    env->ReleaseStringUTFChars(jtags, tags);
288a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage);
289a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    paa->content_type =
290a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi            (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
291a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
292a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi
293a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    ALOGV("AudioTrack_setup for usage=%d content=%d flags=0x%#x tags=%s",
294a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi            paa->usage, paa->content_type, paa->flags, paa->tags);
295a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi
296532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    // initialize the callback information:
297532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    // this data will be passed with every AudioTrack callback
298532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    AudioTrackJniStorage* lpJniStorage = new AudioTrackJniStorage();
299532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz);
300532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    // we use a weak reference so the AudioTrack object can be garbage collected.
301532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this);
302532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    lpJniStorage->mCallbackData.busy = false;
303532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // initialize the native AudioTrack object
3052defed988f74c98d5af8d02551ebf7262490cc5bJean-Michel Trivi    status_t status = NO_ERROR;
3063d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten    switch (memoryMode) {
3073d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten    case MODE_STREAM:
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
309c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten        status = lpTrack->set(
310c8d6b6fc7dd05c10ca301e654f063cc89781c9beJean-Michel Trivi                AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
311a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                sampleRateInHertz,
312a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                format,// word length, PCM
313a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                nativeChannelMask,
314a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                frameCount,
315a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                AUDIO_OUTPUT_FLAG_NONE,
316a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
317a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
318a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                0,// shared mem
319a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                true,// thread can call Java
320a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                sessionId,// audio session ID
321c8d6b6fc7dd05c10ca301e654f063cc89781c9beJean-Michel Trivi                AudioTrack::TRANSFER_SYNC,
322a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                NULL,                         // default offloadInfo
323a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                -1, -1,                       // default uid, pid values
324a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                paa);
3253d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten        break;
32618db49a46259020387c40fff36d92edc1087a366Glenn Kasten
3273d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten    case MODE_STATIC:
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // AudioTrack is using shared memory
32918db49a46259020387c40fff36d92edc1087a366Glenn Kasten
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) {
3313762c311729fe9f3af085c14c5c1fb471d994c03Steve Block            ALOGE("Error creating AudioTrack in static mode: error creating mem heap base");
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            goto native_init_failure;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
33418db49a46259020387c40fff36d92edc1087a366Glenn Kasten
335c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten        status = lpTrack->set(
336c8d6b6fc7dd05c10ca301e654f063cc89781c9beJean-Michel Trivi                AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
337a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                sampleRateInHertz,
338a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                format,// word length, PCM
339a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                nativeChannelMask,
340a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                frameCount,
341a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                AUDIO_OUTPUT_FLAG_NONE,
342a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
343a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
344a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                lpJniStorage->mMemBase,// shared mem
345a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                true,// thread can call Java
346a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                sessionId,// audio session ID
347c8d6b6fc7dd05c10ca301e654f063cc89781c9beJean-Michel Trivi                AudioTrack::TRANSFER_SHARED,
348a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                NULL,                         // default offloadInfo
349a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                -1, -1,                       // default uid, pid values
350a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                paa);
3513d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten        break;
3523d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten
3533d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten    default:
3543d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten        ALOGE("Unknown mode %d", memoryMode);
3553d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten        goto native_init_failure;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
358c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten    if (status != NO_ERROR) {
359c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten        ALOGE("Error %d initializing AudioTrack", status);
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto native_init_failure;
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3632fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
3642fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    if (nSession == NULL) {
3653762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Error creating AudioTrack: Error retrieving session id pointer");
3662fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent        goto native_init_failure;
3672fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent    }
368619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    // read the audio session ID back from AudioTrack in case we create a new session
369619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    nSession[0] = lpTrack->getSessionId();
370619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
371619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    nSession = NULL;
372619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent
373532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    {   // scope for the lock
374532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        Mutex::Autolock l(sLock);
375532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        sAudioTrackCallBackCookies.add(&lpJniStorage->mCallbackData);
376532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    }
37718db49a46259020387c40fff36d92edc1087a366Glenn Kasten    // save our newly created C++ AudioTrack in the "nativeTrackInJavaObj" field
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // of the Java object (in mNativeTrackInJavaObj)
379532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    setAudioTrack(env, thiz, lpTrack);
38018db49a46259020387c40fff36d92edc1087a366Glenn Kasten
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // save the JNI resources so we can free them later
382075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    //ALOGV("storing lpJniStorage: %x\n", (long)lpJniStorage);
383075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, javaAudioTrackFields.jniData, (jlong)lpJniStorage);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
385a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    // since we had audio attributes, the stream type was derived from them during the
386a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    // creation of the native AudioTrack: push the same value to the Java object
387a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    env->SetIntField(thiz, javaAudioTrackFields.fieldStreamType, (jint) lpTrack->streamType());
388a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    // audio attributes were copied in AudioTrack creation
389a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    free(paa);
390a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    paa = NULL;
391a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi
392a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi
393bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    return (jint) AUDIO_JAVA_SUCCESS;
39418db49a46259020387c40fff36d92edc1087a366Glenn Kasten
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // failures:
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnative_init_failure:
397a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    if (paa != NULL) {
398a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        free(paa);
399a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    }
400619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    if (nSession != NULL) {
401619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
402619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    }
4038a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi    env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_class);
4048a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi    env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_ref);
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete lpJniStorage;
406075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, javaAudioTrackFields.jniData, 0);
40718db49a46259020387c40fff36d92edc1087a366Glenn Kasten
408075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_start(JNIEnv *env, jobject thiz)
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
416532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
417532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for start()");
4207070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        return;
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
42221dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lpTrack->start();
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_stop(JNIEnv *env, jobject thiz)
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
431532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
432532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for stop()");
4357070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        return;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lpTrack->stop();
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_pause(JNIEnv *env, jobject thiz)
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
446532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
447532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for pause()");
4507070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        return;
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lpTrack->pause();
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_flush(JNIEnv *env, jobject thiz)
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
461532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
462532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for flush()");
4657070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        return;
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lpTrack->flush();
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_set_volume(JNIEnv *env, jobject thiz, jfloat leftVol, jfloat rightVol )
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
475532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
476532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for setVolume()");
4797070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        return;
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    lpTrack->setVolume(leftVol, rightVol);
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
48618db49a46259020387c40fff36d92edc1087a366Glenn Kasten
487532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent#define CALLBACK_COND_WAIT_TIMEOUT_MS 1000
488eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic void android_media_AudioTrack_release(JNIEnv *env,  jobject thiz) {
489532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = setAudioTrack(env, thiz, 0);
490532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
491532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        return;
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
493532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    //ALOGV("deleting lpTrack: %x\n", (int)lpTrack);
494532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    lpTrack->stop();
49518db49a46259020387c40fff36d92edc1087a366Glenn Kasten
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // delete the JNI data
497075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField(
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        thiz, javaAudioTrackFields.jniData);
499532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    // reset the native resources in the Java object so any attempt to access
500532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    // them after a call to release fails.
501075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, javaAudioTrackFields.jniData, 0);
502532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (pJniStorage) {
504532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        Mutex::Autolock l(sLock);
505532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        audiotrack_callback_cookie *lpCookie = &pJniStorage->mCallbackData;
50671f2cf116aab893e224056c38ab146bd1538dd3eSteve Block        //ALOGV("deleting pJniStorage: %x\n", (int)pJniStorage);
507532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        while (lpCookie->busy) {
508532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent            if (lpCookie->cond.waitRelative(sLock,
509532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent                                            milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) !=
510532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent                                                    NO_ERROR) {
511532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent                break;
512532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent            }
513532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        }
514532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        sAudioTrackCallBackCookies.remove(lpCookie);
515532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        // delete global refs created in native_setup
516532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        env->DeleteGlobalRef(lpCookie->audioTrack_class);
517532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent        env->DeleteGlobalRef(lpCookie->audioTrack_ref);
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete pJniStorage;
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
52218db49a46259020387c40fff36d92edc1087a366Glenn Kasten
523532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent// ----------------------------------------------------------------------------
524eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic void android_media_AudioTrack_finalize(JNIEnv *env,  jobject thiz) {
525eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi    //ALOGV("android_media_AudioTrack_finalize jobject: %x\n", (int)thiz);
526eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi    android_media_AudioTrack_release(env, thiz);
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5294aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung// overloaded JNI array helper functions (same as in android_media_AudioRecord)
5304aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline
5314aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungjbyte *envGetArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) {
5324aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    return env->GetByteArrayElements(array, isCopy);
5334aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung}
5344aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung
5354aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline
5364aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungvoid envReleaseArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, jint mode) {
5374aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    env->ReleaseByteArrayElements(array, elems, mode);
5384aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung}
5394aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung
5404aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline
5414aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungjshort *envGetArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy) {
5424aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    return env->GetShortArrayElements(array, isCopy);
5434aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung}
5444aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung
5454aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline
5464aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungvoid envReleaseArrayElements(JNIEnv *env, jshortArray array, jshort *elems, jint mode) {
5474aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    env->ReleaseShortArrayElements(array, elems, mode);
5484aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung}
5494aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung
5504aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline
5514aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungjfloat *envGetArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy) {
5524aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    return env->GetFloatArrayElements(array, isCopy);
5534aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung}
5544aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung
5554aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic inline
5564aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungvoid envReleaseArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, jint mode) {
5574aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    env->ReleaseFloatArrayElements(array, elems, mode);
5584aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung}
5594aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
5614aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungtemplate <typename T>
5624aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const T *data,
5634aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung                         jint offsetInSamples, jint sizeInSamples, bool blocking) {
56421dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi    // give the data to the native AudioTrack object (the data starts at the offset)
56521dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi    ssize_t written = 0;
56621dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi    // regular write() or copy the data to the AudioTrack's shared memory?
5674aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    size_t sizeInBytes = sizeInSamples * sizeof(T);
568532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (track->sharedBuffer() == 0) {
5694aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        written = track->write(data + offsetInSamples, sizeInBytes, blocking);
5709b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten        // for compatibility with earlier behavior of write(), return 0 in this case
5719b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten        if (written == (ssize_t) WOULD_BLOCK) {
5729b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten            written = 0;
5739b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten        }
57421dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi    } else {
5752c0e17c029eccc06deb883d8d564a7e19d98f65eAndy Hung        // writing to shared memory, check for capacity
5762c0e17c029eccc06deb883d8d564a7e19d98f65eAndy Hung        if ((size_t)sizeInBytes > track->sharedBuffer()->size()) {
5772c0e17c029eccc06deb883d8d564a7e19d98f65eAndy Hung            sizeInBytes = track->sharedBuffer()->size();
57821dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi        }
5794aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        memcpy(track->sharedBuffer()->pointer(), data + offsetInSamples, sizeInBytes);
5802c0e17c029eccc06deb883d8d564a7e19d98f65eAndy Hung        written = sizeInBytes;
58121dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi    }
5824aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    if (written > 0) {
5834aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        return written / sizeof(T);
5844aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    }
5854aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    // for compatibility, error codes pass through unchanged
58621dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi    return written;
58721dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi}
58821dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi
58921dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi// ----------------------------------------------------------------------------
5904aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungtemplate <typename T>
5914aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hungstatic jint android_media_AudioTrack_writeArray(JNIEnv *env, jobject thiz,
5924aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung                                                T javaAudioData,
5934aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung                                                jint offsetInSamples, jint sizeInSamples,
5944aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung                                                jint javaAudioFormat,
5954aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung                                                jboolean isWriteBlocking) {
5964aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    //ALOGV("android_media_AudioTrack_writeArray(offset=%d, sizeInSamples=%d) called",
5974aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    //        offsetInSamples, sizeInSamples);
598532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (lpTrack == NULL) {
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for write()");
6024aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        return (jint)AUDIO_JAVA_INVALID_OPERATION;
6034aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    }
6044aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung
6054aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    if (javaAudioData == NULL) {
6064aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        ALOGE("NULL java array of audio data to play");
6074aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        return (jint)AUDIO_JAVA_BAD_VALUE;
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
610421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent    // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
611421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent    // a way that it becomes much more efficient. When doing so, we will have to prevent the
612421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent    // AudioSystem callback to be called while in critical section (in case of media server
613421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent    // process crash for instance)
6144aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung
6154aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    // get the pointer for the audio data from the java array
6164aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    auto cAudioData = envGetArrayElements(env, javaAudioData, NULL);
6174aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    if (cAudioData == NULL) {
6184aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        ALOGE("Error retrieving source of audio data to play");
6194aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        return (jint)AUDIO_JAVA_BAD_VALUE; // out of memory or no data to load
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6224aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    jint samplesWritten = writeToTrack(lpTrack, javaAudioFormat, cAudioData,
6234aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung            offsetInSamples, sizeInSamples, isWriteBlocking == JNI_TRUE /* blocking */);
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6254aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    envReleaseArrayElements(env, javaAudioData, cAudioData, 0);
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6274aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    //ALOGV("write wrote %d (tried %d) samples in the native AudioTrack with offset %d",
6284aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    //        (int)samplesWritten, (int)(sizeInSamples), (int)offsetInSamples);
6294aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    return samplesWritten;
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
6337ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivistatic jint android_media_AudioTrack_write_native_bytes(JNIEnv *env,  jobject thiz,
6345d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi        jbyteArray javaBytes, jint byteOffset, jint sizeInBytes,
6357ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        jint javaAudioFormat, jboolean isWriteBlocking) {
6367ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    //ALOGV("android_media_AudioTrack_write_native_bytes(offset=%d, sizeInBytes=%d) called",
6377ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    //    offsetInBytes, sizeInBytes);
6387ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
6397ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    if (lpTrack == NULL) {
6407ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        jniThrowException(env, "java/lang/IllegalStateException",
6417ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                "Unable to retrieve AudioTrack pointer for write()");
6424aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        return (jint)AUDIO_JAVA_INVALID_OPERATION;
6437ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    }
6447ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
6457ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    ScopedBytesRO bytes(env, javaBytes);
6467ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    if (bytes.get() == NULL) {
6477ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        ALOGE("Error retrieving source of audio data to play, can't play");
648bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_BAD_VALUE;
6497ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    }
6507ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
6515d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi    jint written = writeToTrack(lpTrack, javaAudioFormat, bytes.get(), byteOffset,
6527ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            sizeInBytes, isWriteBlocking == JNI_TRUE /* blocking */);
6537ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
6547ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    return written;
6557ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi}
6567ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
6577ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi// ----------------------------------------------------------------------------
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_native_frame_count(JNIEnv *env,  jobject thiz) {
659532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
660532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for frameCount()");
663bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
665532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent
666532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    return lpTrack->frameCount();
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
67188e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurentstatic jint android_media_AudioTrack_set_playback_rate(JNIEnv *env,  jobject thiz,
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jint sampleRateInHz) {
673532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
674532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for setSampleRate()");
677bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
679bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    return nativeToJavaStatus(lpTrack->setSampleRate(sampleRateInHz));
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_playback_rate(JNIEnv *env,  jobject thiz) {
685532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
686532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for getSampleRate()");
689bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
691532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    return (jint) lpTrack->getSampleRate();
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
6962d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jiastatic void android_media_AudioTrack_set_playback_params(JNIEnv *env,  jobject thiz,
6972d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia        jobject params) {
698263b4c97823295c41900210515d0c769a236190cAndy Hung    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
699263b4c97823295c41900210515d0c769a236190cAndy Hung    if (lpTrack == NULL) {
700263b4c97823295c41900210515d0c769a236190cAndy Hung        jniThrowException(env, "java/lang/IllegalStateException",
701263b4c97823295c41900210515d0c769a236190cAndy Hung            "AudioTrack not initialized");
702263b4c97823295c41900210515d0c769a236190cAndy Hung        return;
703263b4c97823295c41900210515d0c769a236190cAndy Hung    }
704263b4c97823295c41900210515d0c769a236190cAndy Hung
705973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    PlaybackParams pbp;
706973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    pbp.fillFromJobject(env, gPlaybackParamsFields, params);
707fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung
7082d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia    ALOGV("setPlaybackParams: %d:%f %d:%f %d:%u %d:%u",
709973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung            pbp.speedSet, pbp.audioRate.mSpeed,
710973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung            pbp.pitchSet, pbp.audioRate.mPitch,
711973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung            pbp.audioFallbackModeSet, pbp.audioRate.mFallbackMode,
712973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung            pbp.audioStretchModeSet, pbp.audioRate.mStretchMode);
713973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung
714973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    // to simulate partially set params, we do a read-modify-write.
715973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    // TODO: pass in the valid set mask into AudioTrack.
716973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    AudioPlaybackRate rate = lpTrack->getPlaybackRate();
717973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    bool updatedRate = false;
718973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    if (pbp.speedSet) {
719973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung        rate.mSpeed = pbp.audioRate.mSpeed;
720973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung        updatedRate = true;
721973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    }
722973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    if (pbp.pitchSet) {
723973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung        rate.mPitch = pbp.audioRate.mPitch;
724973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung        updatedRate = true;
725973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    }
726973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    if (pbp.audioFallbackModeSet) {
727973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung        rate.mFallbackMode = pbp.audioRate.mFallbackMode;
728973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung        updatedRate = true;
729973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    }
730973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    if (pbp.audioStretchModeSet) {
731973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung        rate.mStretchMode = pbp.audioRate.mStretchMode;
732973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung        updatedRate = true;
733973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    }
734973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung    if (updatedRate) {
735973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung        if (lpTrack->setPlaybackRate(rate) != OK) {
736973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung            jniThrowException(env, "java/lang/IllegalArgumentException",
737973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung                    "arguments out of range");
738973b8851eecbdcbab4992be01aaab568fd371a0aAndy Hung        }
739263b4c97823295c41900210515d0c769a236190cAndy Hung    }
740263b4c97823295c41900210515d0c769a236190cAndy Hung}
741263b4c97823295c41900210515d0c769a236190cAndy Hung
742263b4c97823295c41900210515d0c769a236190cAndy Hung
743263b4c97823295c41900210515d0c769a236190cAndy Hung// ----------------------------------------------------------------------------
7442d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jiastatic jobject android_media_AudioTrack_get_playback_params(JNIEnv *env,  jobject thiz,
7452d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia        jobject params) {
746263b4c97823295c41900210515d0c769a236190cAndy Hung    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
747263b4c97823295c41900210515d0c769a236190cAndy Hung    if (lpTrack == NULL) {
748263b4c97823295c41900210515d0c769a236190cAndy Hung        jniThrowException(env, "java/lang/IllegalStateException",
749263b4c97823295c41900210515d0c769a236190cAndy Hung            "AudioTrack not initialized");
750fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung        return NULL;
751263b4c97823295c41900210515d0c769a236190cAndy Hung    }
752263b4c97823295c41900210515d0c769a236190cAndy Hung
7532d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia    PlaybackParams pbs;
754fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung    pbs.audioRate = lpTrack->getPlaybackRate();
755fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung    pbs.speedSet = true;
756fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung    pbs.pitchSet = true;
757fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung    pbs.audioFallbackModeSet = true;
758fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung    pbs.audioStretchModeSet = true;
7592d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia    return pbs.asJobject(env, gPlaybackParamsFields);
760263b4c97823295c41900210515d0c769a236190cAndy Hung}
761263b4c97823295c41900210515d0c769a236190cAndy Hung
762263b4c97823295c41900210515d0c769a236190cAndy Hung
763263b4c97823295c41900210515d0c769a236190cAndy Hung// ----------------------------------------------------------------------------
76418db49a46259020387c40fff36d92edc1087a366Glenn Kastenstatic jint android_media_AudioTrack_set_marker_pos(JNIEnv *env,  jobject thiz,
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jint markerPos) {
766532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
767532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for setMarkerPosition()");
770bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
772bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    return nativeToJavaStatus( lpTrack->setMarkerPosition(markerPos) );
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_marker_pos(JNIEnv *env,  jobject thiz) {
778532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t markerPos = 0;
78018db49a46259020387c40fff36d92edc1087a366Glenn Kasten
781532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for getMarkerPosition()");
784bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
786532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    lpTrack->getMarkerPosition(&markerPos);
787532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    return (jint)markerPos;
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_set_pos_update_period(JNIEnv *env,  jobject thiz,
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jint period) {
794532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
795532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for setPositionUpdatePeriod()");
798bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
79918db49a46259020387c40fff36d92edc1087a366Glenn Kasten    }
800bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    return nativeToJavaStatus( lpTrack->setPositionUpdatePeriod(period) );
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_pos_update_period(JNIEnv *env,  jobject thiz) {
806532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t period = 0;
80818db49a46259020387c40fff36d92edc1087a366Glenn Kasten
809532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for getPositionUpdatePeriod()");
812bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
814532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    lpTrack->getPositionUpdatePeriod(&period);
815532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    return (jint)period;
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
82018db49a46259020387c40fff36d92edc1087a366Glenn Kastenstatic jint android_media_AudioTrack_set_position(JNIEnv *env,  jobject thiz,
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jint position) {
822532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
823532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for setPosition()");
826bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
828bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    return nativeToJavaStatus( lpTrack->setPosition(position) );
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_position(JNIEnv *env,  jobject thiz) {
834532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t position = 0;
83618db49a46259020387c40fff36d92edc1087a366Glenn Kasten
837532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for getPosition()");
840bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
842532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    lpTrack->getPosition(&position);
843532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    return (jint)position;
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
84861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodmanstatic jint android_media_AudioTrack_get_latency(JNIEnv *env,  jobject thiz) {
84961dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
85061dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman
85161dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    if (lpTrack == NULL) {
85261dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman        jniThrowException(env, "java/lang/IllegalStateException",
85361dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman            "Unable to retrieve AudioTrack pointer for latency()");
854bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
85561dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    }
85661dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    return (jint)lpTrack->latency();
85761dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman}
85861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman
85961dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman
86061dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman// ----------------------------------------------------------------------------
861948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kastenstatic jint android_media_AudioTrack_get_timestamp(JNIEnv *env,  jobject thiz, jlongArray jTimestamp) {
862948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
863948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten
864948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    if (lpTrack == NULL) {
865948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        ALOGE("Unable to retrieve AudioTrack pointer for getTimestamp()");
866bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
867948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    }
868948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    AudioTimestamp timestamp;
869948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    status_t status = lpTrack->getTimestamp(timestamp);
870948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    if (status == OK) {
871948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        jlong* nTimestamp = (jlong *) env->GetPrimitiveArrayCritical(jTimestamp, NULL);
872948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        if (nTimestamp == NULL) {
873948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten            ALOGE("Unable to get array for getTimestamp()");
874bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent            return (jint)AUDIO_JAVA_ERROR;
875948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        }
876948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        nTimestamp[0] = (jlong) timestamp.mPosition;
877948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        nTimestamp[1] = (jlong) ((timestamp.mTime.tv_sec * 1000000000LL) + timestamp.mTime.tv_nsec);
878948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        env->ReleasePrimitiveArrayCritical(jTimestamp, nTimestamp, 0);
879948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    }
880bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    return (jint) nativeToJavaStatus(status);
881948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten}
882948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten
883948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten
884948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten// ----------------------------------------------------------------------------
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_set_loop(JNIEnv *env,  jobject thiz,
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jint loopStart, jint loopEnd, jint loopCount) {
887532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
888532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "Unable to retrieve AudioTrack pointer for setLoop()");
891bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
893bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    return nativeToJavaStatus( lpTrack->setLoop(loopStart, loopEnd, loopCount) );
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_reload(JNIEnv *env,  jobject thiz) {
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 reload()");
903bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
905bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    return nativeToJavaStatus( lpTrack->reload() );
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_output_sample_rate(JNIEnv *env,  jobject thiz,
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        jint javaStreamType) {
91285fbc871ded0f71f9638f85e7d2f03a35bf39ddaGlenn Kasten    uint32_t afSamplingRate;
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // convert the stream type from Java to native value
914eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi    // FIXME: code duplication with android_media_AudioTrack_setup()
91524fc2fb1c541e954b83fd31ea9f786a5e9b45501Dima Zavin    audio_stream_type_t nativeStreamType;
91629a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten    switch (javaStreamType) {
91729a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten    case AUDIO_STREAM_VOICE_CALL:
91829a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten    case AUDIO_STREAM_SYSTEM:
91929a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten    case AUDIO_STREAM_RING:
92029a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten    case AUDIO_STREAM_MUSIC:
92129a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten    case AUDIO_STREAM_ALARM:
92229a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten    case AUDIO_STREAM_NOTIFICATION:
92329a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten    case AUDIO_STREAM_BLUETOOTH_SCO:
92429a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten    case AUDIO_STREAM_DTMF:
92529a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten        nativeStreamType = (audio_stream_type_t) javaStreamType;
92629a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten        break;
92729a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten    default:
92824fc2fb1c541e954b83fd31ea9f786a5e9b45501Dima Zavin        nativeStreamType = AUDIO_STREAM_DEFAULT;
92929a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten        break;
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9328f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten    status_t status = AudioSystem::getOutputSamplingRate(&afSamplingRate, nativeStreamType);
9338f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten    if (status != NO_ERROR) {
9348f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten        ALOGE("Error %d in AudioSystem::getOutputSamplingRate() for stream type %d "
9358f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten              "in AudioTrack JNI", status, nativeStreamType);
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return DEFAULT_OUTPUT_SAMPLE_RATE;
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return afSamplingRate;
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// returns the minimum required size for the successful creation of a streaming AudioTrack
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// returns -1 if there was an error querying the hardware.
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env,  jobject thiz,
9475b8fd44365f03601aaba41879ac18e70ce814a0fGlenn Kasten    jint sampleRateInHertz, jint channelCount, jint audioFormat) {
948c3308074cd6f06bbb35c1999b5260f938742a9e7Chia-chi Yeh
949659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten    size_t frameCount;
950659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten    const status_t status = AudioTrack::getMinFrameCount(&frameCount, AUDIO_STREAM_DEFAULT,
951659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten            sampleRateInHertz);
952659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten    if (status != NO_ERROR) {
953659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten        ALOGE("AudioTrack::getMinFrameCount() for sample rate %d failed with status %d",
954659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten                sampleRateInHertz, status);
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
957fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten    const audio_format_t format = audioFormatToNative(audioFormat);
958ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent    if (audio_is_linear_pcm(format)) {
959ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        const size_t bytesPerSample = audio_bytes_per_sample(format);
960ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        return frameCount * channelCount * bytesPerSample;
961ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent    } else {
962ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        return frameCount;
963ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent    }
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9667070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent// ----------------------------------------------------------------------------
9673009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kastenstatic jint
9687070b36549d511d6627538c73dfbab23fbae5b43Eric Laurentandroid_media_AudioTrack_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level )
9697070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent{
970532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
9717070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    if (lpTrack == NULL ) {
9727070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        jniThrowException(env, "java/lang/IllegalStateException",
9737070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent            "Unable to retrieve AudioTrack pointer for setAuxEffectSendLevel()");
9743009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten        return -1;
9757070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    }
9767070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent
9773009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten    status_t status = lpTrack->setAuxEffectSendLevel(level);
9783009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten    if (status != NO_ERROR) {
9793009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten        ALOGE("AudioTrack::setAuxEffectSendLevel() for level %g failed with status %d",
9803009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten                level, status);
9813009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten    }
9823009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten    return (jint) status;
9837070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent}
9847070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent
9857070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent// ----------------------------------------------------------------------------
9867070b36549d511d6627538c73dfbab23fbae5b43Eric Laurentstatic jint android_media_AudioTrack_attachAuxEffect(JNIEnv *env,  jobject thiz,
9877070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        jint effectId) {
988532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
989532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent    if (lpTrack == NULL) {
9907070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        jniThrowException(env, "java/lang/IllegalStateException",
9917070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent            "Unable to retrieve AudioTrack pointer for attachAuxEffect()");
992bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent        return (jint)AUDIO_JAVA_ERROR;
9937070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    }
994bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    return nativeToJavaStatus( lpTrack->attachAuxEffect(effectId) );
9957070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent}
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
99788e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLeanstatic jboolean android_media_AudioTrack_setOutputDevice(
99888e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean                JNIEnv *env,  jobject thiz, jint device_id) {
99988e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean
100088e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
100188e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    return lpTrack->setOutputDevice(device_id) == NO_ERROR;
100288e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean}
100388e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean
10044bcdba848449b33d7022de527c526943aff1f5fdEric Laurentstatic jint android_media_AudioTrack_getRoutedDeviceId(
10054bcdba848449b33d7022de527c526943aff1f5fdEric Laurent                JNIEnv *env,  jobject thiz) {
10064bcdba848449b33d7022de527c526943aff1f5fdEric Laurent
10074bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
10084bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    if (lpTrack == NULL) {
10094bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        return 0;
10104bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    }
10114bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    return (jint)lpTrack->getRoutedDeviceId();
10124bcdba848449b33d7022de527c526943aff1f5fdEric Laurent}
10134bcdba848449b33d7022de527c526943aff1f5fdEric Laurent
10144bcdba848449b33d7022de527c526943aff1f5fdEric Laurentstatic void android_media_AudioTrack_enableDeviceCallback(
10154bcdba848449b33d7022de527c526943aff1f5fdEric Laurent                JNIEnv *env,  jobject thiz) {
10164bcdba848449b33d7022de527c526943aff1f5fdEric Laurent
10174bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
10184bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    if (lpTrack == NULL) {
10194bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        return;
10204bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    }
10214bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField(
10224bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        thiz, javaAudioTrackFields.jniData);
10234bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    if (pJniStorage == NULL || pJniStorage->mDeviceCallback != 0) {
10244bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        return;
10254bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    }
10264bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    pJniStorage->mDeviceCallback =
10274bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    new JNIDeviceCallback(env, thiz, pJniStorage->mCallbackData.audioTrack_ref,
10284bcdba848449b33d7022de527c526943aff1f5fdEric Laurent                          javaAudioTrackFields.postNativeEventInJava);
10294bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    lpTrack->addAudioDeviceCallback(pJniStorage->mDeviceCallback);
10304bcdba848449b33d7022de527c526943aff1f5fdEric Laurent}
10314bcdba848449b33d7022de527c526943aff1f5fdEric Laurent
10324bcdba848449b33d7022de527c526943aff1f5fdEric Laurentstatic void android_media_AudioTrack_disableDeviceCallback(
10334bcdba848449b33d7022de527c526943aff1f5fdEric Laurent                JNIEnv *env,  jobject thiz) {
10344bcdba848449b33d7022de527c526943aff1f5fdEric Laurent
10354bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
10364bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    if (lpTrack == NULL) {
10374bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        return;
10384bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    }
10394bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField(
10404bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        thiz, javaAudioTrackFields.jniData);
10414bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    if (pJniStorage == NULL || pJniStorage->mDeviceCallback == 0) {
10424bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        return;
10434bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    }
10444bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    lpTrack->removeAudioDeviceCallback(pJniStorage->mDeviceCallback);
10454bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    pJniStorage->mDeviceCallback.clear();
10464bcdba848449b33d7022de527c526943aff1f5fdEric Laurent}
10474bcdba848449b33d7022de527c526943aff1f5fdEric Laurent
10484bcdba848449b33d7022de527c526943aff1f5fdEric Laurent
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = {
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // name,              signature,     funcPtr
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_start",         "()V",      (void *)android_media_AudioTrack_start},
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_stop",          "()V",      (void *)android_media_AudioTrack_stop},
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_pause",         "()V",      (void *)android_media_AudioTrack_pause},
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_flush",         "()V",      (void *)android_media_AudioTrack_flush},
105730d794360f35592554403922bcc07835fea4737bAndy Hung    {"native_setup",     "(Ljava/lang/Object;Ljava/lang/Object;IIIIII[I)I",
1058eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi                                         (void *)android_media_AudioTrack_setup},
1059eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi    {"native_finalize",      "()V",      (void *)android_media_AudioTrack_finalize},
1060eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi    {"native_release",       "()V",      (void *)android_media_AudioTrack_release},
10614aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    {"native_write_byte",    "([BIIIZ)I",(void *)android_media_AudioTrack_writeArray<jbyteArray>},
10627ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    {"native_write_native_bytes",
10635d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi                             "(Ljava/lang/Object;IIIZ)I",
10647ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                                         (void *)android_media_AudioTrack_write_native_bytes},
10654aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    {"native_write_short",   "([SIIIZ)I",(void *)android_media_AudioTrack_writeArray<jshortArray>},
10664aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    {"native_write_float",   "([FIIIZ)I",(void *)android_media_AudioTrack_writeArray<jfloatArray>},
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_setVolume",     "(FF)V",    (void *)android_media_AudioTrack_set_volume},
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_get_native_frame_count",
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             "()I",      (void *)android_media_AudioTrack_get_native_frame_count},
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_set_playback_rate",
107188e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent                             "(I)I",     (void *)android_media_AudioTrack_set_playback_rate},
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_get_playback_rate",
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             "()I",      (void *)android_media_AudioTrack_get_playback_rate},
10742d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia    {"native_set_playback_params",
10752d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia                             "(Landroid/media/PlaybackParams;)V",
10762d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia                                         (void *)android_media_AudioTrack_set_playback_params},
10772d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia    {"native_get_playback_params",
10782d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia                             "()Landroid/media/PlaybackParams;",
10792d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia                                         (void *)android_media_AudioTrack_get_playback_params},
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_set_marker_pos","(I)I",     (void *)android_media_AudioTrack_set_marker_pos},
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_get_marker_pos","()I",      (void *)android_media_AudioTrack_get_marker_pos},
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_set_pos_update_period",
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             "(I)I",     (void *)android_media_AudioTrack_set_pos_update_period},
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_get_pos_update_period",
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             "()I",      (void *)android_media_AudioTrack_get_pos_update_period},
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_set_position",  "(I)I",     (void *)android_media_AudioTrack_set_position},
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_get_position",  "()I",      (void *)android_media_AudioTrack_get_position},
108861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    {"native_get_latency",   "()I",      (void *)android_media_AudioTrack_get_latency},
1089948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    {"native_get_timestamp", "([J)I",    (void *)android_media_AudioTrack_get_timestamp},
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_set_loop",      "(III)I",   (void *)android_media_AudioTrack_set_loop},
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_reload_static", "()I",      (void *)android_media_AudioTrack_reload},
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_get_output_sample_rate",
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             "(I)I",      (void *)android_media_AudioTrack_get_output_sample_rate},
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {"native_get_min_buff_size",
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             "(III)I",   (void *)android_media_AudioTrack_get_min_buff_size},
10967070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    {"native_setAuxEffectSendLevel",
10973009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten                             "(F)I",     (void *)android_media_AudioTrack_setAuxEffectSendLevel},
10987070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    {"native_attachAuxEffect",
10997070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent                             "(I)I",     (void *)android_media_AudioTrack_attachAuxEffect},
110088e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    {"native_setOutputDevice", "(I)Z",
110188e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean                             (void *)android_media_AudioTrack_setOutputDevice},
11024bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    {"native_getRoutedDeviceId", "()I", (void *)android_media_AudioTrack_getRoutedDeviceId},
11034bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    {"native_enableDeviceCallback", "()V", (void *)android_media_AudioTrack_enableDeviceCallback},
11044bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    {"native_disableDeviceCallback", "()V", (void *)android_media_AudioTrack_disableDeviceCallback},
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// field names found in android/media/AudioTrack.java
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_POSTEVENT_CALLBACK_NAME                    "postEventFromNative"
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME            "mNativeTrackInJavaObj"
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_JNIDATA_FIELD_NAME                         "mJniData"
1112a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi#define JAVA_STREAMTYPE_FIELD_NAME                      "mStreamType"
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// preconditions:
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//    theClass is valid
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool android_media_getIntConstantFromClass(JNIEnv* pEnv, jclass theClass, const char* className,
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             const char* constName, int* constVal) {
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID javaConst = NULL;
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    javaConst = pEnv->GetStaticFieldID(theClass, constName, "I");
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (javaConst != NULL) {
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        *constVal = pEnv->GetStaticIntField(theClass, javaConst);
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
11253762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find %s.%s", className, constName);
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_media_AudioTrack(JNIEnv *env)
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    javaAudioTrackFields.nativeTrackInJavaObj = NULL;
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    javaAudioTrackFields.postNativeEventInJava = NULL;
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Get the AudioTrack class
1138ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass audioTrackClass = FindClassOrDie(env, kClassPathName);
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Get the postEvent method
1141ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    javaAudioTrackFields.postNativeEventInJava = GetStaticMethodIDOrDie(env,
1142ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            audioTrackClass, JAVA_POSTEVENT_CALLBACK_NAME,
1143ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            "(Ljava/lang/Object;IIILjava/lang/Object;)V");
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Get the variables fields
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //      nativeTrackInJavaObj
1147ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    javaAudioTrackFields.nativeTrackInJavaObj = GetFieldIDOrDie(env,
1148ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            audioTrackClass, JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME, "J");
1149a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    //      jniData
1150ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    javaAudioTrackFields.jniData = GetFieldIDOrDie(env,
1151ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            audioTrackClass, JAVA_JNIDATA_FIELD_NAME, "J");
1152a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    //      fieldStreamType
1153ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    javaAudioTrackFields.fieldStreamType = GetFieldIDOrDie(env,
1154ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            audioTrackClass, JAVA_STREAMTYPE_FIELD_NAME, "I");
1155a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi
1156fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung    env->DeleteLocalRef(audioTrackClass);
1157fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung
1158a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    // Get the AudioAttributes class and fields
1159ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    jclass audioAttrClass = FindClassOrDie(env, kAudioAttributesClassPathName);
1160ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    javaAudioAttrFields.fieldUsage = GetFieldIDOrDie(env, audioAttrClass, "mUsage", "I");
1161ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    javaAudioAttrFields.fieldContentType = GetFieldIDOrDie(env,
1162ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            audioAttrClass, "mContentType", "I");
1163ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    javaAudioAttrFields.fieldFlags = GetFieldIDOrDie(env, audioAttrClass, "mFlags", "I");
1164ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    javaAudioAttrFields.fieldFormattedTags = GetFieldIDOrDie(env,
1165ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            audioAttrClass, "mFormattedTags", "Ljava/lang/String;");
1166ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
1167fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung    env->DeleteLocalRef(audioAttrClass);
1168fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung
11692d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia    // initialize PlaybackParams field info
11702d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia    gPlaybackParamsFields.init(env);
1171fe48e0dfb9862356cd4af645fb010236fc273a4aAndy Hung
1172ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ----------------------------------------------------------------------------
1177