blob: 0156e23e94b6bf0fcfee94a4655f234ebf5564e7 [file] [log] [blame]
Glenn Kastenb3db2132012-01-19 08:59:58 -08001/*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
Eric Laurent3a241992014-05-19 19:33:26 -070018//#define LOG_NDEBUG 0
19
Eric Laurentb69681c2014-05-19 19:02:51 -070020#define LOG_TAG "AudioSystem-JNI"
Glenn Kastenc81d31c2012-03-13 14:46:23 -070021#include <utils/Log.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022
Andy Hung737d9fb2016-08-16 18:38:49 -070023#include <sstream>
jiabinc0f49442018-01-05 10:23:50 -080024#include <vector>
Glenn Kastenc81d31c2012-03-13 14:46:23 -070025#include <jni.h>
Steven Moreland2279b252017-07-19 09:50:45 -070026#include <nativehelper/JNIHelp.h>
Andreas Gampeed6b9df2014-11-20 22:02:20 -080027#include "core_jni_helpers.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028
Jean-Michel Trivi21cd5412019-10-30 08:16:51 -070029#include "android_media_AudioAttributes.h"
30#include "android_media_AudioDeviceAddress.h"
31#include "android_media_AudioEffectDescriptor.h"
32#include "android_media_AudioErrors.h"
33#include "android_media_AudioFormat.h"
34#include "android_media_MicrophoneInfo.h"
Mikhail Naganova00883d2019-04-18 12:36:27 -070035#include <audiomanager/AudioManager.h>
Eric Laurent7f5eb9f2014-12-01 19:36:30 -080036#include <media/AudioPolicy.h>
Jean-Michel Trivi21cd5412019-10-30 08:16:51 -070037#include <media/AudioSystem.h>
jiabinc0f49442018-01-05 10:23:50 -080038#include <media/MicrophoneInfo.h>
Andy Hung737d9fb2016-08-16 18:38:49 -070039#include <nativehelper/ScopedLocalRef.h>
Dima Zavin34bb4192011-05-11 14:15:23 -070040#include <system/audio.h>
Dima Zavin290029d2011-06-13 18:16:26 -070041#include <system/audio_policy.h>
Dima Zavin24fc2fb2011-04-19 22:30:36 -070042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043// ----------------------------------------------------------------------------
44
45using namespace android;
46
Glenn Kastened0079d2011-04-04 10:50:50 -070047static const char* const kClassPathName = "android/media/AudioSystem";
48
Eric Laurentb69681c2014-05-19 19:02:51 -070049static jclass gArrayListClass;
50static struct {
51 jmethodID add;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -080052 jmethodID toArray;
Eric Laurentb69681c2014-05-19 19:02:51 -070053} gArrayListMethods;
54
jiabin39940752018-04-02 18:18:45 -070055static jclass gBooleanClass;
56static jmethodID gBooleanCstor;
57
58static jclass gIntegerClass;
59static jmethodID gIntegerCstor;
60
61static jclass gMapClass;
62static jmethodID gMapPut;
63
Eric Laurentb69681c2014-05-19 19:02:51 -070064static jclass gAudioHandleClass;
65static jmethodID gAudioHandleCstor;
66static struct {
67 jfieldID mId;
68} gAudioHandleFields;
69
70static jclass gAudioPortClass;
71static jmethodID gAudioPortCstor;
72static struct {
73 jfieldID mHandle;
74 jfieldID mRole;
75 jfieldID mGains;
76 jfieldID mActiveConfig;
Hongwei Wangf44a5682018-08-24 10:37:56 -070077 // Valid only if an AudioDevicePort
78 jfieldID mType;
79 jfieldID mAddress;
Eric Laurentb69681c2014-05-19 19:02:51 -070080 // other fields unused by JNI
81} gAudioPortFields;
82
83static jclass gAudioPortConfigClass;
84static jmethodID gAudioPortConfigCstor;
85static struct {
86 jfieldID mPort;
87 jfieldID mSamplingRate;
88 jfieldID mChannelMask;
89 jfieldID mFormat;
90 jfieldID mGain;
Eric Laurent3a241992014-05-19 19:33:26 -070091 jfieldID mConfigMask;
Eric Laurentb69681c2014-05-19 19:02:51 -070092} gAudioPortConfigFields;
93
94static jclass gAudioDevicePortClass;
95static jmethodID gAudioDevicePortCstor;
96
97static jclass gAudioDevicePortConfigClass;
98static jmethodID gAudioDevicePortConfigCstor;
99
100static jclass gAudioMixPortClass;
101static jmethodID gAudioMixPortCstor;
102
103static jclass gAudioMixPortConfigClass;
104static jmethodID gAudioMixPortConfigCstor;
105
106static jclass gAudioGainClass;
107static jmethodID gAudioGainCstor;
108
109static jclass gAudioGainConfigClass;
110static jmethodID gAudioGainConfigCstor;
111static struct {
112 jfieldID mIndex;
113 jfieldID mMode;
114 jfieldID mChannelMask;
115 jfieldID mValues;
116 jfieldID mRampDurationMs;
117 // other fields unused by JNI
118} gAudioGainConfigFields;
119
120static jclass gAudioPatchClass;
121static jmethodID gAudioPatchCstor;
122static struct {
123 jfieldID mHandle;
124 // other fields unused by JNI
125} gAudioPatchFields;
126
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800127static jclass gAudioMixClass;
128static struct {
129 jfieldID mRule;
130 jfieldID mFormat;
131 jfieldID mRouteFlags;
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -0700132 jfieldID mDeviceType;
133 jfieldID mDeviceAddress;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800134 jfieldID mMixType;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700135 jfieldID mCallbackFlags;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800136} gAudioMixFields;
137
138static jclass gAudioFormatClass;
139static struct {
140 jfieldID mEncoding;
141 jfieldID mSampleRate;
142 jfieldID mChannelMask;
143 // other fields unused by JNI
144} gAudioFormatFields;
145
146static jclass gAudioMixingRuleClass;
147static struct {
148 jfieldID mCriteria;
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -0800149 jfieldID mAllowPrivilegedPlaybackCapture;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800150 // other fields unused by JNI
151} gAudioMixingRuleFields;
152
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800153static jclass gAudioMixMatchCriterionClass;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800154static struct {
155 jfieldID mAttr;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800156 jfieldID mIntProp;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800157 jfieldID mRule;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800158} gAudioMixMatchCriterionFields;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800159
Eric Laurent700e7342014-05-02 18:33:15 -0700160static const char* const kEventHandlerClassPathName =
161 "android/media/AudioPortEventHandler";
Eric Laurent2615afb2015-03-25 14:51:08 -0700162static struct {
163 jfieldID mJniCallback;
164} gEventHandlerFields;
165static struct {
166 jmethodID postEventFromNative;
167} gAudioPortEventHandlerMethods;
168
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700169static struct {
170 jmethodID postDynPolicyEventFromNative;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800171 jmethodID postRecordConfigEventFromNative;
172} gAudioPolicyEventHandlerMethods;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700173
Paul McLeanb3ae6d92018-11-05 15:16:59 -0700174//
175// JNI Initialization for OpenSLES routing
176//
177jmethodID gMidAudioTrackRoutingProxy_ctor;
178jmethodID gMidAudioTrackRoutingProxy_release;
179jmethodID gMidAudioRecordRoutingProxy_ctor;
180jmethodID gMidAudioRecordRoutingProxy_release;
181
182jclass gClsAudioTrackRoutingProxy;
183jclass gClsAudioRecordRoutingProxy;
184
Eric Laurent2615afb2015-03-25 14:51:08 -0700185static Mutex gLock;
Eric Laurentb69681c2014-05-19 19:02:51 -0700186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187enum AudioError {
188 kAudioStatusOk = 0,
189 kAudioStatusError = 1,
190 kAudioStatusMediaServerDied = 100
191};
192
Eric Laurent700e7342014-05-02 18:33:15 -0700193enum {
194 AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1,
195 AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2,
196 AUDIOPORT_EVENT_SERVICE_DIED = 3,
197};
198
Eric Laurentb69681c2014-05-19 19:02:51 -0700199#define MAX_PORT_GENERATION_SYNC_ATTEMPTS 5
200
Eric Laurent700e7342014-05-02 18:33:15 -0700201// ----------------------------------------------------------------------------
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700202// ref-counted object for audio port callbacks
Eric Laurent700e7342014-05-02 18:33:15 -0700203class JNIAudioPortCallback: public AudioSystem::AudioPortCallback
204{
205public:
206 JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
207 ~JNIAudioPortCallback();
208
209 virtual void onAudioPortListUpdate();
210 virtual void onAudioPatchListUpdate();
211 virtual void onServiceDied();
212
213private:
214 void sendEvent(int event);
215
Eric Laurent2615afb2015-03-25 14:51:08 -0700216 jclass mClass; // Reference to AudioPortEventHandler class
217 jobject mObject; // Weak ref to AudioPortEventHandler Java object to call on
Eric Laurent700e7342014-05-02 18:33:15 -0700218};
219
220JNIAudioPortCallback::JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
221{
222
Eric Laurent2615afb2015-03-25 14:51:08 -0700223 // Hold onto the AudioPortEventHandler class for use in calling the static method
Eric Laurent700e7342014-05-02 18:33:15 -0700224 // that posts events to the application thread.
225 jclass clazz = env->GetObjectClass(thiz);
226 if (clazz == NULL) {
227 ALOGE("Can't find class %s", kEventHandlerClassPathName);
228 return;
229 }
230 mClass = (jclass)env->NewGlobalRef(clazz);
231
Eric Laurent2615afb2015-03-25 14:51:08 -0700232 // We use a weak reference so the AudioPortEventHandler object can be garbage collected.
Eric Laurent700e7342014-05-02 18:33:15 -0700233 // The reference is only used as a proxy for callbacks.
234 mObject = env->NewGlobalRef(weak_thiz);
235}
236
237JNIAudioPortCallback::~JNIAudioPortCallback()
238{
239 // remove global references
240 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800241 if (env == NULL) {
242 return;
243 }
Eric Laurent700e7342014-05-02 18:33:15 -0700244 env->DeleteGlobalRef(mObject);
245 env->DeleteGlobalRef(mClass);
246}
247
248void JNIAudioPortCallback::sendEvent(int event)
249{
250 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800251 if (env == NULL) {
252 return;
253 }
Eric Laurent2615afb2015-03-25 14:51:08 -0700254 env->CallStaticVoidMethod(mClass, gAudioPortEventHandlerMethods.postEventFromNative, mObject,
Eric Laurent700e7342014-05-02 18:33:15 -0700255 event, 0, 0, NULL);
256 if (env->ExceptionCheck()) {
257 ALOGW("An exception occurred while notifying an event.");
258 env->ExceptionClear();
259 }
260}
261
262void JNIAudioPortCallback::onAudioPortListUpdate()
263{
264 sendEvent(AUDIOPORT_EVENT_PORT_LIST_UPDATED);
265}
266
267void JNIAudioPortCallback::onAudioPatchListUpdate()
268{
269 sendEvent(AUDIOPORT_EVENT_PATCH_LIST_UPDATED);
270}
271
272void JNIAudioPortCallback::onServiceDied()
273{
274 sendEvent(AUDIOPORT_EVENT_SERVICE_DIED);
275}
276
Eric Laurent2615afb2015-03-25 14:51:08 -0700277static sp<JNIAudioPortCallback> setJniCallback(JNIEnv* env,
278 jobject thiz,
279 const sp<JNIAudioPortCallback>& callback)
280{
281 Mutex::Autolock l(gLock);
282 sp<JNIAudioPortCallback> old =
283 (JNIAudioPortCallback*)env->GetLongField(thiz, gEventHandlerFields.mJniCallback);
284 if (callback.get()) {
285 callback->incStrong((void*)setJniCallback);
286 }
287 if (old != 0) {
288 old->decStrong((void*)setJniCallback);
289 }
290 env->SetLongField(thiz, gEventHandlerFields.mJniCallback, (jlong)callback.get());
291 return old;
292}
293
Mikhail Naganov5caa57d2018-04-02 10:35:45 -0700294#define check_AudioSystem_Command(status) _check_AudioSystem_Command(__func__, (status))
295
296static int _check_AudioSystem_Command(const char* caller, status_t status)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297{
Mikhail Naganov5caa57d2018-04-02 10:35:45 -0700298 ALOGE_IF(status, "Command failed for %s: %d", caller, status);
Eric Laurentdfb881f2013-07-18 14:41:39 -0700299 switch (status) {
300 case DEAD_OBJECT:
301 return kAudioStatusMediaServerDied;
302 case NO_ERROR:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 return kAudioStatusOk;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700304 default:
305 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 }
Eric Laurentdfb881f2013-07-18 14:41:39 -0700307 return kAudioStatusError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308}
309
Oscar Azucena76788f02019-11-27 17:34:29 -0800310static jint getVectorOfAudioDeviceTypeAddr(JNIEnv *env, jintArray deviceTypes,
311 jobjectArray deviceAddresses,
312 Vector<AudioDeviceTypeAddr> &audioDeviceTypeAddrVector) {
313 if (deviceTypes == nullptr || deviceAddresses == nullptr) {
314 return (jint)AUDIO_JAVA_BAD_VALUE;
315 }
316 jsize deviceCount = env->GetArrayLength(deviceTypes);
317 if (deviceCount == 0 || deviceCount != env->GetArrayLength(deviceAddresses)) {
318 return (jint)AUDIO_JAVA_BAD_VALUE;
319 }
320 // retrieve all device types
321 std::vector<audio_devices_t> deviceTypesVector;
322 jint *typesPtr = nullptr;
323 typesPtr = env->GetIntArrayElements(deviceTypes, 0);
324 if (typesPtr == nullptr) {
325 return (jint)AUDIO_JAVA_BAD_VALUE;
326 }
327 for (jint i = 0; i < deviceCount; i++) {
328 deviceTypesVector.push_back((audio_devices_t)typesPtr[i]);
329 }
330 // check each address is a string and add device type/address to list
331 jclass stringClass = FindClassOrDie(env, "java/lang/String");
332 for (jint i = 0; i < deviceCount; i++) {
333 jobject addrJobj = env->GetObjectArrayElement(deviceAddresses, i);
334 if (!env->IsInstanceOf(addrJobj, stringClass)) {
335 return (jint)AUDIO_JAVA_BAD_VALUE;
336 }
337 const char *address = env->GetStringUTFChars((jstring)addrJobj, NULL);
338 AudioDeviceTypeAddr dev = AudioDeviceTypeAddr(typesPtr[i], address);
339 audioDeviceTypeAddrVector.add(dev);
340 env->ReleaseStringUTFChars((jstring)addrJobj, address);
341 }
342 env->ReleaseIntArrayElements(deviceTypes, typesPtr, 0);
343
344 return (jint)NO_ERROR;
345}
346
Ashok Bhat075e9a12014-01-06 13:45:09 +0000347static jint
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
349{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000350 return (jint) check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351}
352
353static jboolean
354android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
355{
356 bool state = false;
357 AudioSystem::isMicrophoneMuted(&state);
358 return state;
359}
360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361static jboolean
Eric Laurent25101b02011-02-02 09:33:30 -0800362android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363{
364 bool state = false;
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800365 AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 return state;
367}
368
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700369static jboolean
Jean-Michel Trivi679d5042013-02-04 16:24:09 -0800370android_media_AudioSystem_isStreamActiveRemotely(JNIEnv *env, jobject thiz, jint stream,
371 jint inPastMs)
372{
373 bool state = false;
374 AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs);
375 return state;
376}
377
378static jboolean
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700379android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
380{
381 bool state = false;
382 AudioSystem::isSourceActive((audio_source_t) source, &state);
383 return state;
384}
385
Ashok Bhat075e9a12014-01-06 13:45:09 +0000386static jint
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700387android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
388{
Glenn Kasten211d9052016-02-26 16:22:40 -0800389 return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700390}
391
392static jint
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -0800393android_media_AudioSystem_newAudioPlayerId(JNIEnv *env, jobject thiz)
394{
Mikhail Naganova00883d2019-04-18 12:36:27 -0700395 int id = AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_CLIENT);
396 return id != AUDIO_UNIQUE_ID_ALLOCATE ? id : PLAYER_PIID_INVALID;
397}
398
399static jint
400android_media_AudioSystem_newAudioRecorderId(JNIEnv *env, jobject thiz)
401{
402 int id = AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_CLIENT);
403 return id != AUDIO_UNIQUE_ID_ALLOCATE ? id : RECORD_RIID_INVALID;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -0800404}
405
406static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700407android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408{
Eric Laurenta553c252009-07-17 12:17:14 -0700409 const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
410 String8 c_keyValuePairs8;
411 if (keyValuePairs) {
Dan Albert66987492014-11-20 11:41:21 -0800412 c_keyValuePairs8 = String8(
413 reinterpret_cast<const char16_t*>(c_keyValuePairs),
414 env->GetStringLength(keyValuePairs));
Eric Laurenta553c252009-07-17 12:17:14 -0700415 env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
416 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800417 int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
Ashok Bhat075e9a12014-01-06 13:45:09 +0000418 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700419}
420
421static jstring
422android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
423{
424 const jchar* c_keys = env->GetStringCritical(keys, 0);
425 String8 c_keys8;
426 if (keys) {
Dan Albert66987492014-11-20 11:41:21 -0800427 c_keys8 = String8(reinterpret_cast<const char16_t*>(c_keys),
428 env->GetStringLength(keys));
Eric Laurenta553c252009-07-17 12:17:14 -0700429 env->ReleaseStringCritical(keys, c_keys);
430 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800431 return env->NewStringUTF(AudioSystem::getParameters(c_keys8).string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432}
433
Glenn Kastened0079d2011-04-04 10:50:50 -0700434static void
435android_media_AudioSystem_error_callback(status_t err)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436{
Eric Laurent539719a2013-07-18 14:08:00 -0700437 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent0e7a4d92010-10-15 12:33:16 -0700438 if (env == NULL) {
439 return;
440 }
441
Glenn Kastened0079d2011-04-04 10:50:50 -0700442 jclass clazz = env->FindClass(kClassPathName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443
Eric Laurentdfb881f2013-07-18 14:41:39 -0700444 env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
445 "errorCallbackFromNative","(I)V"),
446 check_AudioSystem_Command(err));
Viorel Sumanb637ccf2014-05-30 16:51:07 +0300447
448 env->DeleteLocalRef(clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449}
450
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700451static void
452android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
453{
454 JNIEnv *env = AndroidRuntime::getJNIEnv();
455 if (env == NULL) {
456 return;
457 }
458
459 jclass clazz = env->FindClass(kClassPathName);
460 const char* zechars = regId.string();
461 jstring zestring = env->NewStringUTF(zechars);
462
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800463 env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative,
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700464 event, zestring, val);
465
466 env->ReleaseStringUTFChars(zestring, zechars);
467 env->DeleteLocalRef(clazz);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800468}
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700469
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800470static void
Eric Laurentc7a0cdf2018-11-30 12:16:52 -0800471android_media_AudioSystem_recording_callback(int event,
472 const record_client_info_t *clientInfo,
473 const audio_config_base_t *clientConfig,
474 std::vector<effect_descriptor_t> clientEffects,
475 const audio_config_base_t *deviceConfig,
476 std::vector<effect_descriptor_t> effects __unused,
477 audio_patch_handle_t patchHandle,
478 audio_source_t source)
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800479{
480 JNIEnv *env = AndroidRuntime::getJNIEnv();
481 if (env == NULL) {
482 return;
483 }
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800484 if (clientInfo == NULL || clientConfig == NULL || deviceConfig == NULL) {
485 ALOGE("Unexpected null client/device info or configurations in recording callback");
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800486 return;
487 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800488
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800489 // create an array for 2*3 integers to store the record configurations (client + device)
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800490 // plus 1 integer for the patch handle
491 const int REC_PARAM_SIZE = 7;
492 jintArray recParamArray = env->NewIntArray(REC_PARAM_SIZE);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800493 if (recParamArray == NULL) {
494 ALOGE("recording callback: Couldn't allocate int array for configuration data");
495 return;
496 }
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800497 jint recParamData[REC_PARAM_SIZE];
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800498 recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
499 // FIXME this doesn't support index-based masks
500 recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
501 recParamData[2] = (jint) clientConfig->sample_rate;
502 recParamData[3] = (jint) audioFormatFromNative(deviceConfig->format);
503 // FIXME this doesn't support index-based masks
504 recParamData[4] = (jint) inChannelMaskFromNative(deviceConfig->channel_mask);
505 recParamData[5] = (jint) deviceConfig->sample_rate;
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800506 recParamData[6] = (jint) patchHandle;
507 env->SetIntArrayRegion(recParamArray, 0, REC_PARAM_SIZE, recParamData);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800508
Eric Laurentc7a0cdf2018-11-30 12:16:52 -0800509 jobjectArray jClientEffects;
510 convertAudioEffectDescriptorVectorFromNative(env, &jClientEffects, clientEffects);
511
512 jobjectArray jEffects;
513 convertAudioEffectDescriptorVectorFromNative(env, &jEffects, effects);
514
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800515 // callback into java
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800516 jclass clazz = env->FindClass(kClassPathName);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800517
Eric Laurentc7a0cdf2018-11-30 12:16:52 -0800518 env->CallStaticVoidMethod(clazz,
519 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
Mikhail Naganova00883d2019-04-18 12:36:27 -0700520 event, (jint) clientInfo->riid, (jint) clientInfo->uid,
521 clientInfo->session, clientInfo->source, clientInfo->port_id,
522 clientInfo->silenced, recParamArray, jClientEffects, jEffects,
523 source);
Eric Laurentc7a0cdf2018-11-30 12:16:52 -0800524 env->DeleteLocalRef(clazz);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800525 env->DeleteLocalRef(recParamArray);
Eric Laurentc7a0cdf2018-11-30 12:16:52 -0800526 env->DeleteLocalRef(jClientEffects);
527 env->DeleteLocalRef(jEffects);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700528}
529
Ashok Bhat075e9a12014-01-06 13:45:09 +0000530static jint
Aniket Kumar Lata9fbc2052019-01-11 02:02:33 -0800531android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name,
Eric Laurent1d43aec2019-01-16 18:24:08 -0800532 jint codec)
Eric Laurenta553c252009-07-17 12:17:14 -0700533{
534 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Paul McLean10804eb2015-01-28 11:16:35 -0800535 const char *c_name = env->GetStringUTFChars(device_name, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700536 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
537 static_cast <audio_policy_dev_state_t>(state),
Eric Laurent1d43aec2019-01-16 18:24:08 -0800538 c_address, c_name,
539 static_cast <audio_format_t>(codec)));
Eric Laurenta553c252009-07-17 12:17:14 -0700540 env->ReleaseStringUTFChars(device_address, c_address);
Paul McLean10804eb2015-01-28 11:16:35 -0800541 env->ReleaseStringUTFChars(device_name, c_name);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000542 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700543}
544
Ashok Bhat075e9a12014-01-06 13:45:09 +0000545static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700546android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
547{
548 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700549 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
Eric Laurenta553c252009-07-17 12:17:14 -0700550 c_address));
551 env->ReleaseStringUTFChars(device_address, c_address);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000552 return (jint) state;
Eric Laurenta553c252009-07-17 12:17:14 -0700553}
554
Ashok Bhat075e9a12014-01-06 13:45:09 +0000555static jint
Aniket Kumar Lata9fbc2052019-01-11 02:02:33 -0800556android_media_AudioSystem_handleDeviceConfigChange(JNIEnv *env, jobject thiz, jint device, jstring device_address, jstring device_name,
Eric Laurent1d43aec2019-01-16 18:24:08 -0800557 jint codec)
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800558{
559 const char *c_address = env->GetStringUTFChars(device_address, NULL);
560 const char *c_name = env->GetStringUTFChars(device_name, NULL);
561 int status = check_AudioSystem_Command(AudioSystem::handleDeviceConfigChange(static_cast <audio_devices_t>(device),
Eric Laurent1d43aec2019-01-16 18:24:08 -0800562 c_address, c_name, static_cast <audio_format_t>(codec)));
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800563 env->ReleaseStringUTFChars(device_address, c_address);
564 env->ReleaseStringUTFChars(device_name, c_name);
565 return (jint) status;
566}
567
568static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700569android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
570{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000571 return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
Eric Laurenta553c252009-07-17 12:17:14 -0700572}
573
Ashok Bhat075e9a12014-01-06 13:45:09 +0000574static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700575android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
576{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000577 return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700578 static_cast <audio_policy_forced_cfg_t>(config)));
Eric Laurenta553c252009-07-17 12:17:14 -0700579}
580
Ashok Bhat075e9a12014-01-06 13:45:09 +0000581static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700582android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
583{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000584 return static_cast <jint>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
Eric Laurenta553c252009-07-17 12:17:14 -0700585}
586
Ashok Bhat075e9a12014-01-06 13:45:09 +0000587static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700588android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
589{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000590 return (jint) check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
Eric Laurenta553c252009-07-17 12:17:14 -0700591 indexMin,
592 indexMax));
593}
594
Ashok Bhat075e9a12014-01-06 13:45:09 +0000595static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800596android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
597 jobject thiz,
598 jint stream,
599 jint index,
600 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700601{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000602 return (jint) check_AudioSystem_Command(
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800603 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
604 index,
605 (audio_devices_t)device));
Eric Laurenta553c252009-07-17 12:17:14 -0700606}
607
Ashok Bhat075e9a12014-01-06 13:45:09 +0000608static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800609android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
610 jobject thiz,
611 jint stream,
612 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700613{
614 int index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800615 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
616 &index,
617 (audio_devices_t)device)
618 != NO_ERROR) {
Eric Laurenta553c252009-07-17 12:17:14 -0700619 index = -1;
620 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000621 return (jint) index;
Eric Laurenta553c252009-07-17 12:17:14 -0700622}
623
Ashok Bhat075e9a12014-01-06 13:45:09 +0000624static jint
François Gaffieebb67d02018-09-14 15:05:04 +0200625android_media_AudioSystem_setVolumeIndexForAttributes(JNIEnv *env,
626 jobject thiz,
627 jobject jaa,
628 jint index,
629 jint device)
630{
631 // read the AudioAttributes values
632 JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
633 jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
634 if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
635 return jStatus;
636 }
637 return (jint) check_AudioSystem_Command(
638 AudioSystem::setVolumeIndexForAttributes(*(paa.get()), index, (audio_devices_t)device));
639}
640
641static jint
642android_media_AudioSystem_getVolumeIndexForAttributes(JNIEnv *env,
643 jobject thiz,
644 jobject jaa,
645 jint device)
646{
647 // read the AudioAttributes values
648 JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
649 jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
650 if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
651 return jStatus;
652 }
653 int index;
654 if (AudioSystem::getVolumeIndexForAttributes(*(paa.get()), index, (audio_devices_t)device)
655 != NO_ERROR) {
656 index = -1;
657 }
658 return (jint) index;
659}
660
661static jint
662android_media_AudioSystem_getMinVolumeIndexForAttributes(JNIEnv *env,
663 jobject thiz,
664 jobject jaa)
665{
666 // read the AudioAttributes values
667 JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
668 jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
669 if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
670 return jStatus;
671 }
672 int index;
673 if (AudioSystem::getMinVolumeIndexForAttributes(*(paa.get()), index)
674 != NO_ERROR) {
675 index = -1;
676 }
677 return (jint) index;
678}
679
680static jint
681android_media_AudioSystem_getMaxVolumeIndexForAttributes(JNIEnv *env,
682 jobject thiz,
683 jobject jaa)
684{
685 // read the AudioAttributes values
686 JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
687 jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
688 if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
689 return jStatus;
690 }
691 int index;
692 if (AudioSystem::getMaxVolumeIndexForAttributes(*(paa.get()), index)
693 != NO_ERROR) {
694 index = -1;
695 }
696 return (jint) index;
697}
698
699static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400700android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
701{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000702 return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400703}
704
705static jfloat
706android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz)
707{
708 float value;
709 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) {
710 value = -1.0;
711 }
712 return value;
713}
714
Ashok Bhat075e9a12014-01-06 13:45:09 +0000715static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400716android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
717{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000718 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400719}
720
Vladimir Markoc1bcdbb2014-10-29 20:34:15 +0000721static jboolean
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400722android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
723{
724 bool mute;
725 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) {
726 mute = false;
727 }
728 return mute;
729}
730
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800731static jint
Andy Hungf04b84d2015-12-18 17:33:27 -0800732android_media_AudioSystem_setMasterMono(JNIEnv *env, jobject thiz, jboolean mono)
733{
734 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMono(mono));
735}
736
737static jboolean
738android_media_AudioSystem_getMasterMono(JNIEnv *env, jobject thiz)
739{
740 bool mono;
741 if (AudioSystem::getMasterMono(&mono) != NO_ERROR) {
742 mono = false;
743 }
744 return mono;
745}
746
747static jint
Edward Savage-Jones35c292f2017-01-13 09:04:34 +0100748android_media_AudioSystem_setMasterBalance(JNIEnv *env, jobject thiz, jfloat balance)
749{
750 return (jint) check_AudioSystem_Command(AudioSystem::setMasterBalance(balance));
751}
752
753static jfloat
754android_media_AudioSystem_getMasterBalance(JNIEnv *env, jobject thiz)
755{
756 float balance;
757 const status_t status = AudioSystem::getMasterBalance(&balance);
758 if (status != NO_ERROR) {
759 ALOGW("%s getMasterBalance error %d, returning 0.f, audioserver down?", __func__, status);
760 balance = 0.f;
761 }
762 return balance;
763}
764
765static jint
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800766android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
767{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700768 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800769}
770
Glenn Kastenc6c43652012-09-24 17:32:30 -0700771static jint
772android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
773{
774 return (jint) AudioSystem::getPrimaryOutputSamplingRate();
775}
776
777static jint
778android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
779{
780 return (jint) AudioSystem::getPrimaryOutputFrameCount();
781}
782
Oliver Woodman61dcdf32013-06-26 12:43:36 +0100783static jint
784android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
785{
786 uint32_t afLatency;
787 if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
788 != NO_ERROR) {
789 afLatency = -1;
790 }
791 return (jint) afLatency;
792}
793
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700794static jint
Andy Hung79583582018-01-23 13:58:02 -0800795android_media_AudioSystem_setLowRamDevice(
796 JNIEnv *env, jobject clazz, jboolean isLowRamDevice, jlong totalMemory)
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700797{
Andy Hung79583582018-01-23 13:58:02 -0800798 return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice, (int64_t) totalMemory);
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700799}
800
Ashok Bhat075e9a12014-01-06 13:45:09 +0000801static jint
Eric Laurentdfb881f2013-07-18 14:41:39 -0700802android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
803{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000804 return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
Eric Laurentdfb881f2013-07-18 14:41:39 -0700805}
806
Eric Laurentb69681c2014-05-19 19:02:51 -0700807
808static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role)
809{
810 return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
811 ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
812}
813
Eric Laurent3a241992014-05-19 19:33:26 -0700814static void convertAudioGainConfigToNative(JNIEnv *env,
815 struct audio_gain_config *nAudioGainConfig,
816 const jobject jAudioGainConfig,
817 bool useInMask)
818{
819 nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
820 nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
821 ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
822 jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
823 audio_channel_mask_t nMask;
824 if (useInMask) {
825 nMask = inChannelMaskToNative(jMask);
826 ALOGV("convertAudioGainConfigToNative IN mask java %x native %x", jMask, nMask);
827 } else {
828 nMask = outChannelMaskToNative(jMask);
829 ALOGV("convertAudioGainConfigToNative OUT mask java %x native %x", jMask, nMask);
830 }
831 nAudioGainConfig->channel_mask = nMask;
832 nAudioGainConfig->ramp_duration_ms = env->GetIntField(jAudioGainConfig,
833 gAudioGainConfigFields.mRampDurationMs);
834 jintArray jValues = (jintArray)env->GetObjectField(jAudioGainConfig,
835 gAudioGainConfigFields.mValues);
836 int *nValues = env->GetIntArrayElements(jValues, NULL);
837 size_t size = env->GetArrayLength(jValues);
838 memcpy(nAudioGainConfig->values, nValues, size * sizeof(int));
839 env->DeleteLocalRef(jValues);
840}
841
Eric Laurentb69681c2014-05-19 19:02:51 -0700842static jint convertAudioPortConfigToNative(JNIEnv *env,
843 struct audio_port_config *nAudioPortConfig,
Eric Laurent6368a7d2014-11-19 12:18:32 -0800844 const jobject jAudioPortConfig,
845 bool useConfigMask)
Eric Laurentb69681c2014-05-19 19:02:51 -0700846{
847 jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
848 jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
849 nAudioPortConfig->id = env->GetIntField(jHandle, gAudioHandleFields.mId);
850 nAudioPortConfig->role = (audio_port_role_t)env->GetIntField(jAudioPort,
851 gAudioPortFields.mRole);
852 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
853 nAudioPortConfig->type = AUDIO_PORT_TYPE_DEVICE;
854 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
855 nAudioPortConfig->type = AUDIO_PORT_TYPE_MIX;
856 } else {
857 env->DeleteLocalRef(jAudioPort);
858 env->DeleteLocalRef(jHandle);
859 return (jint)AUDIO_JAVA_ERROR;
860 }
861 ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
862 nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
863
Eric Laurent6368a7d2014-11-19 12:18:32 -0800864 unsigned int configMask = 0;
865
Eric Laurentb69681c2014-05-19 19:02:51 -0700866 nAudioPortConfig->sample_rate = env->GetIntField(jAudioPortConfig,
867 gAudioPortConfigFields.mSamplingRate);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800868 if (nAudioPortConfig->sample_rate != 0) {
869 configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
870 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700871
872 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
873 audio_channel_mask_t nMask;
874 jint jMask = env->GetIntField(jAudioPortConfig,
875 gAudioPortConfigFields.mChannelMask);
876 if (useInMask) {
877 nMask = inChannelMaskToNative(jMask);
878 ALOGV("convertAudioPortConfigToNative IN mask java %x native %x", jMask, nMask);
879 } else {
880 nMask = outChannelMaskToNative(jMask);
881 ALOGV("convertAudioPortConfigToNative OUT mask java %x native %x", jMask, nMask);
882 }
883 nAudioPortConfig->channel_mask = nMask;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800884 if (nAudioPortConfig->channel_mask != AUDIO_CHANNEL_NONE) {
885 configMask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
886 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700887
888 jint jFormat = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mFormat);
889 audio_format_t nFormat = audioFormatToNative(jFormat);
890 ALOGV("convertAudioPortConfigToNative format %d native %d", jFormat, nFormat);
891 nAudioPortConfig->format = nFormat;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800892 if (nAudioPortConfig->format != AUDIO_FORMAT_DEFAULT &&
893 nAudioPortConfig->format != AUDIO_FORMAT_INVALID) {
894 configMask |= AUDIO_PORT_CONFIG_FORMAT;
895 }
896
Eric Laurentb69681c2014-05-19 19:02:51 -0700897 jobject jGain = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mGain);
898 if (jGain != NULL) {
Eric Laurent3a241992014-05-19 19:33:26 -0700899 convertAudioGainConfigToNative(env, &nAudioPortConfig->gain, jGain, useInMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700900 env->DeleteLocalRef(jGain);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800901 configMask |= AUDIO_PORT_CONFIG_GAIN;
Eric Laurentb69681c2014-05-19 19:02:51 -0700902 } else {
903 ALOGV("convertAudioPortConfigToNative no gain");
904 nAudioPortConfig->gain.index = -1;
905 }
Eric Laurent6368a7d2014-11-19 12:18:32 -0800906 if (useConfigMask) {
907 nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
908 gAudioPortConfigFields.mConfigMask);
909 } else {
910 nAudioPortConfig->config_mask = configMask;
911 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700912 env->DeleteLocalRef(jAudioPort);
913 env->DeleteLocalRef(jHandle);
914 return (jint)AUDIO_JAVA_SUCCESS;
915}
916
Hongwei Wangf44a5682018-08-24 10:37:56 -0700917/**
918 * Extends convertAudioPortConfigToNative with extra device port info.
919 * Mix / Session specific info is not fulfilled.
920 */
921static jint convertAudioPortConfigToNativeWithDevicePort(JNIEnv *env,
922 struct audio_port_config *nAudioPortConfig,
923 const jobject jAudioPortConfig,
924 bool useConfigMask)
925{
926 jint jStatus = convertAudioPortConfigToNative(env,
927 nAudioPortConfig,
928 jAudioPortConfig,
929 useConfigMask);
930 if (jStatus != AUDIO_JAVA_SUCCESS) {
931 return jStatus;
932 }
933 // Supports AUDIO_PORT_TYPE_DEVICE only
934 if (nAudioPortConfig->type != AUDIO_PORT_TYPE_DEVICE) {
935 return (jint)AUDIO_JAVA_BAD_VALUE;
936 }
937
938 jobject jAudioDevicePort = env->GetObjectField(jAudioPortConfig,
939 gAudioPortConfigFields.mPort);
940 nAudioPortConfig->ext.device.type = env->GetIntField(jAudioDevicePort,
941 gAudioPortFields.mType);
942 jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioDevicePort,
943 gAudioPortFields.mAddress);
944 const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
945 strncpy(nAudioPortConfig->ext.device.address,
946 nDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN - 1);
947 env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
948 env->DeleteLocalRef(jDeviceAddress);
949 env->DeleteLocalRef(jAudioDevicePort);
950 return jStatus;
951}
952
Eric Laurentb69681c2014-05-19 19:02:51 -0700953static jint convertAudioPortConfigFromNative(JNIEnv *env,
954 jobject jAudioPort,
955 jobject *jAudioPortConfig,
956 const struct audio_port_config *nAudioPortConfig)
957{
958 jint jStatus = AUDIO_JAVA_SUCCESS;
959 jobject jAudioGainConfig = NULL;
960 jobject jAudioGain = NULL;
961 jintArray jGainValues;
962 bool audioportCreated = false;
963
964 ALOGV("convertAudioPortConfigFromNative jAudioPort %p", jAudioPort);
965
966 if (jAudioPort == NULL) {
967 jobject jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
968 nAudioPortConfig->id);
969
970 ALOGV("convertAudioPortConfigFromNative handle %d is a %s", nAudioPortConfig->id,
971 nAudioPortConfig->type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix");
972
973 if (jHandle == NULL) {
974 return (jint)AUDIO_JAVA_ERROR;
975 }
976 // create dummy port and port config objects with just the correct handle
977 // and configuration data. The actual AudioPortConfig objects will be
978 // constructed by java code with correct class type (device, mix etc...)
979 // and reference to AudioPort instance in this client
980 jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
Paul McLeanf29e5f32015-06-15 10:19:22 -0700981 jHandle, // handle
982 0, // role
983 NULL, // name
984 NULL, // samplingRates
985 NULL, // channelMasks
986 NULL, // channelIndexMasks
987 NULL, // formats
988 NULL); // gains
Eric Laurentb69681c2014-05-19 19:02:51 -0700989 env->DeleteLocalRef(jHandle);
990 if (jAudioPort == NULL) {
991 return (jint)AUDIO_JAVA_ERROR;
992 }
993 ALOGV("convertAudioPortConfigFromNative jAudioPort created for handle %d",
994 nAudioPortConfig->id);
995
996 audioportCreated = true;
997 }
998
999 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
1000
1001 audio_channel_mask_t nMask;
1002 jint jMask;
1003
1004 int gainIndex = nAudioPortConfig->gain.index;
1005 if (gainIndex >= 0) {
1006 ALOGV("convertAudioPortConfigFromNative gain found with index %d mode %x",
1007 gainIndex, nAudioPortConfig->gain.mode);
1008 if (audioportCreated) {
1009 ALOGV("convertAudioPortConfigFromNative creating gain");
1010 jAudioGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
1011 gainIndex,
1012 0,
1013 0,
1014 0,
1015 0,
1016 0,
1017 0,
1018 0,
1019 0);
1020 if (jAudioGain == NULL) {
1021 ALOGV("convertAudioPortConfigFromNative creating gain FAILED");
1022 jStatus = (jint)AUDIO_JAVA_ERROR;
1023 goto exit;
1024 }
1025 } else {
1026 ALOGV("convertAudioPortConfigFromNative reading gain from port");
1027 jobjectArray jGains = (jobjectArray)env->GetObjectField(jAudioPort,
1028 gAudioPortFields.mGains);
1029 if (jGains == NULL) {
1030 ALOGV("convertAudioPortConfigFromNative could not get gains from port");
1031 jStatus = (jint)AUDIO_JAVA_ERROR;
1032 goto exit;
1033 }
1034 jAudioGain = env->GetObjectArrayElement(jGains, gainIndex);
1035 env->DeleteLocalRef(jGains);
1036 if (jAudioGain == NULL) {
1037 ALOGV("convertAudioPortConfigFromNative could not get gain at index %d", gainIndex);
1038 jStatus = (jint)AUDIO_JAVA_ERROR;
1039 goto exit;
1040 }
1041 }
Eric Laurent0078c7c2014-06-04 09:49:52 -07001042 int numValues;
1043 if (useInMask) {
1044 numValues = audio_channel_count_from_in_mask(nAudioPortConfig->gain.channel_mask);
1045 } else {
1046 numValues = audio_channel_count_from_out_mask(nAudioPortConfig->gain.channel_mask);
1047 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001048 jGainValues = env->NewIntArray(numValues);
1049 if (jGainValues == NULL) {
1050 ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
1051 jStatus = (jint)AUDIO_JAVA_ERROR;
1052 goto exit;
1053 }
1054 env->SetIntArrayRegion(jGainValues, 0, numValues,
1055 nAudioPortConfig->gain.values);
1056
1057 nMask = nAudioPortConfig->gain.channel_mask;
1058 if (useInMask) {
1059 jMask = inChannelMaskFromNative(nMask);
1060 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
1061 } else {
1062 jMask = outChannelMaskFromNative(nMask);
1063 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
1064 }
1065
1066 jAudioGainConfig = env->NewObject(gAudioGainConfigClass,
1067 gAudioGainConfigCstor,
1068 gainIndex,
1069 jAudioGain,
1070 nAudioPortConfig->gain.mode,
1071 jMask,
1072 jGainValues,
1073 nAudioPortConfig->gain.ramp_duration_ms);
1074 env->DeleteLocalRef(jGainValues);
1075 if (jAudioGainConfig == NULL) {
1076 ALOGV("convertAudioPortConfigFromNative could not create gain config");
1077 jStatus = (jint)AUDIO_JAVA_ERROR;
1078 goto exit;
1079 }
1080 }
1081 jclass clazz;
1082 jmethodID methodID;
1083 if (audioportCreated) {
1084 clazz = gAudioPortConfigClass;
1085 methodID = gAudioPortConfigCstor;
1086 ALOGV("convertAudioPortConfigFromNative building a generic port config");
1087 } else {
1088 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
1089 clazz = gAudioDevicePortConfigClass;
1090 methodID = gAudioDevicePortConfigCstor;
1091 ALOGV("convertAudioPortConfigFromNative building a device config");
1092 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
1093 clazz = gAudioMixPortConfigClass;
1094 methodID = gAudioMixPortConfigCstor;
1095 ALOGV("convertAudioPortConfigFromNative building a mix config");
1096 } else {
1097 jStatus = (jint)AUDIO_JAVA_ERROR;
1098 goto exit;
1099 }
1100 }
1101 nMask = nAudioPortConfig->channel_mask;
1102 if (useInMask) {
1103 jMask = inChannelMaskFromNative(nMask);
1104 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
1105 } else {
1106 jMask = outChannelMaskFromNative(nMask);
1107 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
1108 }
1109
1110 *jAudioPortConfig = env->NewObject(clazz, methodID,
1111 jAudioPort,
1112 nAudioPortConfig->sample_rate,
1113 jMask,
1114 audioFormatFromNative(nAudioPortConfig->format),
1115 jAudioGainConfig);
1116 if (*jAudioPortConfig == NULL) {
1117 ALOGV("convertAudioPortConfigFromNative could not create new port config");
1118 jStatus = (jint)AUDIO_JAVA_ERROR;
1119 } else {
1120 ALOGV("convertAudioPortConfigFromNative OK");
1121 }
1122
1123exit:
1124 if (audioportCreated) {
1125 env->DeleteLocalRef(jAudioPort);
1126 if (jAudioGain != NULL) {
1127 env->DeleteLocalRef(jAudioGain);
1128 }
1129 }
1130 if (jAudioGainConfig != NULL) {
1131 env->DeleteLocalRef(jAudioGainConfig);
1132 }
1133 return jStatus;
1134}
1135
Paul McLean4e5e9e92015-06-17 10:10:11 -07001136static bool hasFormat(int* formats, size_t size, int format) {
1137 for (size_t index = 0; index < size; index++) {
1138 if (formats[index] == format) {
1139 return true; // found
1140 }
1141 }
1142 return false; // not found
1143}
1144
Andy Hung737d9fb2016-08-16 18:38:49 -07001145// TODO: pull out to separate file
1146template <typename T, size_t N>
1147static constexpr size_t array_size(const T (&)[N]) {
1148 return N;
1149}
1150
Eric Laurentb69681c2014-05-19 19:02:51 -07001151static jint convertAudioPortFromNative(JNIEnv *env,
1152 jobject *jAudioPort, const struct audio_port *nAudioPort)
1153{
1154 jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
1155 jintArray jSamplingRates = NULL;
1156 jintArray jChannelMasks = NULL;
Paul McLeanf29e5f32015-06-15 10:19:22 -07001157 jintArray jChannelIndexMasks = NULL;
Paul McLean4e5e9e92015-06-17 10:10:11 -07001158 int* cFormats = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -07001159 jintArray jFormats = NULL;
1160 jobjectArray jGains = NULL;
1161 jobject jHandle = NULL;
xiaomi/hanli82840c42017-07-19 18:53:03 +08001162 jobject jAudioPortConfig = NULL;
Paul McLean10804eb2015-01-28 11:16:35 -08001163 jstring jDeviceName = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -07001164 bool useInMask;
Paul McLeanf29e5f32015-06-15 10:19:22 -07001165 size_t numPositionMasks = 0;
1166 size_t numIndexMasks = 0;
Paul McLean2db94372015-06-18 12:47:34 -07001167 size_t numUniqueFormats = 0;
1168
Paul McLean10804eb2015-01-28 11:16:35 -08001169 ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
1170 nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
Eric Laurentb69681c2014-05-19 19:02:51 -07001171
Andy Hung737d9fb2016-08-16 18:38:49 -07001172 // Verify audio port array count info.
1173 if (nAudioPort->num_sample_rates > array_size(nAudioPort->sample_rates)
1174 || nAudioPort->num_channel_masks > array_size(nAudioPort->channel_masks)
1175 || nAudioPort->num_formats > array_size(nAudioPort->formats)
1176 || nAudioPort->num_gains > array_size(nAudioPort->gains)) {
1177
1178 std::stringstream ss;
1179 ss << "convertAudioPortFromNative array count out of bounds:"
1180 << " num_sample_rates " << nAudioPort->num_sample_rates
1181 << " num_channel_masks " << nAudioPort->num_channel_masks
1182 << " num_formats " << nAudioPort->num_formats
1183 << " num_gains " << nAudioPort->num_gains
1184 ;
1185 std::string s = ss.str();
1186
1187 // Prefer to log through Java wtf instead of native ALOGE.
1188 ScopedLocalRef<jclass> jLogClass(env, env->FindClass("android/util/Log"));
1189 jmethodID jWtfId = (jLogClass.get() == nullptr)
1190 ? nullptr
1191 : env->GetStaticMethodID(jLogClass.get(), "wtf",
1192 "(Ljava/lang/String;Ljava/lang/String;)I");
1193 if (jWtfId != nullptr) {
1194 ScopedLocalRef<jstring> jMessage(env, env->NewStringUTF(s.c_str()));
1195 ScopedLocalRef<jstring> jTag(env, env->NewStringUTF(LOG_TAG));
1196 (void)env->CallStaticIntMethod(jLogClass.get(), jWtfId, jTag.get(), jMessage.get());
1197 } else {
1198 ALOGE("%s", s.c_str());
1199 }
1200 jStatus = (jint)AUDIO_JAVA_ERROR;
1201 goto exit;
1202 }
1203
Eric Laurentb69681c2014-05-19 19:02:51 -07001204 jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
1205 if (jSamplingRates == NULL) {
1206 jStatus = (jint)AUDIO_JAVA_ERROR;
1207 goto exit;
1208 }
1209 if (nAudioPort->num_sample_rates) {
1210 env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates,
1211 (jint *)nAudioPort->sample_rates);
1212 }
1213
Paul McLeanf29e5f32015-06-15 10:19:22 -07001214 // count up how many masks are positional and indexed
1215 for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) {
1216 const audio_channel_mask_t mask = nAudioPort->channel_masks[index];
1217 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
1218 numIndexMasks++;
1219 } else {
1220 numPositionMasks++;
1221 }
1222 }
1223
1224 jChannelMasks = env->NewIntArray(numPositionMasks);
Eric Laurentb69681c2014-05-19 19:02:51 -07001225 if (jChannelMasks == NULL) {
1226 jStatus = (jint)AUDIO_JAVA_ERROR;
1227 goto exit;
1228 }
Paul McLeanf29e5f32015-06-15 10:19:22 -07001229 jChannelIndexMasks = env->NewIntArray(numIndexMasks);
1230 if (jChannelIndexMasks == NULL) {
1231 jStatus = (jint)AUDIO_JAVA_ERROR;
1232 goto exit;
1233 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001234 useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
1235
Paul McLeanf29e5f32015-06-15 10:19:22 -07001236 // put the masks in the output arrays
1237 for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
1238 maskIndex < nAudioPort->num_channel_masks; maskIndex++) {
1239 const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex];
1240 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
1241 jint jMask = audio_channel_mask_get_bits(mask);
1242 env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -07001243 } else {
Paul McLeanf29e5f32015-06-15 10:19:22 -07001244 jint jMask = useInMask ? inChannelMaskFromNative(mask)
1245 : outChannelMaskFromNative(mask);
1246 env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -07001247 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001248 }
1249
Paul McLeanf29e5f32015-06-15 10:19:22 -07001250 // formats
Paul McLean2db94372015-06-18 12:47:34 -07001251 if (nAudioPort->num_formats != 0) {
1252 cFormats = new int[nAudioPort->num_formats];
1253 for (size_t index = 0; index < nAudioPort->num_formats; index++) {
1254 int format = audioFormatFromNative(nAudioPort->formats[index]);
1255 if (!hasFormat(cFormats, numUniqueFormats, format)) {
1256 cFormats[numUniqueFormats++] = format;
1257 }
Paul McLean4e5e9e92015-06-17 10:10:11 -07001258 }
1259 }
1260 jFormats = env->NewIntArray(numUniqueFormats);
Eric Laurentb69681c2014-05-19 19:02:51 -07001261 if (jFormats == NULL) {
1262 jStatus = (jint)AUDIO_JAVA_ERROR;
1263 goto exit;
1264 }
Paul McLean2db94372015-06-18 12:47:34 -07001265 if (numUniqueFormats != 0) {
1266 env->SetIntArrayRegion(jFormats, 0, numUniqueFormats, cFormats);
1267 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001268
Paul McLeanf29e5f32015-06-15 10:19:22 -07001269 // gains
Eric Laurentb69681c2014-05-19 19:02:51 -07001270 jGains = env->NewObjectArray(nAudioPort->num_gains,
1271 gAudioGainClass, NULL);
1272 if (jGains == NULL) {
1273 jStatus = (jint)AUDIO_JAVA_ERROR;
1274 goto exit;
1275 }
Paul McLeanf29e5f32015-06-15 10:19:22 -07001276
Eric Laurentb69681c2014-05-19 19:02:51 -07001277 for (size_t j = 0; j < nAudioPort->num_gains; j++) {
1278 audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask;
Paul McLeanf29e5f32015-06-15 10:19:22 -07001279 jint jMask;
Eric Laurentb69681c2014-05-19 19:02:51 -07001280 if (useInMask) {
1281 jMask = inChannelMaskFromNative(nMask);
1282 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
1283 } else {
1284 jMask = outChannelMaskFromNative(nMask);
1285 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
1286 }
1287
1288 jobject jGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
1289 j,
1290 nAudioPort->gains[j].mode,
1291 jMask,
1292 nAudioPort->gains[j].min_value,
1293 nAudioPort->gains[j].max_value,
1294 nAudioPort->gains[j].default_value,
1295 nAudioPort->gains[j].step_value,
1296 nAudioPort->gains[j].min_ramp_ms,
1297 nAudioPort->gains[j].max_ramp_ms);
1298 if (jGain == NULL) {
1299 jStatus = (jint)AUDIO_JAVA_ERROR;
1300 goto exit;
1301 }
1302 env->SetObjectArrayElement(jGains, j, jGain);
1303 env->DeleteLocalRef(jGain);
1304 }
1305
1306 jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1307 nAudioPort->id);
1308 if (jHandle == NULL) {
1309 jStatus = (jint)AUDIO_JAVA_ERROR;
1310 goto exit;
1311 }
1312
Paul McLean10804eb2015-01-28 11:16:35 -08001313 jDeviceName = env->NewStringUTF(nAudioPort->name);
1314
Eric Laurentb69681c2014-05-19 19:02:51 -07001315 if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
1316 ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
1317 jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
1318 *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
Paul McLean10804eb2015-01-28 11:16:35 -08001319 jHandle, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001320 jSamplingRates, jChannelMasks, jChannelIndexMasks,
1321 jFormats, jGains,
Eric Laurentb69681c2014-05-19 19:02:51 -07001322 nAudioPort->ext.device.type, jAddress);
1323 env->DeleteLocalRef(jAddress);
1324 } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
1325 ALOGV("convertAudioPortFromNative is a mix");
1326 *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
Eric Laurent4bcdba82015-05-01 11:37:49 -07001327 jHandle, nAudioPort->ext.mix.handle,
1328 nAudioPort->role, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001329 jSamplingRates, jChannelMasks, jChannelIndexMasks,
Eric Laurentb69681c2014-05-19 19:02:51 -07001330 jFormats, jGains);
1331 } else {
1332 ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
1333 jStatus = (jint)AUDIO_JAVA_ERROR;
1334 goto exit;
1335 }
1336 if (*jAudioPort == NULL) {
1337 jStatus = (jint)AUDIO_JAVA_ERROR;
1338 goto exit;
1339 }
1340
Eric Laurentb69681c2014-05-19 19:02:51 -07001341 jStatus = convertAudioPortConfigFromNative(env,
1342 *jAudioPort,
1343 &jAudioPortConfig,
1344 &nAudioPort->active_config);
1345 if (jStatus != AUDIO_JAVA_SUCCESS) {
Andy Hung737d9fb2016-08-16 18:38:49 -07001346 goto exit;
Eric Laurentb69681c2014-05-19 19:02:51 -07001347 }
1348
1349 env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
1350
1351exit:
Paul McLean10804eb2015-01-28 11:16:35 -08001352 if (jDeviceName != NULL) {
1353 env->DeleteLocalRef(jDeviceName);
1354 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001355 if (jSamplingRates != NULL) {
1356 env->DeleteLocalRef(jSamplingRates);
1357 }
1358 if (jChannelMasks != NULL) {
1359 env->DeleteLocalRef(jChannelMasks);
1360 }
Paul McLean4e5e9e92015-06-17 10:10:11 -07001361 if (jChannelIndexMasks != NULL) {
1362 env->DeleteLocalRef(jChannelIndexMasks);
1363 }
1364 if (cFormats != NULL) {
1365 delete[] cFormats;
1366 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001367 if (jFormats != NULL) {
1368 env->DeleteLocalRef(jFormats);
1369 }
1370 if (jGains != NULL) {
1371 env->DeleteLocalRef(jGains);
1372 }
1373 if (jHandle != NULL) {
1374 env->DeleteLocalRef(jHandle);
1375 }
xiaomi/hanli82840c42017-07-19 18:53:03 +08001376 if (jAudioPortConfig != NULL) {
1377 env->DeleteLocalRef(jAudioPortConfig);
1378 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001379
1380 return jStatus;
1381}
1382
Eric Laurentb69681c2014-05-19 19:02:51 -07001383static jint
1384android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz,
1385 jobject jPorts, jintArray jGeneration)
1386{
1387 ALOGV("listAudioPorts");
1388
1389 if (jPorts == NULL) {
1390 ALOGE("listAudioPorts NULL AudioPort ArrayList");
1391 return (jint)AUDIO_JAVA_BAD_VALUE;
1392 }
1393 if (!env->IsInstanceOf(jPorts, gArrayListClass)) {
1394 ALOGE("listAudioPorts not an arraylist");
1395 return (jint)AUDIO_JAVA_BAD_VALUE;
1396 }
1397
1398 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1399 return (jint)AUDIO_JAVA_BAD_VALUE;
1400 }
1401
1402 status_t status;
1403 unsigned int generation1;
1404 unsigned int generation;
1405 unsigned int numPorts;
1406 jint *nGeneration;
1407 struct audio_port *nPorts = NULL;
1408 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
Eric Laurentb36d1042016-04-14 18:00:38 -07001409 jint jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001410
1411 // get the port count and all the ports until they both return the same generation
1412 do {
1413 if (attempts-- < 0) {
1414 status = TIMED_OUT;
1415 break;
1416 }
1417
1418 numPorts = 0;
1419 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1420 AUDIO_PORT_TYPE_NONE,
1421 &numPorts,
1422 NULL,
1423 &generation1);
Eric Laurentb36d1042016-04-14 18:00:38 -07001424 if (status != NO_ERROR) {
Eric Laurentb69681c2014-05-19 19:02:51 -07001425 ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status);
1426 break;
1427 }
Eric Laurentb36d1042016-04-14 18:00:38 -07001428 if (numPorts == 0) {
1429 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1430 goto exit;
1431 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001432 nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port));
1433
1434 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1435 AUDIO_PORT_TYPE_NONE,
1436 &numPorts,
1437 nPorts,
1438 &generation);
1439 ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
1440 numPorts, generation, generation1);
1441 } while (generation1 != generation && status == NO_ERROR);
1442
Eric Laurentb36d1042016-04-14 18:00:38 -07001443 jStatus = nativeToJavaStatus(status);
Eric Laurentb69681c2014-05-19 19:02:51 -07001444 if (jStatus != AUDIO_JAVA_SUCCESS) {
1445 goto exit;
1446 }
1447
Eric Laurentb69681c2014-05-19 19:02:51 -07001448 for (size_t i = 0; i < numPorts; i++) {
xiaomi/hanli82840c42017-07-19 18:53:03 +08001449 jobject jAudioPort = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -07001450 jStatus = convertAudioPortFromNative(env, &jAudioPort, &nPorts[i]);
1451 if (jStatus != AUDIO_JAVA_SUCCESS) {
1452 goto exit;
1453 }
1454 env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort);
xiaomi/hanli82840c42017-07-19 18:53:03 +08001455 if (jAudioPort != NULL) {
1456 env->DeleteLocalRef(jAudioPort);
1457 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001458 }
1459
1460exit:
Eric Laurentb36d1042016-04-14 18:00:38 -07001461 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1462 if (nGeneration == NULL) {
1463 jStatus = (jint)AUDIO_JAVA_ERROR;
1464 } else {
1465 nGeneration[0] = generation1;
1466 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1467 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001468 free(nPorts);
1469 return jStatus;
1470}
1471
1472static int
1473android_media_AudioSystem_createAudioPatch(JNIEnv *env, jobject clazz,
1474 jobjectArray jPatches, jobjectArray jSources, jobjectArray jSinks)
1475{
1476 status_t status;
1477 jint jStatus;
1478
1479 ALOGV("createAudioPatch");
1480 if (jPatches == NULL || jSources == NULL || jSinks == NULL) {
1481 return (jint)AUDIO_JAVA_BAD_VALUE;
1482 }
1483
1484 if (env->GetArrayLength(jPatches) != 1) {
1485 return (jint)AUDIO_JAVA_BAD_VALUE;
1486 }
1487 jint numSources = env->GetArrayLength(jSources);
1488 if (numSources == 0 || numSources > AUDIO_PATCH_PORTS_MAX) {
1489 return (jint)AUDIO_JAVA_BAD_VALUE;
1490 }
1491
1492 jint numSinks = env->GetArrayLength(jSinks);
1493 if (numSinks == 0 || numSinks > AUDIO_PATCH_PORTS_MAX) {
1494 return (jint)AUDIO_JAVA_BAD_VALUE;
1495 }
1496
1497 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1498 jobject jPatch = env->GetObjectArrayElement(jPatches, 0);
1499 jobject jPatchHandle = NULL;
1500 if (jPatch != NULL) {
1501 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1502 return (jint)AUDIO_JAVA_BAD_VALUE;
1503 }
1504 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1505 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1506 }
1507
Mikhail Naganov304eafc2018-05-23 16:54:12 -07001508 struct audio_patch nPatch = { .id = handle };
Eric Laurentb69681c2014-05-19 19:02:51 -07001509
Eric Laurentb69681c2014-05-19 19:02:51 -07001510 jobject jSource = NULL;
1511 jobject jSink = NULL;
1512
1513 for (jint i = 0; i < numSources; i++) {
1514 jSource = env->GetObjectArrayElement(jSources, i);
1515 if (!env->IsInstanceOf(jSource, gAudioPortConfigClass)) {
1516 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1517 goto exit;
1518 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001519 jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001520 env->DeleteLocalRef(jSource);
1521 jSource = NULL;
1522 if (jStatus != AUDIO_JAVA_SUCCESS) {
1523 goto exit;
1524 }
1525 nPatch.num_sources++;
1526 }
1527
1528 for (jint i = 0; i < numSinks; i++) {
1529 jSink = env->GetObjectArrayElement(jSinks, i);
1530 if (!env->IsInstanceOf(jSink, gAudioPortConfigClass)) {
1531 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1532 goto exit;
1533 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001534 jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001535 env->DeleteLocalRef(jSink);
1536 jSink = NULL;
1537 if (jStatus != AUDIO_JAVA_SUCCESS) {
1538 goto exit;
1539 }
1540 nPatch.num_sinks++;
1541 }
1542
1543 ALOGV("AudioSystem::createAudioPatch");
1544 status = AudioSystem::createAudioPatch(&nPatch, &handle);
1545 ALOGV("AudioSystem::createAudioPatch() returned %d hande %d", status, handle);
1546
1547 jStatus = nativeToJavaStatus(status);
1548 if (jStatus != AUDIO_JAVA_SUCCESS) {
1549 goto exit;
1550 }
1551
1552 if (jPatchHandle == NULL) {
1553 jPatchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1554 handle);
1555 if (jPatchHandle == NULL) {
1556 jStatus = (jint)AUDIO_JAVA_ERROR;
1557 goto exit;
1558 }
1559 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle, jSources, jSinks);
1560 if (jPatch == NULL) {
1561 jStatus = (jint)AUDIO_JAVA_ERROR;
1562 goto exit;
1563 }
1564 env->SetObjectArrayElement(jPatches, 0, jPatch);
1565 } else {
1566 env->SetIntField(jPatchHandle, gAudioHandleFields.mId, handle);
1567 }
1568
1569exit:
1570 if (jPatchHandle != NULL) {
1571 env->DeleteLocalRef(jPatchHandle);
1572 }
1573 if (jPatch != NULL) {
1574 env->DeleteLocalRef(jPatch);
1575 }
1576 if (jSource != NULL) {
1577 env->DeleteLocalRef(jSource);
1578 }
1579 if (jSink != NULL) {
1580 env->DeleteLocalRef(jSink);
1581 }
1582 return jStatus;
1583}
1584
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001585static jint
Eric Laurentb69681c2014-05-19 19:02:51 -07001586android_media_AudioSystem_releaseAudioPatch(JNIEnv *env, jobject clazz,
1587 jobject jPatch)
1588{
1589 ALOGV("releaseAudioPatch");
1590 if (jPatch == NULL) {
1591 return (jint)AUDIO_JAVA_BAD_VALUE;
1592 }
1593
1594 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1595 jobject jPatchHandle = NULL;
1596 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1597 return (jint)AUDIO_JAVA_BAD_VALUE;
1598 }
1599 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1600 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1601 env->DeleteLocalRef(jPatchHandle);
1602
1603 ALOGV("AudioSystem::releaseAudioPatch");
1604 status_t status = AudioSystem::releaseAudioPatch(handle);
1605 ALOGV("AudioSystem::releaseAudioPatch() returned %d", status);
1606 jint jStatus = nativeToJavaStatus(status);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001607 return jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001608}
1609
1610static jint
1611android_media_AudioSystem_listAudioPatches(JNIEnv *env, jobject clazz,
1612 jobject jPatches, jintArray jGeneration)
1613{
1614 ALOGV("listAudioPatches");
1615 if (jPatches == NULL) {
1616 ALOGE("listAudioPatches NULL AudioPatch ArrayList");
1617 return (jint)AUDIO_JAVA_BAD_VALUE;
1618 }
1619 if (!env->IsInstanceOf(jPatches, gArrayListClass)) {
1620 ALOGE("listAudioPatches not an arraylist");
1621 return (jint)AUDIO_JAVA_BAD_VALUE;
1622 }
1623
1624 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1625 return (jint)AUDIO_JAVA_BAD_VALUE;
1626 }
1627
1628 status_t status;
1629 unsigned int generation1;
1630 unsigned int generation;
1631 unsigned int numPatches;
1632 jint *nGeneration;
1633 struct audio_patch *nPatches = NULL;
1634 jobjectArray jSources = NULL;
1635 jobject jSource = NULL;
1636 jobjectArray jSinks = NULL;
1637 jobject jSink = NULL;
1638 jobject jPatch = NULL;
1639 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
Eric Laurentb36d1042016-04-14 18:00:38 -07001640 jint jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001641
1642 // get the patch count and all the patches until they both return the same generation
1643 do {
1644 if (attempts-- < 0) {
1645 status = TIMED_OUT;
1646 break;
1647 }
1648
1649 numPatches = 0;
1650 status = AudioSystem::listAudioPatches(&numPatches,
1651 NULL,
1652 &generation1);
Eric Laurentb36d1042016-04-14 18:00:38 -07001653 if (status != NO_ERROR) {
Eric Laurentb69681c2014-05-19 19:02:51 -07001654 ALOGE_IF(status != NO_ERROR, "listAudioPatches AudioSystem::listAudioPatches error %d",
1655 status);
1656 break;
1657 }
Eric Laurentb36d1042016-04-14 18:00:38 -07001658 if (numPatches == 0) {
1659 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1660 goto exit;
1661 }
1662
Eric Laurentb69681c2014-05-19 19:02:51 -07001663 nPatches = (struct audio_patch *)realloc(nPatches, numPatches * sizeof(struct audio_patch));
1664
1665 status = AudioSystem::listAudioPatches(&numPatches,
1666 nPatches,
1667 &generation);
1668 ALOGV("listAudioPatches AudioSystem::listAudioPatches numPatches %d generation %d generation1 %d",
1669 numPatches, generation, generation1);
1670
1671 } while (generation1 != generation && status == NO_ERROR);
1672
Eric Laurentb36d1042016-04-14 18:00:38 -07001673 jStatus = nativeToJavaStatus(status);
Eric Laurentb69681c2014-05-19 19:02:51 -07001674 if (jStatus != AUDIO_JAVA_SUCCESS) {
1675 goto exit;
1676 }
1677
Eric Laurentb69681c2014-05-19 19:02:51 -07001678 for (size_t i = 0; i < numPatches; i++) {
1679 jobject patchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1680 nPatches[i].id);
1681 if (patchHandle == NULL) {
1682 jStatus = AUDIO_JAVA_ERROR;
1683 goto exit;
1684 }
Dan Albert46d84442014-11-18 16:07:51 -08001685 ALOGV("listAudioPatches patch %zu num_sources %d num_sinks %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001686 i, nPatches[i].num_sources, nPatches[i].num_sinks);
1687
1688 env->SetIntField(patchHandle, gAudioHandleFields.mId, nPatches[i].id);
1689
1690 // load sources
1691 jSources = env->NewObjectArray(nPatches[i].num_sources,
1692 gAudioPortConfigClass, NULL);
1693 if (jSources == NULL) {
1694 jStatus = AUDIO_JAVA_ERROR;
1695 goto exit;
1696 }
1697
1698 for (size_t j = 0; j < nPatches[i].num_sources; j++) {
1699 jStatus = convertAudioPortConfigFromNative(env,
1700 NULL,
1701 &jSource,
1702 &nPatches[i].sources[j]);
1703 if (jStatus != AUDIO_JAVA_SUCCESS) {
1704 goto exit;
1705 }
1706 env->SetObjectArrayElement(jSources, j, jSource);
1707 env->DeleteLocalRef(jSource);
1708 jSource = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001709 ALOGV("listAudioPatches patch %zu source %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001710 i, j,
1711 nPatches[i].sources[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1712 nPatches[i].sources[j].id);
1713 }
1714 // load sinks
1715 jSinks = env->NewObjectArray(nPatches[i].num_sinks,
1716 gAudioPortConfigClass, NULL);
1717 if (jSinks == NULL) {
1718 jStatus = AUDIO_JAVA_ERROR;
1719 goto exit;
1720 }
1721
1722 for (size_t j = 0; j < nPatches[i].num_sinks; j++) {
1723 jStatus = convertAudioPortConfigFromNative(env,
1724 NULL,
1725 &jSink,
1726 &nPatches[i].sinks[j]);
1727
1728 if (jStatus != AUDIO_JAVA_SUCCESS) {
1729 goto exit;
1730 }
1731 env->SetObjectArrayElement(jSinks, j, jSink);
1732 env->DeleteLocalRef(jSink);
1733 jSink = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001734 ALOGV("listAudioPatches patch %zu sink %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001735 i, j,
1736 nPatches[i].sinks[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1737 nPatches[i].sinks[j].id);
1738 }
1739
1740 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor,
1741 patchHandle, jSources, jSinks);
1742 env->DeleteLocalRef(jSources);
1743 jSources = NULL;
1744 env->DeleteLocalRef(jSinks);
1745 jSinks = NULL;
1746 if (jPatch == NULL) {
1747 jStatus = AUDIO_JAVA_ERROR;
1748 goto exit;
1749 }
1750 env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch);
1751 env->DeleteLocalRef(jPatch);
1752 jPatch = NULL;
1753 }
1754
1755exit:
Eric Laurentb36d1042016-04-14 18:00:38 -07001756
1757 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1758 if (nGeneration == NULL) {
1759 jStatus = AUDIO_JAVA_ERROR;
1760 } else {
1761 nGeneration[0] = generation1;
1762 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1763 }
1764
Eric Laurentb69681c2014-05-19 19:02:51 -07001765 if (jSources != NULL) {
1766 env->DeleteLocalRef(jSources);
1767 }
1768 if (jSource != NULL) {
1769 env->DeleteLocalRef(jSource);
1770 }
1771 if (jSinks != NULL) {
1772 env->DeleteLocalRef(jSinks);
1773 }
1774 if (jSink != NULL) {
1775 env->DeleteLocalRef(jSink);
1776 }
1777 if (jPatch != NULL) {
1778 env->DeleteLocalRef(jPatch);
1779 }
1780 free(nPatches);
1781 return jStatus;
1782}
1783
Eric Laurent3a241992014-05-19 19:33:26 -07001784static jint
1785android_media_AudioSystem_setAudioPortConfig(JNIEnv *env, jobject clazz,
1786 jobject jAudioPortConfig)
1787{
1788 ALOGV("setAudioPortConfig");
1789 if (jAudioPortConfig == NULL) {
1790 return AUDIO_JAVA_BAD_VALUE;
1791 }
1792 if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
1793 return AUDIO_JAVA_BAD_VALUE;
1794 }
Mikhail Naganov304eafc2018-05-23 16:54:12 -07001795 struct audio_port_config nAudioPortConfig = {};
Eric Laurent6368a7d2014-11-19 12:18:32 -08001796 jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
Eric Laurent3a241992014-05-19 19:33:26 -07001797 if (jStatus != AUDIO_JAVA_SUCCESS) {
1798 return jStatus;
1799 }
1800 status_t status = AudioSystem::setAudioPortConfig(&nAudioPortConfig);
1801 ALOGV("AudioSystem::setAudioPortConfig() returned %d", status);
1802 jStatus = nativeToJavaStatus(status);
1803 return jStatus;
1804}
1805
Hongwei Wangf44a5682018-08-24 10:37:56 -07001806/**
1807 * Returns handle if the audio source is successfully started.
1808 */
1809static jint
1810android_media_AudioSystem_startAudioSource(JNIEnv *env, jobject clazz,
1811 jobject jAudioPortConfig,
1812 jobject jAudioAttributes)
1813{
1814 ALOGV("startAudioSource");
1815 if (jAudioPortConfig == NULL || jAudioAttributes == NULL) {
1816 return AUDIO_JAVA_BAD_VALUE;
1817 }
1818 if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
1819 return AUDIO_JAVA_BAD_VALUE;
1820 }
Hongwei Wangf44a5682018-08-24 10:37:56 -07001821 struct audio_port_config nAudioPortConfig = {};
1822 jint jStatus = convertAudioPortConfigToNativeWithDevicePort(env,
1823 &nAudioPortConfig, jAudioPortConfig, false);
1824 if (jStatus != AUDIO_JAVA_SUCCESS) {
1825 return jStatus;
1826 }
François Gaffieb4691282018-07-09 13:07:32 +02001827 auto paa = JNIAudioAttributeHelper::makeUnique();
1828 jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAudioAttributes, paa.get());
1829 if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
Hongwei Wangf44a5682018-08-24 10:37:56 -07001830 return jStatus;
1831 }
1832 audio_port_handle_t handle;
François Gaffieb4691282018-07-09 13:07:32 +02001833 status_t status = AudioSystem::startAudioSource(&nAudioPortConfig, paa.get(), &handle);
Hongwei Wangf44a5682018-08-24 10:37:56 -07001834 ALOGV("AudioSystem::startAudioSource() returned %d handle %d", status, handle);
1835 return handle > 0 ? handle : nativeToJavaStatus(status);
1836}
1837
1838static jint
1839android_media_AudioSystem_stopAudioSource(JNIEnv *env, jobject clazz, jint handle)
1840{
1841 ALOGV("stopAudioSource");
1842 status_t status = AudioSystem::stopAudioSource(
1843 static_cast <audio_port_handle_t>(handle));
1844 ALOGV("AudioSystem::stopAudioSource() returned %d", status);
1845 return nativeToJavaStatus(status);
1846}
1847
Eric Laurent700e7342014-05-02 18:33:15 -07001848static void
1849android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
1850{
1851 ALOGV("eventHandlerSetup");
1852
1853 sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
1854
Eric Laurent2615afb2015-03-25 14:51:08 -07001855 if (AudioSystem::addAudioPortCallback(callback) == NO_ERROR) {
1856 setJniCallback(env, thiz, callback);
1857 }
Eric Laurent700e7342014-05-02 18:33:15 -07001858}
1859
1860static void
1861android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz)
1862{
1863 ALOGV("eventHandlerFinalize");
1864
Eric Laurent2615afb2015-03-25 14:51:08 -07001865 sp<JNIAudioPortCallback> callback = setJniCallback(env, thiz, 0);
Eric Laurent700e7342014-05-02 18:33:15 -07001866
Eric Laurent2615afb2015-03-25 14:51:08 -07001867 if (callback != 0) {
1868 AudioSystem::removeAudioPortCallback(callback);
1869 }
Eric Laurent700e7342014-05-02 18:33:15 -07001870}
1871
Eric Laurentb634e1b2014-08-01 14:44:46 -07001872static jint
1873android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
1874{
Glenn Kasten33b84042016-03-08 12:02:55 -08001875 return (jint) AudioSystem::getAudioHwSyncForSession((audio_session_t) sessionId);
Eric Laurentb634e1b2014-08-01 14:44:46 -07001876}
1877
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001878static void
1879android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz)
1880{
1881 AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback);
1882}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001883
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001884static void
1885android_media_AudioSystem_registerRecordingCallback(JNIEnv *env, jobject thiz)
1886{
1887 AudioSystem::setRecordConfigCallback(android_media_AudioSystem_recording_callback);
1888}
1889
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001890
1891static jint convertAudioMixToNative(JNIEnv *env,
1892 AudioMix *nAudioMix,
1893 const jobject jAudioMix)
1894{
1895 nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
1896 nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07001897 nAudioMix->mDeviceType = (audio_devices_t)
1898 env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001899
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07001900 jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioMix,
1901 gAudioMixFields.mDeviceAddress);
1902 const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
1903 nAudioMix->mDeviceAddress = String8(nDeviceAddress);
1904 env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
1905 env->DeleteLocalRef(jDeviceAddress);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001906
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001907 nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
1908
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001909 jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
1910 nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
1911 gAudioFormatFields.mSampleRate);
1912 nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
1913 gAudioFormatFields.mChannelMask));
1914 nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
1915 gAudioFormatFields.mEncoding));
1916 env->DeleteLocalRef(jFormat);
1917
1918 jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
1919 jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -08001920 nAudioMix->mAllowPrivilegedPlaybackCapture =
1921 env->GetBooleanField(jRule, gAudioMixingRuleFields.mAllowPrivilegedPlaybackCapture);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001922 env->DeleteLocalRef(jRule);
1923 jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
1924 gArrayListMethods.toArray);
1925 env->DeleteLocalRef(jRuleCriteria);
1926
1927 jint numCriteria = env->GetArrayLength(jCriteria);
1928 if (numCriteria > MAX_CRITERIA_PER_MIX) {
1929 numCriteria = MAX_CRITERIA_PER_MIX;
1930 }
1931
1932 for (jint i = 0; i < numCriteria; i++) {
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001933 AudioMixMatchCriterion nCriterion;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001934
1935 jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
1936
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001937 nCriterion.mRule = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mRule);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001938
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001939 const uint32_t match_rule = nCriterion.mRule & ~RULE_EXCLUSION_MASK;
1940 switch (match_rule) {
1941 case RULE_MATCH_UID:
1942 nCriterion.mValue.mUid = env->GetIntField(jCriterion,
1943 gAudioMixMatchCriterionFields.mIntProp);
1944 break;
Oscar Azucena76788f02019-11-27 17:34:29 -08001945 case RULE_MATCH_USERID:
1946 nCriterion.mValue.mUserId =
1947 env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mIntProp);
1948 break;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001949 case RULE_MATCH_ATTRIBUTE_USAGE:
1950 case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
1951 jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
François Gaffieb4691282018-07-09 13:07:32 +02001952
1953 auto paa = JNIAudioAttributeHelper::makeUnique();
1954 jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAttributes, paa.get());
1955 if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
1956 return jStatus;
1957 }
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001958 if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
François Gaffieb4691282018-07-09 13:07:32 +02001959 nCriterion.mValue.mUsage = paa->usage;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001960 } else {
François Gaffieb4691282018-07-09 13:07:32 +02001961 nCriterion.mValue.mSource = paa->source;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001962 }
1963 env->DeleteLocalRef(jAttributes);
1964 }
1965 break;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001966 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001967
1968 nAudioMix->mCriteria.add(nCriterion);
1969 env->DeleteLocalRef(jCriterion);
1970 }
1971
1972 env->DeleteLocalRef(jCriteria);
1973
1974 return (jint)AUDIO_JAVA_SUCCESS;
1975}
1976
1977static jint
1978android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
1979 jobject jMixesList, jboolean registration)
1980{
1981 ALOGV("registerPolicyMixes");
1982
1983 if (jMixesList == NULL) {
1984 return (jint)AUDIO_JAVA_BAD_VALUE;
1985 }
1986 if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
1987 return (jint)AUDIO_JAVA_BAD_VALUE;
1988 }
1989 jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
1990 gArrayListMethods.toArray);
1991 jint numMixes = env->GetArrayLength(jMixes);
1992 if (numMixes > MAX_MIXES_PER_POLICY) {
1993 numMixes = MAX_MIXES_PER_POLICY;
1994 }
1995
1996 status_t status;
1997 jint jStatus;
1998 jobject jAudioMix = NULL;
1999 Vector <AudioMix> mixes;
2000 for (jint i = 0; i < numMixes; i++) {
2001 jAudioMix = env->GetObjectArrayElement(jMixes, i);
2002 if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
2003 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
2004 goto exit;
2005 }
2006 AudioMix mix;
2007 jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
2008 env->DeleteLocalRef(jAudioMix);
2009 jAudioMix = NULL;
2010 if (jStatus != AUDIO_JAVA_SUCCESS) {
2011 goto exit;
2012 }
2013 mixes.add(mix);
2014 }
2015
2016 ALOGV("AudioSystem::registerPolicyMixes numMixes %d registration %d", numMixes, registration);
2017 status = AudioSystem::registerPolicyMixes(mixes, registration);
2018 ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
2019
2020 jStatus = nativeToJavaStatus(status);
2021 if (jStatus != AUDIO_JAVA_SUCCESS) {
2022 goto exit;
2023 }
2024
2025exit:
2026 if (jAudioMix != NULL) {
2027 env->DeleteLocalRef(jAudioMix);
2028 }
2029 return jStatus;
2030}
2031
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08002032static jint android_media_AudioSystem_setUidDeviceAffinities(JNIEnv *env, jobject clazz,
2033 jint uid, jintArray deviceTypes, jobjectArray deviceAddresses) {
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08002034 Vector<AudioDeviceTypeAddr> deviceVector;
Oscar Azucena76788f02019-11-27 17:34:29 -08002035 jint results = getVectorOfAudioDeviceTypeAddr(env, deviceTypes, deviceAddresses, deviceVector);
2036 if (results != NO_ERROR) {
2037 return results;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08002038 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08002039 status_t status = AudioSystem::setUidDeviceAffinities((uid_t) uid, deviceVector);
2040 return (jint) nativeToJavaStatus(status);
2041}
2042
2043static jint android_media_AudioSystem_removeUidDeviceAffinities(JNIEnv *env, jobject clazz,
2044 jint uid) {
Oscar Azucena3d6341f2019-04-26 23:45:28 -07002045 status_t status = AudioSystem::removeUidDeviceAffinities((uid_t) uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08002046 return (jint) nativeToJavaStatus(status);
2047}
2048
Oscar Azucena76788f02019-11-27 17:34:29 -08002049static jint android_media_AudioSystem_setUserIdDeviceAffinities(JNIEnv *env, jobject clazz,
2050 jint userId, jintArray deviceTypes,
2051 jobjectArray deviceAddresses) {
2052 Vector<AudioDeviceTypeAddr> deviceVector;
2053 jint results = getVectorOfAudioDeviceTypeAddr(env, deviceTypes, deviceAddresses, deviceVector);
2054 if (results != NO_ERROR) {
2055 return results;
2056 }
2057 status_t status = AudioSystem::setUserIdDeviceAffinities((int)userId, deviceVector);
2058 return (jint)nativeToJavaStatus(status);
2059}
2060
2061static jint android_media_AudioSystem_removeUserIdDeviceAffinities(JNIEnv *env, jobject clazz,
2062 jint userId) {
2063 status_t status = AudioSystem::removeUserIdDeviceAffinities((int)userId);
2064 return (jint)nativeToJavaStatus(status);
2065}
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08002066
Eric Laurent0867bed2015-05-20 14:49:08 -07002067static jint
2068android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
2069{
2070 return nativeToJavaStatus(AudioSystem::systemReady());
2071}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002072
Eric Laurenteab40d12017-06-09 12:45:21 -07002073static jfloat
2074android_media_AudioSystem_getStreamVolumeDB(JNIEnv *env, jobject thiz,
2075 jint stream, jint index, jint device)
2076{
2077 return (jfloat)AudioSystem::getStreamVolumeDB((audio_stream_type_t)stream,
2078 (int)index,
2079 (audio_devices_t)device);
2080}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002081
Jean-Michel Trivi980d38f2018-01-08 15:43:35 -08002082static jboolean
2083android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz,
Jean-Michel Trivif3fd84a2019-03-21 16:08:50 -07002084 jint encoding, jint sampleRate, jint channelMask, jint channelIndexMask, jint streamType)
Jean-Michel Trivi980d38f2018-01-08 15:43:35 -08002085{
2086 audio_offload_info_t format = AUDIO_INFO_INITIALIZER;
2087 format.format = (audio_format_t) audioFormatToNative(encoding);
2088 format.sample_rate = (uint32_t) sampleRate;
2089 format.channel_mask = nativeChannelMaskFromJavaChannelMasks(channelMask, channelIndexMask);
Jean-Michel Trivif3fd84a2019-03-21 16:08:50 -07002090 format.stream_type = (audio_stream_type_t) streamType;
Jean-Michel Trivi980d38f2018-01-08 15:43:35 -08002091 format.has_video = false;
2092 format.is_streaming = false;
2093 // offload duration unknown at this point:
2094 // client side code cannot access "audio.offload.min.duration.secs" property to make a query
2095 // agnostic of duration, so using acceptable estimate of 2mn
2096 format.duration_us = 120 * 1000000;
2097 return AudioSystem::isOffloadSupported(format);
2098}
2099
jiabinc0f49442018-01-05 10:23:50 -08002100static jint
2101android_media_AudioSystem_getMicrophones(JNIEnv *env, jobject thiz, jobject jMicrophonesInfo)
2102{
2103 ALOGV("getMicrophones");
2104
2105 if (jMicrophonesInfo == NULL) {
2106 ALOGE("jMicrophonesInfo NULL MicrophoneInfo ArrayList");
2107 return (jint)AUDIO_JAVA_BAD_VALUE;
2108 }
2109 if (!env->IsInstanceOf(jMicrophonesInfo, gArrayListClass)) {
2110 ALOGE("getMicrophones not an arraylist");
2111 return (jint)AUDIO_JAVA_BAD_VALUE;
2112 }
2113
2114 jint jStatus;
2115 std::vector<media::MicrophoneInfo> microphones;
2116 status_t status = AudioSystem::getMicrophones(&microphones);
2117 if (status != NO_ERROR) {
Arun Mirpuricb102fa2019-01-11 18:39:21 -08002118 ALOGE("AudioSystem::getMicrophones error %d", status);
jiabinc0f49442018-01-05 10:23:50 -08002119 jStatus = nativeToJavaStatus(status);
2120 return jStatus;
2121 }
2122 if (microphones.size() == 0) {
2123 jStatus = (jint)AUDIO_JAVA_SUCCESS;
2124 return jStatus;
2125 }
2126 for (size_t i = 0; i < microphones.size(); i++) {
2127 jobject jMicrophoneInfo;
2128 jStatus = convertMicrophoneInfoFromNative(env, &jMicrophoneInfo, &microphones[i]);
2129 if (jStatus != AUDIO_JAVA_SUCCESS) {
2130 return jStatus;
2131 }
2132 env->CallBooleanMethod(jMicrophonesInfo, gArrayListMethods.add, jMicrophoneInfo);
2133 env->DeleteLocalRef(jMicrophoneInfo);
2134 }
2135
2136 return jStatus;
2137}
2138
jiabin39940752018-04-02 18:18:45 -07002139static jint
Arun Mirpuricb102fa2019-01-11 18:39:21 -08002140android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP(
2141 JNIEnv *env, jobject thiz, jobject jEncodingFormatList)
2142{
2143 ALOGV("%s", __FUNCTION__);
2144 jint jStatus = AUDIO_JAVA_SUCCESS;
2145 if (!env->IsInstanceOf(jEncodingFormatList, gArrayListClass)) {
2146 ALOGE("%s: jEncodingFormatList not an ArrayList", __FUNCTION__);
2147 return (jint)AUDIO_JAVA_BAD_VALUE;
2148 }
2149 std::vector<audio_format_t> encodingFormats;
Eric Laurentfffeac82019-01-17 09:03:47 -08002150 status_t status = AudioSystem::getHwOffloadEncodingFormatsSupportedForA2DP(
2151 &encodingFormats);
Arun Mirpuricb102fa2019-01-11 18:39:21 -08002152 if (status != NO_ERROR) {
2153 ALOGE("%s: error %d", __FUNCTION__, status);
2154 jStatus = nativeToJavaStatus(status);
2155 return jStatus;
2156 }
2157
2158 for (size_t i = 0; i < encodingFormats.size(); i++) {
2159 ScopedLocalRef<jobject> jEncodingFormat(
2160 env, env->NewObject(gIntegerClass, gIntegerCstor, encodingFormats[i]));
2161 env->CallBooleanMethod(jEncodingFormatList, gArrayListMethods.add,
2162 jEncodingFormat.get());
2163 }
2164 return jStatus;
2165}
2166
2167static jint
jiabin39940752018-04-02 18:18:45 -07002168android_media_AudioSystem_getSurroundFormats(JNIEnv *env, jobject thiz,
2169 jobject jSurroundFormats, jboolean reported)
2170{
2171 ALOGV("getSurroundFormats");
2172
2173 if (jSurroundFormats == NULL) {
2174 ALOGE("jSurroundFormats is NULL");
2175 return (jint)AUDIO_JAVA_BAD_VALUE;
2176 }
2177 if (!env->IsInstanceOf(jSurroundFormats, gMapClass)) {
2178 ALOGE("getSurroundFormats not a map");
2179 return (jint)AUDIO_JAVA_BAD_VALUE;
2180 }
2181
2182 jint jStatus;
2183 unsigned int numSurroundFormats = 0;
2184 audio_format_t *surroundFormats = NULL;
2185 bool *surroundFormatsEnabled = NULL;
2186 status_t status = AudioSystem::getSurroundFormats(
2187 &numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
2188 if (status != NO_ERROR) {
2189 ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status);
2190 jStatus = nativeToJavaStatus(status);
2191 goto exit;
2192 }
2193 if (numSurroundFormats == 0) {
2194 jStatus = (jint)AUDIO_JAVA_SUCCESS;
2195 goto exit;
2196 }
2197 surroundFormats = (audio_format_t *)calloc(numSurroundFormats, sizeof(audio_format_t));
2198 surroundFormatsEnabled = (bool *)calloc(numSurroundFormats, sizeof(bool));
2199 status = AudioSystem::getSurroundFormats(
2200 &numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
2201 jStatus = nativeToJavaStatus(status);
2202 if (status != NO_ERROR) {
2203 ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status);
2204 goto exit;
2205 }
2206 for (size_t i = 0; i < numSurroundFormats; i++) {
2207 jobject surroundFormat = env->NewObject(gIntegerClass, gIntegerCstor,
2208 audioFormatFromNative(surroundFormats[i]));
2209 jobject enabled = env->NewObject(gBooleanClass, gBooleanCstor, surroundFormatsEnabled[i]);
2210 env->CallObjectMethod(jSurroundFormats, gMapPut, surroundFormat, enabled);
2211 env->DeleteLocalRef(surroundFormat);
2212 env->DeleteLocalRef(enabled);
2213 }
2214
2215exit:
2216 free(surroundFormats);
2217 free(surroundFormatsEnabled);
2218 return jStatus;
2219}
2220
2221static jint
2222android_media_AudioSystem_setSurroundFormatEnabled(JNIEnv *env, jobject thiz,
2223 jint audioFormat, jboolean enabled)
2224{
2225 status_t status = AudioSystem::setSurroundFormatEnabled(audioFormatToNative(audioFormat),
2226 (bool)enabled);
2227 if (status != NO_ERROR) {
2228 ALOGE_IF(status != NO_ERROR, "AudioSystem::setSurroundFormatEnabled error %d", status);
2229 }
2230 return (jint)nativeToJavaStatus(status);
2231}
2232
Paul McLeanb3ae6d92018-11-05 15:16:59 -07002233static jint android_media_AudioSystem_get_FCC_8(JNIEnv *env, jobject thiz) {
2234 return FCC_8;
2235}
2236
Eric Laurent1c9c1d52018-10-17 10:06:46 -07002237static jint
2238android_media_AudioSystem_setAssistantUid(JNIEnv *env, jobject thiz, jint uid)
2239{
2240 status_t status = AudioSystem::setAssistantUid(uid);
2241 return (jint)nativeToJavaStatus(status);
2242}
2243
2244static jint
2245android_media_AudioSystem_setA11yServicesUids(JNIEnv *env, jobject thiz, jintArray uids) {
2246 std::vector<uid_t> nativeUidsVector;
2247
2248 if (uids != nullptr) {
2249 jsize len = env->GetArrayLength(uids);
2250
2251 if (len > 0) {
2252 int *nativeUids = nullptr;
2253 nativeUids = env->GetIntArrayElements(uids, 0);
2254 if (nativeUids != nullptr) {
2255 for (size_t i = 0; i < len; i++) {
2256 nativeUidsVector.push_back(nativeUids[i]);
2257 }
2258 env->ReleaseIntArrayElements(uids, nativeUids, 0);
2259 }
2260 }
2261 }
2262 status_t status = AudioSystem::setA11yServicesUids(nativeUidsVector);
2263 return (jint)nativeToJavaStatus(status);
2264}
2265
jiabin66f9e722018-11-02 16:20:19 -07002266static jboolean
2267android_media_AudioSystem_isHapticPlaybackSupported(JNIEnv *env, jobject thiz)
2268{
2269 return AudioSystem::isHapticPlaybackSupported();
2270}
2271
Hayden Gomes62812aa2019-12-23 11:40:27 -08002272static jint android_media_AudioSystem_setSupportedSystemUsages(JNIEnv *env, jobject thiz,
2273 jintArray systemUsages) {
2274 std::vector<audio_usage_t> nativeSystemUsagesVector;
2275
2276 if (systemUsages == nullptr) {
2277 return (jint) AUDIO_JAVA_BAD_VALUE;
2278 }
2279
2280 int *nativeSystemUsages = nullptr;
2281 nativeSystemUsages = env->GetIntArrayElements(systemUsages, 0);
2282
2283 if (nativeSystemUsages != nullptr) {
2284 jsize len = env->GetArrayLength(systemUsages);
2285 for (size_t i = 0; i < len; i++) {
2286 audio_usage_t nativeAudioUsage =
2287 static_cast<audio_usage_t>(nativeSystemUsages[i]);
2288 nativeSystemUsagesVector.push_back(nativeAudioUsage);
2289 }
2290 env->ReleaseIntArrayElements(systemUsages, nativeSystemUsages, 0);
2291 }
2292
2293 status_t status = AudioSystem::setSupportedSystemUsages(nativeSystemUsagesVector);
2294 return (jint)nativeToJavaStatus(status);
2295}
2296
Kevin Rocard7919c2a2019-03-21 10:28:01 -07002297static jint
2298android_media_AudioSystem_setAllowedCapturePolicy(JNIEnv *env, jobject thiz, jint uid, jint flags) {
2299 return AudioSystem::setAllowedCapturePolicy(uid, flags);
2300}
2301
Eric Laurent6acdc092019-06-11 14:29:42 -07002302static jint
2303android_media_AudioSystem_setRttEnabled(JNIEnv *env, jobject thiz, jboolean enabled)
2304{
2305 return (jint) check_AudioSystem_Command(AudioSystem::setRttEnabled(enabled));
2306}
2307
Eric Laurent4a5db4c2019-11-04 17:22:02 -08002308static jint
2309android_media_AudioSystem_setAudioHalPids(JNIEnv *env, jobject clazz, jintArray jPids)
2310{
2311 if (jPids == NULL) {
Jean-Michel Trivi21cd5412019-10-30 08:16:51 -07002312 return (jint) AUDIO_JAVA_BAD_VALUE;
Eric Laurent4a5db4c2019-11-04 17:22:02 -08002313 }
Jean-Michel Trivi21cd5412019-10-30 08:16:51 -07002314 pid_t *nPidsArray = (pid_t *) env->GetIntArrayElements(jPids, NULL);
Eric Laurent4a5db4c2019-11-04 17:22:02 -08002315 std::vector<pid_t> nPids(nPidsArray, nPidsArray + env->GetArrayLength(jPids));
2316 status_t status = AudioSystem::setAudioHalPids(nPids);
2317 env->ReleaseIntArrayElements(jPids, nPidsArray, 0);
2318 jint jStatus = nativeToJavaStatus(status);
2319 return jStatus;
2320}
2321
Eric Laurent2d7197fc2019-11-06 10:17:06 -08002322static jboolean
2323android_media_AudioSystem_isCallScreeningModeSupported(JNIEnv *env, jobject thiz)
2324{
2325 return AudioSystem::isCallScreenModeSupported();
2326}
2327
Jean-Michel Trivi21cd5412019-10-30 08:16:51 -07002328static jint
2329android_media_AudioSystem_setPreferredDeviceForStrategy(JNIEnv *env, jobject thiz,
2330 jint strategy, jint deviceType, jstring deviceAddress) {
2331
2332 const char *c_address = env->GetStringUTFChars(deviceAddress, NULL);
2333 int status = check_AudioSystem_Command(
2334 AudioSystem::setPreferredDeviceForStrategy((product_strategy_t) strategy,
2335 AudioDeviceTypeAddr(deviceType, c_address)));
2336 env->ReleaseStringUTFChars(deviceAddress, c_address);
2337 return (jint) status;
2338}
2339
2340static jint
2341android_media_AudioSystem_removePreferredDeviceForStrategy(JNIEnv *env, jobject thiz, jint strategy)
2342{
2343 return (jint) check_AudioSystem_Command(
2344 AudioSystem::removePreferredDeviceForStrategy((product_strategy_t) strategy));
2345}
2346
2347static jint
2348android_media_AudioSystem_getPreferredDeviceForStrategy(JNIEnv *env, jobject thiz,
2349 jint strategy, jobjectArray jDeviceArray)
2350{
2351 if (jDeviceArray == nullptr || env->GetArrayLength(jDeviceArray) != 1) {
2352 ALOGE("%s invalid array to store AudioDeviceAddress", __FUNCTION__);
2353 return (jint)AUDIO_JAVA_BAD_VALUE;
2354 }
2355
2356 AudioDeviceTypeAddr elDevice;
2357 status_t status = check_AudioSystem_Command(
2358 AudioSystem::getPreferredDeviceForStrategy((product_strategy_t) strategy, elDevice));
2359 if (status != NO_ERROR) {
2360 return (jint) status;
2361 }
2362 jobject jAudioDeviceAddress = NULL;
2363 jint jStatus = createAudioDeviceAddressFromNative(env, &jAudioDeviceAddress, &elDevice);
2364 if (jStatus == AUDIO_JAVA_SUCCESS) {
2365 env->SetObjectArrayElement(jDeviceArray, 0, jAudioDeviceAddress);
2366 }
2367 return jStatus;
2368}
2369
Jean-Michel Trivi56b97b72020-01-07 14:18:05 -08002370static jint
2371android_media_AudioSystem_getDevicesForAttributes(JNIEnv *env, jobject thiz,
2372 jobject jaa, jobjectArray jDeviceArray)
2373{
2374 const jsize maxResultSize = env->GetArrayLength(jDeviceArray);
2375 // the JNI is always expected to provide us with an array capable of holding enough
2376 // devices i.e. the most we ever route a track to. This is preferred over receiving an ArrayList
2377 // with reverse JNI to make the array grow as need as this would be less efficient, and some
2378 // components call this method often
2379 if (jDeviceArray == nullptr || maxResultSize == 0) {
2380 ALOGE("%s invalid array to store AudioDeviceAddress", __FUNCTION__);
2381 return (jint)AUDIO_JAVA_BAD_VALUE;
2382 }
2383
2384 JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
2385 jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
2386 if (jStatus != (jint) AUDIO_JAVA_SUCCESS) {
2387 return jStatus;
2388 }
2389
2390 AudioDeviceTypeAddrVector devices;
2391 jStatus = check_AudioSystem_Command(
2392 AudioSystem::getDevicesForAttributes(*(paa.get()), &devices));
2393 if (jStatus != NO_ERROR) {
2394 return jStatus;
2395 }
2396
2397 if (devices.size() > maxResultSize) {
2398 return AUDIO_JAVA_INVALID_OPERATION;
2399 }
2400 size_t index = 0;
2401 jobject jAudioDeviceAddress = NULL;
2402 for (const auto& device : devices) {
2403 jStatus = createAudioDeviceAddressFromNative(env, &jAudioDeviceAddress, &device);
2404 if (jStatus != AUDIO_JAVA_SUCCESS) {
2405 return jStatus;
2406 }
2407 env->SetObjectArrayElement(jDeviceArray, index++, jAudioDeviceAddress);
2408 }
2409 return jStatus;
2410}
2411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412// ----------------------------------------------------------------------------
2413
Daniel Micay76f6a862015-09-19 17:31:01 -04002414static const JNINativeMethod gMethods[] = {
Eric Laurenta553c252009-07-17 12:17:14 -07002415 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
2416 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002417 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
2418 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07002419 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
Jean-Michel Trivi679d5042013-02-04 16:24:09 -08002420 {"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07002421 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -07002422 {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08002423 {"newAudioPlayerId", "()I", (void *)android_media_AudioSystem_newAudioPlayerId},
Mikhail Naganova00883d2019-04-18 12:36:27 -07002424 {"newAudioRecorderId", "()I", (void *)android_media_AudioSystem_newAudioRecorderId},
Aniket Kumar Lata9fbc2052019-01-11 02:02:33 -08002425 {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;I)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
Eric Laurenta553c252009-07-17 12:17:14 -07002426 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
Aniket Kumar Lata9fbc2052019-01-11 02:02:33 -08002427 {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;I)I", (void *)android_media_AudioSystem_handleDeviceConfigChange},
Eric Laurenta553c252009-07-17 12:17:14 -07002428 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
Eric Laurenta553c252009-07-17 12:17:14 -07002429 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
2430 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
2431 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume},
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002432 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
2433 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex},
François Gaffieebb67d02018-09-14 15:05:04 +02002434 {"setVolumeIndexForAttributes","(Landroid/media/AudioAttributes;II)I", (void *)android_media_AudioSystem_setVolumeIndexForAttributes},
2435 {"getVolumeIndexForAttributes","(Landroid/media/AudioAttributes;I)I", (void *)android_media_AudioSystem_getVolumeIndexForAttributes},
2436 {"getMinVolumeIndexForAttributes","(Landroid/media/AudioAttributes;)I", (void *)android_media_AudioSystem_getMinVolumeIndexForAttributes},
2437 {"getMaxVolumeIndexForAttributes","(Landroid/media/AudioAttributes;)I", (void *)android_media_AudioSystem_getMaxVolumeIndexForAttributes},
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -04002438 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume},
2439 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume},
2440 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute},
2441 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute},
Andy Hungf04b84d2015-12-18 17:33:27 -08002442 {"setMasterMono", "(Z)I", (void *)android_media_AudioSystem_setMasterMono},
2443 {"getMasterMono", "()Z", (void *)android_media_AudioSystem_getMasterMono},
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01002444 {"setMasterBalance", "(F)I", (void *)android_media_AudioSystem_setMasterBalance},
2445 {"getMasterBalance", "()F", (void *)android_media_AudioSystem_getMasterBalance},
Glenn Kasten8b4b97a2011-02-04 13:54:26 -08002446 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
Glenn Kastenc6c43652012-09-24 17:32:30 -07002447 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
2448 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
Oliver Woodman61dcdf32013-06-26 12:43:36 +01002449 {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
Andy Hung79583582018-01-23 13:58:02 -08002450 {"setLowRamDevice", "(ZJ)I", (void *)android_media_AudioSystem_setLowRamDevice},
Eric Laurentdfb881f2013-07-18 14:41:39 -07002451 {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
Eric Laurentb69681c2014-05-19 19:02:51 -07002452 {"listAudioPorts", "(Ljava/util/ArrayList;[I)I",
2453 (void *)android_media_AudioSystem_listAudioPorts},
2454 {"createAudioPatch", "([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)I",
2455 (void *)android_media_AudioSystem_createAudioPatch},
2456 {"releaseAudioPatch", "(Landroid/media/AudioPatch;)I",
2457 (void *)android_media_AudioSystem_releaseAudioPatch},
2458 {"listAudioPatches", "(Ljava/util/ArrayList;[I)I",
2459 (void *)android_media_AudioSystem_listAudioPatches},
Eric Laurent3a241992014-05-19 19:33:26 -07002460 {"setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
2461 (void *)android_media_AudioSystem_setAudioPortConfig},
Hongwei Wangf44a5682018-08-24 10:37:56 -07002462 {"startAudioSource", "(Landroid/media/AudioPortConfig;Landroid/media/AudioAttributes;)I",
2463 (void *)android_media_AudioSystem_startAudioSource},
2464 {"stopAudioSource", "(I)I", (void *)android_media_AudioSystem_stopAudioSource},
Eric Laurentb634e1b2014-08-01 14:44:46 -07002465 {"getAudioHwSyncForSession", "(I)I",
2466 (void *)android_media_AudioSystem_getAudioHwSyncForSession},
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002467 {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
2468 (void *)android_media_AudioSystem_registerPolicyMixes},
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08002469 {"setUidDeviceAffinities", "(I[I[Ljava/lang/String;)I",
2470 (void *)android_media_AudioSystem_setUidDeviceAffinities},
2471 {"removeUidDeviceAffinities", "(I)I",
2472 (void *)android_media_AudioSystem_removeUidDeviceAffinities},
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07002473 {"native_register_dynamic_policy_callback", "()V",
2474 (void *)android_media_AudioSystem_registerDynPolicyCallback},
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08002475 {"native_register_recording_callback", "()V",
2476 (void *)android_media_AudioSystem_registerRecordingCallback},
Eric Laurent0867bed2015-05-20 14:49:08 -07002477 {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
Eric Laurenteab40d12017-06-09 12:45:21 -07002478 {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB},
Jean-Michel Trivif3fd84a2019-03-21 16:08:50 -07002479 {"native_is_offload_supported", "(IIIII)Z", (void *)android_media_AudioSystem_isOffloadSupported},
jiabinc0f49442018-01-05 10:23:50 -08002480 {"getMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_getMicrophones},
jiabin39940752018-04-02 18:18:45 -07002481 {"getSurroundFormats", "(Ljava/util/Map;Z)I", (void *)android_media_AudioSystem_getSurroundFormats},
2482 {"setSurroundFormatEnabled", "(IZ)I", (void *)android_media_AudioSystem_setSurroundFormatEnabled},
Eric Laurent1c9c1d52018-10-17 10:06:46 -07002483 {"setAssistantUid", "(I)I", (void *)android_media_AudioSystem_setAssistantUid},
2484 {"setA11yServicesUids", "([I)I", (void *)android_media_AudioSystem_setA11yServicesUids},
jiabin66f9e722018-11-02 16:20:19 -07002485 {"isHapticPlaybackSupported", "()Z", (void *)android_media_AudioSystem_isHapticPlaybackSupported},
Arun Mirpuricb102fa2019-01-11 18:39:21 -08002486 {"getHwOffloadEncodingFormatsSupportedForA2DP", "(Ljava/util/ArrayList;)I",
2487 (void*)android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP},
Hayden Gomes62812aa2019-12-23 11:40:27 -08002488 {"setSupportedSystemUsages", "([I)I", (void *)android_media_AudioSystem_setSupportedSystemUsages},
Kevin Rocard7919c2a2019-03-21 10:28:01 -07002489 {"setAllowedCapturePolicy", "(II)I", (void *)android_media_AudioSystem_setAllowedCapturePolicy},
Eric Laurent6acdc092019-06-11 14:29:42 -07002490 {"setRttEnabled", "(Z)I", (void *)android_media_AudioSystem_setRttEnabled},
Eric Laurent4a5db4c2019-11-04 17:22:02 -08002491 {"setAudioHalPids", "([I)I", (void *)android_media_AudioSystem_setAudioHalPids},
Eric Laurent2d7197fc2019-11-06 10:17:06 -08002492 {"isCallScreeningModeSupported", "()Z", (void *)android_media_AudioSystem_isCallScreeningModeSupported},
Jean-Michel Trivi21cd5412019-10-30 08:16:51 -07002493 {"setPreferredDeviceForStrategy", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setPreferredDeviceForStrategy},
2494 {"removePreferredDeviceForStrategy", "(I)I", (void *)android_media_AudioSystem_removePreferredDeviceForStrategy},
2495 {"getPreferredDeviceForStrategy", "(I[Landroid/media/AudioDeviceAddress;)I", (void *)android_media_AudioSystem_getPreferredDeviceForStrategy},
Oscar Azucena76788f02019-11-27 17:34:29 -08002496 {"getDevicesForAttributes", "(Landroid/media/AudioAttributes;[Landroid/media/AudioDeviceAddress;)I", (void *)android_media_AudioSystem_getDevicesForAttributes},
2497 {"setUserIdDeviceAffinities", "(I[I[Ljava/lang/String;)I", (void *)android_media_AudioSystem_setUserIdDeviceAffinities},
2498 {"removeUserIdDeviceAffinities", "(I)I", (void *)android_media_AudioSystem_removeUserIdDeviceAffinities}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002499};
2500
Daniel Micay76f6a862015-09-19 17:31:01 -04002501static const JNINativeMethod gEventHandlerMethods[] = {
Eric Laurent700e7342014-05-02 18:33:15 -07002502 {"native_setup",
2503 "(Ljava/lang/Object;)V",
2504 (void *)android_media_AudioSystem_eventHandlerSetup},
2505 {"native_finalize",
2506 "()V",
2507 (void *)android_media_AudioSystem_eventHandlerFinalize},
2508};
2509
Paul McLeanb3ae6d92018-11-05 15:16:59 -07002510static const JNINativeMethod gGetFCC8Methods[] = {
2511 {"native_get_FCC_8", "()I", (void *)android_media_AudioSystem_get_FCC_8},
2512};
2513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002514int register_android_media_AudioSystem(JNIEnv *env)
2515{
Paul McLeanb3ae6d92018-11-05 15:16:59 -07002516 // This needs to be done before hooking up methods AudioTrackRoutingProxy (below)
2517 RegisterMethodsOrDie(env, kClassPathName, gGetFCC8Methods, NELEM(gGetFCC8Methods));
2518
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002519 jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
2520 gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
2521 gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
Eric Laurent09378972014-12-10 10:42:08 -08002522 gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;");
Eric Laurentb69681c2014-05-19 19:02:51 -07002523
jiabin39940752018-04-02 18:18:45 -07002524 jclass booleanClass = FindClassOrDie(env, "java/lang/Boolean");
2525 gBooleanClass = MakeGlobalRefOrDie(env, booleanClass);
2526 gBooleanCstor = GetMethodIDOrDie(env, booleanClass, "<init>", "(Z)V");
2527
2528 jclass integerClass = FindClassOrDie(env, "java/lang/Integer");
2529 gIntegerClass = MakeGlobalRefOrDie(env, integerClass);
2530 gIntegerCstor = GetMethodIDOrDie(env, integerClass, "<init>", "(I)V");
2531
2532 jclass mapClass = FindClassOrDie(env, "java/util/Map");
2533 gMapClass = MakeGlobalRefOrDie(env, mapClass);
2534 gMapPut = GetMethodIDOrDie(env, mapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
2535
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002536 jclass audioHandleClass = FindClassOrDie(env, "android/media/AudioHandle");
2537 gAudioHandleClass = MakeGlobalRefOrDie(env, audioHandleClass);
2538 gAudioHandleCstor = GetMethodIDOrDie(env, audioHandleClass, "<init>", "(I)V");
2539 gAudioHandleFields.mId = GetFieldIDOrDie(env, audioHandleClass, "mId", "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07002540
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002541 jclass audioPortClass = FindClassOrDie(env, "android/media/AudioPort");
2542 gAudioPortClass = MakeGlobalRefOrDie(env, audioPortClass);
2543 gAudioPortCstor = GetMethodIDOrDie(env, audioPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07002544 "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002545 gAudioPortFields.mHandle = GetFieldIDOrDie(env, audioPortClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07002546 "Landroid/media/AudioHandle;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002547 gAudioPortFields.mRole = GetFieldIDOrDie(env, audioPortClass, "mRole", "I");
2548 gAudioPortFields.mGains = GetFieldIDOrDie(env, audioPortClass, "mGains",
Eric Laurentb69681c2014-05-19 19:02:51 -07002549 "[Landroid/media/AudioGain;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002550 gAudioPortFields.mActiveConfig = GetFieldIDOrDie(env, audioPortClass, "mActiveConfig",
2551 "Landroid/media/AudioPortConfig;");
Eric Laurentb69681c2014-05-19 19:02:51 -07002552
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002553 jclass audioPortConfigClass = FindClassOrDie(env, "android/media/AudioPortConfig");
2554 gAudioPortConfigClass = MakeGlobalRefOrDie(env, audioPortConfigClass);
2555 gAudioPortConfigCstor = GetMethodIDOrDie(env, audioPortConfigClass, "<init>",
2556 "(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V");
2557 gAudioPortConfigFields.mPort = GetFieldIDOrDie(env, audioPortConfigClass, "mPort",
Eric Laurentb69681c2014-05-19 19:02:51 -07002558 "Landroid/media/AudioPort;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002559 gAudioPortConfigFields.mSamplingRate = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07002560 "mSamplingRate", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002561 gAudioPortConfigFields.mChannelMask = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07002562 "mChannelMask", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002563 gAudioPortConfigFields.mFormat = GetFieldIDOrDie(env, audioPortConfigClass, "mFormat", "I");
2564 gAudioPortConfigFields.mGain = GetFieldIDOrDie(env, audioPortConfigClass, "mGain",
Eric Laurentb69681c2014-05-19 19:02:51 -07002565 "Landroid/media/AudioGainConfig;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002566 gAudioPortConfigFields.mConfigMask = GetFieldIDOrDie(env, audioPortConfigClass, "mConfigMask",
2567 "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07002568
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002569 jclass audioDevicePortConfigClass = FindClassOrDie(env, "android/media/AudioDevicePortConfig");
2570 gAudioDevicePortConfigClass = MakeGlobalRefOrDie(env, audioDevicePortConfigClass);
2571 gAudioDevicePortConfigCstor = GetMethodIDOrDie(env, audioDevicePortConfigClass, "<init>",
2572 "(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07002573
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002574 jclass audioMixPortConfigClass = FindClassOrDie(env, "android/media/AudioMixPortConfig");
2575 gAudioMixPortConfigClass = MakeGlobalRefOrDie(env, audioMixPortConfigClass);
2576 gAudioMixPortConfigCstor = GetMethodIDOrDie(env, audioMixPortConfigClass, "<init>",
2577 "(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07002578
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002579 jclass audioDevicePortClass = FindClassOrDie(env, "android/media/AudioDevicePort");
2580 gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass);
2581 gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07002582 "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07002583
Hongwei Wangf44a5682018-08-24 10:37:56 -07002584 // When access AudioPort as AudioDevicePort
2585 gAudioPortFields.mType = GetFieldIDOrDie(env, audioDevicePortClass, "mType", "I");
2586 gAudioPortFields.mAddress = GetFieldIDOrDie(env, audioDevicePortClass, "mAddress",
2587 "Ljava/lang/String;");
2588
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002589 jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
2590 gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
2591 gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07002592 "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07002593
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002594 jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
2595 gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
2596 gAudioGainCstor = GetMethodIDOrDie(env, audioGainClass, "<init>", "(IIIIIIIII)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07002597
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002598 jclass audioGainConfigClass = FindClassOrDie(env, "android/media/AudioGainConfig");
2599 gAudioGainConfigClass = MakeGlobalRefOrDie(env, audioGainConfigClass);
2600 gAudioGainConfigCstor = GetMethodIDOrDie(env, audioGainConfigClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07002601 "(ILandroid/media/AudioGain;II[II)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002602 gAudioGainConfigFields.mIndex = GetFieldIDOrDie(env, gAudioGainConfigClass, "mIndex", "I");
2603 gAudioGainConfigFields.mMode = GetFieldIDOrDie(env, audioGainConfigClass, "mMode", "I");
2604 gAudioGainConfigFields.mChannelMask = GetFieldIDOrDie(env, audioGainConfigClass, "mChannelMask",
Eric Laurentb69681c2014-05-19 19:02:51 -07002605 "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002606 gAudioGainConfigFields.mValues = GetFieldIDOrDie(env, audioGainConfigClass, "mValues", "[I");
2607 gAudioGainConfigFields.mRampDurationMs = GetFieldIDOrDie(env, audioGainConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07002608 "mRampDurationMs", "I");
2609
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002610 jclass audioPatchClass = FindClassOrDie(env, "android/media/AudioPatch");
2611 gAudioPatchClass = MakeGlobalRefOrDie(env, audioPatchClass);
2612 gAudioPatchCstor = GetMethodIDOrDie(env, audioPatchClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07002613"(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002614 gAudioPatchFields.mHandle = GetFieldIDOrDie(env, audioPatchClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07002615 "Landroid/media/AudioHandle;");
2616
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002617 jclass eventHandlerClass = FindClassOrDie(env, kEventHandlerClassPathName);
Eric Laurent2615afb2015-03-25 14:51:08 -07002618 gAudioPortEventHandlerMethods.postEventFromNative = GetStaticMethodIDOrDie(
2619 env, eventHandlerClass, "postEventFromNative",
2620 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
2621 gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env,
2622 eventHandlerClass, "mJniCallback", "J");
Eric Laurent700e7342014-05-02 18:33:15 -07002623
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08002624 gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative =
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07002625 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
2626 "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08002627 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
2628 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
Mikhail Naganova00883d2019-04-18 12:36:27 -07002629 "recordingCallbackFromNative", "(IIIIIIZ[I[Landroid/media/audiofx/AudioEffect$Descriptor;[Landroid/media/audiofx/AudioEffect$Descriptor;I)V");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07002630
Eric Laurent09378972014-12-10 10:42:08 -08002631 jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
2632 gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
2633 gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002634 "Landroid/media/audiopolicy/AudioMixingRule;");
Eric Laurent09378972014-12-10 10:42:08 -08002635 gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002636 "Landroid/media/AudioFormat;");
Eric Laurent09378972014-12-10 10:42:08 -08002637 gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07002638 gAudioMixFields.mDeviceType = GetFieldIDOrDie(env, audioMixClass, "mDeviceSystemType", "I");
2639 gAudioMixFields.mDeviceAddress = GetFieldIDOrDie(env, audioMixClass, "mDeviceAddress",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002640 "Ljava/lang/String;");
Eric Laurent09378972014-12-10 10:42:08 -08002641 gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07002642 gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002643
Eric Laurent09378972014-12-10 10:42:08 -08002644 jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat");
2645 gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass);
2646 gAudioFormatFields.mEncoding = GetFieldIDOrDie(env, audioFormatClass, "mEncoding", "I");
2647 gAudioFormatFields.mSampleRate = GetFieldIDOrDie(env, audioFormatClass, "mSampleRate", "I");
2648 gAudioFormatFields.mChannelMask = GetFieldIDOrDie(env, audioFormatClass, "mChannelMask", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002649
Eric Laurent09378972014-12-10 10:42:08 -08002650 jclass audioMixingRuleClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule");
2651 gAudioMixingRuleClass = MakeGlobalRefOrDie(env, audioMixingRuleClass);
2652 gAudioMixingRuleFields.mCriteria = GetFieldIDOrDie(env, audioMixingRuleClass, "mCriteria",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002653 "Ljava/util/ArrayList;");
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -08002654 gAudioMixingRuleFields.mAllowPrivilegedPlaybackCapture =
2655 GetFieldIDOrDie(env, audioMixingRuleClass, "mAllowPrivilegedPlaybackCapture", "Z");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002656
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08002657 jclass audioMixMatchCriterionClass =
2658 FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion");
2659 gAudioMixMatchCriterionClass = MakeGlobalRefOrDie(env,audioMixMatchCriterionClass);
2660 gAudioMixMatchCriterionFields.mAttr = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mAttr",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002661 "Landroid/media/AudioAttributes;");
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08002662 gAudioMixMatchCriterionFields.mIntProp = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mIntProp",
2663 "I");
2664 gAudioMixMatchCriterionFields.mRule = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002665 "I");
Paul McLeanb3ae6d92018-11-05 15:16:59 -07002666 // AudioTrackRoutingProxy methods
2667 gClsAudioTrackRoutingProxy =
2668 android::FindClassOrDie(env, "android/media/AudioTrackRoutingProxy");
2669 // make sure this reference doesn't get deleted
2670 gClsAudioTrackRoutingProxy = (jclass)env->NewGlobalRef(gClsAudioTrackRoutingProxy);
2671
2672 gMidAudioTrackRoutingProxy_ctor =
2673 android::GetMethodIDOrDie(env, gClsAudioTrackRoutingProxy, "<init>", "(J)V");
2674 gMidAudioTrackRoutingProxy_release =
2675 android::GetMethodIDOrDie(env, gClsAudioTrackRoutingProxy, "native_release", "()V");
2676
2677 // AudioRecordRoutingProxy
2678 gClsAudioRecordRoutingProxy =
2679 android::FindClassOrDie(env, "android/media/AudioRecordRoutingProxy");
2680 // make sure this reference doesn't get deleted
2681 gClsAudioRecordRoutingProxy = (jclass)env->NewGlobalRef(gClsAudioRecordRoutingProxy);
2682
2683 gMidAudioRecordRoutingProxy_ctor =
2684 android::GetMethodIDOrDie(env, gClsAudioRecordRoutingProxy, "<init>", "(J)V");
2685 gMidAudioRecordRoutingProxy_release =
2686 android::GetMethodIDOrDie(env, gClsAudioRecordRoutingProxy, "native_release", "()V");
2687
Ytai Ben-Tsvi48a36602020-01-09 15:26:11 -08002688 AudioSystem::addErrorCallback(android_media_AudioSystem_error_callback);
Glenn Kasten18db49a2012-03-12 16:29:55 -07002689
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002690 RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
2691 return RegisterMethodsOrDie(env, kEventHandlerClassPathName, gEventHandlerMethods,
2692 NELEM(gEventHandlerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693}