Merge "logd: best 2/3 filter for timezone glitches"
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 3ed2a7d..b132118 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -30,12 +30,31 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
+#include "adb.h"
 #include "adb_trace.h"
 #include "sysdeps.h"
 
 ADB_MUTEX_DEFINE(basename_lock);
 ADB_MUTEX_DEFINE(dirname_lock);
 
+#if defined(_WIN32)
+constexpr char kNullFileName[] = "NUL";
+#else
+constexpr char kNullFileName[] = "/dev/null";
+#endif
+
+void close_stdin() {
+    int fd = unix_open(kNullFileName, O_RDONLY);
+    if (fd == -1) {
+        fatal_errno("failed to open %s", kNullFileName);
+    }
+
+    if (TEMP_FAILURE_RETRY(dup2(fd, STDIN_FILENO)) == -1) {
+        fatal_errno("failed to redirect stdin to %s", kNullFileName);
+    }
+    unix_close(fd);
+}
+
 bool getcwd(std::string* s) {
   char* cwd = getcwd(nullptr, 0);
   if (cwd != nullptr) *s = cwd;
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index 537d0e4..388d7dd 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -19,6 +19,8 @@
 
 #include <string>
 
+void close_stdin();
+
 bool getcwd(std::string* cwd);
 bool directory_exists(const std::string& path);
 
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 3ce5242..b37d04d 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -34,11 +34,10 @@
 #include "adb.h"
 #include "adb_auth.h"
 #include "adb_listeners.h"
+#include "adb_utils.h"
 #include "transport.h"
 
 #if defined(_WIN32)
-static const char kNullFileName[] = "NUL";
-
 static BOOL WINAPI ctrlc_handler(DWORD type) {
     // TODO: Consider trying to kill a starting up adb server (if we're in
     // launch_server) by calling GenerateConsoleCtrlEvent().
@@ -66,24 +65,11 @@
     return temp_path_utf8 + log_name;
 }
 #else
-static const char kNullFileName[] = "/dev/null";
-
 static std::string GetLogFilePath() {
     return std::string("/tmp/adb.log");
 }
 #endif
 
-static void close_stdin() {
-    int fd = unix_open(kNullFileName, O_RDONLY);
-    if (fd == -1) {
-        fatal("cannot open '%s': %s", kNullFileName, strerror(errno));
-    }
-    if (dup2(fd, STDIN_FILENO) == -1) {
-        fatal("cannot redirect stdin: %s", strerror(errno));
-    }
-    unix_close(fd);
-}
-
 static void setup_daemon_logging(void) {
     const std::string log_file_path(GetLogFilePath());
     int fd = unix_open(log_file_path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0640);
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index d244f7d..8575c86 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -112,9 +112,10 @@
         "                                 (-a preserves file timestamp and mode)\n"
         "  adb sync [ <directory> ]     - copy host->device only if changed\n"
         "                                 (-l means list but don't copy)\n"
-        "  adb shell [-e escape] [-Tt] [-x] [command]\n"
+        "  adb shell [-e escape] [-n] [-Tt] [-x] [command]\n"
         "                               - run remote shell command (interactive shell if no command given)\n"
         "                                 (-e: choose escape character, or \"none\"; default '~')\n"
+        "                                 (-n: don't read from stdin)\n"
         "                                 (-T: disable PTY allocation)\n"
         "                                 (-t: force PTY allocation)\n"
         "                                 (-x: disable remote exit codes and stdout/stderr separation)\n"
@@ -733,6 +734,11 @@
             use_shell_protocol = false;
             --argc;
             ++argv;
+        } else if (!strcmp(argv[0], "-n")) {
+            close_stdin();
+
+            --argc;
+            ++argv;
         } else {
             break;
         }
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 10c5296..3e4fc92 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -34,6 +34,7 @@
 #include "adb.h"
 #include "adb_auth.h"
 #include "adb_listeners.h"
+#include "adb_utils.h"
 #include "transport.h"
 
 static const char* root_seclabel = nullptr;
@@ -217,16 +218,6 @@
     return 0;
 }
 
