Preliminary Android port of Ceres

This change adds several of the pieces needed to build Ceres on
Android. The port is incomplete, since GFlags doesn't build which
causes the tests to not build. However, simple_bundle_adjuster
builds and runs on the phone.

Thanks to Scott Ettinger for the original version of the minimal
GLog implementation which made this port possible. The Ceres logs
go to the various Android logging levels, as documented in
miniglog/glog/logging.h.

To control the Android build, this adds a new CMake build option:

  -DBUILD_ANDROID=ON/OFF

However, users may not want to set this manually, and should
instead run the script found in android/build_android.sh. The
script calls the NDK to make a standalone toolchain, downloads the
android-cmake toolchain, then configures CMake to cross-compile
Ceres to Android.

Note: At time of writing, the android-cmake toolchain that the
script downloads from Google Code doesn't work with the latest
Jellybean NDK. It's possible to manually hack the toolchain file
to make it build by setting the compiler version and manually
setting the path to the STL includes. I don't yet have a patch
suitable for upstreaming to http://android-cmake.googlecode.com.

Change-Id: Icb615be203145e87413d6acd05883171a395499d
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c1f7b56..dc31231 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,6 +52,10 @@
        "Enable tests"
        ON)
 
+OPTION(BUILD_ANDROID
+       "Build for Android. Use build_android.sh instead of setting this."
+       OFF)
+
 # To get a more static build, try the following line on Mac and Linux:
 # SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
 
@@ -315,22 +319,29 @@
 ENDIF (${GFLAGS})
 
 # Google Logging
-MESSAGE("-- Check for Google Log")
-FIND_LIBRARY(GLOG_LIB NAMES glog PATHS ${SEARCH_LIBS})
-IF (NOT EXISTS ${GLOG_LIB})
-  MESSAGE(FATAL_ERROR
-          "Can't find Google Log. Please specify: "
-          "-DGLOG_LIB=...")
-ENDIF (NOT EXISTS ${GLOG_LIB})
-MESSAGE("-- Found Google Log library: ${GLOG_LIB}")
+IF (NOT ${BUILD_ANDROID})
+  MESSAGE("-- Check for Google Log")
+  FIND_LIBRARY(GLOG_LIB NAMES glog PATHS ${SEARCH_LIBS})
+  IF (NOT EXISTS ${GLOG_LIB})
+    MESSAGE(FATAL_ERROR
+            "Can't find Google Log. Please specify: "
+            "-DGLOG_LIB=...")
+  ENDIF (NOT EXISTS ${GLOG_LIB})
+  MESSAGE("-- Found Google Log library: ${GLOG_LIB}")
 
-FIND_PATH(GLOG_INCLUDE NAMES glog/logging.h PATHS ${SEARCH_HEADERS})
-IF (NOT EXISTS ${GLOG_INCLUDE})
-  MESSAGE(FATAL_ERROR
-          "Can't find Google Log. Please specify: "
-          "-DGLOG_INCLUDE=...")
-ENDIF (NOT EXISTS ${GLOG_INCLUDE})
-MESSAGE("-- Found Google Log header in: ${GLOG_INCLUDE}")
+  FIND_PATH(GLOG_INCLUDE NAMES glog/logging.h PATHS ${SEARCH_HEADERS})
+  IF (NOT EXISTS ${GLOG_INCLUDE})
+    MESSAGE(FATAL_ERROR
+            "Can't find Google Log. Please specify: "
+            "-DGLOG_INCLUDE=...")
+  ENDIF (NOT EXISTS ${GLOG_INCLUDE})
+  MESSAGE("-- Found Google Log header in: ${GLOG_INCLUDE}")
+ELSE (NOT ${BUILD_ANDROID})
+  SET(GLOG_LIB miniglog)
+  MESSAGE("-- Using minimal Glog substitute for Android (library): ${GLOG_LIB}")
+  SET(GLOG_INCLUDE internal/ceres/miniglog)
+  MESSAGE("-- Using minimal Glog substitute for Android (include): ${GLOG_INCLUDE}")
+ENDIF (NOT ${BUILD_ANDROID})
 
 # Eigen
 MESSAGE("-- Check for Eigen 3.0")
