author | Kyle Machulis <kmachulis@mozilla.com> |
Wed, 07 Dec 2011 18:58:56 +0800 | |
changeset 82162 | c160a02d2d2a87266944c390fc70f2504e1a612d |
parent 82161 | e487df6617edf52b63cb50376fb44ca6b3063b47 |
child 82163 | 4f9095c87c188adc4127229f6344445a06cdd887 |
push id | 21584 |
push user | mbrubeck@mozilla.com |
push date | Wed, 07 Dec 2011 20:15:44 +0000 |
treeherder | mozilla-central@7ab478082ca7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | cjones |
bugs | 699222 |
milestone | 11.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
dom/system/b2g/RadioManager.cpp | file | annotate | diff | comparison | revisions | |
ipc/Makefile.in | file | annotate | diff | comparison | revisions | |
ipc/ril/Makefile.in | file | annotate | diff | comparison | revisions | |
ipc/ril/Ril.cpp | file | annotate | diff | comparison | revisions | |
ipc/ril/Ril.h | file | annotate | diff | comparison | revisions | |
toolkit/library/Makefile.in | file | annotate | diff | comparison | revisions |
--- a/dom/system/b2g/RadioManager.cpp +++ b/dom/system/b2g/RadioManager.cpp @@ -83,17 +83,17 @@ PostToRIL(JSContext *cx, uintN argc, jsv if (argc != 1) { JS_ReportError(cx, "Expecting a single argument with the RIL message"); return false; } jsval v = JS_ARGV(cx, vp)[0]; - nsAutoPtr<RilMessage> rm(new RilMessage()); + nsAutoPtr<RilRawData> rm(new RilRawData()); JSAutoByteString abs; void *data; size_t size; if (JSVAL_IS_STRING(v)) { JSString *str = JSVAL_TO_STRING(v); if (!abs.encode(cx, str)) { return false; } @@ -118,26 +118,26 @@ PostToRIL(JSContext *cx, uintN argc, jsv size = JS_GetTypedArrayByteLength(obj); data = JS_GetTypedArrayData(obj); } else { JS_ReportError(cx, "Incorrect argument. Expecting a string or a typed array"); return false; } - if (size > RilMessage::DATA_SIZE) { + if (size > RilRawData::MAX_DATA_SIZE) { JS_ReportError(cx, "Passed-in data is too large"); return false; } rm->mSize = size; memcpy(rm->mData, data, size); - RilMessage *tosend = rm.forget(); - JS_ALWAYS_TRUE(SendRilMessage(&tosend)); + RilRawData *tosend = rm.forget(); + JS_ALWAYS_TRUE(SendRilRawData(&tosend)); return true; } bool ConnectWorkerToRIL::RunTask(JSContext *aCx) { // Set up the postRILMessage on the function for worker -> RIL thread // communication. @@ -147,32 +147,32 @@ ConnectWorkerToRIL::RunTask(JSContext *a return JS_DefineFunction(aCx, workerGlobal, "postRILMessage", PostToRIL, 1, 0); } class RILReceiver : public RilConsumer { class DispatchRILEvent : public WorkerTask { public: - DispatchRILEvent(RilMessage *aMessage) + DispatchRILEvent(RilRawData *aMessage) : mMessage(aMessage) { } virtual bool RunTask(JSContext *aCx); private: - nsAutoPtr<RilMessage> mMessage; + nsAutoPtr<RilRawData> mMessage; }; public: RILReceiver(WorkerCrossThreadDispatcher *aDispatcher) : mDispatcher(aDispatcher) { } - virtual void MessageReceived(RilMessage *aMessage) { + virtual void MessageReceived(RilRawData *aMessage) { nsRefPtr<DispatchRILEvent> dre(new DispatchRILEvent(aMessage)); mDispatcher->PostTask(dre); } private: nsRefPtr<WorkerCrossThreadDispatcher> mDispatcher; };
--- a/ipc/Makefile.in +++ b/ipc/Makefile.in @@ -38,11 +38,15 @@ DEPTH = .. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk DIRS += chromium glue ipdl testshell +ifdef MOZ_B2G_RIL #{ +DIRS += ril +endif #} + TOOL_DIRS = app include $(topsrcdir)/config/rules.mk
new file mode 100644 --- /dev/null +++ b/ipc/ril/Makefile.in @@ -0,0 +1,65 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (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.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Mozilla IPC. +# +# The Initial Developer of the Original Code is +# The Mozilla Foundation +# Portions created by the Initial Developer are Copyright (C) 2009 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Chris Jones <jones.chris.g@gmail.com> +# Kyle Machulis <kyle@nonpolynomial.com> +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = ipc +LIBRARY_NAME = mozril_s +FORCE_STATIC_LIB = 1 +LIBXUL_LIBRARY = 1 +EXPORT_LIBRARY = 1 + +EXPORTS_NAMESPACES = mozilla/ipc + +EXPORTS_mozilla/ipc = \ + Ril.h \ + $(NULL) + +CPPSRCS += \ + Ril.cpp \ + $(NULL) + +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk + +include $(topsrcdir)/config/rules.mk
new file mode 100644 --- /dev/null +++ b/ipc/ril/Ril.cpp @@ -0,0 +1,359 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set sw=4 ts=8 et ft=cpp: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Code. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones <jones.chris.g@gmail.com> + * Kyle Machulis <kyle@nonpolynomial.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include <fcntl.h> +#include <unistd.h> + +#include <queue> + +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/select.h> +#include <sys/types.h> + +#include "base/eintr_wrapper.h" +#include "base/message_loop.h" +#include "mozilla/FileUtils.h" +#include "mozilla/Monitor.h" +#include "mozilla/Util.h" +#include "nsAutoPtr.h" +#include "nsIThread.h" +#include "nsXULAppAPI.h" +#include "Ril.h" + +#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 + +using namespace base; +using namespace std; + +namespace mozilla { +namespace ipc { + +struct RilClient : public RefCounted<RilClient>, + public MessageLoopForIO::Watcher + +{ + typedef queue<RilRawData*> RilRawDataQueue; + + RilClient() : mSocket(-1) + , mMutex("RilClient.mMutex") + , mBlockedOnWrite(false) + , mCurrentRilRawData(NULL) + { } + virtual ~RilClient() { } + + bool OpenSocket(); + + virtual void OnFileCanReadWithoutBlocking(int fd); + virtual void OnFileCanWriteWithoutBlocking(int fd); + + ScopedClose mSocket; + MessageLoopForIO::FileDescriptorWatcher mReadWatcher; + MessageLoopForIO::FileDescriptorWatcher mWriteWatcher; + nsAutoPtr<RilRawData> mIncoming; + Mutex mMutex; + RilRawDataQueue mOutgoingQ; + bool mBlockedOnWrite; + MessageLoopForIO* mIOLoop; + nsAutoPtr<RilRawData> mCurrentRilRawData; + size_t mCurrentWriteOffset; +}; + +static RefPtr<RilClient> sClient; +static RefPtr<RilConsumer> sConsumer; + +//----------------------------------------------------------------------------- +// This code runs on the IO thread. +// + +class RilWriteTask : public Task { + virtual void Run(); +}; + +void RilWriteTask::Run() { + sClient->OnFileCanWriteWithoutBlocking(sClient->mSocket.mFd); +} + +static void +ConnectToRil(Monitor* aMonitor, bool* aSuccess) +{ + MOZ_ASSERT(!sClient); + + sClient = new RilClient(); + if (!(*aSuccess = sClient->OpenSocket())) { + sClient = nsnull; + } + + { + MonitorAutoLock lock(*aMonitor); + lock.Notify(); + } + // aMonitor may have gone out of scope by now, don't touch it +} + +bool +RilClient::OpenSocket() +{ +#if defined(MOZ_WIDGET_GONK) + // Using a network socket to test basic functionality + // before we see how this works on the phone. + struct sockaddr_un addr; + socklen_t alen; + size_t namelen; + int err; + memset(&addr, 0, sizeof(addr)); + strcpy(addr.sun_path, "/dev/socket/rilb2g"); + addr.sun_family = AF_LOCAL; + mSocket.mFd = socket(AF_LOCAL, SOCK_STREAM, 0); + alen = strlen("/dev/socket/rilb2g") + offsetof(struct sockaddr_un, sun_path) + 1; +#else + struct hostent *hp; + struct sockaddr_in addr; + socklen_t alen; + + hp = gethostbyname("localhost"); + if (hp == 0) return -1; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = hp->h_addrtype; + addr.sin_port = htons(6200); + memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); + mSocket.mFd = socket(hp->h_addrtype, SOCK_STREAM, 0); + alen = sizeof(addr); +#endif + + if (mSocket.mFd < 0) { + LOG("Cannot create socket for RIL!\n"); + return -1; + } + + if (connect(mSocket.mFd, (struct sockaddr *) &addr, alen) < 0) { + LOG("Cannot open socket for RIL!\n"); + close(mSocket.mFd); + return false; + } + LOG("Socket open for RIL\n"); + + // Set close-on-exec bit. + int flags = fcntl(mSocket.mFd, F_GETFD); + if (-1 == flags) { + return false; + } + + flags |= FD_CLOEXEC; + if (-1 == fcntl(mSocket.mFd, F_SETFD, flags)) { + return false; + } + + // Select non-blocking IO. + if (-1 == fcntl(mSocket.mFd, F_SETFL, O_NONBLOCK)) { + return false; + } + mIOLoop = MessageLoopForIO::current(); + if (!mIOLoop->WatchFileDescriptor(mSocket.mFd, + true, + MessageLoopForIO::WATCH_READ, + &mReadWatcher, + this)) { + return false; + } + return true; +} + +void +RilClient::OnFileCanReadWithoutBlocking(int fd) +{ + // Keep reading data until either + // + // - mIncoming is completely read + // If so, sConsumer->MessageReceived(mIncoming.forget()) + // + // - mIncoming isn't completely read, but there's no more + // data available on the socket + // If so, break; + + MOZ_ASSERT(fd == mSocket.mFd); + while (true) { + if (!mIncoming) { + mIncoming = new RilRawData(); + int ret = read(fd, mIncoming->mData, 1024); + if (ret <= 0) { + LOG("Cannot read from network, error %d\n", ret); + return; + } + mIncoming->mSize = ret; + sConsumer->MessageReceived(mIncoming.forget()); + if (ret < 1024) { + return; + } + } + } +} + +void +RilClient::OnFileCanWriteWithoutBlocking(int fd) +{ + // Try to write the bytes of mCurrentRilRawData. If all were written, continue. + // + // Otherwise, save the byte position of the next byte to write + // within mCurrentRilRawData, and request another write when the + // system won't block. + // + + MOZ_ASSERT(fd == mSocket.mFd); + + while (!mOutgoingQ.empty() || mCurrentRilRawData != NULL) { + if(!mCurrentRilRawData) { + mCurrentRilRawData = mOutgoingQ.front(); + mOutgoingQ.pop(); + mCurrentWriteOffset = 0; + } + const uint8_t *toWrite; + + toWrite = mCurrentRilRawData->mData; + + while (mCurrentWriteOffset < mCurrentRilRawData->mSize) { + ssize_t write_amount = mCurrentRilRawData->mSize - mCurrentWriteOffset; + ssize_t written; + written = write (fd, toWrite + mCurrentWriteOffset, + write_amount); + if(written > 0) { + mCurrentWriteOffset += written; + } + if (written != write_amount) { + break; + } + } + + if(mCurrentWriteOffset != mCurrentRilRawData->mSize) { + MessageLoopForIO::current()->WatchFileDescriptor( + fd, + false, + MessageLoopForIO::WATCH_WRITE, + &mWriteWatcher, + this); + return; + } + mCurrentRilRawData = NULL; + } +} + + +static void +DisconnectFromRil(Monitor* aMonitor) +{ + // XXX This might "strand" messages in the outgoing queue. We'll + // assume that's OK for now. + sClient = nsnull; + { + MonitorAutoLock lock(*aMonitor); + lock.Notify(); + } +} + +//----------------------------------------------------------------------------- +// This code runs on any thread. +// + +bool +StartRil(RilConsumer* aConsumer) +{ + MOZ_ASSERT(aConsumer); + sConsumer = aConsumer; + + Monitor monitor("StartRil.monitor"); + bool success; + { + MonitorAutoLock lock(monitor); + + XRE_GetIOMessageLoop()->PostTask( + FROM_HERE, + NewRunnableFunction(ConnectToRil, &monitor, &success)); + + lock.Wait(); + } + + return success; +} + +bool +SendRilRawData(RilRawData** aMessage) +{ + if (!sClient) { + return false; + } + + RilRawData *msg = *aMessage; + *aMessage = nsnull; + + { + MutexAutoLock lock(sClient->mMutex); + sClient->mOutgoingQ.push(msg); + } + sClient->mIOLoop->PostTask(FROM_HERE, new RilWriteTask()); + + return true; +} + +void +StopRil() +{ + Monitor monitor("StopRil.monitor"); + { + MonitorAutoLock lock(monitor); + + XRE_GetIOMessageLoop()->PostTask( + FROM_HERE, + NewRunnableFunction(DisconnectFromRil, &monitor)); + + lock.Wait(); + } + + sConsumer = nsnull; +} + + +} // namespace ipc +} // namespace mozilla
new file mode 100644 --- /dev/null +++ b/ipc/ril/Ril.h @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Code. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones <jones.chris.g@gmail.com> + * Kyle Machulis <kyle@nonpolynomial.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef mozilla_ipc_Ril_h +#define mozilla_ipc_Ril_h 1 + +#include "mozilla/RefPtr.h" + +namespace base { +class MessageLoop; +} + +class nsIThread; + +namespace mozilla { +namespace ipc { + + +/* + * Represents raw data going to or coming from the RIL socket. Can + * actually contain multiple RIL parcels in the data block, and may + * also contain incomplete parcels on the front or back. Actual parcel + * construction is handled in the worker thread. + */ +struct RilRawData +{ + static const size_t MAX_DATA_SIZE = 1024; + uint8_t mData[MAX_DATA_SIZE]; + + // Number of octets in mData. + size_t mSize; +}; + +class RilConsumer : public RefCounted<RilConsumer> +{ +public: + virtual ~RilConsumer() { } + virtual void MessageReceived(RilRawData* aMessage) { } +}; + +bool StartRil(RilConsumer* aConsumer); + +bool SendRilRawData(RilRawData** aMessage); + +void StopRil(); + +} // namespace ipc +} // namepsace mozilla + +#endif // mozilla_ipc_Ril_h
--- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -142,16 +142,20 @@ STATIC_LIBS += \ mozipc_s \ mozipdlgen_s \ ipcshell_s \ gfx2d \ gfxipc_s \ hal_s \ $(NULL) +ifdef MOZ_B2G_RIL #{ +STATIC_LIBS += mozril_s +endif #} + ifdef MOZ_IPDL_TESTS STATIC_LIBS += ipdlunittest_s endif ifeq (Linux,$(OS_ARCH)) ifneq (Android,$(OS_TARGET)) OS_LIBS += -lrt endif