-static void close_stdin() {
-    int fd = unix_open("/dev/null", O_RDONLY);
-    if (fd == -1) {
-        perror("failed to open /dev/null, stdin will remain open");
-        return;
-    }
-    dup2(fd, STDIN_FILENO);
-    unix_close(fd);
-}
-
 int main(int argc, char** argv) {
     while (true) {
         static struct option opts[] = {
diff --git a/crash_reporter/Android.mk b/crash_reporter/Android.mk
index 81cb458..565963c 100644
--- a/crash_reporter/Android.mk
+++ b/crash_reporter/Android.mk
@@ -43,11 +43,12 @@
 LOCAL_C_INCLUDES := $(crash_reporter_includes)
 LOCAL_RTTI_FLAG := -frtti
 LOCAL_SHARED_LIBRARIES := libchrome \
+    libbinder \
     libbrillo \
     libcutils \
-    libdbus \
     libmetrics \
     libpcrecpp
+LOCAL_STATIC_LIBRARIES := libmetricscollectorservice
 LOCAL_SRC_FILES := $(crash_reporter_src)
 include $(BUILD_STATIC_LIBRARY)
 
@@ -60,18 +61,19 @@
 LOCAL_REQUIRED_MODULES := core2md \
     crash_reporter_logs.conf \
     crash_sender \
-    crash_server \
-    dbus-send
+    crash_server
 LOCAL_INIT_RC := crash_reporter.rc
 LOCAL_RTTI_FLAG := -frtti
 LOCAL_SHARED_LIBRARIES := libchrome \
+    libbinder \
     libbrillo \
     libcutils \
-    libdbus \
     libmetrics \
-    libpcrecpp
+    libpcrecpp \
+    libutils
 LOCAL_SRC_FILES := crash_reporter.cc
-LOCAL_STATIC_LIBRARIES := libcrash
+LOCAL_STATIC_LIBRARIES := libcrash \
+    libmetricscollectorservice
 include $(BUILD_EXECUTABLE)
 
 # Crash sender script.
@@ -140,7 +142,6 @@
 LOCAL_SHARED_LIBRARIES := libchrome \
     libbrillo \
     libcutils \
-    libdbus \
     libpcrecpp
 LOCAL_SRC_FILES := $(crash_reporter_test_src)
 LOCAL_STATIC_LIBRARIES := libcrash libgmock
diff --git a/crash_reporter/crash_reporter.cc b/crash_reporter/crash_reporter.cc
index 3955fe5..26ffa38 100644
--- a/crash_reporter/crash_reporter.cc
+++ b/crash_reporter/crash_reporter.cc
@@ -25,10 +25,13 @@
 #include <base/strings/string_split.h>
 #include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
+#include <binder/IServiceManager.h>
 #include <brillo/flag_helper.h>
-#include <brillo/process.h>
 #include <brillo/syslog_logging.h>
+#include <metrics/metrics_collector_service_client.h>
 #include <metrics/metrics_library.h>
+#include <utils/String16.h>
+
 
 #include "kernel_collector.h"
 #include "kernel_warning_collector.h"
@@ -37,8 +40,6 @@
 #include "user_collector.h"
 
 static const char kCrashCounterHistogram[] = "Logging.CrashCounter";
-static const char kUserCrashSignal[] =
-    "org.chromium.CrashReporter.UserCrash";
 static const char kKernelCrashDetected[] = "/var/run/kernel-crash-detected";
 static const char kUncleanShutdownDetected[] =
     "/var/run/unclean-shutdown-detected";
@@ -56,6 +57,7 @@
 
 static MetricsLibrary s_metrics_lib;
 
+using android::brillo::metrics::IMetricsCollectorService;
 using base::FilePath;
 using base::StringPrintf;
 
@@ -88,32 +90,14 @@
 
 static void CountUserCrash() {
   SendCrashMetrics(kCrashKindUser, "user");
-  // Announce through D-Bus whenever a user crash happens. This is
-  // used by the metrics daemon to log active use time between
-  // crashes.
-  //
-  // We run in the background in case dbus-daemon itself is crashed
-  // and not responding.  This allows us to not block and potentially
-  // deadlock on a dbus-daemon crash.  If dbus-daemon crashes without
-  // restarting, each crash will fork off a lot of dbus-send
-  // processes.  Such a system is in a unusable state and will need
-  // to be restarted anyway.
-  //
-  // Note: This will mean that the dbus-send process will become a zombie and
-  // reparent to init for reaping, but that's OK -- see above.
+  // Tell the metrics collector about the user crash, in order to log active
+  // use time between crashes.
+  MetricsCollectorServiceClient metrics_collector_service;
 
-  brillo::ProcessImpl dbus_send;
-  dbus_send.AddArg("/system/bin/dbus-send");
-  dbus_send.AddArg("--type=signal");
-  dbus_send.AddArg("--system");
-  dbus_send.AddArg("/");
-  dbus_send.AddArg(kUserCrashSignal);
-  bool status = dbus_send.Start();
-  if (status) {
-    dbus_send.Release();
-  } else {
-    PLOG(WARNING) << "Sending UserCrash DBus signal failed";
-  }
+  if (metrics_collector_service.Init())
+    metrics_collector_service.notifyUserCrash();
+  else
+    LOG(ERROR) << "Failed to send user crash notification to metrics_collector";
 }
 
 
diff --git a/logd/main.cpp b/logd/main.cpp
index 8e75b37..0f55d60 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -349,7 +349,7 @@
         memset(&p, 0, sizeof(p));
         p.fd = sock;
         p.events = POLLIN;
-        ret = TEMP_FAILURE_RETRY(poll(&p, 1, 100));
+        ret = TEMP_FAILURE_RETRY(poll(&p, 1, 1000));
         if (ret < 0) {
             return -errno;
         }
diff --git a/metricsd/Android.mk b/metricsd/Android.mk
index 3553753..2149a4b 100644
--- a/metricsd/Android.mk
+++ b/metricsd/Android.mk
@@ -28,6 +28,7 @@
   collectors/cpu_usage_collector.cc \
   collectors/disk_usage_collector.cc \
   metrics_collector.cc \
+  metrics_collector_service_trampoline.cc \
   persistent_integer.cc
 
 metricsd_common := \
@@ -69,6 +70,7 @@
   $(LOCAL_PATH)/include
 libmetrics_shared_libraries := libchrome libbinder libbrillo libutils
 metrics_collector_shared_libraries := $(libmetrics_shared_libraries) \
+  libbrillo-binder \
   libbrillo-dbus \
   libbrillo-http \
   libchrome-dbus \
@@ -77,6 +79,8 @@
   librootdev \
   libweaved
 
+metrics_collector_static_libraries := libmetricscollectorservice
+
 metricsd_shared_libraries := \
   libbinder \
   libbrillo \
@@ -86,7 +90,7 @@
   libupdate_engine_client \
   libutils
 
-# Static proxy library for the binder interface.
+# Static proxy library for the metricsd binder interface.
 # ========================================================
 include $(CLEAR_VARS)
 LOCAL_MODULE := metricsd_binder_proxy
@@ -94,6 +98,21 @@
 LOCAL_SRC_FILES := aidl/android/brillo/metrics/IMetricsd.aidl
 include $(BUILD_STATIC_LIBRARY)
 
+# Static library for the metrics_collector binder interface.
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libmetricscollectorservice
+LOCAL_SHARED_LIBRARIES := libbinder libbrillo-binder libchrome libutils
+LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_SRC_FILES := \
+  aidl/android/brillo/metrics/IMetricsCollectorService.aidl \
+  metrics_collector_service_impl.cc \
+  metrics_collector_service_client.cc
+LOCAL_RTTI_FLAG := -fno-rtti
+include $(BUILD_STATIC_LIBRARY)
+
 # Shared library for metrics.
 # ========================================================
 include $(CLEAR_VARS)
@@ -151,7 +170,8 @@
 LOCAL_SHARED_LIBRARIES := $(metrics_collector_shared_libraries)
 LOCAL_SRC_FILES := $(metrics_collector_common) \
   metrics_collector_main.cc
-LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy
+LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy \
+  $(metrics_collector_static_libraries)
 include $(BUILD_EXECUTABLE)
 
 # metricsd daemon.
@@ -197,7 +217,8 @@
 LOCAL_SHARED_LIBRARIES := $(metrics_collector_shared_libraries)
 LOCAL_SRC_FILES := $(metrics_collector_tests_sources) \
   $(metrics_collector_common)
-LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_binder_proxy
+LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_binder_proxy \
+  $(metrics_collector_static_libraries)
 include $(BUILD_NATIVE_TEST)
 
 # Weave schema files
diff --git a/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl b/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl
new file mode 100644
index 0000000..49f484f
--- /dev/null
+++ b/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+package android.brillo.metrics;
+
+interface IMetricsCollectorService {
+  oneway void notifyUserCrash();
+}
diff --git a/metricsd/include/metrics/metrics_collector_service_client.h b/metricsd/include/metrics/metrics_collector_service_client.h
new file mode 100644
index 0000000..c800eae
--- /dev/null
+++ b/metricsd/include/metrics/metrics_collector_service_client.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+// Client interface to IMetricsCollectorService.
+
+#ifndef METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
+#define METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
+
+#include "android/brillo/metrics/IMetricsCollectorService.h"
+
+class MetricsCollectorServiceClient {
+ public:
+  MetricsCollectorServiceClient() = default;
+  ~MetricsCollectorServiceClient() = default;
+
+  // Initialize.  Returns true if OK, or false if IMetricsCollectorService
+  // is not registered.
+  bool Init();
+
+  // Called by crash_reporter to report a userspace crash event.  Returns
+  // true if successfully called the IMetricsCollectorService method of the
+  // same name, or false if the service was not registered at Init() time.
+  bool notifyUserCrash();
+
+ private:
+  // IMetricsCollectorService binder proxy
+  android::sp<android::brillo::metrics::IMetricsCollectorService>
+      metrics_collector_service_;
+};
+
+#endif  // METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
diff --git a/metricsd/metrics_collector.cc b/metricsd/metrics_collector.cc
index 5468b9f..b5c2289 100644
--- a/metricsd/metrics_collector.cc
+++ b/metricsd/metrics_collector.cc
@@ -33,6 +33,7 @@
 #include <dbus/message.h>
 
 #include "constants.h"
+#include "metrics_collector_service_trampoline.h"
 
 using base::FilePath;
 using base::StringPrintf;
@@ -46,11 +47,6 @@
 
 namespace {
 
-const char kCrashReporterInterface[] = "org.chromium.CrashReporter";
-const char kCrashReporterUserCrashSignal[] = "UserCrash";
-const char kCrashReporterMatchRule[] =
-    "type='signal',interface='%s',path='/',member='%s'";
-
 const int kSecondsPerMinute = 60;
 const int kMinutesPerHour = 60;
 const int kHoursPerDay = 24;
@@ -130,6 +126,10 @@
     version_cumulative_cpu_use_->Set(0);
   }
 
+  // Start metricscollectorservice via trampoline
+  MetricsCollectorServiceTrampoline metricscollectorservice_trampoline(this);
+  metricscollectorservice_trampoline.Run();
+
   return brillo::DBusDaemon::Run();
 }
 
@@ -223,28 +223,6 @@
   bus_->AssertOnDBusThread();
   CHECK(bus_->SetUpAsyncOperations());
 
-  if (bus_->is_connected()) {
-    const std::string match_rule =
-        base::StringPrintf(kCrashReporterMatchRule,
-                           kCrashReporterInterface,
-                           kCrashReporterUserCrashSignal);
-
-    bus_->AddFilterFunction(&MetricsCollector::MessageFilter, this);
-
-    DBusError error;
-    dbus_error_init(&error);
-    bus_->AddMatch(match_rule, &error);
-
-    if (dbus_error_is_set(&error)) {
-      LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got "
-          << error.name << ": " << error.message;
-      return EX_SOFTWARE;
-    }
-  } else {
-    LOG(ERROR) << "DBus isn't connected.";
-    return EX_UNAVAILABLE;
-  }
-
   device_ = weaved::Device::CreateInstance(
       bus_,
       base::Bind(&MetricsCollector::UpdateWeaveState, base::Unretained(this)));
@@ -268,23 +246,6 @@
 }
 
 void MetricsCollector::OnShutdown(int* return_code) {
-  if (!testing_ && bus_->is_connected()) {
-    const std::string match_rule =
-        base::StringPrintf(kCrashReporterMatchRule,
-                           kCrashReporterInterface,
-                           kCrashReporterUserCrashSignal);
-
-    bus_->RemoveFilterFunction(&MetricsCollector::MessageFilter, this);
-
-    DBusError error;
-    dbus_error_init(&error);
-    bus_->RemoveMatch(match_rule, &error);
-
-    if (dbus_error_is_set(&error)) {
-      LOG(ERROR) << "Failed to remove match rule \"" << match_rule << "\". Got "
-          << error.name << ": " << error.message;
-    }
-  }
   brillo::DBusDaemon::OnShutdown(return_code);
 }
 
@@ -340,36 +301,6 @@
   }
 }
 