@@ -385,14 +396,22 @@
   ADD_DEFINITIONS(-DCERES_DONT_HAVE_PROTOCOL_BUFFERS)
 ENDIF (${PROTOBUF})
 
-IF (${UNIX})
-  # At least on linux, we need pthreads to be enabled for mutex to
-  # compile. This may not work on windows or android.
+
+# Use threads but not on Android, where there is no support for OpenMP yet.
+IF (${UNIX} AND NOT ${BUILD_ANDROID})
+  # At least on Linux, we need pthreads to be enabled for mutex to compile.
+  # This may not work on windows or android.
   FIND_PACKAGE(Threads REQUIRED)
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_THREAD_LIBS_INIT}")
   ADD_DEFINITIONS(-DCERES_HAVE_PTHREAD)
   ADD_DEFINITIONS(-DCERES_HAVE_RWLOCK)
-ENDIF (${UNIX})
+ENDIF (${UNIX} AND NOT ${BUILD_ANDROID})
+
+# Disable threads in mutex.h. Someday, after there is OpenMP support in
+# Android, this can get removed.
+IF (${BUILD_ANDROID})
+  ADD_DEFINITIONS(-DNO_THREADS)
+ENDIF (${BUILD_ANDROID})
 
 # Use the std namespace for the hash<> and related templates. This may vary by
 # system.
@@ -450,15 +469,19 @@
 
 IF (CMAKE_BUILD_TYPE STREQUAL "Release")
   IF (CMAKE_COMPILER_IS_GNUCXX)
-    # Linux
-    IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-      SET (CERES_CXX_FLAGS "${CERES_CXX_FLAGS} -march=native -mtune=native")
-    ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-
-    # Mac OS X
-    IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-      SET (CERES_CXX_FLAGS "${CERES_CXX_FLAGS} -fast -msse3")
-    ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+    IF (${BUILD_ANDROID})
+      # TODO(keir): Figure out what flags should go here to make an optimized
+      # native ARM binary for Android.
+    ELSE (${BUILD_ANDROID})
+      # Linux
+      IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+        SET (CERES_CXX_FLAGS "${CERES_CXX_FLAGS} -march=native -mtune=native")
+      ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+      # Mac OS X
+      IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+        SET (CERES_CXX_FLAGS "${CERES_CXX_FLAGS} -fast -msse3")
+      ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+    ENDIF (${BUILD_ANDROID})
   ENDIF (CMAKE_COMPILER_IS_GNUCXX)
   SET (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${CERES_CXX_FLAGS}"
        CACHE STRING "Release mode flags to the C++ Compiler" FORCE)
@@ -467,9 +490,9 @@
 # After the tweaks for the compile settings, disable some warnings on MSVC.
 IF (MSVC)
   # Disable signed/unsigned int conversion warnings.
-  ADD_DEFINITIONS( "/wd4018")
+  ADD_DEFINITIONS("/wd4018")
   # Disable warning about using struct/class for the same symobl.
-  ADD_DEFINITIONS( "/wd4099")
+  ADD_DEFINITIONS("/wd4099")
   # Disable warning about the insecurity of using "std::copy".
   ADD_DEFINITIONS("/wd4996")
   # Disable performance warning about int-to-bool conversion.
