Bug 574120 - Add Android support to IPC code, r=cjones
authorMichael Wu <mwu@mozilla.com>
Fri, 25 Jun 2010 11:39:02 -0700
changeset 46920 1727bfc1114752eb69fab020c3866ac3bb91ec84
parent 46919 c37e3ae2d89de2e81fdbc85e81cfbde577c93f72
child 46921 103b167938e5ffa34c6c3fbb4dead5adafab88cc
push id14210
push userdougt@mozilla.com
push dateThu, 01 Jul 2010 06:28:42 +0000
treeherdermozilla-central@3aff97777291 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs574120
milestone1.9.3a6pre
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
Bug 574120 - Add Android support to IPC code, r=cjones
ipc/chromium/Makefile.in
ipc/chromium/src/base/debug_util_posix.cc
ipc/chromium/src/base/file_util.cc
ipc/chromium/src/base/file_util.h
ipc/chromium/src/base/file_util_linux.cc
ipc/chromium/src/base/file_util_posix.cc
ipc/chromium/src/base/message_loop.cc
ipc/chromium/src/base/message_pump_android.cc
ipc/chromium/src/base/message_pump_android.h
ipc/chromium/src/base/platform_file_posix.cc
ipc/chromium/src/base/process_util_posix.cc
ipc/chromium/src/base/shared_memory_posix.cc
ipc/chromium/src/base/sys_info_posix.cc
ipc/chromium/src/base/third_party/nspr/prcpucfg.h
ipc/chromium/src/base/third_party/nspr/prtime.cc
ipc/chromium/src/base/time_posix.cc
ipc/chromium/src/build/build_config.h
ipc/chromium/src/chrome/common/file_descriptor_set_posix.cc
ipc/chromium/src/third_party/libevent/select.c
ipc/glue/GeckoChildProcessHost.cpp
ipc/glue/SharedMemorySysV.h
--- a/ipc/chromium/Makefile.in
+++ b/ipc/chromium/Makefile.in
@@ -199,16 +199,23 @@ CPPSRCS += \
   thread_local_storage_posix.cc \
   waitable_event_posix.cc \
   waitable_event_watcher_posix.cc \
   file_descriptor_set_posix.cc \
   ipc_channel_posix.cc \
   process_watcher_posix_sigchld.cc \
   $(NULL)
 
+ifeq ($(OS_TARGET),Android)
+DEFINES += -DANDROID -D_POSIX_MONOTONIC_CLOCK=0
+CPPSRCS += \
+  message_pump_android.cc \
+  $(NULL)
+endif # Android
+
 endif # } OS_POSIX
 
 ifdef OS_MACOSX # {
 
 CMMSRCS += \
   base_paths_mac.mm \
   file_util_mac.mm \
   file_version_info_mac.mm \
--- a/ipc/chromium/src/base/debug_util_posix.cc
+++ b/ipc/chromium/src/base/debug_util_posix.cc
@@ -1,23 +1,25 @@
 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "build/build_config.h"
 #include "base/debug_util.h"
 
 #include <errno.h>
-#include <execinfo.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <sys/stat.h>
-#include <sys/sysctl.h>
 #include <sys/types.h>
 #include <unistd.h>
+#ifndef ANDROID
+#include <execinfo.h>
+#include <sys/sysctl.h>
+#endif
 
 #include "base/basictypes.h"
 #include "base/eintr_wrapper.h"
 #include "base/logging.h"
 #include "base/scoped_ptr.h"
 #include "base/string_piece.h"
 
 // static
