Merge "metricsd: Give directory group permissions"
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 5d7b151..4dbf32f 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -191,7 +191,7 @@
 
 int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
     // Require a matching vendor id if the user specified one with -i.
-    if (vendor_id != 0  && info->dev_vendor != vendor_id) {
+    if (vendor_id != 0 && info->dev_vendor != vendor_id) {
         return -1;
     }
 
@@ -246,7 +246,7 @@
         if(usb) return usb;
         if(announce) {
             announce = 0;
-            fprintf(stderr,"< waiting for device >\n");
+            fprintf(stderr, "< waiting for %s >\n", serial ? serial : "any device");
         }
         usleep(1000);
     }
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index 7ae2aa5..45ae833 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -293,6 +293,13 @@
 
     // So, we have a device, finally. Grab its vitals.
 
+
+    kr = (*dev)->USBDeviceOpen(dev);
+    if (kr != 0) {
+        WARN("USBDeviceOpen");
+        goto out;
+    }
+
     kr = (*dev)->GetDeviceVendor(dev, &handle->info.dev_vendor);
     if (kr != 0) {
         ERR("GetDeviceVendor");
@@ -365,12 +372,16 @@
         goto error;
     }
 
+    out:
+
+    (*dev)->USBDeviceClose(dev);
     (*dev)->Release(dev);
     return 0;
 
     error:
 
     if (dev != NULL) {
+        (*dev)->USBDeviceClose(dev);
         (*dev)->Release(dev);
     }
 
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 128bb04..97f0ef4 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -102,6 +102,11 @@
   uintptr_t relative_pc = BacktraceMap::GetRelativePc(frame->map, frame->pc);
 
   std::string line(StringPrintf("#%02zu pc %" PRIPTR "  %s", frame->num, relative_pc, map_name));
+  // Special handling for non-zero offset maps, we need to print that
+  // information.
+  if (frame->map.offset != 0) {
+    line += " (offset " + StringPrintf("0x%" PRIxPTR, frame->map.offset) + ")";
+  }
   if (!frame->func_name.empty()) {
     line += " (" + frame->func_name;
     if (frame->func_offset) {
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 6bd7529..9ebd639 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -825,6 +825,15 @@
   EXPECT_EQ("#01 pc 123456dc  MapFake (ProcFake+645)",
 #endif
             backtrace->FormatFrameData(&frame));
+
+  // Check a non-zero map offset.
+  frame.map.offset = 0x1000;
+#if defined(__LP64__)
+  EXPECT_EQ("#01 pc 00000000123456dc  MapFake (offset 0x1000) (ProcFake+645)",
+#else
+  EXPECT_EQ("#01 pc 123456dc  MapFake (offset 0x1000) (ProcFake+645)",
+#endif
+            backtrace->FormatFrameData(&frame));
 }
 
 struct map_test_t {
diff --git a/libsparse/backed_block.c b/libsparse/backed_block.c
index 3e72b57..794cd6b 100644
--- a/libsparse/backed_block.c
+++ b/libsparse/backed_block.c
@@ -221,7 +221,8 @@
 		}
 		break;
 	case BACKED_BLOCK_FILE:
-		if (a->file.filename != b->file.filename ||
+		/* Already make sure b->type is BACKED_BLOCK_FILE */
+		if (strcmp(a->file.filename, b->file.filename) ||
 				a->file.offset + a->len != b->file.offset) {
 			return -EINVAL;
 		}
@@ -279,7 +280,10 @@
 	}
 
 	merge_bb(bbl, new_bb, new_bb->next);
-	merge_bb(bbl, bb, new_bb);
+	if (!merge_bb(bbl, bb, new_bb)) {
+		/* new_bb destroyed, point to retained as last_used */
+		bbl->last_used = bb;
+	}
 
 	return 0;
 }
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index d584925..823a842 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -72,7 +72,7 @@
             return;
         }
         entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask, mPid, mStart);
-        times.push_back(entry);
+        times.push_front(entry);
     }
 
     client->incRef();
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index b9e8973..db3f26c 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -217,34 +217,35 @@
     return len;
 }
 
