Home | History | Annotate | Download | only in itf
      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 
     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 
     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  */
    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 
    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)->mTrackPlayer->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 
    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 
    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  */
    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  */
    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 
    385 void IAndroidConfiguration_init(void *self)
    386 {
    387     IAndroidConfiguration *thiz = (IAndroidConfiguration *) self;
    388     thiz->mItf = &IAndroidConfiguration_Itf;
    389 }
    390 
    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