Home | History | Annotate | Download | only in jni
      1 /*
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #define LOG_TAG "AudioSystem"
     19 #include <utils/Log.h>
     20 
     21 #include <stdio.h>
     22 #include <unistd.h>
     23 #include <fcntl.h>
     24 #include <math.h>
     25 
     26 #include <jni.h>
     27 #include <JNIHelp.h>
     28 #include <android_runtime/AndroidRuntime.h>
     29 
     30 #include <media/AudioSystem.h>
     31 
     32 #include <system/audio.h>
     33 #include <system/audio_policy.h>
     34 
     35 // ----------------------------------------------------------------------------
     36 
     37 using namespace android;
     38 
     39 static const char* const kClassPathName = "android/media/AudioSystem";
     40 
     41 enum AudioError {
     42     kAudioStatusOk = 0,
     43     kAudioStatusError = 1,
     44     kAudioStatusMediaServerDied = 100
     45 };
     46 
     47 static int check_AudioSystem_Command(status_t status)
     48 {
     49     if (status == NO_ERROR) {
     50         return kAudioStatusOk;
     51     } else {
     52         return kAudioStatusError;
     53     }
     54 }
     55 
     56 static int
     57 android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
     58 {
     59     return check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
     60 }
     61 
     62 static jboolean
     63 android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
     64 {
     65     bool state = false;
     66     AudioSystem::isMicrophoneMuted(&state);
     67     return state;
     68 }
     69 
     70 static jboolean
     71 android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
     72 {
     73     bool state = false;
     74     AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
     75     return state;
     76 }
     77 
     78 static jboolean
     79 android_media_AudioSystem_isStreamActiveRemotely(JNIEnv *env, jobject thiz, jint stream,
     80         jint inPastMs)
     81 {
     82     bool state = false;
     83     AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs);
     84     return state;
     85 }
     86 
     87 static jboolean
     88 android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
     89 {
     90     bool state = false;
     91     AudioSystem::isSourceActive((audio_source_t) source, &state);
     92     return state;
     93 }
     94 
     95 static int
     96 android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
     97 {
     98     const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
     99     String8 c_keyValuePairs8;
    100     if (keyValuePairs) {
    101         c_keyValuePairs8 = String8(c_keyValuePairs, env->GetStringLength(keyValuePairs));
    102         env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
    103     }
    104     int status = check_AudioSystem_Command(AudioSystem::setParameters(0, c_keyValuePairs8));
    105     return status;
    106 }
    107 
    108 static jstring
    109 android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
    110 {
    111     const jchar* c_keys = env->GetStringCritical(keys, 0);
    112     String8 c_keys8;
    113     if (keys) {
    114         c_keys8 = String8(c_keys, env->GetStringLength(keys));
    115         env->ReleaseStringCritical(keys, c_keys);
    116     }
    117     return env->NewStringUTF(AudioSystem::getParameters(0, c_keys8).string());
    118 }
    119 
    120 static void
    121 android_media_AudioSystem_error_callback(status_t err)
    122 {
    123     JNIEnv *env = AndroidRuntime::getJNIEnv();
    124     if (env == NULL) {
    125         return;
    126     }
    127 
    128     jclass clazz = env->FindClass(kClassPathName);
    129 
    130     int error;
    131 
    132     switch (err) {
    133     case DEAD_OBJECT:
    134         error = kAudioStatusMediaServerDied;
    135         break;
    136     case NO_ERROR:
    137         error = kAudioStatusOk;
    138         break;
    139     default:
    140         error = kAudioStatusError;
    141         break;
    142     }
    143 
    144     env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz, "errorCallbackFromNative","(I)V"), error);
    145 }
    146 
    147 static int
    148 android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address)
    149 {
    150     const char *c_address = env->GetStringUTFChars(device_address, NULL);
    151     int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
    152                                           static_cast <audio_policy_dev_state_t>(state),
    153                                           c_address));
    154     env->ReleaseStringUTFChars(device_address, c_address);
    155     return status;
    156 }
    157 
    158 static int
    159 android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
    160 {
    161     const char *c_address = env->GetStringUTFChars(device_address, NULL);
    162     int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
    163                                           c_address));
    164     env->ReleaseStringUTFChars(device_address, c_address);
    165     return state;
    166 }
    167 
    168 static int
    169 android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
    170 {
    171     return check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
    172 }
    173 
    174 static int
    175 android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
    176 {
    177     return check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
    178                                                            static_cast <audio_policy_forced_cfg_t>(config)));
    179 }
    180 
    181 static int
    182 android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
    183 {
    184     return static_cast <int>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
    185 }
    186 
    187 static int
    188 android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
    189 {
    190     return check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
    191                                                                    indexMin,
    192                                                                    indexMax));
    193 }
    194 
    195 static int
    196 android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
    197                                                jobject thiz,
    198                                                jint stream,
    199                                                jint index,
    200                                                jint device)
    201 {
    202     return check_AudioSystem_Command(
    203             AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
    204                                               index,
    205                                               (audio_devices_t)device));
    206 }
    207 
    208 static int
    209 android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
    210                                                jobject thiz,
    211                                                jint stream,
    212                                                jint device)
    213 {
    214     int index;
    215     if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
    216                                           &index,
    217                                           (audio_devices_t)device)
    218             != NO_ERROR) {
    219         index = -1;
    220     }
    221     return index;
    222 }
    223 
    224 static int
    225 android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
    226 {
    227     return check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
    228 }
    229 
    230 static jfloat
    231 android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz)
    232 {
    233     float value;
    234     if (AudioSystem::getMasterVolume(&value) != NO_ERROR) {
    235         value = -1.0;
    236     }
    237     return value;
    238 }
    239 
    240 static int
    241 android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
    242 {
    243     return check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
    244 }
    245 
    246 static jfloat
    247 android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
    248 {
    249     bool mute;
    250     if (AudioSystem::getMasterMute(&mute) != NO_ERROR) {
    251         mute = false;
    252     }
    253     return mute;
    254 }
    255 
    256 static jint
    257 android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
    258 {
    259     return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
    260 }
    261 
    262 static jint
    263 android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
    264 {
    265     return (jint) AudioSystem::getPrimaryOutputSamplingRate();
    266 }
    267 
    268 static jint
    269 android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
    270 {
    271     return (jint) AudioSystem::getPrimaryOutputFrameCount();
    272 }
    273 
    274 static jint
    275 android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
    276 {
    277     uint32_t afLatency;
    278     if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
    279             != NO_ERROR) {
    280         afLatency = -1;
    281     }
    282     return (jint) afLatency;
    283 }
    284 
    285 // ----------------------------------------------------------------------------
    286 
    287 static JNINativeMethod gMethods[] = {
    288     {"setParameters",        "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
    289     {"getParameters",        "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
    290     {"muteMicrophone",      "(Z)I",     (void *)android_media_AudioSystem_muteMicrophone},
    291     {"isMicrophoneMuted",   "()Z",      (void *)android_media_AudioSystem_isMicrophoneMuted},
    292     {"isStreamActive",      "(II)Z",    (void *)android_media_AudioSystem_isStreamActive},
    293     {"isStreamActiveRemotely","(II)Z",  (void *)android_media_AudioSystem_isStreamActiveRemotely},
    294     {"isSourceActive",      "(I)Z",     (void *)android_media_AudioSystem_isSourceActive},
    295     {"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
    296     {"getDeviceConnectionState", "(ILjava/lang/String;)I",  (void *)android_media_AudioSystem_getDeviceConnectionState},
    297     {"setPhoneState",       "(I)I",     (void *)android_media_AudioSystem_setPhoneState},
    298     {"setForceUse",         "(II)I",    (void *)android_media_AudioSystem_setForceUse},
    299     {"getForceUse",         "(I)I",     (void *)android_media_AudioSystem_getForceUse},
    300     {"initStreamVolume",    "(III)I",   (void *)android_media_AudioSystem_initStreamVolume},
    301     {"setStreamVolumeIndex","(III)I",   (void *)android_media_AudioSystem_setStreamVolumeIndex},
    302     {"getStreamVolumeIndex","(II)I",    (void *)android_media_AudioSystem_getStreamVolumeIndex},
    303     {"setMasterVolume",     "(F)I",     (void *)android_media_AudioSystem_setMasterVolume},
    304     {"getMasterVolume",     "()F",      (void *)android_media_AudioSystem_getMasterVolume},
    305     {"setMasterMute",       "(Z)I",     (void *)android_media_AudioSystem_setMasterMute},
    306     {"getMasterMute",       "()Z",      (void *)android_media_AudioSystem_getMasterMute},
    307     {"getDevicesForStream", "(I)I",     (void *)android_media_AudioSystem_getDevicesForStream},
    308     {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
    309     {"getPrimaryOutputFrameCount",   "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
    310     {"getOutputLatency",    "(I)I",     (void *)android_media_AudioSystem_getOutputLatency},
    311 };
    312 
    313 int register_android_media_AudioSystem(JNIEnv *env)
    314 {
    315     AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
    316 
    317     return AndroidRuntime::registerNativeMethods(env,
    318                 kClassPathName, gMethods, NELEM(gMethods));
    319 }
    320