android_media_AudioSystem.cpp revision 61dcdf3764b614c6f01e77cb4342d192e3101f8a
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_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
87static jboolean
88android_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
95static int
96android_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
108static jstring
109android_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
120static void
121android_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
147static int
148android_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
158static int
159android_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
168static int
169android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
170{
171    return check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
172}
173
174static int
175android_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
181static int
182android_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
187static int
188android_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
195static int
196android_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
208static int
209android_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
224static int
225android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
226{
227    return check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
228}
229
230static jfloat
231android_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
240static int
241android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
242{
243    return check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
244}
245
246static jfloat
247android_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
256static jint
257android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
258{
259    return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
260}
261
262static jint
263android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
264{
265    return (jint) AudioSystem::getPrimaryOutputSamplingRate();
266}
267
268static jint
269android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
270{
271    return (jint) AudioSystem::getPrimaryOutputFrameCount();
272}
273
274static jint
275android_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
287static 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
313int 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