android_media_AudioSystem.cpp revision d24b8183b93e781080b2c16c487e60d51c12da31
1/* //device/libs/android_runtime/android_media_AudioSystem.cpp
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#include <media/AudioTrack.h>
32
33// ----------------------------------------------------------------------------
34
35using namespace android;
36
37enum AudioError {
38    kAudioStatusOk = 0,
39    kAudioStatusError = 1,
40    kAudioStatusMediaServerDied = 100
41};
42
43static int check_AudioSystem_Command(status_t status)
44{
45    if (status == NO_ERROR) {
46        return kAudioStatusOk;
47    } else {
48        return kAudioStatusError;
49    }
50}
51
52static int
53android_media_AudioSystem_setVolume(JNIEnv *env, jobject clazz, jint type, jint volume)
54{
55    LOGV("setVolume(%d)", int(volume));
56    if (int(type) == AudioTrack::VOICE_CALL) {
57        return check_AudioSystem_Command(AudioSystem::setStreamVolume(type, float(volume) / 100.0));
58    } else if (int(type) == AudioTrack::BLUETOOTH_SCO) {
59        return check_AudioSystem_Command(AudioSystem::setStreamVolume(type, float(1.0)));
60    } else {
61        return check_AudioSystem_Command(AudioSystem::setStreamVolume(type, AudioSystem::linearToLog(volume)));
62    }
63}
64
65static int
66android_media_AudioSystem_getVolume(JNIEnv *env, jobject clazz, jint type)
67{
68    float v;
69    int v_int = -1;
70    if (AudioSystem::getStreamVolume(int(type), &v) == NO_ERROR) {
71        // voice call volume is converted to log scale in the hardware
72        if (int(type) == AudioTrack::VOICE_CALL) {
73            v_int = lrint(v * 100.0);
74        } else {
75            v_int = AudioSystem::logToLinear(v);
76        }
77    }
78    return v_int;
79}
80
81static int
82android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
83{
84    return check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
85}
86
87static jboolean
88android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
89{
90    bool state = false;
91    AudioSystem::isMicrophoneMuted(&state);
92    return state;
93}
94
95static int
96android_media_AudioSystem_setRouting(JNIEnv *env, jobject clazz, jint mode, jint routes, jint mask)
97{
98    return check_AudioSystem_Command(AudioSystem::setRouting(mode, uint32_t(routes), uint32_t(mask)));
99}
100
101static jint
102android_media_AudioSystem_getRouting(JNIEnv *env, jobject clazz, jint mode)
103{
104    uint32_t routes = -1;
105    AudioSystem::getRouting(mode, &routes);
106    return jint(routes);
107}
108
109static int
110android_media_AudioSystem_setMode(JNIEnv *env, jobject clazz, jint mode)
111{
112    return check_AudioSystem_Command(AudioSystem::setMode(mode));
113}
114
115static jint
116android_media_AudioSystem_getMode(JNIEnv *env, jobject clazz)
117{
118    int mode = AudioSystem::MODE_INVALID;
119    AudioSystem::getMode(&mode);
120    return jint(mode);
121}
122
123static jboolean
124android_media_AudioSystem_isMusicActive(JNIEnv *env, jobject thiz)
125{
126    bool state = false;
127    AudioSystem::isMusicActive(&state);
128    return state;
129}
130
131// Temporary interface, do not use
132// TODO: Replace with a more generic key:value get/set mechanism
133static void
134android_media_AudioSystem_setParameter(JNIEnv *env, jobject thiz, jstring key, jstring value)
135{
136    const char *c_key = env->GetStringUTFChars(key, NULL);
137    const char *c_value = env->GetStringUTFChars(value, NULL);
138    AudioSystem::setParameter(c_key, c_value);
139    env->ReleaseStringUTFChars(key, c_key);
140    env->ReleaseStringUTFChars(value, c_value);
141}
142
143void android_media_AudioSystem_error_callback(status_t err)
144{
145    JNIEnv *env = AndroidRuntime::getJNIEnv();
146    jclass clazz = env->FindClass("android/media/AudioSystem");
147
148    int error;
149
150    switch (err) {
151    case DEAD_OBJECT:
152        error = kAudioStatusMediaServerDied;
153        break;
154    case NO_ERROR:
155        error = kAudioStatusOk;
156        break;
157    default:
158        error = kAudioStatusError;
159        break;
160    }
161
162    env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz, "errorCallbackFromNative","(I)V"), error);
163}
164
165// ----------------------------------------------------------------------------
166
167static JNINativeMethod gMethods[] = {
168    {"setVolume",           "(II)I",    (void *)android_media_AudioSystem_setVolume},
169    {"getVolume",           "(I)I",     (void *)android_media_AudioSystem_getVolume},
170    {"setParameter",        "(Ljava/lang/String;Ljava/lang/String;)V", (void *)android_media_AudioSystem_setParameter},
171    {"muteMicrophone",      "(Z)I",     (void *)android_media_AudioSystem_muteMicrophone},
172    {"isMicrophoneMuted",   "()Z",      (void *)android_media_AudioSystem_isMicrophoneMuted},
173    {"setRouting",          "(III)I",   (void *)android_media_AudioSystem_setRouting},
174    {"getRouting",          "(I)I",     (void *)android_media_AudioSystem_getRouting},
175    {"setMode",             "(I)I",     (void *)android_media_AudioSystem_setMode},
176    {"getMode",             "()I",      (void *)android_media_AudioSystem_getMode},
177    {"isMusicActive",       "()Z",      (void *)android_media_AudioSystem_isMusicActive},
178};
179
180const char* const kClassPathName = "android/media/AudioSystem";
181
182int register_android_media_AudioSystem(JNIEnv *env)
183{
184    AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
185
186    return AndroidRuntime::registerNativeMethods(env,
187                "android/media/AudioSystem", gMethods, NELEM(gMethods));
188}
189