blob: e9d448234e17260caf44163fae7f1b9dbbff1018 [file] [log] [blame]
Andrew Chant07a97da2018-02-05 15:55:02 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "UsbAlsaJackDetectorJNI"
18#include "utils/Log.h"
19
20#include "jni.h"
21#include <nativehelper/JNIHelp.h>
22#include "android_runtime/AndroidRuntime.h"
23#include "android_runtime/Log.h"
24
25#include <stdio.h>
26#include <string.h>
27#include <asm/byteorder.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <fcntl.h>
31
32#include <tinyalsa/asoundlib.h>
33
34#define DRIVER_NAME "/dev/usb_accessory"
35
36#define USB_IN_JACK_NAME "USB in Jack"
37#define USB_OUT_JACK_NAME "USB out Jack"
38
39namespace android
40{
41
42static jboolean is_jack_connected(jint card, const char* control) {
43 struct mixer* card_mixer = mixer_open(card);
44 if (card_mixer == NULL) {
45 return true;
46 }
47 struct mixer_ctl* ctl = mixer_get_ctl_by_name(card_mixer, control);
48 if (!ctl) {
49 return true;
50 }
51 mixer_ctl_update(ctl);
52 int val = mixer_ctl_get_value(ctl, 0);
53 ALOGI("JACK %s - value %d\n", control, val);
54 mixer_close(card_mixer);
55
56 return val != 0;
57}
58
59static jboolean android_server_UsbAlsaJackDetector_hasJackDetect(JNIEnv* /* env */,
60 jobject /* thiz */,
61 jint card)
62{
63 struct mixer* card_mixer = mixer_open(card);
64 if (card_mixer == NULL) {
65 return false;
66 }
67
68 jboolean has_jack = false;
69 if ((mixer_get_ctl_by_name(card_mixer, USB_IN_JACK_NAME) != NULL) ||
70 (mixer_get_ctl_by_name(card_mixer, USB_OUT_JACK_NAME) != NULL)) {
71 has_jack = true;
72 }
73 mixer_close(card_mixer);
74 return has_jack;
75}
76
77
78static jboolean android_server_UsbAlsaJackDetector_inputJackConnected(JNIEnv* /* env */,
79 jobject /* thiz */,
80 jint card)
81{
82 return is_jack_connected(card, USB_IN_JACK_NAME);
83}
84
85
86static jboolean android_server_UsbAlsaJackDetector_outputJackConnected(JNIEnv* /* env */,
87 jobject /* thiz */,
88 jint card)
89{
90 return is_jack_connected(card, USB_OUT_JACK_NAME);
91}
92
93static void android_server_UsbAlsaJackDetector_jackDetect(JNIEnv* env,
94 jobject thiz,
95 jint card) {
96 jclass jdclass = env->GetObjectClass(thiz);
97 jmethodID method_jackDetectCallback = env->GetMethodID(jdclass, "jackDetectCallback", "()Z");
98 if (method_jackDetectCallback == NULL) {
99 ALOGE("Can't find jackDetectCallback");
100 return;
101 }
102
103 struct mixer* m = mixer_open(card);
104 if (!m) {
105 ALOGE("Jack detect unable to open mixer\n");
106 return;
107 }
108 mixer_subscribe_events(m, 1);
109 do {
110
111 // Wait for a mixer event. Retry if interrupted, exit on error.
112 int retval;
113 do {
114 retval = mixer_wait_event(m, -1);
115 } while (retval == -EINTR);
116 if (retval < 0) {
117 break;
118 }
119 mixer_consume_event(m);
120 } while (env->CallBooleanMethod(thiz, method_jackDetectCallback));
121
122 mixer_close(m);
123 return;
124}
125
126static const JNINativeMethod method_table[] = {
127 { "nativeHasJackDetect", "(I)Z", (void*)android_server_UsbAlsaJackDetector_hasJackDetect },
128 { "nativeInputJackConnected", "(I)Z",
129 (void*)android_server_UsbAlsaJackDetector_inputJackConnected },
130 { "nativeOutputJackConnected", "(I)Z",
131 (void*)android_server_UsbAlsaJackDetector_outputJackConnected },
132 { "nativeJackDetect", "(I)Z", (void*)android_server_UsbAlsaJackDetector_jackDetect },
133};
134
135int register_android_server_UsbAlsaJackDetector(JNIEnv *env)
136{
137 jclass clazz = env->FindClass("com/android/server/usb/UsbAlsaJackDetector");
138 if (clazz == NULL) {
139 ALOGE("Can't find com/android/server/usb/UsbAlsaJackDetector");
140 return -1;
141 }
142
143 if (!jniRegisterNativeMethods(env, "com/android/server/usb/UsbAlsaJackDetector",
144 method_table, NELEM(method_table))) {
145 ALOGE("Can't register UsbAlsaJackDetector native methods");
146 return -1;
147 }
148
149 return 0;
150}
151
152}