@@ -112,32 +114,38 @@ void DebugUtil::BreakDebugger() {
   asm ("int3");
 #endif
 }
 
 StackTrace::StackTrace() {
   const int kMaxCallers = 256;
 
   void* callers[kMaxCallers];
+#ifndef ANDROID
   int count = backtrace(callers, kMaxCallers);
+#else
+  int count = 0;
+#endif
 
   // Though the backtrace API man page does not list any possible negative
   // return values, we still still exclude them because they would break the
   // memcpy code below.
   if (count > 0) {
     trace_.resize(count);
     memcpy(&trace_[0], callers, sizeof(callers[0]) * count);
   } else {
     trace_.resize(0);
   }
 }
 
 void StackTrace::PrintBacktrace() {
   fflush(stderr);
+#ifndef ANDROID
   backtrace_symbols_fd(&trace_[0], trace_.size(), STDERR_FILENO);
+#endif
 }
 
 void StackTrace::OutputToStream(std::ostream* os) {
 #ifdef CHROMIUM_MOZILLA_BUILD
   return;
 #else
   scoped_ptr_malloc<char*> trace_symbols(
       backtrace_symbols(&trace_[0], trace_.size()));
--- a/ipc/chromium/src/base/file_util.cc
+++ b/ipc/chromium/src/base/file_util.cc
@@ -3,16 +3,17 @@
 // found in the LICENSE file.
 
 #include "base/file_util.h"
 
 #if defined(OS_WIN)
 #include <io.h>
 #endif
 #include <stdio.h>
+#include <unistd.h>
 
 #include <fstream>
 
 #include "base/file_path.h"
 #include "base/logging.h"
 #include "base/string_util.h"
 
 #include "base/string_piece.h"
--- a/ipc/chromium/src/base/file_util.h
+++ b/ipc/chromium/src/base/file_util.h
@@ -7,17 +7,19 @@
 
 #ifndef BASE_FILE_UTIL_H_
 #define BASE_FILE_UTIL_H_
 
 #include "build/build_config.h"
 
 #if defined(OS_WIN)
 #include <windows.h>
-#elif defined(OS_POSIX)
+#elif defined(ANDROID)
+#include <sys/stat.h>
+#elif defined(OS_POSIX) 
 #include <fts.h>
 #include <sys/stat.h>
 #endif
 
 #include <stdio.h>
 
 #include <stack>
 #include <string>
@@ -458,16 +460,18 @@ class FileEnumerator {
 
   // A stack that keeps track of which subdirectories we still need to
   // enumerate in the breadth-first search.
   std::stack<FilePath> pending_paths_;
 
 #if defined(OS_WIN)
   WIN32_FIND_DATA find_data_;
   HANDLE find_handle_;
+#elif defined(ANDROID)
+  void *fts_;
 #elif defined(OS_POSIX)
   FTS* fts_;
   FTSENT* fts_ent_;
 #endif
 
   DISALLOW_EVIL_CONSTRUCTORS(FileEnumerator);
 };
 
--- a/ipc/chromium/src/base/file_util_linux.cc
+++ b/ipc/chromium/src/base/file_util_linux.cc
@@ -20,18 +20,22 @@ bool GetTempDir(FilePath* path) {
   if (tmp)
     *path = FilePath(tmp);
   else
     *path = FilePath("/tmp");
   return true;
 }
 
 bool GetShmemTempDir(FilePath* path) {
+#ifdef ANDROID
+  return GetTempDir(path);
+#else
   *path = FilePath("/dev/shm");
   return true;
+#endif
 }
 
 bool CopyFile(const FilePath& from_path, const FilePath& to_path) {
   int infile = open(from_path.value().c_str(), O_RDONLY);
   if (infile < 0)
     return false;
 
   int outfile = creat(to_path.value().c_str(), 0666);
--- a/ipc/chromium/src/base/file_util_posix.cc
+++ b/ipc/chromium/src/base/file_util_posix.cc
@@ -3,17 +3,19 @@
 // found in the LICENSE file.
 
 #include "base/file_util.h"
 
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fnmatch.h>
+#ifndef ANDROID
 #include <fts.h>
+#endif
 #include <libgen.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/errno.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <time.h>
@@ -111,16 +113,20 @@ bool Delete(const FilePath& path, bool r
     bool ret = (errno == ENOENT || errno == ENOTDIR);
     return ret;
   }
   if (!S_ISDIR(file_info.st_mode))
     return (unlink(path_str) == 0);
   if (!recursive)
     return (rmdir(path_str) == 0);
 
+#ifdef ANDROID
+  // XXX Need ftsless impl for bionic
+  return false;
+#else
   bool success = true;
   int ftsflags = FTS_PHYSICAL | FTS_NOSTAT;
   char top_dir[PATH_MAX];
   if (base::strlcpy(top_dir, path_str,
                     arraysize(top_dir)) >= arraysize(top_dir)) {
     return false;
   }
   char* dir_list[2] = { top_dir, NULL };
@@ -150,16 +156,17 @@ bool Delete(const FilePath& path, bool r
           DCHECK(false);
           break;
       }
       fts_ent = fts_read(fts);
     }
     fts_close(fts);
   }
   return success;