-// If we're using more than 256K of memory for log entries, prune
-// at least 10% of the log entries. For sizes above 1M, prune at
-// least 1% of the log entries.
+// Prune at most 10% of the log entries or 256, whichever is less.
 //
 // mLogElementsLock must be held when this function is called.
 void LogBuffer::maybePrune(log_id_t id) {
     size_t sizes = stats.sizes(id);
     unsigned long maxSize = log_buffer_size(id);
     if (sizes > maxSize) {
-        size_t sizeOver, minElements, elements = stats.elements(id);
-        if (maxSize > (4 * LOG_BUFFER_SIZE)) {
-            sizeOver = sizes - ((maxSize * 99) / 100);
-            minElements = elements / 100;
-        } else {
-            sizeOver = sizes - ((maxSize * 9) / 10);
-            minElements = elements / 10;
-        }
+        size_t sizeOver = sizes - ((maxSize * 9) / 10);
+        size_t elements = stats.elements(id);
+        size_t minElements = elements / 10;
         unsigned long pruneRows = elements * sizeOver / sizes;
         if (pruneRows <= minElements) {
             pruneRows = minElements;
         }
+        if (pruneRows > 256) {
+            pruneRows = 256;
+        }
         prune(id, pruneRows);
     }
 }
 
 LogBufferElementCollection::iterator LogBuffer::erase(LogBufferElementCollection::iterator it) {
     LogBufferElement *e = *it;
+    log_id_t id = e->getLogId();
+    LogBufferIteratorMap::iterator f = mLastWorstUid[id].find(e->getUid());
 
+    if ((f != mLastWorstUid[id].end()) && (it == f->second)) {
+        mLastWorstUid[id].erase(f);
+    }
     it = mLogElements.erase(it);
     stats.subtract(e);
     delete e;
@@ -403,8 +404,17 @@
 
         bool kick = false;
         bool leading = true;
+        it = mLogElements.begin();
+        if (worst != (uid_t) -1) {
+            LogBufferIteratorMap::iterator f = mLastWorstUid[id].find(worst);
+            if ((f != mLastWorstUid[id].end())
+                    && (f->second != mLogElements.end())) {
+                leading = false;
+                it = f->second;
+            }
+        }
         LogBufferElementLast last;
-        for(it = mLogElements.begin(); it != mLogElements.end();) {
+        while (it != mLogElements.end()) {
             LogBufferElement *e = *it;
 
             if (oldest && (oldest->mStart <= e->getSequence())) {
@@ -454,8 +464,10 @@
                 continue;
             }
 
+            // unmerged drop message
             if (dropped) {
                 last.add(e);
+                mLastWorstUid[id][e->getUid()] = it;
                 ++it;
                 continue;
             }
@@ -500,6 +512,7 @@
                     delete e;
                 } else {
                     last.add(e);
+                    mLastWorstUid[id][e->getUid()] = it;
                     ++it;
                 }
             }
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index a13fded..e94598c 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -19,9 +19,10 @@
 
 #include <sys/types.h>
 
+#include <list>
+
 #include <log/log.h>
 #include <sysutils/SocketClient.h>
-#include <utils/List.h>
 
 #include <private/android_filesystem_config.h>
 
@@ -30,7 +31,7 @@
 #include "LogStatistics.h"
 #include "LogWhiteBlackList.h"
 
-typedef android::List<LogBufferElement *> LogBufferElementCollection;
+typedef std::list<LogBufferElement *> LogBufferElementCollection;
 
 class LogBuffer {
     LogBufferElementCollection mLogElements;
@@ -39,6 +40,11 @@
     LogStatistics stats;
 
     PruneList mPrune;
+    // watermark of any worst/chatty uid processing
+    typedef std::unordered_map<uid_t,
+                               LogBufferElementCollection::iterator>
+                LogBufferIteratorMap;
+    LogBufferIteratorMap mLastWorstUid[LOG_ID_MAX];
 
     unsigned long mMaxSize[LOG_ID_MAX];
 
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 783bce6..39bcdd4 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -20,8 +20,10 @@
 #include <pthread.h>
 #include <time.h>
 #include <sys/types.h>
+
+#include <list>
+
 #include <sysutils/SocketClient.h>
-#include <utils/List.h>
 #include <log/log.h>
 
 class LogReader;
@@ -107,6 +109,6 @@
     static int FilterSecondPass(const LogBufferElement *element, void *me);
 };
 
-typedef android::List<LogTimeEntry *> LastLogTimes;
+typedef std::list<LogTimeEntry *> LastLogTimes;
 
-#endif
+#endif // _LOGD_LOG_TIMES_H__
diff --git a/logd/LogWhiteBlackList.cpp b/logd/LogWhiteBlackList.cpp
index 277b3ca..16dd6d2 100644
--- a/logd/LogWhiteBlackList.cpp
+++ b/logd/LogWhiteBlackList.cpp
@@ -50,18 +50,14 @@
 }
 
 PruneList::PruneList() : mWorstUidEnabled(true) {
-    mNaughty.clear();
-    mNice.clear();
 }
 
 PruneList::~PruneList() {
     PruneCollection::iterator it;
     for (it = mNice.begin(); it != mNice.end();) {
-        delete (*it);
         it = mNice.erase(it);
     }
     for (it = mNaughty.begin(); it != mNaughty.end();) {
-        delete (*it);
         it = mNaughty.erase(it);
     }
 }