diff --git a/android/build_android.sh b/android/build_android.sh
new file mode 100644
index 0000000..5cb4383
--- /dev/null
+++ b/android/build_android.sh
@@ -0,0 +1,155 @@
+#!/bin/sh
+#
+# Ceres Solver - A fast non-linear least squares minimizer
+# Copyright 2012 Google Inc. All rights reserved.
+# http://code.google.com/p/ceres-solver/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+#   this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+#   this list of conditions and the following disclaimer in the documentation
+#   and/or other materials provided with the distribution.
+# * Neither the name of Google Inc. nor the names of its contributors may be
+#   used to endorse or promote products derived from this software without
+#   specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Author: keir@google.com
+#         settinger@google.com
+#
+# Ceres build script for Android. To build the ceres.so libraray for Android,
+# cd into an empty directory and run the script. Usage:
+#
+#   build_android.sh \
+#   <path to Android NDK> \
+#   <path to Eigen> \
+#   <path to Ceres source>
+#
+#   make
+#
+# This script exists only to make it easier to get Ceres building on Android;
+# as one can see from the code below, it is only a matter of extracting a
+# standalone NDK toolchain from the NDK, and getting the right arguments to
+# CMake to get it to work.
+#
+# Android NDK version r5 or higher is required. Jellybean does not work out of
+# the box, since the android-cmake toolchain is not yet updated to for it.
+#
+# Note: You may wish to run 'ccmake .', the CMake curses GUI, in order to tweak
+# the build parameters that are set by default. There are a few settings to
+# consider changing:
+#
+# SCHUR_SPECIALIZATIONS:
+#
+# Consider if enabling the schur specializations is a big enough win for the
+# problem you are solving, since compiling the schur specializations
+# considerably increases the binary size. Disable them by running 'ccmake .',
+# finding the SCHUR_SPECIALIZATIONS variable, hitting enter (toggling to "off"),
+# pressing 'c' to generate, then 'g' to generate and exit, followed by 'make'.
+#
+# EXECUTABLE_OUTPUT_PATH
+# LIBRARY_OUTPUT_PATH
+# LIBRARY_OUTPUT_PATH_ROOT:
+#
+# In normal CMake builds, where you do an out of source build, the source
+# directory is untouched when building. However, by default the Android CMake
+# toolchain selects locations under your *source* tree for the final library
+# and binary destinations. For example, if your Ceres git tree is under
+# ceres-solver.git/ and the build directory you are using is
+# ceres-android-bin/, the resulting binaries will live in ceres-solver.git/
+# (but not the intermediate .o files!) By changing the variables
+# EXECUTABLE_OUTPUT_PATH, LIBRARY_OUTPUT_PATH, and LIBRARY_OUTPUT_PATH_ROOT to
+# something under e.g. ceres-android-bin/ then true out-of-ource builds work.
+
+if [ $# -ne 3 ] ; then
+  echo "usage: build_android.sh \\"
+  echo "       <path to Android NDK> \\"
+  echo "       <path to Eigen> \\"
+  echo "       <path to Ceres source>"
+  exit 1
+fi
+
+if [ -f "CMakeLists.txt" ] ; then
+  echo "ERROR: Can't run from inside the source tree."
+  echo "       Make a new directory that's not under"
+  echo "       the main Ceres source tree."
+  exit 1
+fi
+
+# For some reason, using the NDK in-place doesn't work even though the
+# android-cmake toolchain appears to support it.
+#
+# TODO(keir): Figure out the issue with the stand-alone NDK and don't create
+# the extra stand-alone toolchain. Also test with other NDK versions and add
+# explicit checks to ensure a compatible version is used.
+ANDROID_NDK=$1
+MAKE_ANDROID_TOOLCHAIN=$ANDROID_NDK/build/tools/make-standalone-toolchain.sh
+if [ ! -f $MAKE_ANDROID_TOOLCHAIN ] ; then
+  echo "ERROR: First argument doesn't appear to be the NDK root; missing:"
+  echo "       $MAKE_ANDROID_TOOLCHAIN"
+  exit 1
+fi
+
+EIGEN_DIR=$2
+if [ ! -f $EIGEN_DIR/eigen3.pc.in ] ; then
+  echo "ERROR: Second argument doesn't appear to be Eigen3; missing:"
+  echo "       $EIGEN_DIR/eigen3.pc.in"
+  exit 1
+fi
+
+CERES_SOURCE_ROOT=$3
+if [ ! -f "$CERES_SOURCE_ROOT/internal/ceres/CMakeLists.txt" ] ; then
+  echo "ERROR: Third argument doesn't appear to be the Ceres source directory."
+  exit 1
+fi
+echo "Using Ceres source directory: $CERES_SOURCE_ROOT"
+
+# Make a standalone Android NDK toolchain if needed.
+export ANDROID_STANDALONE_TOOLCHAIN="`pwd`/toolchain"
+if [ ! -d "$ANDROID_STANDALONE_TOOLCHAIN" ] ; then
+  echo "Extracting the Android GCC standalone toolchain to:"
+  echo "    $ANDROID_STANDALONE_TOOLCHAIN..."
+  $ANDROID_NDK/build/tools/make-standalone-toolchain.sh \
+  --platform=android-8 \
+  --install-dir=$ANDROID_STANDALONE_TOOLCHAIN
+else
+  echo "Found NDK standalone toolchain; skipping creation."
+fi
+
+# Get the Android CMake NDK toolchain file if needed.
+if [ ! -d "android-cmake" ] ; then
+  hg clone https://code.google.com/p/android-cmake/
+else
+  echo "Found Android-CMake toolchain; skipping download."
+fi
+
+ANDROID_CMAKE_TOOLCHAIN=android-cmake/toolchain/android.toolchain.cmake
+if [ ! -f $ANDROID_CMAKE_TOOLCHAIN ] ; then
+  echo "ERROR: It seems the toolchain file is missing:"
+  echo "       $ANDROID_CMAKE_TOOLCHAIN"
+  exit 1
+fi
+
+cmake $CERES_SOURCE_ROOT \
+      -DCMAKE_TOOLCHAIN_FILE=$ANDROID_CMAKE_TOOLCHAIN \
+      -DCMAKE_BUILD_TYPE=Release \
+      -DEIGEN_INCLUDE=$EIGEN_DIR \
+      -DBUILD_ANDROID=ON \
+      -DSUITESPARSE=OFF \
+      -DGFLAGS=OFF \
+      -DCXSPARSE=OFF \
+      -DPROTOBUF=OFF
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt
index 0d33a86..1c1d4cd 100644
--- a/internal/ceres/CMakeLists.txt
+++ b/internal/ceres/CMakeLists.txt
@@ -103,6 +103,16 @@
   FILE(GLOB CERES_INTERNAL_SCHUR_FILES generated/schur_eliminator_d_d_d.cc)
 ENDIF (${SCHUR_SPECIALIZATIONS})
 
+# For Android, use the internal Glog implementation.
+IF (${BUILD_ANDROID})
+  ADD_LIBRARY(miniglog STATIC
+              miniglog/glog/logging.cc)
+
+  # The Android logging library that defines e.g. __android_log_print is
+  # creatively named "log".
+  TARGET_LINK_LIBRARIES(miniglog log)
+ENDIF (${BUILD_ANDROID})
+
 SET(CERES_LIBRARY_DEPENDENCIES ${GLOG_LIB})
 
 IF (${GFLAGS})
@@ -151,15 +161,15 @@
 
 # Don't build a DLL on MSVC. Supporting Ceres as a DLL on Windows involves
 # nontrivial changes that we haven't made yet.
-IF (NOT MSVC)
+IF (NOT MSVC AND NOT ${BUILD_ANDROID})
   ADD_LIBRARY(ceres_shared SHARED ${CERES_LIBRARY_SOURCE})
   TARGET_LINK_LIBRARIES(ceres_shared ${CERES_LIBRARY_DEPENDENCIES})
   SET_TARGET_PROPERTIES(ceres_shared PROPERTIES
       VERSION ${CERES_VERSION}
       SOVERSION ${CERES_ABI_VERSION})
-ENDIF (NOT MSVC)
+ENDIF (NOT MSVC AND NOT ${BUILD_ANDROID})
 
-IF (${BUILD_TESTING})
+IF (${BUILD_TESTING} AND ${GFLAGS})
   ADD_LIBRARY(gtest gmock_gtest_all.cc gmock_main.cc)
   ADD_LIBRARY(test_util test_util.cc)
   TARGET_LINK_LIBRARIES(gtest ${GFLAGS_LIB} ${GLOG_LIB})
@@ -206,25 +216,17 @@
   CERES_TEST(rotation)
   CERES_TEST(runtime_numeric_diff_cost_function)
   CERES_TEST(schur_complement_solver)
-  IF (GFLAGS)
-    CERES_TEST(schur_eliminator)
-  ENDIF (GFLAGS)
+  CERES_TEST(schur_eliminator)
   CERES_TEST(schur_ordering)
   CERES_TEST(solver_impl)
-  IF (SUITESPARSE)
-    CERES_TEST(suitesparse)
-  ENDIF(SUITESPARSE)
+  CERES_TEST(suitesparse)
   CERES_TEST(symmetric_linear_solver)
   CERES_TEST(triplet_sparse_matrix)
   CERES_TEST(trust_region_minimizer)
   CERES_TEST(unsymmetric_linear_solver)
   CERES_TEST(visibility)
-  IF (GFLAGS)
-    CERES_TEST(visibility_based_preconditioner)
-  ENDIF (GFLAGS)
+  CERES_TEST(visibility_based_preconditioner)
 
-  # Large end to end test for the entire solver.
-  IF (${GFLAGS})
-    CERES_TEST(system)
-  ENDIF (${GFLAGS})
-ENDIF (${BUILD_TESTING})
+  # Put the large end to end test last.
+  CERES_TEST(system)
+ENDIF (${BUILD_TESTING} AND ${GFLAGS})
diff --git a/internal/ceres/miniglog/glog/logging.cc b/internal/ceres/miniglog/glog/logging.cc
new file mode 100644
index 0000000..32a78ce
--- /dev/null
+++ b/internal/ceres/miniglog/glog/logging.cc
@@ -0,0 +1,39 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: keir@google.com (Keir Mierle)
+
+#include "glog/logging.h"
+
+namespace google {
+
+// This is the set of log sinks. This must be in a separate library to ensure
+// that there is only one instance of this across the entire program.
+std::set<google::LogSink *> log_sinks_global;
+
+}  // namespace ceres
diff --git a/internal/ceres/miniglog/glog/logging.h b/internal/ceres/miniglog/glog/logging.h
new file mode 100644
index 0000000..1fc137b
--- /dev/null
+++ b/internal/ceres/miniglog/glog/logging.h
@@ -0,0 +1,391 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2011, 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: settinger@google.com (Scott Ettinger)
+//         keir@google.com (Keir Mierle)
+//
+// Simplified Glog style logging with Android support. Supported macros in
+// decreasing severity level per line:
+//
+//   VLOG(2), VLOG(N)
+//   VLOG(1),
+//   LOG(INFO), VLOG(0), LG
+//   LOG(WARNING),
+//   LOG(ERROR),
+//   LOG(FATAL),
+//
+// With VLOG(n), the output is directed to one of the 5 Android log levels:
+//
+//   2 - Verbose
+//   1 - Debug
+//   0 - Info
+//  -1 - Warning
+//  -2 - Error
+//  -3 - Fatal
+//
+// Any logging of level 2 and above is directed to the Verbose level. All
+// Android log output is tagged with the string "native".
+//
+// If the symbol ANDROID is not defined, all output goes to std::cerr.
+// This allows code to be built on a different system for debug.
+//
+// Portions of this code are taken from the GLOG package.  This code is only a
+// small subset of the GLOG functionality. Notable differences from GLOG
+// behavior include lack of support for displaying unprintable characters and
+// lack of stack trace information upon failure of the CHECK macros.  On
+// non-Android systems, log output goes to std::cerr and is not written to a
+// file.
+//
+// CHECK macros are defined to test for conditions within code.  Any CHECK that
+// fails will log the failure and terminate the application.
+// e.g. CHECK_GE(3, 2) will pass while CHECK_GE(3, 4) will fail after logging
+//      "Check failed 3 >= 4".
+//
+// The following CHECK macros are defined:
+//
+//   CHECK(condition)        - fails if condition is false and logs condition.
+//   CHECK_NOTNULL(variable) - fails if the variable is NULL.
+//
+// The following binary check macros are also defined :
+//
+//   Macro                     Operator equivalent
+//   --------------------      -------------------
+//   CHECK_EQ(val1, val2)      val1 == val2
+//   CHECK_NE(val1, val2)      val1 != val2
+//   CHECK_GT(val1, val2)      val1 > val2
+//   CHECK_GE(val1, val2)      val1 >= val2
+//   CHECK_LT(val1, val2)      val1 < val2
+//   CHECK_LE(val1, val2)      val1 <= val2
+//
+// Debug only versions of all of the check macros are also defined.  These
+// macros generate no code in a release build, but avoid unused variable
+// warnings / errors.
+//
+// To use the debug only versions, prepend a D to the normal check macros, e.g.
+// DCHECK_EQ(a, b).
+
+#ifndef CERCES_INTERNAL_MINIGLOG_GLOG_LOGGING_H_
+#define CERCES_INTERNAL_MINIGLOG_GLOG_LOGGING_H_
+
+#ifdef ANDROID
+#include <android/log.h>
+#endif  // ANDROID
+
+#include <algorithm>
+#include <iostream>
+#include <string>
+#include <fstream>
+#include <set>
+#include <sstream>
+#include <vector>
+
+// Log severity level constants.
+const int FATAL   = -3;
+const int ERROR   = -2;
+const int WARNING = -1;
+const int INFO    =  0;
+
+// ------------------------- Glog compatibility ------------------------------
+
+namespace google {
+
+typedef int LogSeverity;
+const int INFO    = ::INFO;
+const int WARNING = ::WARNING;
+const int ERROR   = ::ERROR;
+const int FATAL   = ::FATAL;
+
+// Sink class used for integration with mock and test functions. If sinks are
+// added, all log output is also sent to each sink through the send function.
+// In this implementation, WaitTillSent() is called immediately after the send.
+// This implementation is not thread safe.
+class LogSink {
+ public:
+  virtual ~LogSink() {}
+  virtual void send(LogSeverity severity,
+                    const char* full_filename,
+                    const char* base_filename,
+                    int line,
+                    const struct tm* tm_time,
+                    const char* message,
+                    size_t message_len) = 0;
+  virtual void WaitTillSent() = 0;
+};
+
+// Global set of log sinks. The actual object is defined in logging.cc.
+extern std::set<LogSink *> log_sinks_global;
+
+inline void InitGoogleLogging(char *argv) {
+  // Do nothing; this is ignored.
+}
+
+// Note: the Log sink functions are not thread safe.
+inline void AddLogSink(LogSink *sink) {
+  // TODO(settinger): Add locks for thread safety.
+  log_sinks_global.insert(sink);
+}
+inline void RemoveLogSink(LogSink *sink) {
+  log_sinks_global.erase(sink);
+}
+
+}  // namespace google
+
+// ---------------------------- Logger Class --------------------------------
+
+// Class created for each use of the logging macros.
+// The logger acts as a stream and routes the final stream contents to the
+// Android logcat output at the proper filter level.  If ANDROID is not
+// defined, output is directed to std::cerr.  This class should not
+// be directly instantiated in code, rather it should be invoked through the
+// use of the log macros LG, LOG, or VLOG.
+class MessageLogger {
+ public:
+  MessageLogger(const char *file, int line, const char *tag, int severity)
+    : file_(file), line_(line), tag_(tag), severity_(severity) {
+    // Pre-pend the stream with the file and line number.
+    StripBasename(std::string(file), &filename_only_);
+    stream_ << filename_only_ << ":" << line << " ";
+  }
+
+  // Output the contents of the stream to the proper channel on destruction.
+  ~MessageLogger() {
+    stream_ << "\n";
+
+#ifdef ANDROID
+    static const int android_log_levels[] = {
+        ANDROID_LOG_FATAL,    // LOG(FATAL)
+        ANDROID_LOG_ERROR,    // LOG(ERROR)
+        ANDROID_LOG_WARN,     // LOG(WARNING)
+        ANDROID_LOG_INFO,     // LOG(INFO), LG, VLOG(0)
+        ANDROID_LOG_DEBUG,    // VLOG(1)
+        ANDROID_LOG_VERBOSE,  // VLOG(2) .. VLOG(N)
+    };
+
+    // Bound the logging level.
+    const int kMaxVerboseLevel = 2;
+    int android_level_index = std::min(std::max(FATAL, severity_),
+                                       kMaxVerboseLevel) - FATAL;
+    int android_log_level = android_log_levels[android_level_index];
+
+    // Output the log string the Android log at the appropriate level.
+    __android_log_print(android_log_level, tag_.c_str(), stream_.str().c_str());
+
+    // Indicate termination if needed.
+    if (severity_ == FATAL) {
+      __android_log_print(ANDROID_LOG_FATAL,
+                          tag_.c_str(),
+                          "terminating.\n");
+    }
+#else
+    // If not building on Android, log all output to std::cerr.
+    std::cerr << stream_.str();
+#endif  // ANDROID
+
+    LogToSinks(severity_);
+    WaitForSinks();
+
+    // Android logging at level FATAL does not terminate execution, so abort()
+    // is still required to stop the program.
+    if (severity_ == FATAL) {
+      abort();
+    }
+  }
+
+  // Return the stream associated with the logger object.
+  std::stringstream &stream() { return stream_; }
+
+ private:
+  void LogToSinks(int severity) {
+    time_t rawtime;
+    struct tm* timeinfo;
+
+    time (&rawtime);
+    timeinfo = localtime(&rawtime);
+    std::set<google::LogSink*>::iterator iter;
+    // Send the log message to all sinks.
+    for (iter = google::log_sinks_global.begin();
+         iter != google::log_sinks_global.end(); ++iter) {
+      (*iter)->send(severity, file_.c_str(), filename_only_.c_str(), line_,
+                    timeinfo, stream_.str().c_str(), stream_.str().size());
+    }
+  }
+
+  void WaitForSinks() {
+    // TODO(settinger): Add locks for thread safety.
+    std::set<google::LogSink *>::iterator iter;
+
+    // Call WaitTillSent() for all sinks.
+    for (iter = google::log_sinks_global.begin();
+         iter != google::log_sinks_global.end(); ++iter) {
+      (*iter)->WaitTillSent();
+    }
+  }
+
+  void StripBasename(const std::string &full_path, std::string *filename) {
+    // TODO(settinger): add support for OS with different path separators.
+    const char kSeparator = '/';
+    size_t pos = full_path.rfind(kSeparator);
+    if (pos != std::string::npos) {
+      *filename = full_path.substr(pos + 1, std::string::npos);
+    } else {
+      *filename = full_path;
+    }
+  }
+
+  std::string file_;
+  std::string filename_only_;
+  int line_;
+  std::string tag_;
+  std::stringstream stream_;
+  int severity_;
+};
+
+// ---------------------- Logging Macro definitions --------------------------
+
+#define LG MessageLogger((char *)__FILE__, __LINE__, "native", \
+                         INFO).stream()
+
+#define LOG(n) MessageLogger((char *)__FILE__, __LINE__, "native", \
+                             n).stream()
+
+#define VLOG(n) MessageLogger((char *)__FILE__, __LINE__, "native", \
+                              n).stream()
+
+// Currently, VLOG is always on.
+#define VLOG_IS_ON(x) true
+
+// ---------------------------- CHECK helpers --------------------------------
+
+// This class is used to explicitly ignore values in the conditional
+// logging macros.  This avoids compiler warnings like "value computed
+// is not used" and "statement has no effect".
+class LoggerVoidify {
+ public:
+  LoggerVoidify() { }
+  // This has to be an operator with a precedence lower than << but
+  // higher than ?:
+  void operator&(const std::ostream &s) { }
+};
+
+// Log only if condition is met.  Otherwise evaluates to void.
+#define LOG_IF(severity, condition) \
+  condition ? (void) 0 : LoggerVoidify() & LOG(severity)
+
+// Log a message and terminate.
+template<class T>
+void LogMessageFatal(const char *file, int line, const T &message) {
+  MessageLogger((char *)__FILE__, __LINE__, "native", FATAL).stream()
+      << message;
+}
+
+// ---------------------------- CHECK macros ---------------------------------
+
+// Check for a given boolean condition.
+#define CHECK(condition) LOG_IF(FATAL, condition) \
+        << "Check failed: " #condition " "
+
+#ifndef NDEBUG
+// Debug only version of CHECK
+#define DCHECK(condition) LOG_IF(FATAL, condition) \
+        << "Check failed: " #condition " "
+#else
+// Optimized version - generates no code.
+#define DCHECK(condition) if (false) LOG_IF(FATAL, condition) \
+        << "Check failed: " #condition " "
+#endif  // NDEBUG
+
+// ------------------------- CHECK_OP macros ---------------------------------
+
+// Generic binary operator check macro. This should not be directly invoked,
+// instead use the binary comparison macros defined below.
+#define CHECK_OP(val1, val2, op) LOG_IF(FATAL, (val1 op val2)) \
+  << "Check failed: " #val1 " " #op " " #val2 " "
+
+// Check_op macro definitions
+#define CHECK_EQ(val1, val2) CHECK_OP(val1, val2, ==)
+#define CHECK_NE(val1, val2) CHECK_OP(val1, val2, !=)
+#define CHECK_LE(val1, val2) CHECK_OP(val1, val2, <=)
+#define CHECK_LT(val1, val2) CHECK_OP(val1, val2, <)
+#define CHECK_GE(val1, val2) CHECK_OP(val1, val2, >=)
+#define CHECK_GT(val1, val2) CHECK_OP(val1, val2, >)
+
+#ifndef NDEBUG
+// Debug only versions of CHECK_OP macros.
+#define DCHECK_EQ(val1, val2) CHECK_OP(val1, val2, ==)
+#define DCHECK_NE(val1, val2) CHECK_OP(val1, val2, !=)
+#define DCHECK_LE(val1, val2) CHECK_OP(val1, val2, <=)
+#define DCHECK_LT(val1, val2) CHECK_OP(val1, val2, <)
+#define DCHECK_GE(val1, val2) CHECK_OP(val1, val2, >=)
+#define DCHECK_GT(val1, val2) CHECK_OP(val1, val2, >)
+#else
+// These versions generate no code in optimized mode.
+#define DCHECK_EQ(val1, val2) if (false) CHECK_OP(val1, val2, ==)
+#define DCHECK_NE(val1, val2) if (false) CHECK_OP(val1, val2, !=)
+#define DCHECK_LE(val1, val2) if (false) CHECK_OP(val1, val2, <=)
+#define DCHECK_LT(val1, val2) if (false) CHECK_OP(val1, val2, <)
+#define DCHECK_GE(val1, val2) if (false) CHECK_OP(val1, val2, >=)
+#define DCHECK_GT(val1, val2) if (false) CHECK_OP(val1, val2, >)
+#endif  // NDEBUG
+
+// ---------------------------CHECK_NOTNULL macros ---------------------------
+
+// Helpers for CHECK_NOTNULL(). Two are necessary to support both raw pointers
+// and smart pointers.
+template <typename T>
+T& CheckNotNullCommon(const char *file, int line, const char *names, T& t) {
+  if (t == NULL) {
+    LogMessageFatal(file, line, std::string(names));
+  }
+  return t;
+}
+
+template <typename T>
+T* CheckNotNull(const char *file, int line, const char *names, T* t) {
+  return CheckNotNullCommon(file, line, names, t);
+}
+
+template <typename T>
+T& CheckNotNull(const char *file, int line, const char *names, T& t) {
+  return CheckNotNullCommon(file, line, names, t);
+}
+
+// Check that a pointer is not null.
+#define CHECK_NOTNULL(val) \
+  CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
+
+#ifndef NDEBUG
+// Debug only version of CHECK_NOTNULL
+#define DCHECK_NOTNULL(val) \
+  CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
+#else
+// Optimized version - generates no code.
+#define DCHECK_NOTNULL(val) if (false)\
+  CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
+#endif  // NDEBUG
+
+#endif  // CERCES_INTERNAL_MINIGLOG_GLOG_LOGGING_H_