Merge "adb / libbase: clean up NOGDI and evil ERROR macro"
diff --git a/base/file.cpp b/base/file.cpp
index 6b19818..9a340b7 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -51,7 +51,7 @@
     return false;
   }
   bool result = ReadFdToString(fd, content);
-  TEMP_FAILURE_RETRY(close(fd));
+  close(fd);
   return result;
 }
 
@@ -102,7 +102,7 @@
     ALOGE("android::WriteStringToFile write failed: %s", strerror(errno));
     return CleanUpAfterFailedWrite(path);
   }
-  TEMP_FAILURE_RETRY(close(fd));
+  close(fd);
   return true;
 }
 #endif
@@ -116,7 +116,7 @@
   }
 
   bool result = WriteStringToFd(content, fd);
-  TEMP_FAILURE_RETRY(close(fd));
+  close(fd);
   return result || CleanUpAfterFailedWrite(path);
 }
 
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index c33dca6..8c0a0be 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -295,7 +295,8 @@
         ssize_t index = -1;
         while((index = next(index)) >= 0) {
             LogBufferElement *l = editEntryAt(index).getLast();
-            if ((l->getDropped() >= 4) && (current > l->getRealTime().nsec())) {
+            if ((l->getDropped() >= EXPIRE_THRESHOLD)
+                    && (current > l->getRealTime().nsec())) {
                 removeAt(index);
                 index = -1;
             }
@@ -387,6 +388,7 @@
         bool kick = false;
         bool leading = true;
         LogBufferElementLast last;
+        log_time start(log_time::EPOCH);
         for(it = mLogElements.begin(); it != mLogElements.end();) {
             LogBufferElement *e = *it;
 
@@ -446,11 +448,29 @@
             }
 
             if (e->getUid() != worst) {
+                if (start != log_time::EPOCH) {
+                    static const timespec too_old = {
+                        EXPIRE_HOUR_THRESHOLD * 60 * 60, 0
+                    };
+                    start = e->getRealTime() + too_old;
+                }
                 last.clear(e);
                 ++it;
                 continue;
             }
 
+            if ((start != log_time::EPOCH) && (e->getRealTime() > start)) {
+                // KISS. Really a heuristic rather than algorithmically strong,
+                // a crude mechanism, the following loops will move the oldest
+                // watermark possibly wiping out the extra EXPIRE_HOUR_THRESHOLD
+                // we just thought we were preserving. We count on the typical
+                // pruneRows of 10% of total not being a sledgehammer.
+                // A stronger algorithm would have us loop back to the top if
+                // we have worst-UID enabled and we start expiring messages
+                // below less than EXPIRE_HOUR_THRESHOLD old.
+                break;
+            }
+
             pruneRows--;
             if (pruneRows == 0) {
                 break;
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index 5dabaac..3dcf9d1 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -48,6 +48,11 @@
 
 class LogBuffer;
 
+#define EXPIRE_HOUR_THRESHOLD 24 // Only expire chatty UID logs to preserve
+                                 // non-chatty UIDs less than this age in hours
+#define EXPIRE_THRESHOLD 4       // A smaller expire count is considered too
+                                 // chatty for the temporal expire messages
+
 class LogBufferElement {
     const log_id_t mLogId;
     const uid_t mUid;