merge in nougat-cts-release history after reset to nougat-cts-dev
diff --git a/simpleperf/environment.cpp b/simpleperf/environment.cpp
index 5a8552a..a73aa1c 100644
--- a/simpleperf/environment.cpp
+++ b/simpleperf/environment.cpp
@@ -477,3 +477,17 @@
 #endif
   return true;
 }
+
+bool GetMaxSampleFrequency(uint64_t* max_sample_freq) {
+  std::string s;
+  if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_max_sample_rate", &s)) {
+    PLOG(DEBUG) << "failed to read /proc/sys/kernel/perf_event_max_sample_rate";
+    return false;
+  }
+  s = android::base::Trim(s);
+  if (!android::base::ParseUint(s.c_str(), max_sample_freq)) {
+    LOG(ERROR) << "failed to parse /proc/sys/kernel/perf_event_max_sample_rate: " << s;
+    return false;
+  }
+  return true;
+}
diff --git a/simpleperf/environment.h b/simpleperf/environment.h
index 6da632b..0b565ea 100644
--- a/simpleperf/environment.h
+++ b/simpleperf/environment.h
@@ -80,5 +80,6 @@
 bool ProcessKernelSymbols(const std::string& symbol_file,
                           std::function<bool(const KernelSymbol&)> callback);
 bool CheckPerfEventLimit();
+bool GetMaxSampleFrequency(uint64_t* max_sample_freq);
 
 #endif  // SIMPLE_PERF_ENVIRONMENT_H_
diff --git a/simpleperf/event_fd.cpp b/simpleperf/event_fd.cpp
index 808639b..80becb2 100644
--- a/simpleperf/event_fd.cpp
+++ b/simpleperf/event_fd.cpp
@@ -31,6 +31,7 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 
+#include "environment.h"
 #include "event_type.h"
 #include "perf_event.h"
 #include "utils.h"
@@ -44,13 +45,20 @@
 
 std::unique_ptr<EventFd> EventFd::OpenEventFile(const perf_event_attr& attr, pid_t tid, int cpu,
                                                 bool report_error) {
-  perf_event_attr perf_attr = attr;
   std::string event_name = "unknown event";
-  const EventType* event_type = FindEventTypeByConfig(perf_attr.type, perf_attr.config);
+  const EventType* event_type = FindEventTypeByConfig(attr.type, attr.config);
   if (event_type != nullptr) {
     event_name = event_type->name;
   }
-  int perf_event_fd = perf_event_open(&perf_attr, tid, cpu, -1, 0);
+  perf_event_attr real_attr = attr;
+  if (attr.freq) {
+    uint64_t max_sample_freq;
+    if (GetMaxSampleFrequency(&max_sample_freq) && max_sample_freq < attr.sample_freq) {
+      PLOG(INFO) << "Adjust sample freq to max allowed sample freq " << max_sample_freq;
+      real_attr.sample_freq = max_sample_freq;
+    }
+  }
+  int perf_event_fd = perf_event_open(&real_attr, tid, cpu, -1, 0);
   if (perf_event_fd == -1) {
     if (report_error) {
       PLOG(ERROR) << "open perf_event_file (event " << event_name << ", tid " << tid << ", cpu "