@@ -70,11 +66,9 @@
     mWorstUidEnabled = true;
     PruneCollection::iterator it;
     for (it = mNice.begin(); it != mNice.end();) {
-        delete (*it);
         it = mNice.erase(it);
     }
     for (it = mNaughty.begin(); it != mNaughty.end();) {
-        delete (*it);
         it = mNaughty.erase(it);
     }
 
@@ -142,28 +136,28 @@
         // insert sequentially into list
         PruneCollection::iterator it = list->begin();
         while (it != list->end()) {
-            Prune *p = *it;
-            int m = uid - p->mUid;
+            Prune &p = *it;
+            int m = uid - p.mUid;
             if (m == 0) {
-                if (p->mPid == p->pid_all) {
+                if (p.mPid == p.pid_all) {
                     break;
                 }
-                if ((pid == p->pid_all) && (p->mPid != p->pid_all)) {
+                if ((pid == p.pid_all) && (p.mPid != p.pid_all)) {
                     it = list->erase(it);
                     continue;
                 }
-                m = pid - p->mPid;
+                m = pid - p.mPid;
             }
             if (m <= 0) {
                 if (m < 0) {
-                    list->insert(it, new Prune(uid,pid));
+                    list->insert(it, Prune(uid,pid));
                 }
                 break;
             }
             ++it;
         }
         if (it == list->end()) {
-            list->push_back(new Prune(uid,pid));
+            list->push_back(Prune(uid,pid));
         }
         if (!*str) {
             break;
@@ -193,7 +187,7 @@
 
     for (it = mNice.begin(); it != mNice.end(); ++it) {
         char *a = NULL;
-        (*it)->format(&a);
+        (*it).format(&a);
 
         string.appendFormat(fmt, a);
         fmt = nice_format;
@@ -205,7 +199,7 @@
     fmt = naughty_format + (*fmt != ' ');
     for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
         char *a = NULL;
-        (*it)->format(&a);
+        (*it).format(&a);
 
         string.appendFormat(fmt, a);
         fmt = naughty_format;
@@ -223,7 +217,7 @@
 bool PruneList::naughty(LogBufferElement *element) {
     PruneCollection::iterator it;
     for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
-        if (!(*it)->cmp(element)) {
+        if (!(*it).cmp(element)) {
             return true;
         }
     }
@@ -233,7 +227,7 @@
 bool PruneList::nice(LogBufferElement *element) {
     PruneCollection::iterator it;
     for (it = mNice.begin(); it != mNice.end(); ++it) {
-        if (!(*it)->cmp(element)) {
+        if (!(*it).cmp(element)) {
             return true;
         }
     }
diff --git a/logd/LogWhiteBlackList.h b/logd/LogWhiteBlackList.h
index 5f60801..57cd03b 100644
--- a/logd/LogWhiteBlackList.h
+++ b/logd/LogWhiteBlackList.h
@@ -19,7 +19,7 @@
 
 #include <sys/types.h>
 
-#include <utils/List.h>
+#include <list>
 
 #include <LogBufferElement.h>
 
@@ -47,7 +47,7 @@
     void format(char **strp);
 };
 
-typedef android::List<Prune *> PruneCollection;
+typedef std::list<Prune> PruneCollection;
 
 class PruneList {
     PruneCollection mNaughty;
diff --git a/metricsd/constants.h b/metricsd/constants.h
index d65e0e0..56dac0d 100644
--- a/metricsd/constants.h
+++ b/metricsd/constants.h
@@ -21,7 +21,7 @@
 static const char kMetricsDirectory[] = "/data/misc/metrics/";
 static const char kMetricsEventsFilePath[] = "/data/misc/metrics/uma-events";
 static const char kMetricsGUIDFilePath[] = "/data/misc/metrics/Sysinfo.GUID";
-static const char kMetricsServer[] = "http://clients4.google.com/uma/v2";
+static const char kMetricsServer[] = "https://clients4.google.com/uma/v2";
 static const char kConsentFilePath[] = "/data/misc/metrics/enabled";
 static const char kDefaultVersion[] = "0.0.0.0";
 }  // namespace metrics
diff --git a/metricsd/uploader/metrics_log.cc b/metricsd/uploader/metrics_log.cc
index 5f4c599..1f16ca1 100644
--- a/metricsd/uploader/metrics_log.cc
+++ b/metricsd/uploader/metrics_log.cc
@@ -48,6 +48,6 @@
   stability->set_unclean_system_shutdown_count(current + 1);
 }
 
-void MetricsLog::PopulateSystemProfile(SystemProfileSetter* profile_setter) {
-  profile_setter->Populate(uma_proto());
+bool MetricsLog::PopulateSystemProfile(SystemProfileSetter* profile_setter) {
+  return profile_setter->Populate(uma_proto());
 }
diff --git a/metricsd/uploader/metrics_log.h b/metricsd/uploader/metrics_log.h
index 50fed89..5e09070 100644
--- a/metricsd/uploader/metrics_log.h
+++ b/metricsd/uploader/metrics_log.h
@@ -39,7 +39,7 @@
   void IncrementUncleanShutdownCount();
 
   // Populate the system profile with system information using setter.
-  void PopulateSystemProfile(SystemProfileSetter* setter);
+  bool PopulateSystemProfile(SystemProfileSetter* setter);
 
  private:
   FRIEND_TEST(UploadServiceTest, LogContainsAggregatedValues);
diff --git a/metricsd/uploader/system_profile_cache.cc b/metricsd/uploader/system_profile_cache.cc
index 35910d7..7dd0323 100644
--- a/metricsd/uploader/system_profile_cache.cc
+++ b/metricsd/uploader/system_profile_cache.cc
@@ -75,7 +75,7 @@
 
   if (!base::SysInfo::GetLsbReleaseValue("BRILLO_BUILD_TARGET_ID",
                                          &profile_.build_target_id)) {
-    LOG(ERROR) << "Could not initialize system profile.";
+    LOG(ERROR) << "BRILLO_BUILD_TARGET_ID is not set in /etc/lsb-release.";
     return false;
   }
 
@@ -109,11 +109,12 @@
   return initialized_ || Initialize();
 }
 
-void SystemProfileCache::Populate(
+bool SystemProfileCache::Populate(
     metrics::ChromeUserMetricsExtension* metrics_proto) {
   CHECK(metrics_proto);
-  CHECK(InitializeOrCheck())
-      << "failed to initialize system information.";
+  if (not InitializeOrCheck()) {
+    return false;
+  }
 
   // The client id is hashed before being sent.
   metrics_proto->set_client_id(
@@ -132,6 +133,8 @@
   metrics::SystemProfileProto_BrilloDeviceData* device_data =
       profile_proto->mutable_brillo();
   device_data->set_build_target_id(profile_.build_target_id);
+
+  return true;
 }
 
 std::string SystemProfileCache::GetPersistentGUID(
diff --git a/metricsd/uploader/system_profile_cache.h b/metricsd/uploader/system_profile_cache.h
index c53a18e..ac80b47 100644
--- a/metricsd/uploader/system_profile_cache.h
+++ b/metricsd/uploader/system_profile_cache.h
@@ -52,7 +52,7 @@
   SystemProfileCache(bool testing, const std::string& config_root);
 
   // Populates the ProfileSystem protobuf with system information.
-  void Populate(metrics::ChromeUserMetricsExtension* metrics_proto) override;
+  bool Populate(metrics::ChromeUserMetricsExtension* metrics_proto) override;
 
   // Converts a string representation of the channel to a
   // SystemProfileProto_Channel
diff --git a/metricsd/uploader/system_profile_setter.h b/metricsd/uploader/system_profile_setter.h
index cd311a4..bd3ff42 100644
--- a/metricsd/uploader/system_profile_setter.h
+++ b/metricsd/uploader/system_profile_setter.h
@@ -27,7 +27,7 @@
  public:
   virtual ~SystemProfileSetter() {}
   // Populates the protobuf with system informations.
-  virtual void Populate(metrics::ChromeUserMetricsExtension* profile_proto) = 0;
+  virtual bool Populate(metrics::ChromeUserMetricsExtension* profile_proto) = 0;
 };
 
 #endif  // METRICS_UPLOADER_SYSTEM_PROFILE_SETTER_H_
diff --git a/metricsd/uploader/upload_service.cc b/metricsd/uploader/upload_service.cc
index 63b5789..2335630 100644
--- a/metricsd/uploader/upload_service.cc
+++ b/metricsd/uploader/upload_service.cc
@@ -73,7 +73,6 @@
   CHECK(!staged_log_) << "the staged log should be discarded before starting "
                          "a new metrics log";
   MetricsLog* log = new MetricsLog();
-  log->PopulateSystemProfile(system_profile_setter_.get());
   current_log_.reset(log);
 }
 
@@ -97,13 +96,12 @@
   // Previous upload successful, reading metrics sample from the file.
   ReadMetrics();
   GatherHistograms();
-
-  // No samples found. Exit to avoid sending an empty log.
-  if (!current_log_)
-    return;
-
   StageCurrentLog();
-  SendStagedLog();
+
+  // If a log is available for upload, upload it.
+  if (staged_log_) {
+    SendStagedLog();
+  }
 }
 
 void UploadService::SendStagedLog() {
@@ -225,6 +223,11 @@
 
   staged_log_.swap(current_log_);
   staged_log_->CloseLog();
+  if (!staged_log_->PopulateSystemProfile(system_profile_setter_.get())) {
+    LOG(WARNING) << "Error while adding metadata to the log. Discarding the "
+                 << "log.";
+    staged_log_.reset();
+  }
   failed_upload_count_ = 0;
 }