-// static
-DBusHandlerResult MetricsCollector::MessageFilter(DBusConnection* connection,
-                                                   DBusMessage* message,
-                                                   void* user_data) {
-  int message_type = dbus_message_get_type(message);
-  if (message_type != DBUS_MESSAGE_TYPE_SIGNAL) {
-    DLOG(WARNING) << "unexpected message type " << message_type;
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-  }
-
-  // Signal messages always have interfaces.
-  const std::string interface(dbus_message_get_interface(message));
-  const std::string member(dbus_message_get_member(message));
-  DLOG(INFO) << "Got " << interface << "." << member << " D-Bus signal";
-
-  MetricsCollector* daemon = static_cast<MetricsCollector*>(user_data);
-
-  DBusMessageIter iter;
-  dbus_message_iter_init(message, &iter);
-  if (interface == kCrashReporterInterface) {
-    CHECK_EQ(member, kCrashReporterUserCrashSignal);
-    daemon->ProcessUserCrash();
-  } else {
-    // Ignore messages from the bus itself.
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-  }
-
-  return DBUS_HANDLER_RESULT_HANDLED;
-}
-
 void MetricsCollector::ProcessUserCrash() {
   // Counts the active time up to now.
   UpdateStats(TimeTicks::Now(), Time::Now());
diff --git a/metricsd/metrics_collector.h b/metricsd/metrics_collector.h
index 69747d0..422ed7c 100644
--- a/metricsd/metrics_collector.h
+++ b/metricsd/metrics_collector.h
@@ -63,6 +63,10 @@
   // Returns the active time since boot (uptime minus sleep time) in seconds.
   static double GetActiveTime();
 
+  // Updates the active use time and logs time between user-space
+  // process crashes.  Called via MetricsCollectorServiceTrampoline.
+  void ProcessUserCrash();
+
  protected:
   // Used also by the unit tests.
   static const char kComprDataSizeName[];
@@ -108,11 +112,6 @@
     int value;               // value from /proc/meminfo
   };
 
