Merge "boottime/init: Report ro.boottime.init* properties in milliseconds."
diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp
index e541f6e..d4fc7c0 100644
--- a/adb/client/usb_osx.cpp
+++ b/adb/client/usb_osx.cpp
@@ -44,6 +44,7 @@
 
 using namespace std::chrono_literals;
 
+namespace native {
 struct usb_handle
 {
     UInt8 bulkIn;
@@ -298,7 +299,8 @@
         usb_handle* handle_p = handle.get();
         VLOG(USB) << "Add usb device " << serial;
         AddDevice(std::move(handle));
-        register_usb_transport(handle_p, serial, devpath.c_str(), 1);
+        register_usb_transport(reinterpret_cast<::usb_handle*>(handle_p), serial, devpath.c_str(),
+                               1);
     }
 }
 
@@ -558,3 +560,4 @@
     std::lock_guard<std::mutex> lock_guard(g_usb_handles_mutex);
     usb_kick_locked(handle);
 }
+} // namespace native
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index c009869..501d089 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -297,13 +297,6 @@
   }
 
   log_signal_summary(signal_number, info);
-  if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
-    // The process has disabled core dumps and PTRACE_ATTACH, and does not want to be dumped.
-    __libc_format_log(ANDROID_LOG_INFO, "libc",
-                      "Suppressing debuggerd output because prctl(PR_GET_DUMPABLE)==0");
-    resend_signal(info, false);
-    return;
-  }
 
   if (prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1) {
     // The process has NO_NEW_PRIVS enabled, so we can't transition to the crash_dump context.
diff --git a/init/seccomp.cpp b/init/seccomp.cpp
index d632302..92f30e8 100644
--- a/init/seccomp.cpp
+++ b/init/seccomp.cpp
@@ -213,6 +213,12 @@
     // Needed for kernel to restart syscalls
     AllowSyscall(f, 0);  // __NR_restart_syscall
 
+    // Needed for debugging 32-bit Chrome
+    AllowSyscall(f, 42); // __NR_pipe
+
+    // b/34732712
+    AllowSyscall(f, 364); // __NR_perf_event_open
+
     // arm32-on-arm64 only filter - autogenerated from bionic syscall usage
     for (size_t i = 0; i < arm_filter_size; ++i)
         f.push_back(arm_filter[i]);
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index f6c0f0e..cf266dc 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -98,7 +98,7 @@
                 "ashmem-dev.c",
                 "klog.cpp",
                 "partition_utils.c",
-                "properties.c",
+                "properties.cpp",
                 "qtaguid.c",
                 "trace-dev.c",
                 "uevent.c",
diff --git a/libcutils/properties.c b/libcutils/properties.cpp
similarity index 85%
rename from libcutils/properties.c
rename to libcutils/properties.cpp
index bdbddd0..43ad574 100644
--- a/libcutils/properties.c
+++ b/libcutils/properties.cpp
@@ -112,9 +112,7 @@
 }
 
 int property_get(const char *key, char *value, const char *default_value) {
-    int len;
-
-    len = __system_property_get(key, value);
+    int len = __system_property_get(key, value);
     if (len > 0) {
         return len;
     }
@@ -126,21 +124,21 @@
     return len;
 }
 
