1 /*
2  **
3  ** Copyright 2008, 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 "ToneGenerator"
19 
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 
24 #include <jni.h>
25 #include <JNIHelp.h>
26 #include "core_jni_helpers.h"
27 
28 #include <utils/Log.h>
29 #include <media/AudioSystem.h>
30 #include <media/ToneGenerator.h>
31 
32 // ----------------------------------------------------------------------------
33 
34 using namespace android;
35 
36 struct fields_t {
37     jfieldID context;
38 };
39 static fields_t fields;
40 
android_media_ToneGenerator_startTone(JNIEnv * env,jobject thiz,jint toneType,jint durationMs)41 static jboolean android_media_ToneGenerator_startTone(JNIEnv *env, jobject thiz, jint toneType, jint durationMs) {
42     ALOGV("android_media_ToneGenerator_startTone: %p", thiz);
43 
44     ToneGenerator *lpToneGen = (ToneGenerator *)env->GetLongField(thiz,
45             fields.context);
46     if (lpToneGen == NULL) {
47         jniThrowRuntimeException(env, "Method called after release()");
48         return false;
49     }
50 
51     return lpToneGen->startTone((ToneGenerator::tone_type) toneType, durationMs);
52 }
53 
android_media_ToneGenerator_stopTone(JNIEnv * env,jobject thiz)54 static void android_media_ToneGenerator_stopTone(JNIEnv *env, jobject thiz) {
55     ALOGV("android_media_ToneGenerator_stopTone: %p", thiz);
56 
57     ToneGenerator *lpToneGen = (ToneGenerator *)env->GetLongField(thiz,
58             fields.context);
59 
60     ALOGV("ToneGenerator lpToneGen: %p", lpToneGen);
61     if (lpToneGen == NULL) {
62         jniThrowRuntimeException(env, "Method called after release()");
63         return;
64     }
65     lpToneGen->stopTone();
66 }
67 
android_media_ToneGenerator_getAudioSessionId(JNIEnv * env,jobject thiz)68 static jint android_media_ToneGenerator_getAudioSessionId(JNIEnv *env, jobject thiz) {
69     ToneGenerator *lpToneGen = (ToneGenerator *)env->GetLongField(thiz,
70             fields.context);
71     if (lpToneGen == NULL) {
72         jniThrowRuntimeException(env, "Method called after release()");
73         return 0;
74     }
75     return lpToneGen->getSessionId();
76 }
77 
android_media_ToneGenerator_release(JNIEnv * env,jobject thiz)78 static void android_media_ToneGenerator_release(JNIEnv *env, jobject thiz) {
79     ToneGenerator *lpToneGen = (ToneGenerator *)env->GetLongField(thiz,
80             fields.context);
81     ALOGV("android_media_ToneGenerator_release lpToneGen: %p", lpToneGen);
82 
83     env->SetLongField(thiz, fields.context, 0);
84 
85     delete lpToneGen;
86 }
87 
android_media_ToneGenerator_native_setup(JNIEnv * env,jobject thiz,jint streamType,jint volume)88 static void android_media_ToneGenerator_native_setup(JNIEnv *env, jobject thiz,
89         jint streamType, jint volume) {
90     ToneGenerator *lpToneGen = new ToneGenerator((audio_stream_type_t) streamType, AudioSystem::linearToLog(volume), true);
91 
92     env->SetLongField(thiz, fields.context, 0);
93 
94     ALOGV("android_media_ToneGenerator_native_setup jobject: %p", thiz);
95 
96     ALOGV("ToneGenerator lpToneGen: %p", lpToneGen);
97 
98     if (!lpToneGen->isInited()) {
99         ALOGE("ToneGenerator init failed");
100         jniThrowRuntimeException(env, "Init failed");
101         delete lpToneGen;
102         return;
103     }
104 
105     // Stow our new C++ ToneGenerator in an opaque field in the Java object.
106     env->SetLongField(thiz, fields.context, (jlong)lpToneGen);
107 
108     ALOGV("ToneGenerator fields.context: %p", (void*) env->GetLongField(thiz, fields.context));
109 }
110 
android_media_ToneGenerator_native_finalize(JNIEnv * env,jobject thiz)111 static void android_media_ToneGenerator_native_finalize(JNIEnv *env,
112         jobject thiz) {
113     ALOGV("android_media_ToneGenerator_native_finalize jobject: %p", thiz);
114 
115     ToneGenerator *lpToneGen = (ToneGenerator *)env->GetLongField(thiz,
116             fields.context);
117 
118     if (lpToneGen != NULL) {
119         ALOGV("delete lpToneGen: %p", lpToneGen);
120         delete lpToneGen;
121     }
122 }
123 
124 // ----------------------------------------------------------------------------
125 
126 static const JNINativeMethod gMethods[] = {
127     { "startTone", "(II)Z", (void *)android_media_ToneGenerator_startTone },
128     { "stopTone", "()V", (void *)android_media_ToneGenerator_stopTone },
129     { "getAudioSessionId", "()I", (void *)android_media_ToneGenerator_getAudioSessionId},
130     { "release", "()V", (void *)android_media_ToneGenerator_release },
131     { "native_setup", "(II)V", (void *)android_media_ToneGenerator_native_setup },
132     { "native_finalize", "()V", (void *)android_media_ToneGenerator_native_finalize }
133 };
134 
135 
register_android_media_ToneGenerator(JNIEnv * env)136 int register_android_media_ToneGenerator(JNIEnv *env) {
137     jclass clazz = FindClassOrDie(env, "android/media/ToneGenerator");
138 
139     fields.context = GetFieldIDOrDie(env, clazz, "mNativeContext", "J");
140     ALOGV("register_android_media_ToneGenerator ToneGenerator fields.context: %p", fields.context);
141 
142     return RegisterMethodsOrDie(env, "android/media/ToneGenerator", gMethods, NELEM(gMethods));
143 }
144