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