-  // D-Bus filter callback.
-  static DBusHandlerResult MessageFilter(DBusConnection* connection,
-                                         DBusMessage* message,
-                                         void* user_data);
-
   // Enables metrics reporting.
   void OnEnableMetrics(const std::weak_ptr<weaved::Command>& cmd);
 
@@ -122,10 +121,6 @@
   // Updates the weave device state.
   void UpdateWeaveState();
 
-  // Updates the active use time and logs time between user-space
-  // process crashes.
-  void ProcessUserCrash();
-
   // Updates the active use time and logs time between kernel crashes.
   void ProcessKernelCrash();
 
diff --git a/metricsd/metrics_collector_service_client.cc b/metricsd/metrics_collector_service_client.cc
new file mode 100644
index 0000000..08aaa4a
--- /dev/null
+++ b/metricsd/metrics_collector_service_client.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+// Client interface to IMetricsCollectorService.
+
+#include "metrics/metrics_collector_service_client.h"
+
+#include <base/logging.h>
+#include <binder/IServiceManager.h>
+#include <utils/String16.h>
+
+#include "android/brillo/metrics/IMetricsCollectorService.h"
+
+namespace {
+const char kMetricsCollectorServiceName[] =
+    "android.brillo.metrics.IMetricsCollectorService";
+}
+
+bool MetricsCollectorServiceClient::Init() {
+  const android::String16 name(kMetricsCollectorServiceName);
+  metrics_collector_service_ = android::interface_cast<
+      android::brillo::metrics::IMetricsCollectorService>(
+      android::defaultServiceManager()->checkService(name));
+
+  if (metrics_collector_service_ == nullptr)
+    LOG(ERROR) << "Unable to lookup service " << kMetricsCollectorServiceName;
+
+  return metrics_collector_service_ != nullptr;
+}
+
+bool MetricsCollectorServiceClient::notifyUserCrash() {
+  if (metrics_collector_service_ == nullptr)
+    return false;
+
+  metrics_collector_service_->notifyUserCrash();
+  return true;
+}
diff --git a/metricsd/metrics_collector_service_impl.cc b/metricsd/metrics_collector_service_impl.cc
new file mode 100644
index 0000000..dbb0578
--- /dev/null
+++ b/metricsd/metrics_collector_service_impl.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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 "metrics_collector_service_impl.h"
+
+#include <binder/IServiceManager.h>
+#include <binder/Status.h>
+#include <brillo/binder_watcher.h>
+#include <utils/Errors.h>
+
+#include "metrics_collector_service_trampoline.h"
+
+using namespace android;
+
+BnMetricsCollectorServiceImpl::BnMetricsCollectorServiceImpl(
+    MetricsCollectorServiceTrampoline* metrics_collector_service_trampoline) {
+  metrics_collector_service_trampoline_ = metrics_collector_service_trampoline;
+}
+
+void BnMetricsCollectorServiceImpl::Run() {
+  status_t status =
+      defaultServiceManager()->addService(getInterfaceDescriptor(), this);
+  CHECK(status == OK) << "libmetricscollectorservice: failed to add service";
+  binder_watcher_.reset(new ::brillo::BinderWatcher);
+  CHECK(binder_watcher_->Init()) << "Binder FD watcher init failed";
+}
+
+android::binder::Status BnMetricsCollectorServiceImpl::notifyUserCrash() {
+  metrics_collector_service_trampoline_->ProcessUserCrash();
+  return android::binder::Status::ok();
+}
diff --git a/metricsd/metrics_collector_service_impl.h b/metricsd/metrics_collector_service_impl.h
new file mode 100644
index 0000000..bdcab50
--- /dev/null
+++ b/metricsd/metrics_collector_service_impl.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 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 METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
+#define METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
+
+// metrics_collector binder service implementation.  Constructed by
+// MetricsCollectorServiceTrampoline, which we use to call back into
+// MetricsCollector.  The trampoline isolates us from the -frtti code of
+// metrics_collector / libbrillo.
+
+#include "android/brillo/metrics/BnMetricsCollectorService.h"
+
+#include <memory>
+
+#include <binder/Status.h>
+#include <brillo/binder_watcher.h>
+
+class MetricsCollectorServiceTrampoline;
+
+//#include "metrics_collector_service_trampoline.h"
+
+class BnMetricsCollectorServiceImpl
+    : public android::brillo::metrics::BnMetricsCollectorService {
+ public:
+  // Passed a this pointer from the MetricsCollectorServiceTrampoline
+  // object that constructs us.
+  explicit BnMetricsCollectorServiceImpl(
+      MetricsCollectorServiceTrampoline* metrics_collector_service_trampoline);
+
+  virtual ~BnMetricsCollectorServiceImpl() = default;
+
+  // Starts the binder main loop.
+  void Run();
+
+  // Called by crash_reporter to report a userspace crash event.  We relay
+  // this to MetricsCollector using the trampoline.
+  android::binder::Status notifyUserCrash();
+
+ private:
+  // Trampoline object that constructs us, we use this to call MetricsCollector
+  // methods via the trampoline.
+  MetricsCollectorServiceTrampoline* metrics_collector_service_trampoline_;
+
+  // BinderWatcher object we construct for handling Binder traffic
+  std::unique_ptr<brillo::BinderWatcher> binder_watcher_;
+};
+
+#endif  // METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
diff --git a/metricsd/metrics_collector_service_trampoline.cc b/metricsd/metrics_collector_service_trampoline.cc
new file mode 100644
index 0000000..12b80a1
--- /dev/null
+++ b/metricsd/metrics_collector_service_trampoline.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 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 "metrics_collector_service_trampoline.h"
+#include "metrics_collector.h"
+#include "metrics_collector_service_impl.h"
+
+MetricsCollectorServiceTrampoline::MetricsCollectorServiceTrampoline(
+    MetricsCollector* metrics_collector) {
+  metrics_collector_ = metrics_collector;
+}
+
+void MetricsCollectorServiceTrampoline::Run() {
+  // Start metricscollectorservice binder service
+  metrics_collector_service.reset(new BnMetricsCollectorServiceImpl(this));
+  metrics_collector_service->Run();
+}
+
+void MetricsCollectorServiceTrampoline::ProcessUserCrash() {
+  metrics_collector_->ProcessUserCrash();
+}
diff --git a/metricsd/metrics_collector_service_trampoline.h b/metricsd/metrics_collector_service_trampoline.h
new file mode 100644
index 0000000..5da9fa5
--- /dev/null
+++ b/metricsd/metrics_collector_service_trampoline.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 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 METRICSD_METRICS_COLLECTOR_SERVICE_TRAMPOLINE_H_
+#define METRICSD_METRICS_COLLECTOR_SERVICE_TRAMPOLINE_H_
+
+// Trampoline between the -fno-rtti compile of libmetricsservice and the
+// -frtti compile of metrics_collector.  MetricsCollectorServiceTrampoline
+// is called from MetricsCollector to run the IMetricsCollectorService
+// server, and acts as a go-between for calls from server back to
+// MetricsCollector.
+
+#include <memory>
+
+#include "metrics_collector_service_impl.h"
+
+// Forward declaration of MetricsCollector.  Don't include the header file
+// for the class here, as it pulls in -frtti stuff.
+class MetricsCollector;
+
+class MetricsCollectorServiceTrampoline {
+ public:
+  // Constructor take a this pointer from the MetricsCollector class that
+  // constructs these objects.
+  explicit MetricsCollectorServiceTrampoline(
+      MetricsCollector* metrics_collector);
+
+  // Initialize and run the IMetricsCollectorService
+  void Run();
+
+  // Called from IMetricsCollectorService to trampoline into the
+  // MetricsCollector method of the same name.
+  void ProcessUserCrash();
+
+ private:
+  // The MetricsCollector object that constructs us, for which we act as
+  // the go-between for MetricsCollectorServiceImpl use.
+  MetricsCollector* metrics_collector_;
+
+  // The IMetricsCollectorService implementation we construct.
+  std::unique_ptr<BnMetricsCollectorServiceImpl> metrics_collector_service;
+};
+
+#endif  // METRICSD_METRICS_COLLECTOR_SERVICE_TRAMPOLINE_H_
diff --git a/metricsd/metrics_collector_test.cc b/metricsd/metrics_collector_test.cc
index 956e56b..5fb3ac8 100644
--- a/metricsd/metrics_collector_test.cc
+++ b/metricsd/metrics_collector_test.cc
@@ -115,37 +115,6 @@
   StrictMock<MetricsLibraryMock> metrics_lib_;
 };
 
