Revert "Revert "Add profman tool: responsible to process profiles""

This reverts commit 3da74687e42de7d33a8e75df9bd64374e650f75e.

Change-Id: Id005096bd8063c6c602744d4476d5eb7e0d34e90
diff --git a/runtime/base/scoped_flock.cc b/runtime/base/scoped_flock.cc
index 814cbd0..0e8031f 100644
--- a/runtime/base/scoped_flock.cc
+++ b/runtime/base/scoped_flock.cc
@@ -83,7 +83,7 @@
 }
 
 bool ScopedFlock::Init(File* file, std::string* error_msg) {
-  file_.reset(new File(dup(file->Fd()), true));
+  file_.reset(new File(dup(file->Fd()), file->GetPath(), file->CheckUsage(), file->ReadOnlyMode()));
   if (file_->Fd() == -1) {
     file_.reset();
     *error_msg = StringPrintf("Failed to duplicate open file '%s': %s",
@@ -114,7 +114,13 @@
   if (file_.get() != nullptr) {
     int flock_result = TEMP_FAILURE_RETRY(flock(file_->Fd(), LOCK_UN));
     CHECK_EQ(0, flock_result);
-    if (file_->FlushCloseOrErase() != 0) {
+    int close_result = -1;
+    if (file_->ReadOnlyMode()) {
+      close_result = file_->Close();
+    } else {
+      close_result = file_->FlushCloseOrErase();
+    }
+    if (close_result != 0) {
       PLOG(WARNING) << "Could not close scoped file lock file.";
     }
   }
diff --git a/runtime/base/unix_file/fd_file.cc b/runtime/base/unix_file/fd_file.cc
index e17bebb..4672948 100644
--- a/runtime/base/unix_file/fd_file.cc
+++ b/runtime/base/unix_file/fd_file.cc
@@ -35,18 +35,22 @@
 
 namespace unix_file {
 
-FdFile::FdFile() : guard_state_(GuardState::kClosed), fd_(-1), auto_close_(true) {
+FdFile::FdFile()
+    : guard_state_(GuardState::kClosed), fd_(-1), auto_close_(true), read_only_mode_(false) {
 }
 
 FdFile::FdFile(int fd, bool check_usage)
     : guard_state_(check_usage ? GuardState::kBase : GuardState::kNoCheck),
-      fd_(fd), auto_close_(true) {
+      fd_(fd), auto_close_(true), read_only_mode_(false) {
 }
 
 FdFile::FdFile(int fd, const std::string& path, bool check_usage)
+    : FdFile(fd, path, check_usage, false) {
+}
+
+FdFile::FdFile(int fd, const std::string& path, bool check_usage, bool read_only_mode)
     : guard_state_(check_usage ? GuardState::kBase : GuardState::kNoCheck),
-      fd_(fd), file_path_(path), auto_close_(true) {
-  CHECK_NE(0U, path.size());
+      fd_(fd), file_path_(path), auto_close_(true), read_only_mode_(read_only_mode) {
 }
 
 FdFile::~FdFile() {
@@ -99,6 +103,7 @@
 
 bool FdFile::Open(const std::string& path, int flags, mode_t mode) {
   CHECK_EQ(fd_, -1) << path;
+  read_only_mode_ = (flags & O_RDONLY) != 0;
   fd_ = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
   if (fd_ == -1) {
     return false;
@@ -136,6 +141,7 @@
 }
 
 int FdFile::Flush() {
+  DCHECK(!read_only_mode_);
 #ifdef __linux__
   int rc = TEMP_FAILURE_RETRY(fdatasync(fd_));
 #else
@@ -155,6 +161,7 @@
 }
 
 int FdFile::SetLength(int64_t new_length) {
+  DCHECK(!read_only_mode_);
 #ifdef __linux__
   int rc = TEMP_FAILURE_RETRY(ftruncate64(fd_, new_length));
 #else
@@ -171,6 +178,7 @@
 }
 
 int64_t FdFile::Write(const char* buf, int64_t byte_count, int64_t offset) {
+  DCHECK(!read_only_mode_);
 #ifdef __linux__
   int rc = TEMP_FAILURE_RETRY(pwrite64(fd_, buf, byte_count, offset));
 #else
@@ -184,6 +192,14 @@
   return fd_;
 }
 
+bool FdFile::ReadOnlyMode() const {
+  return read_only_mode_;
+}
+
+bool FdFile::CheckUsage() const {
+  return guard_state_ != GuardState::kNoCheck;
+}
+
 bool FdFile::IsOpened() const {
   return fd_ >= 0;
 }
@@ -219,6 +235,7 @@
 }
 
 bool FdFile::WriteFully(const void* buffer, size_t byte_count) {
+  DCHECK(!read_only_mode_);
   const char* ptr = static_cast<const char*>(buffer);
   moveTo(GuardState::kBase, GuardState::kClosed, "Writing into closed file.");
   while (byte_count > 0) {
@@ -233,6 +250,7 @@
 }
 
 bool FdFile::Copy(FdFile* input_file, int64_t offset, int64_t size) {
+  DCHECK(!read_only_mode_);
   off_t off = static_cast<off_t>(offset);
   off_t sz = static_cast<off_t>(size);
   if (offset < 0 || static_cast<int64_t>(off) != offset ||
@@ -279,12 +297,14 @@
 }
 
 void FdFile::Erase() {
+  DCHECK(!read_only_mode_);
   TEMP_FAILURE_RETRY(SetLength(0));
   TEMP_FAILURE_RETRY(Flush());
   TEMP_FAILURE_RETRY(Close());
 }
 
 int FdFile::FlushCloseOrErase() {
+  DCHECK(!read_only_mode_);
   int flush_result = TEMP_FAILURE_RETRY(Flush());
   if (flush_result != 0) {
     LOG(::art::ERROR) << "CloseOrErase failed while flushing a file.";
@@ -301,6 +321,7 @@
 }
 
 int FdFile::FlushClose() {
+  DCHECK(!read_only_mode_);
   int flush_result = TEMP_FAILURE_RETRY(Flush());
   if (flush_result != 0) {
     LOG(::art::ERROR) << "FlushClose failed while flushing a file.";
@@ -317,6 +338,7 @@
 }
 
 bool FdFile::ClearContent() {
+  DCHECK(!read_only_mode_);
   if (SetLength(0) < 0) {
     PLOG(art::ERROR) << "Failed to reset the length";
     return false;
@@ -325,6 +347,7 @@
 }
 
 bool FdFile::ResetOffset() {
+  DCHECK(!read_only_mode_);
   off_t rc =  TEMP_FAILURE_RETRY(lseek(fd_, 0, SEEK_SET));
   if (rc == static_cast<off_t>(-1)) {
     PLOG(art::ERROR) << "Failed to reset the offset";
diff --git a/runtime/base/unix_file/fd_file.h b/runtime/base/unix_file/fd_file.h
index 1e2d8af..8040afe 100644
--- a/runtime/base/unix_file/fd_file.h
+++ b/runtime/base/unix_file/fd_file.h
@@ -37,6 +37,7 @@
   // file descriptor. (Use DisableAutoClose to retain ownership.)
   FdFile(int fd, bool checkUsage);
   FdFile(int fd, const std::string& path, bool checkUsage);
+  FdFile(int fd, const std::string& path, bool checkUsage, bool read_only_mode);
 
   // Destroys an FdFile, closing the file descriptor if Close hasn't already
   // been called. (If you care about the return value of Close, call it
@@ -68,6 +69,8 @@
 
   // Bonus API.
   int Fd() const;
+  bool ReadOnlyMode() const;
+  bool CheckUsage() const;
   bool IsOpened() const;
   const std::string& GetPath() const {
     return file_path_;
@@ -119,6 +122,7 @@
   int fd_;
   std::string file_path_;
   bool auto_close_;
+  bool read_only_mode_;
 
   DISALLOW_COPY_AND_ASSIGN(FdFile);
 };
diff --git a/runtime/jit/offline_profiling_info.cc b/runtime/jit/offline_profiling_info.cc
index 0aff1f7..747b112 100644
--- a/runtime/jit/offline_profiling_info.cc
+++ b/runtime/jit/offline_profiling_info.cc
@@ -125,8 +125,8 @@
  *    app.apk,131232145,11,23,454,54
  *    app.apk:classes5.dex,218490184,39,13,49,1
  **/
-bool ProfileCompilationInfo::Save(uint32_t fd) {
-  DCHECK_GE(fd, 0u);
+bool ProfileCompilationInfo::Save(int fd) {
+  DCHECK_GE(fd, 0);
   // TODO(calin): Profile this and see how much memory it takes. If too much,
   // write to file directly.
   std::ostringstream os;
@@ -232,8 +232,8 @@
   return new_line_pos == -1 ? new_line_pos : new_line_pos + 1;
 }
 
-bool ProfileCompilationInfo::Load(uint32_t fd) {
-  DCHECK_GE(fd, 0u);
+bool ProfileCompilationInfo::Load(int fd) {
+  DCHECK_GE(fd, 0);
 
   std::string current_line;
   const int kBufferSize = 1024;
@@ -343,7 +343,7 @@
   return os.str();
 }
 
-bool ProfileCompilationInfo::Equals(ProfileCompilationInfo& other) {
+bool ProfileCompilationInfo::Equals(const ProfileCompilationInfo& other) {
   return info_.Equals(other.info_);
 }
 
diff --git a/runtime/jit/offline_profiling_info.h b/runtime/jit/offline_profiling_info.h
index c388c4a..edc591c 100644
--- a/runtime/jit/offline_profiling_info.h
+++ b/runtime/jit/offline_profiling_info.h
@@ -46,11 +46,11 @@
                                 const std::vector<ArtMethod*>& methods);
 
   // Loads profile information from the given file descriptor.
-  bool Load(uint32_t fd);
+  bool Load(int fd);
   // Loads the data from another ProfileCompilationInfo object.
   bool Load(const ProfileCompilationInfo& info);
   // Saves the profile data to the given file descriptor.
-  bool Save(uint32_t fd);
+  bool Save(int fd);
   // Returns the number of methods that were profiled.
   uint32_t GetNumberOfMethods() const;
 
@@ -65,8 +65,7 @@
                        bool print_full_dex_location = true) const;
 
   // For testing purposes.
-  bool Equals(ProfileCompilationInfo& other);
-  // Exposed for testing purpose.
+  bool Equals(const ProfileCompilationInfo& other);
   static std::string GetProfileDexFileKey(const std::string& dex_location);
 
  private:
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 07f94c0..13564a6 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -1392,9 +1392,8 @@
   return filename;
 }
 
-bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) {
+int ExecAndReturnCode(std::vector<std::string>& arg_vector, std::string* error_msg) {
   const std::string command_line(Join(arg_vector, ' '));
-
   CHECK_GE(arg_vector.size(), 1U) << command_line;
 
   // Convert the args to char pointers.
@@ -1417,7 +1416,6 @@
     setpgid(0, 0);
 
     execv(program, &args[0]);
-
     PLOG(ERROR) << "Failed to execv(" << command_line << ")";
     // _exit to avoid atexit handlers in child.
     _exit(1);
@@ -1425,23 +1423,32 @@
     if (pid == -1) {
       *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
                                 command_line.c_str(), strerror(errno));
-      return false;
+      return -1;
     }
 
     // wait for subprocess to finish
-    int status;
+    int status = -1;
     pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
     if (got_pid != pid) {
       *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
                                 "wanted %d, got %d: %s",
                                 command_line.c_str(), pid, got_pid, strerror(errno));
-      return false;
+      return -1;
     }
-    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
-      *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
-                                command_line.c_str());
-      return false;
+    if (WIFEXITED(status)) {
+      return WEXITSTATUS(status);
     }
+    return -1;
+  }
+}
+
+bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) {
+  int status = ExecAndReturnCode(arg_vector, error_msg);
+  if (status != 0) {
+    const std::string command_line(Join(arg_vector, ' '));
+    *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
+                              command_line.c_str());
+    return false;
   }
   return true;
 }
diff --git a/runtime/utils.h b/runtime/utils.h
index c00db11..36f9abf 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -287,6 +287,7 @@
 
 // Wrapper on fork/execv to run a command in a subprocess.
 bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg);
+int ExecAndReturnCode(std::vector<std::string>& arg_vector, std::string* error_msg);
 
 // Returns true if the file exists.
 bool FileExists(const std::string& filename);
@@ -343,7 +344,7 @@
                             UsageFn Usage,
                             bool is_long_option = true) {
   std::string option_prefix = option_name + (is_long_option ? "=" : "");
-  DCHECK(option.starts_with(option_prefix));
+  DCHECK(option.starts_with(option_prefix)) << option << " " << option_prefix;
   const char* value_string = option.substr(option_prefix.size()).data();
   int64_t parsed_integer_value = 0;
   if (!ParseInt(value_string, &parsed_integer_value)) {