Implement lock contention event logging.

Change-Id: I88b30985590157bb5d04229a97f191b898f141bb
diff --git a/src/monitor_android.cc b/src/monitor_android.cc
new file mode 100644
index 0000000..95dd397
--- /dev/null
+++ b/src/monitor_android.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 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 "monitor.h"
+#include "object.h"
+#include "thread.h"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "cutils/log.h"
+
+#define EVENT_LOG_TAG_dvm_lock_sample 20003
+
+namespace art {
+
+static void Set4LE(uint8_t* buf, uint32_t val) {
+  *buf++ = (uint8_t)(val);
+  *buf++ = (uint8_t)(val >> 8);
+  *buf++ = (uint8_t)(val >> 16);
+  *buf = (uint8_t)(val >> 24);
+}
+
+static char* EventLogWriteInt(char* dst, int value) {
+  *dst++ = EVENT_TYPE_INT;
+  Set4LE((uint8_t*) dst, value);
+  return dst + 4;
+}
+
+static char* EventLogWriteString(char* dst, const char* value, size_t len) {
+  *dst++ = EVENT_TYPE_STRING;
+  len = len < 32 ? len : 32;
+  Set4LE((uint8_t*) dst, len);
+  dst += 4;
+  memcpy(dst, value, len);
+  return dst + len;
+}
+
+void Monitor::LogContentionEvent(Thread* self, uint32_t wait_ms, uint32_t sample_percent, const char* owner_filename, uint32_t owner_line_number) {
+  // Emit the event list length, 1 byte.
+  char eventBuffer[174];
+  char* cp = eventBuffer;
+  *cp++ = 9;
+
+  // Emit the process name, <= 37 bytes.
+  int fd = open("/proc/self/cmdline", O_RDONLY);
+  char procName[33];
+  memset(procName, 0, sizeof(procName));
+  read(fd, procName, sizeof(procName) - 1);
+  close(fd);
+  size_t len = strlen(procName);
+  cp = EventLogWriteString(cp, procName, len);
+
+  // Emit the sensitive thread ("main thread") status, 5 bytes.
+  cp = EventLogWriteInt(cp, Monitor::IsSensitiveThread());
+
+  // Emit self thread name string, <= 37 bytes.
+  std::string thread_name(self->GetName()->ToModifiedUtf8());
+  cp = EventLogWriteString(cp, thread_name.c_str(), thread_name.size());
+
+  // Emit the wait time, 5 bytes.
+  cp = EventLogWriteInt(cp, wait_ms);
+
+  // Emit the source code file name, <= 37 bytes.
+  const char* filename;
+  uint32_t line_number;
+  self->GetCurrentLocation(filename, line_number);
+  cp = EventLogWriteString(cp, filename, strlen(filename));
+
+  // Emit the source code line number, 5 bytes.
+  cp = EventLogWriteInt(cp, line_number);
+
+  // Emit the lock owner source code file name, <= 37 bytes.
+  if (owner_filename == NULL) {
+    owner_filename = "";
+  } else if (strcmp(filename, owner_filename) == 0) {
+    // Common case, so save on log space.
+    owner_filename = "-";
+  }
+  cp = EventLogWriteString(cp, owner_filename, strlen(owner_filename));
+
+  // Emit the source code line number, 5 bytes.
+  cp = EventLogWriteInt(cp, owner_line_number);
+
+  // Emit the sample percentage, 5 bytes.
+  cp = EventLogWriteInt(cp, sample_percent);
+
+  CHECK_LE((size_t)(cp - eventBuffer), sizeof(eventBuffer));
+  android_btWriteLog(EVENT_LOG_TAG_dvm_lock_sample, EVENT_TYPE_LIST, eventBuffer, (size_t)(cp - eventBuffer));
+}
+
+}  // namespace art