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