--- a/dom/bluetooth/Makefile.in
+++ b/dom/bluetooth/Makefile.in
@@ -23,10 +23,22 @@ CPPSRCS = \
$(NULL)
XPIDLSRCS = \
nsIDOMNavigatorBluetooth.idl \
nsIDOMBluetoothAdapter.idl \
nsIDOMBluetoothDevice.idl \
$(NULL)
+ifneq (gonk,$(MOZ_WIDGET_TOOLKIT))
+CFLAGS += $(MOZ_DBUS_CFLAGS)
+CXXFLAGS += $(MOZ_DBUS_CFLAGS) -DHAVE_PTHREADS
+endif
+
include $(topsrcdir)/config/rules.mk
+ifeq (Linux,$(OS_TARGET))
+ifdef MOZ_ENABLE_DBUS
+CFLAGS += $(MOZ_DBUS_GLIB_CFLAGS)
+CXXFLAGS += $(MOZ_DBUS_GLIB_CFLAGS) -DHAVE_PTHREADS
+endif
+endif
+
--- a/dom/system/gonk/SystemWorkerManager.cpp
+++ b/dom/system/gonk/SystemWorkerManager.cpp
@@ -44,16 +44,19 @@
#include "nsIRadioInterfaceLayer.h"
#include "nsIWifi.h"
#include "nsIWorkerHolder.h"
#include "nsIXPConnect.h"
#include "jstypedarray.h"
#include "mozilla/dom/workers/Workers.h"
#include "mozilla/ipc/Ril.h"
+#ifdef MOZ_B2G_BT
+#include "mozilla/ipc/DBusThread.h"
+#endif
#include "nsContentUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "nsRadioInterfaceLayer.h"
#include "WifiWorker.h"
USING_WORKERS_NAMESPACE
@@ -226,16 +229,21 @@ SystemWorkerManager::Init()
}
rv = InitRIL(cx);
NS_ENSURE_SUCCESS(rv, rv);
rv = InitWifi(cx);
NS_ENSURE_SUCCESS(rv, rv);
+#ifdef MOZ_B2G_BT
+ rv = InitBluetooth(cx);
+ NS_ENSURE_SUCCESS(rv, rv);
+#endif
+
nsCOMPtr<nsIObserverService> obs =
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
if (!obs) {
NS_WARNING("Failed to get observer service!");
return NS_ERROR_FAILURE;
}
rv = obs->AddObserver(this, WORKERS_SHUTDOWN_TOPIC, false);
@@ -247,17 +255,19 @@ SystemWorkerManager::Init()
void
SystemWorkerManager::Shutdown()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
mShutdown = true;
StopRil();
-
+#ifdef MOZ_B2G_BT
+ StopDBus();
+#endif
mRILWorker = nsnull;
nsCOMPtr<nsIWifi> wifi(do_QueryInterface(mWifiWorker));
if (wifi) {
wifi->Shutdown();
wifi = nsnull;
}
mWifiWorker = nsnull;
@@ -360,16 +370,29 @@ SystemWorkerManager::InitWifi(JSContext
{
nsCOMPtr<nsIWorkerHolder> worker = do_CreateInstance(kWifiWorkerCID);
NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
mWifiWorker = worker;
return NS_OK;
}
+nsresult
+SystemWorkerManager::InitBluetooth(JSContext *cx)
+{
+ // nsCOMPtr<nsIWorkerHolder> worker = do_CreateInstance(kWifiWorkerCID);
+ // NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
+
+ // mWifiWorker = worker;
+#ifdef MOZ_B2G_BT
+ StartDBus();
+#endif
+ return NS_OK;
+}
+
NS_IMPL_ISUPPORTS2(SystemWorkerManager, nsIObserver, nsIInterfaceRequestor)
NS_IMETHODIMP
SystemWorkerManager::Observe(nsISupports *aSubject, const char *aTopic,
const PRUnichar *aData)
{
if (!strcmp(aTopic, WORKERS_SHUTDOWN_TOPIC)) {
Shutdown();
--- a/dom/system/gonk/SystemWorkerManager.h
+++ b/dom/system/gonk/SystemWorkerManager.h
@@ -73,17 +73,18 @@ public:
GetInterfaceRequestor();
private:
SystemWorkerManager();
~SystemWorkerManager();
nsresult InitRIL(JSContext *cx);
nsresult InitWifi(JSContext *cx);
-
+ nsresult InitBluetooth(JSContext *cx);
+
nsCOMPtr<nsIWorkerHolder> mRILWorker;
nsCOMPtr<nsIWorkerHolder> mWifiWorker;
bool mShutdown;
};
}
}
--- a/ipc/Makefile.in
+++ b/ipc/Makefile.in
@@ -42,11 +42,15 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS += chromium glue ipdl testshell
ifdef MOZ_B2G_RIL #{
DIRS += ril
endif #}
+ifdef MOZ_B2G_BT #{
+DIRS += dbus
+endif #}
+
TOOL_DIRS = app
include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/ipc/dbus/DBusThread.cpp
@@ -0,0 +1,531 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * NOTE: Due to being based on the dbus compatibility layer for
+ * android's bluetooth implementation, this file is licensed under the
+ * apache license instead of MPL.
+ *
+ */
+
+#include "DBusThread.h"
+#include "RawDBusConnection.h"
+#include "DBusUtils.h"
+
+#include <dbus/dbus.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/select.h>
+#include <sys/types.h>
+
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <poll.h>
+
+#include <list>
+
+#include "base/eintr_wrapper.h"
+#include "base/message_loop.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/Monitor.h"
+#include "mozilla/Util.h"
+#include "mozilla/FileUtils.h"
+#include "nsAutoPtr.h"
+#include "nsIThread.h"
+#include "nsXULAppAPI.h"
+
+#undef LOG
+#if defined(MOZ_WIDGET_GONK)
+#include <android/log.h>
+#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args);
+#else
+#define LOG(args...) printf(args);
+#endif
+
+#define DEFAULT_INITIAL_POLLFD_COUNT 8
+
+// Functions for converting between unix events in the poll struct,
+// and their dbus definitions
+
+// TODO Add Wakeup to this list once we've moved to ics
+
+enum {
+ DBUS_EVENT_LOOP_EXIT = 1,
+ DBUS_EVENT_LOOP_ADD = 2,
+ DBUS_EVENT_LOOP_REMOVE = 3,
+} DBusEventTypes;
+
+// Signals that the DBus thread should listen for. Needs to include
+// all signals any DBus observer object may need.
+
+static const char* DBUS_SIGNALS[] =
+{
+ "type='signal',interface='org.freedesktop.DBus'",
+ "type='signal',interface='org.bluez.Adapter'",
+ "type='signal',interface='org.bluez.Device'",
+ "type='signal',interface='org.bluez.Input'",
+ "type='signal',interface='org.bluez.Network'",
+ "type='signal',interface='org.bluez.NetworkServer'",
+ "type='signal',interface='org.bluez.HealthDevice'",
+ "type='signal',interface='org.bluez.AudioSink'"
+};
+
+static unsigned int UnixEventsToDBusFlags(short events)
+{
+ return (events & DBUS_WATCH_READABLE ? POLLIN : 0) |
+ (events & DBUS_WATCH_WRITABLE ? POLLOUT : 0) |
+ (events & DBUS_WATCH_ERROR ? POLLERR : 0) |
+ (events & DBUS_WATCH_HANGUP ? POLLHUP : 0);
+}
+
+static short DBusFlagsToUnixEvents(unsigned int flags)
+{
+ return (flags & POLLIN ? DBUS_WATCH_READABLE : 0) |
+ (flags & POLLOUT ? DBUS_WATCH_WRITABLE : 0) |
+ (flags & POLLERR ? DBUS_WATCH_ERROR : 0) |
+ (flags & POLLHUP ? DBUS_WATCH_HANGUP : 0);
+}
+
+namespace mozilla {
+namespace ipc {
+
+struct PollFdComparator {
+ bool Equals(const pollfd& a, const pollfd& b) const {
+ return ((a.fd == b.fd) &&
+ (a.events == b.events));
+ }
+ bool LessThan(const pollfd& a, const pollfd&b) const {
+ return false;
+ }
+};
+
+// DBus Thread Class prototype
+
+struct DBusThread : public RawDBusConnection
+{
+ DBusThread();
+ ~DBusThread();
+
+ bool StartEventLoop();
+ void StopEventLoop();
+ bool IsEventLoopRunning();
+ static void* EventLoop(void* aPtr);
+
+ // Thread members
+ pthread_t mThread;
+ Mutex mMutex;
+ bool mIsRunning;
+
+ // Information about the sockets we're polling. Socket counts
+ // increase/decrease depending on how many add/remove watch signals
+ // we're received via the control sockets.
+ nsTArray<pollfd> mPollData;
+ nsTArray<DBusWatch*> mWatchData;
+
+ // Sockets for receiving dbus control information (watch
+ // add/removes, loop shutdown, etc...)
+ ScopedClose mControlFdR;
+ ScopedClose mControlFdW;
+
+protected:
+ bool SetUpEventLoop();
+ bool TearDownData();
+ bool TearDownEventLoop();
+};
+
+static nsAutoPtr<DBusThread> sDBusThread;
+
+// DBus utility functions
+// Free statics, as they're used as function pointers in dbus setup
+
+static dbus_bool_t
+AddWatch(DBusWatch *aWatch, void *aData)
+{
+ DBusThread *dbt = (DBusThread *)aData;
+
+ if (dbus_watch_get_enabled(aWatch)) {
+ // note that we can't just send the watch and inspect it later
+ // because we may get a removeWatch call before this data is reacted
+ // to by our eventloop and remove this watch.. reading the add first
+ // and then inspecting the recently deceased watch would be bad.
+ char control = DBUS_EVENT_LOOP_ADD;
+ write(dbt->mControlFdW.mFd, &control, sizeof(char));
+
+ // TODO change this to dbus_watch_get_unix_fd once we move to ics
+ int fd = dbus_watch_get_fd(aWatch);
+ write(dbt->mControlFdW.mFd, &fd, sizeof(int));
+
+ unsigned int flags = dbus_watch_get_flags(aWatch);
+ write(dbt->mControlFdW.mFd, &flags, sizeof(unsigned int));
+
+ write(dbt->mControlFdW.mFd, &aWatch, sizeof(DBusWatch*));
+ }
+ return true;
+}
+
+static void
+RemoveWatch(DBusWatch *aWatch, void *aData)
+{
+ DBusThread *dbt = (DBusThread *)aData;
+
+ char control = DBUS_EVENT_LOOP_REMOVE;
+ write(dbt->mControlFdW.mFd, &control, sizeof(char));
+
+ // TODO change this to dbus_watch_get_unix_fd once we move to ics
+ int fd = dbus_watch_get_fd(aWatch);
+ write(dbt->mControlFdW.mFd, &fd, sizeof(int));
+
+ unsigned int flags = dbus_watch_get_flags(aWatch);
+ write(dbt->mControlFdW.mFd, &flags, sizeof(unsigned int));
+}
+
+static void
+ToggleWatch(DBusWatch *aWatch, void *aData)
+{
+ if (dbus_watch_get_enabled(aWatch)) {
+ AddWatch(aWatch, aData);
+ } else {
+ RemoveWatch(aWatch, aData);
+ }
+}
+
+static void
+HandleWatchAdd(DBusThread* aDbt)
+{
+ DBusWatch *watch;
+ int newFD;
+ unsigned int flags;
+ read(aDbt->mControlFdR.mFd, &newFD, sizeof(int));
+ read(aDbt->mControlFdR.mFd, &flags, sizeof(unsigned int));
+ read(aDbt->mControlFdR.mFd, &watch, sizeof(DBusWatch *));
+ short events = DBusFlagsToUnixEvents(flags);
+
+ pollfd p;
+ p.fd = newFD;
+ p.revents = 0;
+ p.events = events;
+ if(aDbt->mPollData.Contains(p, PollFdComparator())) return;
+ aDbt->mPollData.AppendElement(p);
+ aDbt->mWatchData.AppendElement(watch);
+}
+
+static void HandleWatchRemove(DBusThread* aDbt) {
+ int removeFD;
+ unsigned int flags;
+
+ read(aDbt->mControlFdR.mFd, &removeFD, sizeof(int));
+ read(aDbt->mControlFdR.mFd, &flags, sizeof(unsigned int));
+ short events = DBusFlagsToUnixEvents(flags);
+ pollfd p;
+ p.fd = removeFD;
+ p.events = events;
+ int index = aDbt->mPollData.IndexOf(p, 0, PollFdComparator());
+ aDbt->mPollData.RemoveElementAt(index);
+
+ // DBusWatch pointers are maintained by DBus, so we won't leak by
+ // removing.
+ aDbt->mWatchData.RemoveElementAt(index);
+}
+
+// Called by dbus during WaitForAndDispatchEventNative()
+static DBusHandlerResult
+EventFilter(DBusConnection *aConn, DBusMessage *aMsg,
+ void *aData)
+{
+ DBusError err;
+
+ dbus_error_init(&err);
+
+ if (dbus_message_get_type(aMsg) != DBUS_MESSAGE_TYPE_SIGNAL) {
+ LOG("%s: not interested (not a signal).\n", __FUNCTION__);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ LOG("%s: Received signal %s:%s from %s\n", __FUNCTION__,
+ dbus_message_get_interface(aMsg), dbus_message_get_member(aMsg),
+ dbus_message_get_path(aMsg));
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+// DBus Thread Implementation
+
+DBusThread::DBusThread() : mMutex("DBusGonk.mMutex")
+ , mIsRunning(false)
+ , mControlFdR(-1)
+ , mControlFdW(-1)
+{
+}
+
+DBusThread::~DBusThread()
+{
+
+}
+
+bool
+DBusThread::SetUpEventLoop()
+{
+ // If we already have a connection, exit
+ if(mConnection) {
+ return false;
+ }
+ // If we can't establish a connection to dbus, nothing else will work
+ if(!Create()) {
+ return false;
+ }
+
+ dbus_threads_init_default();
+ DBusError err;
+ dbus_error_init(&err);
+
+ // Add a filter for all incoming messages_base
+ if (!dbus_connection_add_filter(mConnection, EventFilter, this, NULL)){
+ return false;
+ }
+
+ // Set which messages will be processed by this dbus connection.
+ // Since we are maintaining a single thread for all the DBus bluez
+ // signals we want, register all of them in this thread at startup.
+ // The event handler will sort the destinations out as needed.
+ for(uint32_t i = 0; i < ArrayLength(DBUS_SIGNALS); ++i) {
+ dbus_bus_add_match(mConnection,
+ DBUS_SIGNALS[i],
+ &err);
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+DBusThread::TearDownData()
+{
+ if (mControlFdW.mFd) {
+ close(mControlFdW.mFd);
+ mControlFdW.mFd = 0;
+ }
+ if (mControlFdR.mFd) {
+ close(mControlFdR.mFd);
+ mControlFdR.mFd = 0;
+ }
+ mPollData.Clear();
+
+ // DBusWatch pointers are maintained by DBus, so we won't leak by
+ // clearing.
+ mWatchData.Clear();
+ return true;
+}
+
+bool
+DBusThread::TearDownEventLoop()
+{
+ MOZ_ASSERT(mConnection);
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ for(uint32_t i = 0; i < ArrayLength(DBUS_SIGNALS); ++i) {
+ dbus_bus_remove_match(mConnection,
+ DBUS_SIGNALS[i],
+ &err);
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ }
+
+ dbus_connection_remove_filter(mConnection, EventFilter, this);
+ return true;
+}
+
+void*
+DBusThread::EventLoop(void *aPtr)
+{
+ DBusThread* dbt = static_cast<DBusThread*>(aPtr);
+ MOZ_ASSERT(dbt);
+
+ dbus_connection_set_watch_functions(dbt->mConnection, AddWatch,
+ RemoveWatch, ToggleWatch, aPtr, NULL);
+
+ dbt->mIsRunning = true;
+
+ while (1) {
+ poll(dbt->mPollData.Elements(), dbt->mPollData.Length(), -1);
+
+ for (uint32_t i = 0; i < dbt->mPollData.Length(); i++) {
+ if (!dbt->mPollData[i].revents) {
+ continue;
+ }
+
+ if (dbt->mPollData[i].fd == dbt->mControlFdR.mFd) {
+ char data;
+ while (recv(dbt->mControlFdR.mFd, &data, sizeof(char), MSG_DONTWAIT)
+ != -1) {
+ switch (data) {
+ case DBUS_EVENT_LOOP_EXIT:
+ {
+ dbus_connection_set_watch_functions(dbt->mConnection,
+ NULL, NULL, NULL, NULL, NULL);
+ dbt->TearDownEventLoop();
+ return NULL;
+ }
+ case DBUS_EVENT_LOOP_ADD:
+ {
+ HandleWatchAdd(dbt);
+ break;
+ }
+ case DBUS_EVENT_LOOP_REMOVE:
+ {
+ HandleWatchRemove(dbt);
+ break;
+ }
+ }
+ }
+ } else {
+ short events = dbt->mPollData[i].revents;
+ unsigned int flags = UnixEventsToDBusFlags(events);
+ dbus_watch_handle(dbt->mWatchData[i], flags);
+ dbt->mPollData[i].revents = 0;
+ // Break at this point since we don't know if the operation
+ // was destructive
+ break;
+ }
+ }
+ while (dbus_connection_dispatch(dbt->mConnection) ==
+ DBUS_DISPATCH_DATA_REMAINS)
+ {}
+ }
+}
+
+bool
+DBusThread::StartEventLoop()
+{
+ MutexAutoLock lock(mMutex);
+ mIsRunning = false;
+ if (socketpair(AF_LOCAL, SOCK_STREAM, 0, &(mControlFdR.mFd))) {
+ TearDownData();
+ return false;
+ }
+ pollfd p;
+ p.fd = mControlFdR.mFd;
+ p.events = POLLIN;
+ mPollData.AppendElement(p);
+ // Due to the fact that mPollData and mWatchData have to match, we
+ // push a null to the front of mWatchData since it has the control
+ // fd in the first slot of mPollData.
+ mWatchData.AppendElement((DBusWatch*)NULL);
+ if (SetUpEventLoop() != true) {
+ TearDownData();
+ return false;
+ }
+ pthread_create(&(mThread), NULL, DBusThread::EventLoop, this);
+ return true;
+}
+
+void
+DBusThread::StopEventLoop()
+{
+ MutexAutoLock lock(mMutex);
+ if (mIsRunning) {
+ char data = DBUS_EVENT_LOOP_EXIT;
+ write(mControlFdW.mFd, &data, sizeof(char));
+ void *ret;
+ pthread_join(mThread, &ret);
+ TearDownData();
+ }
+ mIsRunning = false;
+}
+
+bool
+DBusThread::IsEventLoopRunning()
+{
+ MutexAutoLock lock(mMutex);
+ return mIsRunning;
+}
+
+// Startup/Shutdown utility functions
+
+static void
+ConnectDBus(Monitor* aMonitor, bool* aSuccess)
+{
+ MOZ_ASSERT(!sDBusThread);
+
+ sDBusThread = new DBusThread();
+ *aSuccess = true;
+ if(!sDBusThread->StartEventLoop())
+ {
+ *aSuccess = false;
+ }
+ {
+ MonitorAutoLock lock(*aMonitor);
+ lock.Notify();
+ }
+}
+
+static void
+DisconnectDBus(Monitor* aMonitor, bool* aSuccess)
+{
+ MOZ_ASSERT(sDBusThread);
+
+ *aSuccess = true;
+ sDBusThread->StopEventLoop();
+ sDBusThread = NULL;
+ {
+ MonitorAutoLock lock(*aMonitor);
+ lock.Notify();
+ }
+}
+
+bool
+StartDBus()
+{
+ Monitor monitor("StartDBus.monitor");
+ bool success;
+ {
+ MonitorAutoLock lock(monitor);
+
+ XRE_GetIOMessageLoop()->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(ConnectDBus, &monitor, &success));
+ lock.Wait();
+ }
+ return success;
+}
+
+bool
+StopDBus()
+{
+ Monitor monitor("StopDBus.monitor");
+ bool success;
+ {
+ MonitorAutoLock lock(monitor);
+
+ XRE_GetIOMessageLoop()->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(DisconnectDBus, &monitor, &success));
+ lock.Wait();
+ }
+ return success;
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/ipc/dbus/DBusThread.h
@@ -0,0 +1,25 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_ipc_dbus_gonk_dbusthread_h__
+#define mozilla_ipc_dbus_gonk_dbusthread_h__
+
+namespace mozilla {
+namespace ipc {
+
+
+// Starts the DBus thread, which handles returning signals to objects
+// that call asynchronous functions. This should be called from the
+// main thread at startup.
+bool StartDBus();
+
+// Stop the DBus thread, assuming it's currently running. Should be
+// called from main thread.
+bool StopDBus();
+}
+}
+#endif
+
new file mode 100644
--- /dev/null
+++ b/ipc/dbus/DBusUtils.cpp
@@ -0,0 +1,47 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
+/*
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdio.h>
+#include "dbus/dbus.h"
+
+#undef LOG
+#if defined(MOZ_WIDGET_GONK)
+#include <android/log.h>
+#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args);
+#else
+#define LOG(args...) printf(args);
+#endif
+
+namespace mozilla {
+namespace ipc {
+
+void
+log_and_free_dbus_error(DBusError* err, const char* function, DBusMessage* msg)
+{
+ if(msg) {
+ LOG("%s: D-Bus error in %s: %s (%s)", function,
+ dbus_message_get_member((msg)), (err)->name, (err)->message);
+ } else {
+ LOG("%s: D-Bus error: %s (%s)", __FUNCTION__,
+ (err)->name, (err)->message);
+ }
+ dbus_error_free((err));
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/ipc/dbus/DBusUtils.h
@@ -0,0 +1,37 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
+/*
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef mozilla_ipc_dbus_dbusutils_h__
+#define mozilla_ipc_dbus_dbusutils_h__
+
+// LOGE and free a D-Bus error
+// Using #define so that __FUNCTION__ resolves usefully
+#define LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg) log_and_free_dbus_error(err, __FUNCTION__, msg);
+#define LOG_AND_FREE_DBUS_ERROR(err) log_and_free_dbus_error(err, __FUNCTION__);
+
+struct DBusMessage;
+struct DBusError;
+
+namespace mozilla {
+namespace ipc {
+void log_and_free_dbus_error(DBusError* err, const char* function, DBusMessage* msg = NULL);
+}
+}
+
+#endif
+
new file mode 100644
--- /dev/null
+++ b/ipc/dbus/Makefile.in
@@ -0,0 +1,44 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipc
+LIBRARY_NAME = mozdbus_s
+FORCE_STATIC_LIB = 1
+LIBXUL_LIBRARY = 1
+EXPORT_LIBRARY = 1
+
+ifdef MOZ_ENABLE_DBUS
+ LOCAL_INCLUDES += $(MOZ_DBUS_CFLAGS)
+endif
+
+EXPORTS_NAMESPACES = mozilla/ipc
+
+EXPORTS_mozilla/ipc = \
+ RawDBusConnection.h \
+ DBusThread.h \
+ DBusUtils.h \
+ $(NULL)
+
+CPPSRCS += \
+ RawDBusConnection.cpp \
+ DBusThread.cpp \
+ DBusUtils.cpp \
+ $(NULL)
+
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+
+include $(topsrcdir)/config/rules.mk
+
+ifdef MOZ_ENABLE_DBUS
+ CFLAGS += $(MOZ_DBUS_GLIB_CFLAGS)
+ CXXFLAGS += $(MOZ_DBUS_GLIB_CFLAGS)
+endif
new file mode 100644
--- /dev/null
+++ b/ipc/dbus/RawDBusConnection.cpp
@@ -0,0 +1,30 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "RawDBusConnection.h"
+#include <dbus/dbus.h>
+
+using namespace mozilla::ipc;
+
+RawDBusConnection::RawDBusConnection() {
+}
+
+RawDBusConnection::~RawDBusConnection() {
+}
+
+bool RawDBusConnection::Create() {
+ DBusError err;
+ dbus_error_init(&err);
+ dbus_threads_init_default();
+ mConnection = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+ if (dbus_error_is_set(&err)) {
+ dbus_error_free(&err);
+ return false;
+ }
+ dbus_connection_set_exit_on_disconnect(mConnection, FALSE);
+ return true;
+}
+
new file mode 100644
--- /dev/null
+++ b/ipc/dbus/RawDBusConnection.h
@@ -0,0 +1,41 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_ipc_dbus_gonk_rawdbusconnection_h__
+#define mozilla_ipc_dbus_gonk_rawdbusconnection_h__
+
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string>
+#include <stdlib.h>
+#include "mozilla/Scoped.h"
+#include "dbus/dbus.h"
+
+struct DBusConnection;
+
+namespace mozilla {
+namespace ipc {
+
+class RawDBusConnection
+{
+ struct ScopedDBusConnectionPtrTraits : ScopedFreePtrTraits<DBusConnection>
+ {
+ static void release(DBusConnection* ptr) { dbus_connection_unref(ptr); }
+ };
+
+public:
+ RawDBusConnection();
+ ~RawDBusConnection();
+ bool Create();
+protected:
+ Scoped<ScopedDBusConnectionPtrTraits> mConnection;
+};
+
+}
+}
+
+#endif
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -110,16 +110,20 @@ STATIC_LIBS += \
hal_s \
dombindings_s \
$(NULL)
ifdef MOZ_B2G_RIL #{
STATIC_LIBS += mozril_s
endif #}
+ifdef MOZ_B2G_BT #{
+STATIC_LIBS += mozdbus_s
+endif #}
+
ifdef MOZ_IPDL_TESTS
STATIC_LIBS += ipdlunittest_s
endif
ifeq (Linux,$(OS_ARCH))
ifneq (Android,$(OS_TARGET))
OS_LIBS += -lrt
endif
@@ -393,16 +397,17 @@ OS_LIBS += \
-lmedia \
-lhardware_legacy \
-lhardware \
-lutils \
-lcutils \
-lcamera_client \
-lbinder \
-lsensorservice \
+ -ldbus \
$(NULL)
endif
EXTRA_DEPS += \
$(topsrcdir)/intl/unicharutil/util/objs.mk \
$(topsrcdir)/rdf/util/src/objs.mk \
$(NULL)