-TEST_F(MetricsCollectorTest, MessageFilter) {
-  // Ignore calls to SendToUMA.
-  EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _)).Times(AnyNumber());
-
-  DBusMessage* msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
-  DBusHandlerResult res =
-      MetricsCollector::MessageFilter(/* connection */ nullptr, msg, &daemon_);
-  EXPECT_EQ(DBUS_HANDLER_RESULT_NOT_YET_HANDLED, res);
-  DeleteDBusMessage(msg);
-
-  vector<string> signal_args;
-  msg = NewDBusSignalString("/",
-                            "org.chromium.CrashReporter",
-                            "UserCrash",
-                            signal_args);
-  res = MetricsCollector::MessageFilter(/* connection */ nullptr, msg, &daemon_);
-  EXPECT_EQ(DBUS_HANDLER_RESULT_HANDLED, res);
-  DeleteDBusMessage(msg);
-
-  signal_args.clear();
-  signal_args.push_back("randomstate");
-  signal_args.push_back("bob");  // arbitrary username
-  msg = NewDBusSignalString("/",
-                            "org.chromium.UnknownService.Manager",
-                            "StateChanged",
-                            signal_args);
-  res = MetricsCollector::MessageFilter(/* connection */ nullptr, msg, &daemon_);
-  EXPECT_EQ(DBUS_HANDLER_RESULT_NOT_YET_HANDLED, res);
-  DeleteDBusMessage(msg);
-}
-
 TEST_F(MetricsCollectorTest, SendSample) {
   ExpectSample("Dummy.Metric", 3);
   daemon_.SendSample("Dummy.Metric", /* sample */ 3,