• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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