-struct property_list_callback_data {
-    void (*propfn)(const char *key, const char *value, void *cookie);
-    void *cookie;
+struct callback_data {
+    void (*callback)(const char* name, const char* value, void* cookie);
+    void* cookie;
 };
 
-static void property_list_callback(const prop_info *pi, void *cookie) {
-    char name[PROP_NAME_MAX];
-    char value[PROP_VALUE_MAX];
-    struct property_list_callback_data *data = cookie;
-
-    __system_property_read(pi, name, value);
-    data->propfn(name, value, data->cookie);
+static void trampoline(void* raw_data, const char* name, const char* value) {
+    callback_data* data = reinterpret_cast<callback_data*>(raw_data);
+    data->callback(name, value, data->cookie);
 }
 
-int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie) {
-    struct property_list_callback_data data = {propfn, cookie};
+static void property_list_callback(const prop_info* pi, void* data) {
+    __system_property_read_callback(pi, trampoline, data);
+}
+
+int property_list(void (*fn)(const char* name, const char* value, void* cookie), void* cookie) {
+    callback_data data = { fn, cookie };
     return __system_property_foreach(property_list_callback, &data);
 }
diff --git a/liblog/event_tag_map.cpp b/liblog/event_tag_map.cpp
index 1155422..c53ea2c 100644
--- a/liblog/event_tag_map.cpp
+++ b/liblog/event_tag_map.cpp
@@ -38,10 +38,9 @@
 
 typedef std::pair<MapString, MapString> TagFmt;
 
-template <> struct _LIBCPP_TYPE_VIS_ONLY std::hash<TagFmt>
+template <> struct std::hash<TagFmt>
         : public std::unary_function<const TagFmt&, size_t> {
-    _LIBCPP_INLINE_VISIBILITY
-    size_t operator()(const TagFmt& __t) const _NOEXCEPT {
+    size_t operator()(const TagFmt& __t) const noexcept {
         // Tag is typically unique.  Will cost us an extra 100ns for the
         // unordered_map lookup if we instead did a hash that combined
         // both of tag and fmt members, e.g.:
diff --git a/liblog/include_vndk/log/log.h b/liblog/include_vndk/log/log.h
index 1e3556c..f93b377 100644
--- a/liblog/include_vndk/log/log.h
+++ b/liblog/include_vndk/log/log.h
@@ -7,6 +7,8 @@
 #include <log/log_id.h>
 #include <log/log_main.h>
 #include <log/log_radio.h>
+#include <log/log_read.h>
+#include <log/log_time.h>
 
 /*
  * LOG_TAG is the local tag used for the following simplified
diff --git a/liblog/include_vndk/log/log_read.h b/liblog/include_vndk/log/log_read.h
new file mode 120000
index 0000000..01de8b9
--- /dev/null
+++ b/liblog/include_vndk/log/log_read.h
@@ -0,0 +1 @@
+../../include/log/log_read.h
\ No newline at end of file
diff --git a/liblog/include_vndk/log/log_time.h b/liblog/include_vndk/log/log_time.h
new file mode 120000
index 0000000..abfe439
--- /dev/null
+++ b/liblog/include_vndk/log/log_time.h
@@ -0,0 +1 @@
+../../include/log/log_time.h
\ No newline at end of file
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index cc65d47..820ff64 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -1100,6 +1100,10 @@
         }
     }
 
+    // Help detect if the valid message before is from the same source so
+    // we can differentiate chatty filter types.
+    pid_t lastTid[LOG_ID_MAX] = { 0 };
+
     for (; it != mLogElements.end(); ++it) {
         LogBufferElement *element = *it;
 
@@ -1126,10 +1130,19 @@
             }
         }
 
+        bool sameTid = lastTid[element->getLogId()] == element->getTid();
+        // Dropped (chatty) immediately following a valid log from the
+        // same source in the same log buffer indicates we have a
+        // multiple identical squash.  chatty that differs source
+        // is due to spam filter.  chatty to chatty of different
+        // source is also due to spam filter.
+        lastTid[element->getLogId()] = (element->getDropped() && !sameTid) ?
+                0 : element->getTid();
+
         pthread_mutex_unlock(&mLogElementsLock);
 
         // range locking in LastLogTimes looks after us
-        max = element->flushTo(reader, this, privileged);
+        max = element->flushTo(reader, this, privileged, sameTid);
 
         if (max == element->FLUSH_ERROR) {
             return max;
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 5e37a30..a651fd4 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -113,8 +113,8 @@
 }
 
 // assumption: mMsg == NULL
-size_t LogBufferElement::populateDroppedMessage(char *&buffer,
-        LogBuffer *parent) {
+size_t LogBufferElement::populateDroppedMessage(char*& buffer,
+        LogBuffer* parent, bool lastSame) {
     static const char tag[] = "chatty";
 
     if (!__android_log_is_loggable_len(ANDROID_LOG_INFO,
@@ -123,7 +123,7 @@
         return 0;
     }
 
-    static const char format_uid[] = "uid=%u%s%s expire %u line%s";
+    static const char format_uid[] = "uid=%u%s%s %s %u line%s";
     parent->lock();
     const char *name = parent->uidToName(mUid);
     parent->unlock();
@@ -165,8 +165,9 @@
         }
     }
     // identical to below to calculate the buffer size required
+    const char* type = lastSame ? "identical" : "expire";
     size_t len = snprintf(NULL, 0, format_uid, mUid, name ? name : "",
-                          commName ? commName : "",
+                          commName ? commName : "", type,
                           mDropped, (mDropped > 1) ? "s" : "");
 
     size_t hdrLen;
@@ -198,7 +199,7 @@
     }
 
     snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "",
-             commName ? commName : "",
+             commName ? commName : "", type,
              mDropped, (mDropped > 1) ? "s" : "");
     free(const_cast<char *>(name));
     free(const_cast<char *>(commName));
@@ -206,8 +207,8 @@
     return retval;
 }
 
-uint64_t LogBufferElement::flushTo(SocketClient *reader, LogBuffer *parent,
-                                   bool privileged) {
+uint64_t LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent,
+                                   bool privileged, bool lastSame) {
     struct logger_entry_v4 entry;
 
     memset(&entry, 0, sizeof(struct logger_entry_v4));
@@ -229,7 +230,7 @@
     char *buffer = NULL;
 
     if (!mMsg) {
-        entry.len = populateDroppedMessage(buffer, parent);
+        entry.len = populateDroppedMessage(buffer, parent, lastSame);
         if (!entry.len) {
             return mSequence;
         }
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index f8ffacd..bd98b9c 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -53,8 +53,9 @@
     static atomic_int_fast64_t sequence;
 
     // assumption: mMsg == NULL
-    size_t populateDroppedMessage(char *&buffer,
-                                  LogBuffer *parent);
+    size_t populateDroppedMessage(char*& buffer,
+                                  LogBuffer* parent,
+                                  bool lastSame);
 public:
     LogBufferElement(log_id_t log_id, log_time realtime,
                      uid_t uid, pid_t pid, pid_t tid,
@@ -86,7 +87,8 @@
     log_time getRealTime(void) const { return mRealTime; }
 
     static const uint64_t FLUSH_ERROR;
-    uint64_t flushTo(SocketClient *writer, LogBuffer *parent, bool privileged);
+    uint64_t flushTo(SocketClient* writer, LogBuffer* parent,
+                     bool privileged, bool lastSame);
 };
 
 #endif
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 13a7922..2a6cdc8 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -853,11 +853,13 @@
 
     int expected_count = (count < 2) ? count : 2;
     int expected_chatty_count = (count <= 2) ? 0 : 1;
-    int expected_expire_count = (count < 2) ? 0 : (count - 2);
+    int expected_identical_count = (count < 2) ? 0 : (count - 2);
+    static const int expected_expire_count = 0;
 
     count = 0;
     int second_count = 0;
     int chatty_count = 0;
+    int identical_count = 0;
     int expire_count = 0;
 
     for (;;) {
@@ -887,11 +889,16 @@
             ++chatty_count;
             // int len = get4LE(eventData + 4 + 1);
             log_msg.buf[LOGGER_ENTRY_MAX_LEN] = '\0';
-            const char *cp = strstr(eventData + 4 + 1 + 4, " expire ");
-            if (!cp) continue;
-            unsigned val = 0;
-            sscanf(cp, " expire %u lines", &val);
-            expire_count += val;
+            const char *cp;
+            if ((cp = strstr(eventData + 4 + 1 + 4, " identical "))) {
+                unsigned val = 0;
+                sscanf(cp, " identical %u lines", &val);
+                identical_count += val;
+            } else if ((cp = strstr(eventData + 4 + 1 + 4, " expire "))) {
+                unsigned val = 0;
+                sscanf(cp, " expire %u lines", &val);
+                expire_count += val;
+            }
         }
     }
 
@@ -900,6 +907,7 @@
     EXPECT_EQ(expected_count, count);
     EXPECT_EQ(1, second_count);
     EXPECT_EQ(expected_chatty_count, chatty_count);
+    EXPECT_EQ(expected_identical_count, identical_count);
     EXPECT_EQ(expected_expire_count, expire_count);
 }