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 37using namespace android; 38 39static const char* const kClassPathName = "android/media/AudioSystem"; 40 41enum AudioError { 42 kAudioStatusOk = 0, 43 kAudioStatusError = 1, 44 kAudioStatusMediaServerDied = 100 45}; 46 47static int check_AudioSystem_Command(status_t status) 48{ 49 if (status == NO_ERROR) { 50 return kAudioStatusOk; 51 } else { 52 return kAudioStatusError; 53 } 54} 55 56static int 57android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on) 58{ 59 return check_AudioSystem_Command(AudioSystem::muteMicrophone(on)); 60} 61 62static jboolean 63android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz) 64{ 65 bool state = false; 66 AudioSystem::isMicrophoneMuted(&state); 67 return state; 68} 69 70static jboolean 71android_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 78static jboolean 79android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source) 80{ 81 bool state = false; 82 AudioSystem::isSourceActive((audio_source_t) source, &state); 83 return state; 84} 85 86static int 87android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs) 88{ 89 const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0); 90 String8 c_keyValuePairs8; 91 if (keyValuePairs) { 92 c_keyValuePairs8 = String8(c_keyValuePairs, env->GetStringLength(keyValuePairs)); 93 env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs); 94 } 95 int status = check_AudioSystem_Command(AudioSystem::setParameters(0, c_keyValuePairs8)); 96 return status; 97} 98 99static jstring 100android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys) 101{ 102 const jchar* c_keys = env->GetStringCritical(keys, 0); 103 String8 c_keys8; 104 if (keys) { 105 c_keys8 = String8(c_keys, env->GetStringLength(keys)); 106 env->ReleaseStringCritical(keys, c_keys); 107 } 108 return env->NewStringUTF(AudioSystem::getParameters(0, c_keys8).string()); 109} 110 111static void 112android_media_AudioSystem_error_callback(status_t err) 113{ 114 JNIEnv *env = AndroidRuntime::getJNIEnv(); 115 if (env == NULL) { 116 return; 117 } 118 119 jclass clazz = env->FindClass(kClassPathName); 120 121 int error; 122 123 switch (err) { 124 case DEAD_OBJECT: 125 error = kAudioStatusMediaServerDied; 126 break; 127 case NO_ERROR: 128 error = kAudioStatusOk; 129 break; 130 default: 131 error = kAudioStatusError; 132 break; 133 } 134 135 env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz, "errorCallbackFromNative","(I)V"), error); 136} 137 138static int 139android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address) 140{ 141 const char *c_address = env->GetStringUTFChars(device_address, NULL); 142 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device), 143 static_cast <audio_policy_dev_state_t>(state), 144 c_address)); 145 env->ReleaseStringUTFChars(device_address, c_address); 146 return status; 147} 148 149static int 150android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address) 151{ 152 const char *c_address = env->GetStringUTFChars(device_address, NULL); 153 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device), 154 c_address)); 155 env->ReleaseStringUTFChars(device_address, c_address); 156 return state; 157} 158 159static int 160android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state) 161{ 162 return check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state)); 163} 164 165static int 166android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config) 167{ 168 return check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage), 169 static_cast <audio_policy_forced_cfg_t>(config))); 170} 171 172static int 173android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage) 174{ 175 return static_cast <int>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage))); 176} 177 178static int 179android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax) 180{ 181 return check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream), 182 indexMin, 183 indexMax)); 184} 185 186static int 187android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env, 188 jobject thiz, 189 jint stream, 190 jint index, 191 jint device) 192{ 193 return check_AudioSystem_Command( 194 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream), 195 index, 196 (audio_devices_t)device)); 197} 198 199static int 200android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env, 201 jobject thiz, 202 jint stream, 203 jint device) 204{ 205 int index; 206 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream), 207 &index, 208 (audio_devices_t)device) 209 != NO_ERROR) { 210 index = -1; 211 } 212 return index; 213} 214 215static int 216android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value) 217{ 218 return check_AudioSystem_Command(AudioSystem::setMasterVolume(value)); 219} 220 221static jfloat 222android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz) 223{ 224 float value; 225 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) { 226 value = -1.0; 227 } 228 return value; 229} 230 231static int 232android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute) 233{ 234 return check_AudioSystem_Command(AudioSystem::setMasterMute(mute)); 235} 236 237static jfloat 238android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz) 239{ 240 bool mute; 241 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) { 242 mute = false; 243 } 244 return mute; 245} 246 247static jint 248android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream) 249{ 250 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream)); 251} 252 253static jint 254android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz) 255{ 256 return (jint) AudioSystem::getPrimaryOutputSamplingRate(); 257} 258 259static jint 260android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz) 261{ 262 return (jint) AudioSystem::getPrimaryOutputFrameCount(); 263} 264 265// ---------------------------------------------------------------------------- 266 267static JNINativeMethod gMethods[] = { 268 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters}, 269 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters}, 270 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone}, 271 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted}, 272 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive}, 273 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive}, 274 {"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState}, 275 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState}, 276 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState}, 277 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse}, 278 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse}, 279 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume}, 280 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex}, 281 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex}, 282 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume}, 283 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume}, 284 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute}, 285 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute}, 286 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream}, 287 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate}, 288 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount}, 289}; 290 291int register_android_media_AudioSystem(JNIEnv *env) 292{ 293 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback); 294 295 return AndroidRuntime::registerNativeMethods(env, 296 kClassPathName, gMethods, NELEM(gMethods)); 297} 298