blob: 67c2cfdc9bb3c1705c782979b62bbd2d55d2141b [file] [log] [blame]
Glenn Kastenb3db2132012-01-19 08:59:58 -08001/*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002**
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"
Glenn Kastenc81d31c2012-03-13 14:46:23 -070019#include <utils/Log.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020
21#include <stdio.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <math.h>
25
Glenn Kastenc81d31c2012-03-13 14:46:23 -070026#include <jni.h>
27#include <JNIHelp.h>
28#include <android_runtime/AndroidRuntime.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
30#include <media/AudioSystem.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031
Dima Zavin34bb4192011-05-11 14:15:23 -070032#include <system/audio.h>
Dima Zavin290029d2011-06-13 18:16:26 -070033#include <system/audio_policy.h>
Dima Zavin24fc2fb2011-04-19 22:30:36 -070034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035// ----------------------------------------------------------------------------
36
37using namespace android;
38
Glenn Kastened0079d2011-04-04 10:50:50 -070039static const char* const kClassPathName = "android/media/AudioSystem";
40
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041enum 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057android_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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070static jboolean
Eric Laurent25101b02011-02-02 09:33:30 -080071android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072{
73 bool state = false;
Glenn Kastenbc1d77b2012-01-12 16:38:12 -080074 AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 return state;
76}
77
Jean-Michel Trivid6770542012-10-10 12:03:41 -070078static jboolean
Jean-Michel Trivi679d5042013-02-04 16:24:09 -080079android_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
Jean-Michel Trivid6770542012-10-10 12:03:41 -070088android_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
Eric Laurenta553c252009-07-17 12:17:14 -070095static int
96android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097{
Eric Laurenta553c252009-07-17 12:17:14 -070098 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());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118}
119
Glenn Kastened0079d2011-04-04 10:50:50 -0700120static void
121android_media_AudioSystem_error_callback(status_t err)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122{
123 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent0e7a4d92010-10-15 12:33:16 -0700124 if (env == NULL) {
125 return;
126 }
127
Glenn Kastened0079d2011-04-04 10:50:50 -0700128 jclass clazz = env->FindClass(kClassPathName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129
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
Eric Laurenta553c252009-07-17 12:17:14 -0700147static 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);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700151 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
152 static_cast <audio_policy_dev_state_t>(state),
Eric Laurenta553c252009-07-17 12:17:14 -0700153 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);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700162 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
Eric Laurenta553c252009-07-17 12:17:14 -0700163 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{
Glenn Kastenaccb1142012-01-04 11:00:47 -0800171 return check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
Eric Laurenta553c252009-07-17 12:17:14 -0700172}
173
174static int
Eric Laurenta553c252009-07-17 12:17:14 -0700175android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
176{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700177 return check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
178 static_cast <audio_policy_forced_cfg_t>(config)));
Eric Laurenta553c252009-07-17 12:17:14 -0700179}
180
181static int
182android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
183{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700184 return static_cast <int>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
Eric Laurenta553c252009-07-17 12:17:14 -0700185}
186
187static int
188android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
189{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700190 return check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
Eric Laurenta553c252009-07-17 12:17:14 -0700191 indexMin,
192 indexMax));
193}
194
195static int
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800196android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
197 jobject thiz,
198 jint stream,
199 jint index,
200 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700201{
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800202 return check_AudioSystem_Command(
203 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
204 index,
205 (audio_devices_t)device));
Eric Laurenta553c252009-07-17 12:17:14 -0700206}
207
208static int
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800209android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
210 jobject thiz,
211 jint stream,
212 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700213{
214 int index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800215 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
216 &index,
217 (audio_devices_t)device)
218 != NO_ERROR) {
Eric Laurenta553c252009-07-17 12:17:14 -0700219 index = -1;
220 }
221 return index;
222}
223
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400224static 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
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800256static jint
257android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
258{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700259 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800260}
261
Glenn Kastenc6c43652012-09-24 17:32:30 -0700262static 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
Oliver Woodmane64716a2013-06-26 12:43:36 +0100274static 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285// ----------------------------------------------------------------------------
286
287static JNINativeMethod gMethods[] = {
Eric Laurenta553c252009-07-17 12:17:14 -0700288 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
289 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
291 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted},
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700292 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
Jean-Michel Trivi679d5042013-02-04 16:24:09 -0800293 {"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely},
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700294 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
Eric Laurenta553c252009-07-17 12:17:14 -0700295 {"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},
Eric Laurenta553c252009-07-17 12:17:14 -0700298 {"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},
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800301 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
302 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex},
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400303 {"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},
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800307 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
Glenn Kastenc6c43652012-09-24 17:32:30 -0700308 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
309 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
Oliver Woodmane64716a2013-06-26 12:43:36 +0100310 {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311};
312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313int register_android_media_AudioSystem(JNIEnv *env)
314{
315 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
Glenn Kasten18db49a2012-03-12 16:29:55 -0700316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 return AndroidRuntime::registerNativeMethods(env,
Glenn Kastened0079d2011-04-04 10:50:50 -0700318 kClassPathName, gMethods, NELEM(gMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319}