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_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
54{
55    return check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
56}
57
58static jboolean
59android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
60{
61    bool state = false;
62    AudioSystem::isMicrophoneMuted(&state);
63    return state;
64}
65
66static jboolean
67android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream)
68{
69    bool state = false;
70    AudioSystem::isStreamActive(stream, &state);
71    return state;
72}
73
74static int
75android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
76{
77    const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
78    String8 c_keyValuePairs8;
79    if (keyValuePairs) {
80        c_keyValuePairs8 = String8(c_keyValuePairs, env->GetStringLength(keyValuePairs));
81        env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
82    }
83    int status = check_AudioSystem_Command(AudioSystem::setParameters(0, c_keyValuePairs8));
84    return status;
85}
86
87static jstring
88android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
89{
90    const jchar* c_keys = env->GetStringCritical(keys, 0);
91    String8 c_keys8;
92    if (keys) {
93        c_keys8 = String8(c_keys, env->GetStringLength(keys));
94        env->ReleaseStringCritical(keys, c_keys);
95    }
96    return env->NewStringUTF(AudioSystem::getParameters(0, c_keys8).string());
97}
98
99void android_media_AudioSystem_error_callback(status_t err)
100{
101    JNIEnv *env = AndroidRuntime::getJNIEnv();
102    if (env == NULL) {
103        return;
104    }
105
106    jclass clazz = env->FindClass("android/media/AudioSystem");
107
108    int error;
109
110    switch (err) {
111    case DEAD_OBJECT:
112        error = kAudioStatusMediaServerDied;
113        break;
114    case NO_ERROR:
115        error = kAudioStatusOk;
116        break;
117    default:
118        error = kAudioStatusError;
119        break;
120    }
121
122    env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz, "errorCallbackFromNative","(I)V"), error);
123}
124
125static int
126android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address)
127{
128    const char *c_address = env->GetStringUTFChars(device_address, NULL);
129    int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <AudioSystem::audio_devices>(device),
130                                          static_cast <AudioSystem::device_connection_state>(state),
131                                          c_address));
132    env->ReleaseStringUTFChars(device_address, c_address);
133    return status;
134}
135
136static int
137android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
138{
139    const char *c_address = env->GetStringUTFChars(device_address, NULL);
140    int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <AudioSystem::audio_devices>(device),
141                                          c_address));
142    env->ReleaseStringUTFChars(device_address, c_address);
143    return state;
144}
145
146static int
147android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
148{
149    return check_AudioSystem_Command(AudioSystem::setPhoneState(state));
150}
151
152static int
153android_media_AudioSystem_setRingerMode(JNIEnv *env, jobject thiz, jint mode, jint mask)
154{
155    return check_AudioSystem_Command(AudioSystem::setRingerMode(mode, mask));
156}
157
158static int
159android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
160{
161    return check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <AudioSystem::force_use>(usage),
162                                                           static_cast <AudioSystem::forced_config>(config)));
163}
164
165static int
166android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
167{
168    return static_cast <int>(AudioSystem::getForceUse(static_cast <AudioSystem::force_use>(usage)));
169}
170
171static int
172android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
173{
174    return check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <AudioSystem::stream_type>(stream),
175                                                                   indexMin,
176                                                                   indexMax));
177}
178
179static int
180android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env, jobject thiz, jint stream, jint index)
181{
182    return check_AudioSystem_Command(AudioSystem::setStreamVolumeIndex(static_cast <AudioSystem::stream_type>(stream), index));
183}
184
185static int
186android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env, jobject thiz, jint stream)
187{
188    int index;
189    if (AudioSystem::getStreamVolumeIndex(static_cast <AudioSystem::stream_type>(stream), &index) != NO_ERROR) {
190        index = -1;
191    }
192    return index;
193}
194
195// ----------------------------------------------------------------------------
196
197static JNINativeMethod gMethods[] = {
198    {"setParameters",        "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
199    {"getParameters",        "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
200    {"muteMicrophone",      "(Z)I",     (void *)android_media_AudioSystem_muteMicrophone},
201    {"isMicrophoneMuted",   "()Z",      (void *)android_media_AudioSystem_isMicrophoneMuted},
202    {"isStreamActive",      "(I)Z",     (void *)android_media_AudioSystem_isStreamActive},
203    {"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
204    {"getDeviceConnectionState", "(ILjava/lang/String;)I",  (void *)android_media_AudioSystem_getDeviceConnectionState},
205    {"setPhoneState",       "(I)I",     (void *)android_media_AudioSystem_setPhoneState},
206    {"setRingerMode",       "(II)I",    (void *)android_media_AudioSystem_setRingerMode},
207    {"setForceUse",         "(II)I",    (void *)android_media_AudioSystem_setForceUse},
208    {"getForceUse",         "(I)I",     (void *)android_media_AudioSystem_getForceUse},
209    {"initStreamVolume",    "(III)I",   (void *)android_media_AudioSystem_initStreamVolume},
210    {"setStreamVolumeIndex","(II)I",    (void *)android_media_AudioSystem_setStreamVolumeIndex},
211    {"getStreamVolumeIndex","(I)I",     (void *)android_media_AudioSystem_getStreamVolumeIndex}
212};
213
214const char* const kClassPathName = "android/media/AudioSystem";
215
216int register_android_media_AudioSystem(JNIEnv *env)
217{
218    AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
219
220    return AndroidRuntime::registerNativeMethods(env,
221                "android/media/AudioSystem", gMethods, NELEM(gMethods));
222}
223