+#endif
 }
 
 bool Move(const FilePath& from_path, const FilePath& to_path) {
   if (rename(from_path.value().c_str(), to_path.value().c_str()) == 0)
     return true;
 
   if (!CopyDirectory(from_path, to_path, true))
     return false;
@@ -179,16 +186,20 @@ bool CopyDirectory(const FilePath& from_
   DCHECK(from_path.value().find('*') == std::string::npos);
 
   char top_dir[PATH_MAX];
   if (base::strlcpy(top_dir, from_path.value().c_str(),
                     arraysize(top_dir)) >= arraysize(top_dir)) {
     return false;
   }
 
+#ifdef ANDROID
+  // XXX Need ftsless impl for bionic
+  return false;
+#else
   char* dir_list[] = { top_dir, NULL };
   FTS* fts = fts_open(dir_list, FTS_PHYSICAL | FTS_NOSTAT, NULL);
   if (!fts) {
     LOG(ERROR) << "fts_open failed: " << strerror(errno);
     return false;
   }
 
   int error = 0;
@@ -266,16 +277,17 @@ bool CopyDirectory(const FilePath& from_
       error = errno;
   }
 
   if (error) {
     LOG(ERROR) << "CopyDirectory(): " << strerror(error);
     return false;
   }
   return true;
+#endif
 }
 
 bool PathExists(const FilePath& path) {
   struct stat64 file_info;
   return (stat64(path.value().c_str(), &file_info) == 0);
 }
 
 bool PathIsWritable(const FilePath& path) {
@@ -397,17 +409,21 @@ bool CreateNewTempDirectory(const FilePa
                             FilePath* new_temp_path) {
   FilePath tmpdir;
   if (!GetTempDir(&tmpdir))
     return false;
   tmpdir = tmpdir.Append(kTempFileName);
   std::string tmpdir_string = tmpdir.value();
   // this should be OK since mkdtemp just replaces characters in place
   char* buffer = const_cast<char*>(tmpdir_string.c_str());
+#ifdef ANDROID
+  char* dtemp = NULL;
+#else
   char* dtemp = mkdtemp(buffer);
+#endif
   if (!dtemp)
     return false;
   *new_temp_path = FilePath(dtemp);
   return true;
 }
 
 bool CreateDirectory(const FilePath& full_path) {
   std::vector<FilePath> subpaths;
@@ -523,35 +539,42 @@ FileEnumerator::FileEnumerator(const Fil
   // The Windows version of this code only matches against items in the top-most
   // directory, and we're comparing fnmatch against full paths, so this is the
   // easiest way to get the right pattern.
   pattern_ = pattern_.Append(pattern);
   pending_paths_.push(root_path);
 }
 
 FileEnumerator::~FileEnumerator() {
+#ifndef ANDROID
   if (fts_)
     fts_close(fts_);
+#endif
 }
 
 void FileEnumerator::GetFindInfo(FindInfo* info) {
   DCHECK(info);
 
   if (!is_in_find_op_)
     return;
 
+#ifndef ANDROID
   memcpy(&(info->stat), fts_ent_->fts_statp, sizeof(info->stat));
   info->filename.assign(fts_ent_->fts_name);
+#endif
 }
 
 // As it stands, this method calls itself recursively when the next item of
 // the fts enumeration doesn't match (type, pattern, etc.).  In the case of
 // large directories with many files this can be quite deep.
 // TODO(erikkay) - get rid of this recursive pattern
 FilePath FileEnumerator::Next() {
+#ifdef ANDROID
+  return FilePath();
+#else
   if (!is_in_find_op_) {
     if (pending_paths_.empty())
       return FilePath();
 
     // The last find FindFirstFile operation is done, prepare a new one.
     root_path_ = pending_paths_.top();
     root_path_ = root_path_.StripTrailingSeparators();
     pending_paths_.pop();
@@ -595,16 +618,17 @@ FilePath FileEnumerator::Next() {
     if (!recursive_)
       fts_set(fts_, fts_ent_, FTS_SKIP);
     return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next();
   } else if (fts_ent_->fts_info == FTS_F) {
     return (file_type_ & FileEnumerator::FILES) ? cur_file : Next();
   }
   // TODO(erikkay) - verify that the other fts_info types aren't interesting
   return Next();
+#endif
 }
 
 ///////////////////////////////////////////////
 // MemoryMappedFile
 
 MemoryMappedFile::MemoryMappedFile()
     : file_(-1),
       data_(NULL),
--- a/ipc/chromium/src/base/message_loop.cc
+++ b/ipc/chromium/src/base/message_loop.cc
@@ -22,16 +22,19 @@
 #if defined(OS_LINUX)
 #ifdef MOZ_WIDGET_GTK2
 #include "base/message_pump_glib.h"
 #endif
 #ifdef MOZ_WIDGET_QT
 #include "base/message_pump_qt.h"
 #endif
 #endif
+#ifdef MOZ_WIDGET_ANDROID
+#include "base/message_pump_android.h"
+#endif
 
 #ifdef CHROMIUM_MOZILLA_BUILD
 #include "MessagePump.h"
 #endif
 
 using base::Time;
 using base::TimeDelta;
 
new file mode 100644
--- /dev/null
+++ b/ipc/chromium/src/base/message_pump_android.cc
@@ -0,0 +1,123 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_pump_android.h"
+
+#include <fcntl.h>
+#include <math.h>
+
+#include "base/eintr_wrapper.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/platform_thread.h"
+
+namespace mozilla {
+bool ProcessNextEvent();
+void NotifyEvent();
+}
+
+namespace base {
+
+MessagePumpForUI::MessagePumpForUI()
+  : pump(*this)
+{
+}
+
+MessagePumpForUI::~MessagePumpForUI() {
+}
+
+MessagePumpAndroid::MessagePumpAndroid(MessagePumpForUI &aPump)
+  : pump(aPump)
+{
+}
+
+MessagePumpAndroid::~MessagePumpAndroid()
+{
+}
+
+void MessagePumpForUI::Run(Delegate* delegate) {
+  RunState state;
+  state.delegate = delegate;
+  state.should_quit = false;
+  state.run_depth = state_ ? state_->run_depth + 1 : 1;
+  // We really only do a single task for each iteration of the loop.  If we
+  // have done something, assume there is likely something more to do.  This
+  // will mean that we don't block on the message pump until there was nothing
+  // more to do.  We also set this to true to make sure not to block on the
+  // first iteration of the loop, so RunAllPending() works correctly.
+  state.more_work_is_plausible = true;
+
+  RunState* previous_state = state_;
+  state_ = &state;
+
+  // We run our own loop instead of using g_main_loop_quit in one of the
+  // callbacks.  This is so we only quit our own loops, and we don't quit
+  // nested loops run by others.  TODO(deanm): Is this what we want?
+
+  while (!state_->should_quit) {
+    mozilla::ProcessNextEvent();
+    if (work_scheduled) {
+      work_scheduled = false;
+      HandleDispatch();
+    }
+  }
+
+  state_ = previous_state;
+}
+
+void MessagePumpForUI::HandleDispatch() {
+  // We should only ever have a single message on the wakeup pipe, since we
+  // are only signaled when the queue went from empty to non-empty.  The qApp
+  // poll will tell us whether there was data, so this read shouldn't block.
+  if (state_->should_quit)
+    return;
+
+  state_->more_work_is_plausible = false;
+
+  if (state_->delegate->DoWork())
+    state_->more_work_is_plausible = true;
+
+  if (state_->should_quit)
+    return;
+
+  if (state_->delegate->DoDelayedWork(&delayed_work_time_))
+    state_->more_work_is_plausible = true;
+  if (state_->should_quit)
+    return;
+
+  // Don't do idle work if we think there are more important things
+  // that we could be doing.
+  if (state_->more_work_is_plausible)
+    return;
+
+  if (state_->delegate->DoIdleWork())
+    state_->more_work_is_plausible = true;
+  if (state_->should_quit)
+    return;
+}
+
+void MessagePumpForUI::Quit() {
+  if (state_) {
+    state_->should_quit = true;
+  } else {
+    NOTREACHED() << "Quit called outside Run!";
+  }
+}
+
+void MessagePumpForUI::ScheduleWork() {
+  // This can be called on any thread, so we don't want to touch any state
+  // variables as we would then need locks all over.  This ensures that if
+  // we are sleeping in a poll that we will wake up.
+  work_scheduled = true;
+  mozilla::NotifyEvent();
+}
+
+void MessagePumpForUI::ScheduleDelayedWork(const Time& delayed_work_time) {
+  // We need to wake up the loop in case the poll timeout needs to be
+  // adjusted.  This will cause us to try to do work, but that's ok.
+  delayed_work_time_ = delayed_work_time;
+  ScheduleWork();
+}
+
+}  // namespace base
new file mode 100644
--- /dev/null
+++ b/ipc/chromium/src/base/message_pump_android.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MESSAGE_PUMP_ANDROID_H_
+#define BASE_MESSAGE_PUMP_ANDROID_H_
+
+#include "base/message_pump.h"
+#include "base/time.h"
+
+namespace base {
+
+class MessagePumpForUI;
+
+class MessagePumpAndroid {
+
+ public:
+  MessagePumpAndroid(MessagePumpForUI &pump);
+  ~MessagePumpAndroid();
+
+ private:
+  base::MessagePumpForUI &pump;
+};
+
+// This class implements a MessagePump needed for TYPE_UI MessageLoops on
+// Android
+class MessagePumpForUI : public MessagePump {
+
+ public:
+  MessagePumpForUI();
+  ~MessagePumpForUI();
+
+  virtual void Run(Delegate* delegate);
+  virtual void Quit();
+  virtual void ScheduleWork();
+  virtual void ScheduleDelayedWork(const Time& delayed_work_time);
+
+  // Internal methods used for processing the pump callbacks.  They are
+  // public for simplicity but should not be used directly.
+  // HandleDispatch is called after the poll has completed.
+  void HandleDispatch();
+
+ private:
+  // We may make recursive calls to Run, so we save state that needs to be
+  // separate between them in this structure type.
+  struct RunState {
+    Delegate* delegate;
+
+    // Used to flag that the current Run() invocation should return ASAP.
+    bool should_quit;
+
+    // Used to count how many Run() invocations are on the stack.
+    int run_depth;
+
+    // Used internally for controlling whether we want a message pump
+    // iteration to be blocking or not.
+    bool more_work_is_plausible;
+  };
+
+  RunState* state_;
+
+  // This is the time when we need to do delayed work.
+  Time delayed_work_time_;
+
+  bool work_scheduled;
+
+  // MessagePump implementation for Android based on the GLib implement.
+  MessagePumpAndroid pump;
+
+  DISALLOW_COPY_AND_ASSIGN(MessagePumpForUI);
+};
+
+}  // namespace base
+
+#endif  // BASE_MESSAGE_PUMP_ANDROID_H_
--- a/ipc/chromium/src/base/platform_file_posix.cc
+++ b/ipc/chromium/src/base/platform_file_posix.cc
@@ -1,16 +1,19 @@
 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/platform_file.h"
 
 #include <fcntl.h>
 #include <errno.h>
+#ifdef ANDROID
+#include <linux/stat.h>
+#endif
 
 #include "base/logging.h"
 #include "base/string_util.h"
 
 namespace base {
 
 // TODO(erikkay): does it make sense to support PLATFORM_FILE_EXCLUSIVE_* here?
 PlatformFile CreatePlatformFile(const std::wstring& name,
--- a/ipc/chromium/src/base/process_util_posix.cc
+++ b/ipc/chromium/src/base/process_util_posix.cc
@@ -92,16 +92,20 @@ class ScopedDIRClose {
   inline void operator()(DIR* x) const {
     if (x) {
       closedir(x);
     }
   }
 };
 typedef scoped_ptr_malloc<DIR, ScopedDIRClose> ScopedDIR;
 
+#ifdef ANDROID
+typedef unsigned long int rlim_t;
+#endif
+
 void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
 #if defined(OS_LINUX)
   static const rlim_t kSystemDefaultMaxFds = 8192;
   static const char fd_dir[] = "/proc/self/fd";
 #elif defined(OS_MACOSX)
   static const rlim_t kSystemDefaultMaxFds = 256;
   static const char fd_dir[] = "/dev/fd";
 #endif
--- a/ipc/chromium/src/base/shared_memory_posix.cc
+++ b/ipc/chromium/src/base/shared_memory_posix.cc
@@ -281,16 +281,49 @@ void SharedMemory::Close() {
   Unmap();
 
   if (mapped_file_ > 0) {
     close(mapped_file_);
     mapped_file_ = -1;
   }
 }
 
+#ifdef ANDROID
+void SharedMemory::LockOrUnlockCommon(int function) {
+  DCHECK(mapped_file_ >= 0);
+  struct flock lockreq;
+  lockreq.l_type = function;
+  lockreq.l_whence = SEEK_SET;
+  lockreq.l_start = 0;
+  lockreq.l_len = 0;
+  while (fcntl(mapped_file_, F_SETLKW, &lockreq) < 0) {
+    if (errno == EINTR) {
+      continue;
+    } else if (errno == ENOLCK) {
+      // temporary kernel resource exaustion
+      PlatformThread::Sleep(500);
+      continue;
+    } else {
+      NOTREACHED() << "lockf() failed."
+                   << " function:" << function
+                   << " fd:" << mapped_file_
+                   << " errno:" << errno
+                   << " msg:" << strerror(errno);
+    }
+  }
+}
+
+void SharedMemory::Lock() {
+  LockOrUnlockCommon(F_WRLCK);
+}
+
+void SharedMemory::Unlock() {
+  LockOrUnlockCommon(F_UNLCK);
+}
+#else
 void SharedMemory::LockOrUnlockCommon(int function) {
   DCHECK(mapped_file_ >= 0);
   while (lockf(mapped_file_, function, 0) < 0) {
     if (errno == EINTR) {
       continue;
     } else if (errno == ENOLCK) {
       // temporary kernel resource exaustion
       PlatformThread::Sleep(500);
@@ -307,14 +340,15 @@ void SharedMemory::LockOrUnlockCommon(in
 
 void SharedMemory::Lock() {
   LockOrUnlockCommon(F_LOCK);
 }
 
 void SharedMemory::Unlock() {
   LockOrUnlockCommon(F_ULOCK);
 }
+#endif
 
 SharedMemoryHandle SharedMemory::handle() const {
   return FileDescriptor(mapped_file_, false);
 }
 
 }  // namespace base
--- a/ipc/chromium/src/base/sys_info_posix.cc
+++ b/ipc/chromium/src/base/sys_info_posix.cc
@@ -2,17 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/sys_info.h"
 #include "base/basictypes.h"
 
 #include <errno.h>
 #include <string.h>
+#ifndef ANDROID
 #include <sys/statvfs.h>
+#endif
 #include <sys/utsname.h>
 #include <unistd.h>
 
 #if defined(OS_MACOSX)
 #include <mach/mach_host.h>
 #include <mach/mach_init.h>
 #endif
 
@@ -59,21 +61,25 @@ int64 SysInfo::AmountOfPhysicalMemory() 
   }
 
   return static_cast<int64>(pages) * page_size;
 #endif
 }
 
 // static
 int64 SysInfo::AmountOfFreeDiskSpace(const std::wstring& path) {
+#ifndef ANDROID
   struct statvfs stats;
   if (statvfs(WideToUTF8(path).c_str(), &stats) != 0) {
     return -1;
   }
   return static_cast<int64>(stats.f_bavail) * stats.f_frsize;
+#else
+  return -1;
+#endif
 }
 
 // static
 bool SysInfo::HasEnvVar(const wchar_t* var) {
   std::string var_utf8 = WideToUTF8(std::wstring(var));
   return getenv(var_utf8.c_str()) != NULL;
 }
 
--- a/ipc/chromium/src/base/third_party/nspr/prcpucfg.h
+++ b/ipc/chromium/src/base/third_party/nspr/prcpucfg.h
@@ -29,15 +29,15 @@
 
 #ifndef BASE_THIRD_PARTY_NSPR_PRCPUCFG_H__
 #define BASE_THIRD_PARTY_NSPR_PRCPUCFG_H__
 
 #if defined(WIN32)
 #include "base/third_party/nspr/prcpucfg_win.h"
 #elif defined(__APPLE__)
 #include "base/third_party/nspr/prcpucfg_mac.h"
-#elif defined(__linux__)
+#elif defined(__linux__) || defined(ANDROID)
 #include "base/third_party/nspr/prcpucfg_linux.h"
 #else
 #error Provide a prcpucfg.h appropriate for your platform
 #endif
 
 #endif  // BASE_THIRD_PARTY_NSPR_PRCPUCFG_H__
--- a/ipc/chromium/src/base/third_party/nspr/prtime.cc
+++ b/ipc/chromium/src/base/third_party/nspr/prtime.cc
@@ -78,16 +78,35 @@ namespace nspr {
 
 /* Implements the Unix localtime_r() function for windows */
 #if defined(OS_WIN)
 static void localtime_r(const time_t* secs, struct tm* time) {
   (void) localtime_s(time, secs);
 }
 #endif
 
+/* 
+ * The COUNT_LEAPS macro counts the number of leap years passed by
+ * till the start of the given year Y.  At the start of the year 4
+ * A.D. the number of leap years passed by is 0, while at the start of
+ * the year 5 A.D. this count is 1. The number of years divisible by
+ * 100 but not divisible by 400 (the non-leap years) is deducted from
+ * the count to get the correct number of leap years.
+ *
+ * The COUNT_DAYS macro counts the number of days since 01/01/01 till the
+ * start of the given year Y. The number of days at the start of the year
+ * 1 is 0 while the number of days at the start of the year 2 is 365
+ * (which is ((2)-1) * 365) and so on. The reference point is 01/01/01
+ * midnight 00:00:00.
+ */
+
+#define COUNT_LEAPS(Y)   ( ((Y)-1)/4 - ((Y)-1)/100 + ((Y)-1)/400 )
+#define COUNT_DAYS(Y)  ( ((Y)-1)*365 + COUNT_LEAPS(Y) )
+#define DAYS_BETWEEN_YEARS(A, B)  (COUNT_DAYS(B) - COUNT_DAYS(A))
+
 /*
  *------------------------------------------------------------------------
  *
  * PR_ImplodeTime --
  *
  *     Cf. time_t mktime(struct tm *tp)
  *     Note that 1 year has < 2^25 seconds.  So an PRInt32 is large enough.
  *
@@ -146,16 +165,55 @@ PR_ImplodeTime(const PRExplodedTime *exp
         CFGregorianDateGetAbsoluteTime(gregorian_date, NULL);
     PRTime result = static_cast<PRTime>(absolute_time);
     result -= exploded->tm_params.tp_gmt_offset +
               exploded->tm_params.tp_dst_offset;
     result += kCFAbsoluteTimeIntervalSince1970;  // PRTime epoch is 1970
     result *= kSecondsToMicroseconds;
     result += exploded->tm_usec;
     return result;
+#elif defined(ANDROID)
+#define LL_ADD(r, a, b)     ((r) = (a) + (b))
+#define LL_SUB(r, a, b)     ((r) = (a) - (b))
+
+    PRExplodedTime copy;
+    PRTime retVal;
+    PRInt64 secPerDay, usecPerSec;
+    PRInt64 temp;
+    PRInt64 numSecs64;
+    PRInt32 numDays;
+    PRInt32 numSecs;
+
+    /* Normalize first.  Do this on our copy */
+    copy = *exploded;
+    PR_NormalizeTime(&copy, PR_GMTParameters);
+
+    numDays = DAYS_BETWEEN_YEARS(1970, copy.tm_year);
+
+    numSecs = copy.tm_yday * 86400 + copy.tm_hour * 3600
+            + copy.tm_min * 60 + copy.tm_sec;
+
+    LL_I2L(temp, numDays);
+    LL_I2L(secPerDay, 86400);
+    LL_MUL(temp, temp, secPerDay);
+    LL_I2L(numSecs64, numSecs);
+    LL_ADD(numSecs64, numSecs64, temp);
+
+    /* apply the GMT and DST offsets */
+    LL_I2L(temp,  copy.tm_params.tp_gmt_offset);
+    LL_SUB(numSecs64, numSecs64, temp);
+    LL_I2L(temp,  copy.tm_params.tp_dst_offset);
+    LL_SUB(numSecs64, numSecs64, temp);
+
+    LL_I2L(usecPerSec, 1000000L);
+    LL_MUL(temp, numSecs64, usecPerSec);
+    LL_I2L(retVal, copy.tm_usec);
+    LL_ADD(retVal, retVal, temp);
+
+    return retVal;
 #elif defined(OS_LINUX)
     struct tm exp_tm = {0};
     exp_tm.tm_sec  = exploded->tm_sec;
     exp_tm.tm_min  = exploded->tm_min;
     exp_tm.tm_hour = exploded->tm_hour;
     exp_tm.tm_mday = exploded->tm_mday;
     exp_tm.tm_mon  = exploded->tm_month;
     exp_tm.tm_year = exploded->tm_year - 1900;
@@ -184,35 +242,16 @@ PR_ImplodeTime(const PRExplodedTime *exp
     result *= kSecondsToMicroseconds;
     result += exploded->tm_usec;
     return result;
 #else
 #error No PR_ImplodeTime implemented on your platform.
 #endif
 }
 
-/* 
- * The COUNT_LEAPS macro counts the number of leap years passed by
- * till the start of the given year Y.  At the start of the year 4
- * A.D. the number of leap years passed by is 0, while at the start of
- * the year 5 A.D. this count is 1. The number of years divisible by
- * 100 but not divisible by 400 (the non-leap years) is deducted from
- * the count to get the correct number of leap years.
- *
- * The COUNT_DAYS macro counts the number of days since 01/01/01 till the
- * start of the given year Y. The number of days at the start of the year
- * 1 is 0 while the number of days at the start of the year 2 is 365
- * (which is ((2)-1) * 365) and so on. The reference point is 01/01/01
- * midnight 00:00:00.
- */
-
-#define COUNT_LEAPS(Y)   ( ((Y)-1)/4 - ((Y)-1)/100 + ((Y)-1)/400 )
-#define COUNT_DAYS(Y)  ( ((Y)-1)*365 + COUNT_LEAPS(Y) )
-#define DAYS_BETWEEN_YEARS(A, B)  (COUNT_DAYS(B) - COUNT_DAYS(A))
-
 /*
  * Static variables used by functions in this file
  */
 
 /*
  * The following array contains the day of year for the last day of
  * each month, where index 1 is January, and day 0 is January 1.
  */
--- a/ipc/chromium/src/base/time_posix.cc
+++ b/ipc/chromium/src/base/time_posix.cc
@@ -3,17 +3,21 @@
 // found in the LICENSE file.
 
 #include "base/time.h"
 
 #ifdef OS_MACOSX
 #include <mach/mach_time.h>
 #endif
 #include <sys/time.h>
+#ifdef ANDROID
+#include <time64.h>
+#else
 #include <time.h>
+#endif
 
 #include <limits>
 
 #include "base/basictypes.h"
 #include "base/logging.h"
 
 namespace base {
 
@@ -57,20 +61,24 @@ Time Time::FromExploded(bool is_local, c
   timestruct.tm_year   = exploded.year - 1900;
   timestruct.tm_wday   = exploded.day_of_week;  // mktime/timegm ignore this
   timestruct.tm_yday   = 0;     // mktime/timegm ignore this
   timestruct.tm_isdst  = -1;    // attempt to figure it out
   timestruct.tm_gmtoff = 0;     // not a POSIX field, so mktime/timegm ignore
   timestruct.tm_zone   = NULL;  // not a POSIX field, so mktime/timegm ignore
 
   time_t seconds;
+#ifdef ANDROID
+    seconds = mktime(&timestruct);
+#else
   if (is_local)
     seconds = mktime(&timestruct);
   else
     seconds = timegm(&timestruct);
+#endif
 
   int64 milliseconds;
   // Handle overflow.  Clamping the range to what mktime and timegm might
   // return is the best that can be done here.  It's not ideal, but it's better
   // than failing here or ignoring the overflow case and treating each time
   // overflow as one second prior to the epoch.
   if (seconds == -1 &&
       (exploded.year < 1969 || exploded.year > 1970)) {
--- a/ipc/chromium/src/build/build_config.h
+++ b/ipc/chromium/src/build/build_config.h
@@ -12,17 +12,17 @@
 //    ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
 
 #ifndef BUILD_BUILD_CONFIG_H_
 #define BUILD_BUILD_CONFIG_H_
 
 // A set of macros to use for platform detection.
 #if defined(__APPLE__)
 #define OS_MACOSX 1
-#elif defined(__linux__)
+#elif defined(__linux__) || defined(ANDROID)
 #define OS_LINUX 1
 #elif defined(_WIN32)
 #define OS_WIN 1
 #else
 #error Please add support for your platform in build/build_config.h
 #endif
 
 // For access to standard POSIX features, use OS_POSIX instead of a more
--- a/ipc/chromium/src/chrome/common/file_descriptor_set_posix.cc
+++ b/ipc/chromium/src/chrome/common/file_descriptor_set_posix.cc
@@ -2,16 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "chrome/common/file_descriptor_set_posix.h"
 
 #include "base/eintr_wrapper.h"
 #include "base/logging.h"
 
+#include <unistd.h>
+
 FileDescriptorSet::FileDescriptorSet()
     : consumed_descriptor_highwater_(0) {
 }
 
 FileDescriptorSet::~FileDescriptorSet() {
   if (consumed_descriptor_highwater_ == descriptors_.size())
     return;
 
--- a/ipc/chromium/src/third_party/libevent/select.c
+++ b/ipc/chromium/src/third_party/libevent/select.c
@@ -54,16 +54,20 @@
 #include "event-internal.h"
 #include "evsignal.h"
 #include "log.h"
 
 #ifndef howmany
 #define        howmany(x, y)   (((x)+((y)-1))/(y))
 #endif
 
+#ifdef ANDROID
+typedef unsigned long int fd_mask;
+#endif
+
 struct selectop {
 	int event_fds;		/* Highest fd in fd set */
 	int event_fdsz;
 	fd_set *event_readset_in;
 	fd_set *event_writeset_in;
 	fd_set *event_readset_out;
 	fd_set *event_writeset_out;
 	struct event **event_r_by_fd;
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -50,16 +50,17 @@
 #  define XP_LINUX 1
 #endif
 #include "nsExceptionHandler.h"
 
 #include "nsDirectoryServiceDefs.h"
 #include "nsIFile.h"
 
 #include "mozilla/ipc/BrowserProcessSubThread.h"
+#include <sys/stat.h>
 
 #ifdef XP_WIN
 #include "nsIWinTaskbar.h"
 #define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
 #endif
 
 using mozilla::MonitorAutoEnter;
 using mozilla::ipc::GeckoChildProcessHost;
@@ -192,25 +193,33 @@ GeckoChildProcessHost::PerformAsyncLaunc
   nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
   nsCOMPtr<nsIFile> greDir;
   nsresult rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile), getter_AddRefs(greDir));
   if (NS_SUCCEEDED(rv)) {
     nsCString path;
     greDir->GetNativePath(path);
     exePath = FilePath(path.get());
 #ifdef OS_LINUX
+#ifdef ANDROID
+    path += "/lib";
+#endif
     newEnvVars["LD_LIBRARY_PATH"] = path.get();
 #endif
   }
   else {
     exePath = FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
     exePath = exePath.DirName();
   }
   exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_NAME);
 
+#ifdef ANDROID
+  // The java wrapper unpacks this for us but can't make it executable
+  chmod(exePath.value().c_str(), 0700);
+#endif
+
   // remap the IPC socket fd to a well-known int, as the OS does for
   // STDOUT_FILENO, for example
   int srcChannelFd, dstChannelFd;
   channel().GetClientFileDescriptorMapping(&srcChannelFd, &dstChannelFd);
   mFileMap.push_back(std::pair<int,int>(srcChannelFd, dstChannelFd));
 
   // no need for kProcessChannelID, the child process inherits the
   // other end of the socketpair() from us
--- a/ipc/glue/SharedMemorySysV.h
+++ b/ipc/glue/SharedMemorySysV.h
@@ -35,17 +35,17 @@
  * 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_SharedMemorySysV_h
 #define mozilla_ipc_SharedMemorySysV_h
 
-#ifdef OS_LINUX
+#if defined(OS_LINUX) && !defined(ANDROID)
 
 // SysV shared memory isn't available on Windows, but we define the
 // following macro so that #ifdefs are clearer (compared to #ifdef
 // OS_LINUX).
 #define MOZ_HAVE_SHAREDMEMORYSYSV
 
 #include "SharedMemory.h"