1 /*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* AndroidConfiguration implementation */
18
19 #include <android/log.h>
20
21 #include "sles_allinclusive.h"
22 #include <SLES/OpenSLES_Android.h>
23
24 #include <android_runtime/AndroidRuntime.h>
25
IAndroidConfiguration_SetConfiguration(SLAndroidConfigurationItf self,const SLchar * configKey,const void * pConfigValue,SLuint32 valueSize)26 static SLresult IAndroidConfiguration_SetConfiguration(SLAndroidConfigurationItf self,
27 const SLchar *configKey,
28 const void *pConfigValue,
29 SLuint32 valueSize)
30 {
31 SL_ENTER_INTERFACE
32
33 // object-specific code will check that valueSize is large enough for the key
34 if (NULL == configKey || NULL == pConfigValue || valueSize == 0) {
35 result = SL_RESULT_PARAMETER_INVALID;
36
37 } else {
38 IAndroidConfiguration *thiz = (IAndroidConfiguration *) self;
39 interface_lock_exclusive(thiz);
40
41 // route configuration to the appropriate object
42 switch (IObjectToObjectID((thiz)->mThis)) {
43 case SL_OBJECTID_AUDIORECORDER:
44 SL_LOGV("SetConfiguration issued for AudioRecorder key=%s valueSize=%u",
45 configKey, valueSize);
46 result = android_audioRecorder_setConfig((CAudioRecorder *) thiz->mThis, configKey,
47 pConfigValue, valueSize);
48 break;
49 case SL_OBJECTID_AUDIOPLAYER:
50 SL_LOGV("SetConfiguration issued for AudioPlayer key=%s valueSize=%u",
51 configKey, valueSize);
52 result = android_audioPlayer_setConfig((CAudioPlayer *) thiz->mThis, configKey,
53 pConfigValue, valueSize);
54 break;
55 default:
56 result = SL_RESULT_FEATURE_UNSUPPORTED;
57 break;
58 }
59
60 interface_unlock_exclusive(thiz);
61 }
62
63 SL_LEAVE_INTERFACE
64 }
65
66
IAndroidConfiguration_GetConfiguration(SLAndroidConfigurationItf self,const SLchar * configKey,SLuint32 * pValueSize,void * pConfigValue)67 static SLresult IAndroidConfiguration_GetConfiguration(SLAndroidConfigurationItf self,
68 const SLchar *configKey,
69 SLuint32 *pValueSize,
70 void *pConfigValue)
71 {
72 SL_ENTER_INTERFACE
73
74 // non-NULL pValueSize is required, but a NULL pConfigValue is allowed, so
75 // that we can report the actual value size without returning the value itself
76 if (NULL == configKey || NULL == pValueSize) {
77 result = SL_RESULT_PARAMETER_INVALID;
78 } else {
79 IAndroidConfiguration *thiz = (IAndroidConfiguration *) self;
80 interface_lock_exclusive(thiz);
81
82 // route configuration request to the appropriate object
83 switch (IObjectToObjectID((thiz)->mThis)) {
84 case SL_OBJECTID_AUDIORECORDER:
85 result = android_audioRecorder_getConfig((CAudioRecorder *) thiz->mThis, configKey,
86 pValueSize, pConfigValue);
87 break;
88 case SL_OBJECTID_AUDIOPLAYER:
89 result = android_audioPlayer_getConfig((CAudioPlayer *) thiz->mThis, configKey,
90 pValueSize, pConfigValue);
91 default:
92 result = SL_RESULT_FEATURE_UNSUPPORTED;
93 break;
94 }
95
96 interface_unlock_exclusive(thiz);
97 }
98
99 SL_LEAVE_INTERFACE
100 }
101
102 /*
103 * Native Routing API
104 */
ValidatePlayerConfig(IAndroidConfiguration * iConfig)105 static SLresult ValidatePlayerConfig(IAndroidConfiguration* iConfig) {
106 SLresult result;
107
108 if (iConfig->mRoutingProxy != NULL) {
109 result = SL_RESULT_PRECONDITIONS_VIOLATED;
110 SL_LOGE("Error creating player routing object - Routing Proxy Already Acquired.");
111 }
112 else {
113 IObject* configObj = iConfig->mThis; // get corresponding object
114 CAudioPlayer* player = (CAudioPlayer*)configObj; // get the native player
115
116 switch (player->mAndroidObjType) {
117 case AUDIOPLAYER_FROM_PCM_BUFFERQUEUE:
118 //TODO remove these commented out lines when our comfort level is good
119 // if (player->mObject.mState != SL_OBJECT_STATE_REALIZED) {
120 // // Make sure the player has been realized.
121 // result = SL_RESULT_PRECONDITIONS_VIOLATED;
122 // SL_LOGE("Error creating routing object - Player not realized.");
123 // } else {
124 // android::AudioTrack* pAudioTrack = player->mAudioTrack.get();
125 // if (pAudioTrack == NULL) {
126 // result = SL_RESULT_INTERNAL_ERROR;
127 // SL_LOGE("Error creating routing object - Couldn't get AudioTrack.");
128 // } else {
129 result = SL_RESULT_SUCCESS;
130 // }
131 // }
132 break;
133
134 default:
135 result = SL_RESULT_PARAMETER_INVALID;
136 SL_LOGE("Error creating routing object - Player is not a buffer-queue player.");
137 break;
138 }
139 }
140
141 return result;
142 }
143
AllocPlayerRoutingProxy(IAndroidConfiguration * iConfig,jobject * proxyObj)144 static SLresult AllocPlayerRoutingProxy(IAndroidConfiguration* iConfig, jobject* proxyObj) {
145 SLresult result;
146
147 IObject* configObj = iConfig->mThis; // get corresponding object
148 android::AudioTrack* pAudioTrack = ((CAudioPlayer*)configObj)->mAudioTrack.get();
149
150 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
151
152 // Get the constructor for (Java) AudioTrackRoutingProxy
153 jclass clsAudioTrackRoutingProxy =
154 j_env->FindClass("android/media/AudioTrackRoutingProxy");
155 jmethodID midAudioTrackRoutingProxy_ctor =
156 j_env->GetMethodID(clsAudioTrackRoutingProxy, "<init>", "(J)V");
157
158 j_env->ExceptionClear();
159
160 jobject localObjRef =
161 j_env->NewObject(clsAudioTrackRoutingProxy,
162 midAudioTrackRoutingProxy_ctor,
163 (jlong)pAudioTrack /*audioTrackObjInLong*/);
164
165 *proxyObj = j_env->NewGlobalRef(localObjRef);
166
167 if (j_env->ExceptionCheck()) {
168 SL_LOGE("Java exception creating player routing object.");
169 result = SL_RESULT_INTERNAL_ERROR;
170 } else {
171 // stash it in the Interface object
172 iConfig->mRoutingProxy = *proxyObj;
173 result = SL_RESULT_SUCCESS;
174 }
175
176 return result;
177 }
178
ValidateRecorderConfig(IAndroidConfiguration * iConfig)179 static SLresult ValidateRecorderConfig(IAndroidConfiguration* iConfig) {
180 SLresult result;
181
182 if (iConfig->mRoutingProxy != NULL) {
183 result = SL_RESULT_PRECONDITIONS_VIOLATED;
184 SL_LOGE("Error creating record routing object - Routing Proxy Already Acquired.");
185 } else {
186 IObject* configObj = iConfig->mThis; // get corresponding object
187 CAudioRecorder* recorder = (CAudioRecorder*)configObj; // get the native recorder
188 switch (recorder->mAndroidObjType) {
189 case AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE:
190 //TODO remove these commented out lines when our comfort level is good
191 // if (recorder->mObject.mState != SL_OBJECT_STATE_REALIZED) {
192 // // Make sure the recorder has been realized.
193 // result = SL_RESULT_PRECONDITIONS_VIOLATED;
194 // SL_LOGE("Error creating routing object - Recorder not realized.");
195 // } else {
196 // android::AudioRecord* pAudioRecord = recorder->mAudioRecord.get();
197 // if (pAudioRecord == NULL) {
198 // result = SL_RESULT_INTERNAL_ERROR;
199 // SL_LOGE("Error creating routing object - Couldn't get AudioRecord.");
200 // } else if (iConfig->mRoutingProxy != NULL) {
201 // result = SL_RESULT_PRECONDITIONS_VIOLATED;
202 // SL_LOGE("Error creating routing object - Routing Proxy Already Acquired.");
203 // } else {
204 result = SL_RESULT_SUCCESS;
205 // }
206 // }
207 break;
208
209 default:
210 result = SL_RESULT_PARAMETER_INVALID;
211 SL_LOGE("Error creating routing object - Recorder is not a buffer-queue recorder.");
212 break;
213 }
214 }
215
216 return result;
217 }
218
AllocRecorderRoutingProxy(IAndroidConfiguration * iConfig,jobject * proxyObj)219 static SLresult AllocRecorderRoutingProxy(IAndroidConfiguration* iConfig, jobject* proxyObj) {
220 SLresult result;
221
222 IObject* configObj = iConfig->mThis; // get corresponding object
223 android::AudioRecord* pAudioRecord = ((CAudioRecorder*)configObj)->mAudioRecord.get();
224
225 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
226
227 // Get the constructor for (Java) AudioRecordRoutingProxy
228 jclass clsAudioRecordRoutingProxy =
229 j_env->FindClass("android/media/AudioRecordRoutingProxy");
230 jmethodID midAudioRecordRoutingProxy_ctor =
231 j_env->GetMethodID(clsAudioRecordRoutingProxy, "<init>", "(J)V");
232
233 j_env->ExceptionClear();
234 jobject localObjRef =
235 j_env->NewObject(clsAudioRecordRoutingProxy,
236 midAudioRecordRoutingProxy_ctor,
237 (jlong)pAudioRecord /*audioRecordObjInLong*/);
238
239 *proxyObj = j_env->NewGlobalRef(localObjRef);
240 if (j_env->ExceptionCheck()) {
241 SL_LOGE("Java exception creating recorder routing object.");
242 result = SL_RESULT_INTERNAL_ERROR;
243 } else {
244 // stash it in the Interface object
245 iConfig->mRoutingProxy = *proxyObj;
246 result = SL_RESULT_SUCCESS;
247 }
248
249 return result;
250 }
251
252 /*
253 * Acquires a Java proxy object, such as AudioRouting object which can be used to control
254 * aspects of the associated native player or recorder.
255 * Parameters:
256 * self An SLAndroidConfigurationItf obtained from either an OpenSL ES AudioPlayer
257 * or AudioRecorder.
258 * j_env The Java Environment pointer (passed in to the calling JNI function).
259 * proxyType Specifies the type of proxy desired. Currently only SL_ANDROID_JAVA_PROXY_ROUTING
260 * is supported.
261 * proxyObj
262 * Points to the jobject to receive the acquired Java proxy object (as a GlobalRef).
263 * Returns SL_RESULT_SUCCESS is the proxy object is acquired, SL_RESULT_PARAMETER_INVALID if
264 * there is a problem with the arguments causing the function to fail,
265 * <working on this>
266 * SL_RESULT_PRECONDITIONS_VIOLATED it the AudioPlayer or AudioRecorder object associated
267 * with the ConfigurationItf has not been realized.
268 */
IAndroidConfiguration_AcquireJavaProxy(SLAndroidConfigurationItf self,SLuint32 proxyType,jobject * proxyObj)269 static SLresult IAndroidConfiguration_AcquireJavaProxy(SLAndroidConfigurationItf self,
270 SLuint32 proxyType,
271 jobject* proxyObj)
272 {
273 SL_ENTER_INTERFACE
274
275 if (self == NULL || proxyObj == NULL || proxyType != SL_ANDROID_JAVA_PROXY_ROUTING) {
276 result = SL_RESULT_PARAMETER_INVALID;
277 } else {
278 IAndroidConfiguration* iConfig = (IAndroidConfiguration*)self;
279
280 int objID = IObjectToObjectID(InterfaceToIObject(iConfig));
281 switch (objID) {
282 case SL_OBJECTID_AUDIOPLAYER:
283 result = ValidatePlayerConfig(iConfig);
284 if (result == SL_RESULT_SUCCESS) {
285 result = AllocPlayerRoutingProxy(iConfig, proxyObj);
286 }
287 break;
288
289 case SL_OBJECTID_AUDIORECORDER:
290 result = ValidateRecorderConfig(iConfig);
291 if (result == SL_RESULT_SUCCESS) {
292 result = AllocRecorderRoutingProxy(iConfig, proxyObj);
293 }
294 break;
295
296 default:
297 result = SL_RESULT_PARAMETER_INVALID;
298 break;
299 }
300 }
301
302 SL_LEAVE_INTERFACE
303 }
304
305 /*
306 * Release a Java proxy object, such as AudioRouting object, (and any resources it is holding).
307 * Parameters:
308 * self An SLAndroidConfigurationItf obtained from either an OpenSL ES AudioPlayer
309 * or AudioRecorder.
310 * j_env The Java Environment pointer (passed in to the calling JNI function).
311 * proxyType Specifies the type of proxy object. Currently only SL_ANDROID_JAVA_PROXY_ROUTING
312 * is supported.
313 * Returns SL_RESULT_SUCCESS is the proxy object is release, SL_RESULT_PARAMETER_INVALID if
314 * there is a problem with the arguments causing the function to fail,
315 */
IAndroidConfiguration_ReleaseJavaProxy(SLAndroidConfigurationItf self,SLuint32 proxyType)316 static SLresult IAndroidConfiguration_ReleaseJavaProxy(SLAndroidConfigurationItf self,
317 SLuint32 proxyType) {
318 SL_ENTER_INTERFACE
319
320 IAndroidConfiguration* iConfig = (IAndroidConfiguration*)self;
321
322 if (self == NULL ||
323 proxyType != SL_ANDROID_JAVA_PROXY_ROUTING ||
324 iConfig->mRoutingProxy == NULL) {
325 result = SL_RESULT_PARAMETER_INVALID;
326 } else {
327 int objID = IObjectToObjectID(InterfaceToIObject(iConfig));
328 switch (objID) {
329 case SL_OBJECTID_AUDIOPLAYER:
330 {
331 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
332
333 // Get the release method for (Java) AudioTrackRoutingProxy
334 jclass clsAudioTrackRoutingProxy =
335 j_env->FindClass("android/media/AudioTrackRoutingProxy");
336 jmethodID midAudioTrackRoutingProxy_release =
337 j_env->GetMethodID(clsAudioTrackRoutingProxy, "native_release", "()V");
338
339 j_env->ExceptionClear();
340 j_env->CallVoidMethod(iConfig->mRoutingProxy, midAudioTrackRoutingProxy_release);
341 if (j_env->ExceptionCheck()) {
342 SL_LOGE("Java exception releasing recorder routing object.");
343 result = SL_RESULT_INTERNAL_ERROR;
344 }
345 j_env->DeleteGlobalRef(iConfig->mRoutingProxy);
346 iConfig->mRoutingProxy = NULL;
347 }
348 break;
349
350 case SL_OBJECTID_AUDIORECORDER:
351 {
352 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
353
354 // Get the release method for (Java) AudioTrackRoutingProxy
355 jclass clsAudioRecordRoutingProxy =
356 j_env->FindClass("android/media/AudioRecordRoutingProxy");
357 jmethodID midAudioRecordRoutingProxy_release =
358 j_env->GetMethodID(clsAudioRecordRoutingProxy, "native_release", "()V");
359
360 j_env->ExceptionClear();
361 j_env->CallVoidMethod(iConfig->mRoutingProxy, midAudioRecordRoutingProxy_release);
362 if (j_env->ExceptionCheck()) {
363 SL_LOGE("Java exception releasing recorder routing object.");
364 result = SL_RESULT_INTERNAL_ERROR;
365 }
366 j_env->DeleteGlobalRef(iConfig->mRoutingProxy);
367 iConfig->mRoutingProxy = NULL;
368 }
369 break;
370 }
371
372 result = SL_RESULT_SUCCESS;
373 }
374
375 SL_LEAVE_INTERFACE
376 }
377
378 static const struct SLAndroidConfigurationItf_ IAndroidConfiguration_Itf = {
379 IAndroidConfiguration_SetConfiguration,
380 IAndroidConfiguration_GetConfiguration,
381 IAndroidConfiguration_AcquireJavaProxy,
382 IAndroidConfiguration_ReleaseJavaProxy
383 };
384
IAndroidConfiguration_init(void * self)385 void IAndroidConfiguration_init(void *self)
386 {
387 IAndroidConfiguration *thiz = (IAndroidConfiguration *) self;
388 thiz->mItf = &IAndroidConfiguration_Itf;
389 }
390
IAndroidConfiguration_deinit(void * self)391 void IAndroidConfiguration_deinit(void *self)
392 {
393 IAndroidConfiguration *thiz = (IAndroidConfiguration *) self;
394 if (thiz->mRoutingProxy != NULL) {
395 thiz->mItf->ReleaseJavaProxy(&thiz->mItf, SL_ANDROID_JAVA_PROXY_ROUTING);
396 }
397 }
398
399