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 break;
92 default:
93 result = SL_RESULT_FEATURE_UNSUPPORTED;
94 break;
95 }
96
97 interface_unlock_exclusive(thiz);
98 }
99
100 SL_LEAVE_INTERFACE
101 }
102
103 /*
104 * Native Routing API
105 */
ValidatePlayerConfig(IAndroidConfiguration * iConfig)106 static SLresult ValidatePlayerConfig(IAndroidConfiguration* iConfig) {
107 SLresult result;
108
109 if (iConfig->mRoutingProxy != NULL) {
110 result = SL_RESULT_PRECONDITIONS_VIOLATED;
111 SL_LOGE("Error creating player routing object - Routing Proxy Already Acquired.");
112 }
113 else {
114 IObject* configObj = iConfig->mThis; // get corresponding object
115 CAudioPlayer* player = (CAudioPlayer*)configObj; // get the native player
116
117 switch (player->mAndroidObjType) {
118 case AUDIOPLAYER_FROM_PCM_BUFFERQUEUE:
119 //TODO remove these commented out lines when our comfort level is good
120 // if (player->mObject.mState != SL_OBJECT_STATE_REALIZED) {
121 // // Make sure the player has been realized.
122 // result = SL_RESULT_PRECONDITIONS_VIOLATED;
123 // SL_LOGE("Error creating routing object - Player not realized.");
124 // } else {
125 // android::AudioTrack* pAudioTrack = player->mAudioTrack.get();
126 // if (pAudioTrack == NULL) {
127 // result = SL_RESULT_INTERNAL_ERROR;
128 // SL_LOGE("Error creating routing object - Couldn't get AudioTrack.");
129 // } else {
130 result = SL_RESULT_SUCCESS;
131 // }
132 // }
133 break;
134
135 default:
136 result = SL_RESULT_PARAMETER_INVALID;
137 SL_LOGE("Error creating routing object - Player is not a buffer-queue player.");
138 break;
139 }
140 }
141
142 return result;
143 }
144
AllocPlayerRoutingProxy(IAndroidConfiguration * iConfig,jobject * proxyObj)145 static SLresult AllocPlayerRoutingProxy(IAndroidConfiguration* iConfig, jobject* proxyObj) {
146 SLresult result;
147
148 IObject* configObj = iConfig->mThis; // get corresponding object
149 android::AudioTrack* pAudioTrack = ((CAudioPlayer*)configObj)->mTrackPlayer->mAudioTrack.get();
150
151 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
152
153 // Get the constructor for (Java) AudioTrackRoutingProxy
154 jclass clsAudioTrackRoutingProxy =
155 j_env->FindClass("android/media/AudioTrackRoutingProxy");
156 jmethodID midAudioTrackRoutingProxy_ctor =
157 j_env->GetMethodID(clsAudioTrackRoutingProxy, "<init>", "(J)V");
158
159 j_env->ExceptionClear();
160
161 jobject localObjRef =
162 j_env->NewObject(clsAudioTrackRoutingProxy,
163 midAudioTrackRoutingProxy_ctor,
164 (jlong)pAudioTrack /*audioTrackObjInLong*/);
165
166 *proxyObj = j_env->NewGlobalRef(localObjRef);
167
168 if (j_env->ExceptionCheck()) {
169 SL_LOGE("Java exception creating player routing object.");
170 result = SL_RESULT_INTERNAL_ERROR;
171 } else {
172 // stash it in the Interface object
173 iConfig->mRoutingProxy = *proxyObj;
174 result = SL_RESULT_SUCCESS;
175 }
176
177 return result;
178 }
179
ValidateRecorderConfig(IAndroidConfiguration * iConfig)180 static SLresult ValidateRecorderConfig(IAndroidConfiguration* iConfig) {
181 SLresult result;
182
183 if (iConfig->mRoutingProxy != NULL) {
184 result = SL_RESULT_PRECONDITIONS_VIOLATED;
185 SL_LOGE("Error creating record routing object - Routing Proxy Already Acquired.");
186 } else {
187 IObject* configObj = iConfig->mThis; // get corresponding object
188 CAudioRecorder* recorder = (CAudioRecorder*)configObj; // get the native recorder
189 switch (recorder->mAndroidObjType) {
190 case AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE:
191 //TODO remove these commented out lines when our comfort level is good
192 // if (recorder->mObject.mState != SL_OBJECT_STATE_REALIZED) {
193 // // Make sure the recorder has been realized.
194 // result = SL_RESULT_PRECONDITIONS_VIOLATED;
195 // SL_LOGE("Error creating routing object - Recorder not realized.");
196 // } else {
197 // android::AudioRecord* pAudioRecord = recorder->mAudioRecord.get();
198 // if (pAudioRecord == NULL) {
199 // result = SL_RESULT_INTERNAL_ERROR;
200 // SL_LOGE("Error creating routing object - Couldn't get AudioRecord.");
201 // } else if (iConfig->mRoutingProxy != NULL) {
202 // result = SL_RESULT_PRECONDITIONS_VIOLATED;
203 // SL_LOGE("Error creating routing object - Routing Proxy Already Acquired."
204 // );
205 // } else {
206 result = SL_RESULT_SUCCESS;
207 // }
208 // }
209 break;
210
211 default:
212 result = SL_RESULT_PARAMETER_INVALID;
213 SL_LOGE("Error creating routing object - Recorder is not a buffer-queue recorder.");
214 break;
215 }
216 }
217
218 return result;
219 }
220
AllocRecorderRoutingProxy(IAndroidConfiguration * iConfig,jobject * proxyObj)221 static SLresult AllocRecorderRoutingProxy(IAndroidConfiguration* iConfig, jobject* proxyObj) {
222 SLresult result;
223
224 IObject* configObj = iConfig->mThis; // get corresponding object
225 android::AudioRecord* pAudioRecord = ((CAudioRecorder*)configObj)->mAudioRecord.get();
226
227 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
228
229 // Get the constructor for (Java) AudioRecordRoutingProxy
230 jclass clsAudioRecordRoutingProxy =
231 j_env->FindClass("android/media/AudioRecordRoutingProxy");
232 jmethodID midAudioRecordRoutingProxy_ctor =
233 j_env->GetMethodID(clsAudioRecordRoutingProxy, "<init>", "(J)V");
234
235 j_env->ExceptionClear();
236 jobject localObjRef =
237 j_env->NewObject(clsAudioRecordRoutingProxy,
238 midAudioRecordRoutingProxy_ctor,
239 (jlong)pAudioRecord /*audioRecordObjInLong*/);
240
241 *proxyObj = j_env->NewGlobalRef(localObjRef);
242 if (j_env->ExceptionCheck()) {
243 SL_LOGE("Java exception creating recorder routing object.");
244 result = SL_RESULT_INTERNAL_ERROR;
245 } else {
246 // stash it in the Interface object
247 iConfig->mRoutingProxy = *proxyObj;
248 result = SL_RESULT_SUCCESS;
249 }
250
251 return result;
252 }
253
254 /*
255 * Acquires a Java proxy object, such as AudioRouting object which can be used to control
256 * aspects of the associated native player or recorder.
257 * Parameters:
258 * self An SLAndroidConfigurationItf obtained from either an OpenSL ES AudioPlayer
259 * or AudioRecorder.
260 * j_env The Java Environment pointer (passed in to the calling JNI function).
261 * proxyType Specifies the type of proxy desired. Currently only SL_ANDROID_JAVA_PROXY_ROUTING
262 * is supported.
263 * proxyObj
264 * Points to the jobject to receive the acquired Java proxy object (as a GlobalRef).
265 * Returns SL_RESULT_SUCCESS is the proxy object is acquired, SL_RESULT_PARAMETER_INVALID if
266 * there is a problem with the arguments causing the function to fail,
267 * <working on this>
268 * SL_RESULT_PRECONDITIONS_VIOLATED it the AudioPlayer or AudioRecorder object associated
269 * with the ConfigurationItf has not been realized.
270 */
IAndroidConfiguration_AcquireJavaProxy(SLAndroidConfigurationItf self,SLuint32 proxyType,jobject * proxyObj)271 static SLresult IAndroidConfiguration_AcquireJavaProxy(SLAndroidConfigurationItf self,
272 SLuint32 proxyType,
273 jobject* proxyObj)
274 {
275 SL_ENTER_INTERFACE
276
277 if (self == NULL || proxyObj == NULL || proxyType != SL_ANDROID_JAVA_PROXY_ROUTING) {
278 result = SL_RESULT_PARAMETER_INVALID;
279 } else {
280 IAndroidConfiguration* iConfig = (IAndroidConfiguration*)self;
281
282 int objID = IObjectToObjectID(InterfaceToIObject(iConfig));
283 switch (objID) {
284 case SL_OBJECTID_AUDIOPLAYER:
285 result = ValidatePlayerConfig(iConfig);
286 if (result == SL_RESULT_SUCCESS) {
287 result = AllocPlayerRoutingProxy(iConfig, proxyObj);
288 }
289 break;
290
291 case SL_OBJECTID_AUDIORECORDER:
292 result = ValidateRecorderConfig(iConfig);
293 if (result == SL_RESULT_SUCCESS) {
294 result = AllocRecorderRoutingProxy(iConfig, proxyObj);
295 }
296 break;
297
298 default:
299 result = SL_RESULT_PARAMETER_INVALID;
300 break;
301 }
302 }
303
304 SL_LEAVE_INTERFACE
305 }
306
307 /*
308 * Release a Java proxy object, such as AudioRouting object, (and any resources it is holding).
309 * Parameters:
310 * self An SLAndroidConfigurationItf obtained from either an OpenSL ES AudioPlayer
311 * or AudioRecorder.
312 * j_env The Java Environment pointer (passed in to the calling JNI function).
313 * proxyType Specifies the type of proxy object. Currently only SL_ANDROID_JAVA_PROXY_ROUTING
314 * is supported.
315 * Returns SL_RESULT_SUCCESS is the proxy object is release, SL_RESULT_PARAMETER_INVALID if
316 * there is a problem with the arguments causing the function to fail,
317 */
IAndroidConfiguration_ReleaseJavaProxy(SLAndroidConfigurationItf self,SLuint32 proxyType)318 static SLresult IAndroidConfiguration_ReleaseJavaProxy(SLAndroidConfigurationItf self,
319 SLuint32 proxyType) {
320 SL_ENTER_INTERFACE
321
322 IAndroidConfiguration* iConfig = (IAndroidConfiguration*)self;
323
324 if (self == NULL ||
325 proxyType != SL_ANDROID_JAVA_PROXY_ROUTING ||
326 iConfig->mRoutingProxy == NULL) {
327 result = SL_RESULT_PARAMETER_INVALID;
328 } else {
329 int objID = IObjectToObjectID(InterfaceToIObject(iConfig));
330 switch (objID) {
331 case SL_OBJECTID_AUDIOPLAYER:
332 {
333 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
334
335 // Get the release method for (Java) AudioTrackRoutingProxy
336 jclass clsAudioTrackRoutingProxy =
337 j_env->FindClass("android/media/AudioTrackRoutingProxy");
338 jmethodID midAudioTrackRoutingProxy_release =
339 j_env->GetMethodID(clsAudioTrackRoutingProxy, "native_release", "()V");
340
341 j_env->ExceptionClear();
342 j_env->CallVoidMethod(iConfig->mRoutingProxy, midAudioTrackRoutingProxy_release);
343 if (j_env->ExceptionCheck()) {
344 SL_LOGE("Java exception releasing recorder routing object.");
345 result = SL_RESULT_INTERNAL_ERROR;
346 }
347 j_env->DeleteGlobalRef(iConfig->mRoutingProxy);
348 iConfig->mRoutingProxy = NULL;
349 }
350 break;
351
352 case SL_OBJECTID_AUDIORECORDER:
353 {
354 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
355
356 // Get the release method for (Java) AudioTrackRoutingProxy
357 jclass clsAudioRecordRoutingProxy =
358 j_env->FindClass("android/media/AudioRecordRoutingProxy");
359 jmethodID midAudioRecordRoutingProxy_release =
360 j_env->GetMethodID(clsAudioRecordRoutingProxy, "native_release", "()V");
361
362 j_env->ExceptionClear();
363 j_env->CallVoidMethod(iConfig->mRoutingProxy, midAudioRecordRoutingProxy_release);
364 if (j_env->ExceptionCheck()) {
365 SL_LOGE("Java exception releasing recorder routing object.");
366 result = SL_RESULT_INTERNAL_ERROR;
367 }
368 j_env->DeleteGlobalRef(iConfig->mRoutingProxy);
369 iConfig->mRoutingProxy = NULL;
370 }
371 break;
372 }
373
374 result = SL_RESULT_SUCCESS;
375 }
376
377 SL_LEAVE_INTERFACE
378 }
379
380 static const struct SLAndroidConfigurationItf_ IAndroidConfiguration_Itf = {
381 IAndroidConfiguration_SetConfiguration,
382 IAndroidConfiguration_GetConfiguration,
383 IAndroidConfiguration_AcquireJavaProxy,
384 IAndroidConfiguration_ReleaseJavaProxy
385 };
386
IAndroidConfiguration_init(void * self)387 void IAndroidConfiguration_init(void *self)
388 {
389 IAndroidConfiguration *thiz = (IAndroidConfiguration *) self;
390 thiz->mItf = &IAndroidConfiguration_Itf;
391 }
392
IAndroidConfiguration_deinit(void * self)393 void IAndroidConfiguration_deinit(void *self)
394 {
395 IAndroidConfiguration *thiz = (IAndroidConfiguration *) self;
396 if (thiz->mRoutingProxy != NULL) {
397 thiz->mItf->ReleaseJavaProxy(&thiz->mItf, SL_ANDROID_JAVA_PROXY_ROUTING);
398 }
399 }
400
401