1/*
2 * Copyright (C) 2007 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 DBUS_CLASS_NAME BLUEZ_DBUS_BASE_IFC ".Database"
18#define LOG_TAG "bluetooth_Database.cpp"
19
20#include "android_bluetooth_common.h"
21#include "android_runtime/AndroidRuntime.h"
22#include "JNIHelp.h"
23#include "jni.h"
24#include "utils/Log.h"
25
26#ifdef HAVE_BLUETOOTH
27#include <dbus/dbus.h>
28#endif
29
30namespace android {
31
32#ifdef HAVE_BLUETOOTH
33static DBusConnection* conn = NULL;   // Singleton thread-safe connection
34#endif
35
36static void classInitNative(JNIEnv* env, jclass clazz) {
37    LOGV(__FUNCTION__);
38#ifdef HAVE_BLUETOOTH
39    conn = NULL;
40#endif
41}
42
43static void initializeNativeDataNative(JNIEnv* env, jobject object) {
44    LOGV(__FUNCTION__);
45
46#ifdef HAVE_BLUETOOTH
47    if (conn == NULL) {
48        DBusError err;
49        dbus_error_init(&err);
50        dbus_threads_init_default();
51        conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
52        if (dbus_error_is_set(&err)) {
53            LOGE("Could not get onto the system bus!");
54            dbus_error_free(&err);
55        }
56        dbus_connection_set_exit_on_disconnect(conn, FALSE);
57    }
58#endif
59}
60
61static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
62    LOGV(__FUNCTION__);
63}
64
65static jint addServiceRecordNative(JNIEnv *env, jobject object,
66                                   jbyteArray record) {
67    LOGV(__FUNCTION__);
68#ifdef HAVE_BLUETOOTH
69    if (conn != NULL) {
70        jbyte* c_record = env->GetByteArrayElements(record, NULL);
71        DBusMessage *reply = dbus_func_args(env,
72                                            conn,
73                                            BLUEZ_DBUS_BASE_PATH,
74                                            DBUS_CLASS_NAME,
75                                            "AddServiceRecord",
76                                            DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
77                                            &c_record,
78                                            env->GetArrayLength(record),
79                                            DBUS_TYPE_INVALID);
80        env->ReleaseByteArrayElements(record, c_record, JNI_ABORT);
81        return reply ? dbus_returns_uint32(env, reply) : -1;
82    }
83#endif
84    return -1;
85}
86
87static jint addServiceRecordFromXmlNative(JNIEnv *env, jobject object,
88                                          jstring record) {
89    LOGV(__FUNCTION__);
90#ifdef HAVE_BLUETOOTH
91    if (conn != NULL) {
92        const char *c_record = env->GetStringUTFChars(record, NULL);
93        DBusMessage *reply = dbus_func_args(env,
94                                            conn,
95                                            BLUEZ_DBUS_BASE_PATH,
96                                            DBUS_CLASS_NAME,
97                                            "AddServiceRecordFromXML",
98                                            DBUS_TYPE_STRING, &c_record,
99                                            DBUS_TYPE_INVALID);
100        env->ReleaseStringUTFChars(record, c_record);
101        return reply ? dbus_returns_uint32(env, reply) : -1;
102    }
103#endif
104    return -1;
105}
106
107static void updateServiceRecordNative(JNIEnv *env, jobject object,
108                                      jint handle,
109                                      jbyteArray record) {
110    LOGV(__FUNCTION__);
111#ifdef HAVE_BLUETOOTH
112    if (conn != NULL) {
113        jbyte* c_record = env->GetByteArrayElements(record, NULL);
114        DBusMessage *reply = dbus_func_args(env,
115                                            conn,
116                                            BLUEZ_DBUS_BASE_PATH,
117                                            DBUS_CLASS_NAME,
118                                            "UpdateServiceRecord",
119                                            DBUS_TYPE_UINT32, &handle,
120                                            DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
121                                            &c_record,
122                                            env->GetArrayLength(record),
123                                            DBUS_TYPE_INVALID);
124        env->ReleaseByteArrayElements(record, c_record, JNI_ABORT);
125    }
126#endif
127}
128
129static void updateServiceRecordFromXmlNative(JNIEnv *env, jobject object,
130                                             jint handle,
131                                             jstring record) {
132    LOGV(__FUNCTION__);
133#ifdef HAVE_BLUETOOTH
134    if (conn != NULL) {
135        const char *c_record = env->GetStringUTFChars(record, NULL);
136        DBusMessage *reply = dbus_func_args(env,
137                                            conn,
138                                            BLUEZ_DBUS_BASE_PATH,
139                                            DBUS_CLASS_NAME,
140                                            "UpdateServiceRecordFromXML",
141                                            DBUS_TYPE_UINT32, &handle,
142                                            DBUS_TYPE_STRING, &c_record,
143                                            DBUS_TYPE_INVALID);
144        env->ReleaseStringUTFChars(record, c_record);
145    }
146#endif
147}
148
149/* private static native void removeServiceRecordNative(int handle); */
150static void removeServiceRecordNative(JNIEnv *env, jobject object,
151                                      jint handle) {
152    LOGV(__FUNCTION__);
153#ifdef HAVE_BLUETOOTH
154    if (conn != NULL) {
155        DBusMessage *reply = dbus_func_args(env,
156                                            conn,
157                                            BLUEZ_DBUS_BASE_PATH,
158                                            DBUS_CLASS_NAME,
159                                            "RemoveServiceRecord",
160                                            DBUS_TYPE_UINT32, &handle,
161                                            DBUS_TYPE_INVALID);
162    }
163#endif
164}
165
166
167static JNINativeMethod sMethods[] = {
168     /* name, signature, funcPtr */
169    {"classInitNative", "()V", (void*)classInitNative},
170    {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative},
171    {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
172    {"addServiceRecordNative", "([B)I", (void*)addServiceRecordNative},
173    {"addServiceRecordFromXmlNative", "(Ljava/lang/String;)I", (void*)addServiceRecordFromXmlNative},
174    {"updateServiceRecordNative", "(I[B)V", (void*)updateServiceRecordNative},
175    {"updateServiceRecordFromXmlNative", "(ILjava/lang/String;)V", (void*)updateServiceRecordFromXmlNative},
176    {"removeServiceRecordNative", "(I)V", (void*)removeServiceRecordNative},
177};
178
179int register_android_bluetooth_Database(JNIEnv *env) {
180    return AndroidRuntime::registerNativeMethods(env,
181            "android/bluetooth/Database", sMethods, NELEM(sMethods));
182}
183
184} /* namespace android */
185