• 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         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