Merge "adbd: unconditionally call setgroups"
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
index 9d7d152..d7088b4 100644
--- a/logd/CommandListener.cpp
+++ b/logd/CommandListener.cpp
@@ -74,9 +74,9 @@
 int CommandListener::ClearCmd::runCommand(SocketClient *cli,
                                          int argc, char **argv) {
     setname();
-    if (!clientHasLogCredentials(cli)) {
-        cli->sendMsg("Permission Denied");
-        return 0;
+    uid_t uid = cli->getUid();
+    if (clientHasLogCredentials(cli)) {
+        uid = AID_ROOT;
     }
 
     if (argc < 2) {
@@ -90,7 +90,7 @@
         return 0;
     }
 
-    mBuf.clear((log_id_t) id);
+    mBuf.clear((log_id_t) id, uid);
     cli->sendMsg("success");
     return 0;
 }
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 0448afa..cd9ea20 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -232,7 +232,7 @@
 // prune "pruneRows" of type "id" from the buffer.
 //
 // mLogElementsLock must be held when this function is called.
-void LogBuffer::prune(log_id_t id, unsigned long pruneRows) {
+void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
     LogTimeEntry *oldest = NULL;
 
     LogTimeEntry::lock();
@@ -250,6 +250,38 @@
 
     LogBufferElementCollection::iterator it;
 
+    if (caller_uid != AID_ROOT) {
+        for(it = mLogElements.begin(); it != mLogElements.end();) {
+            LogBufferElement *e = *it;
+
+            if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+                break;
+            }
+
+            if (e->getLogId() != id) {
+                ++it;
+                continue;
+            }
+
+            uid_t uid = e->getUid();
+
+            if (uid == caller_uid) {
+                it = mLogElements.erase(it);
+                unsigned short len = e->getMsgLen();
+                stats.subtract(len, id, uid, e->getPid());
+                delete e;
+                pruneRows--;
+                if (pruneRows == 0) {
+                    break;
+                }
+            } else {
+                ++it;
+            }
+        }
+        LogTimeEntry::unlock();
+        return;
+    }
+
     // prune by worst offender by uid
     while (pruneRows > 0) {
         // recalculate the worst offender on every batched pass
@@ -375,9 +407,9 @@
 }
 
 // clear all rows of type "id" from the buffer.
-void LogBuffer::clear(log_id_t id) {
+void LogBuffer::clear(log_id_t id, uid_t uid) {
     pthread_mutex_lock(&mLogElementsLock);
-    prune(id, ULONG_MAX);
+    prune(id, ULONG_MAX, uid);
     pthread_mutex_unlock(&mLogElementsLock);
 }
 
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index b8a54b9..4b982a8 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -23,6 +23,8 @@
 #include <sysutils/SocketClient.h>
 #include <utils/List.h>
 
+#include <private/android_filesystem_config.h>
+
 #include "LogBufferElement.h"
 #include "LogTimes.h"
 #include "LogStatistics.h"
@@ -55,7 +57,7 @@
                      bool (*filter)(const LogBufferElement *element, void *arg) = NULL,
                      void *arg = NULL);
 
-    void clear(log_id_t id);
+    void clear(log_id_t id, uid_t uid = AID_ROOT);
     unsigned long getSize(log_id_t id);
     int setSize(log_id_t id, unsigned long size);
     unsigned long getSizeUsed(log_id_t id);
@@ -77,7 +79,7 @@
 
 private:
     void maybePrune(log_id_t id);
-    void prune(log_id_t id, unsigned long pruneRows);
+    void prune(log_id_t id, unsigned long pruneRows, uid_t uid = AID_ROOT);
 
 };
 
diff --git a/logd/tests/Android.mk b/logd/tests/Android.mk
index 123e317..f851288 100644
--- a/logd/tests/Android.mk
+++ b/logd/tests/Android.mk
@@ -34,7 +34,7 @@
     -Werror \
     -fno-builtin \
 
-ifeq ($(TARGET_USES_LOGD),true)
+ifneq ($(TARGET_USES_LOGD),false)
 test_c_flags += -DTARGET_USES_LOGD=1
 endif
 
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 5b51b1f..957fdb5 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -568,10 +568,11 @@
 
     while (fgets(buffer, sizeof(buffer), fp)) {
         for (unsigned i = 0; i < sizeof(ns) / sizeof(ns[0]); ++i) {
-            if (strncmp(benchmarks[i], buffer, strlen(benchmarks[i]))) {
+            char *cp = strstr(buffer, benchmarks[i]);
+            if (!cp) {
                 continue;
             }
-            sscanf(buffer, "%*s %lu %lu", &ns[i], &ns[i]);
+            sscanf(cp, "%*s %lu %lu", &ns[i], &ns[i]);
             fprintf(stderr, "%-22s%8lu\n", benchmarks[i], ns[i]);
         }
     }
@@ -592,15 +593,15 @@
 #endif
 
 #ifdef TARGET_USES_LOGD
-    EXPECT_GE(25000UL, ns[log_maximum]); // 14055 user
+    EXPECT_GE(30000UL, ns[log_maximum]); // 27305 user
 #else
     EXPECT_GE(10000UL, ns[log_maximum]); // 5637 kernel
 #endif
 
-    EXPECT_GE(4000UL, ns[clock_overhead]); // 2008
+    EXPECT_GE(4096UL, ns[clock_overhead]); // 4095
 
 #ifdef TARGET_USES_LOGD
-    EXPECT_GE(250000UL, ns[log_overhead]); // 113219 user
+    EXPECT_GE(250000UL, ns[log_overhead]); // 121876 user
 #else
     EXPECT_GE(100000UL, ns[log_overhead]); // 50945 kernel
 #endif
@@ -612,7 +613,7 @@
 #endif
 
 #ifdef TARGET_USES_LOGD
-    EXPECT_GE(20000000UL, ns[log_delay]); // 9542541 user
+    EXPECT_GE(20000000UL, ns[log_delay]); // 10500289 user
 #else
     EXPECT_GE(55000UL, ns[log_delay]); // 27341 kernel
 #endif
@@ -642,36 +643,61 @@
     // 0/4225?     7454388/303656      31488/755
     //                                 ^-- benchmark_statistics_found
 
-    unsigned long nowSize = atol(benchmark_statistics_found);
+    unsigned long nowSpamSize = atol(benchmark_statistics_found);
 
     delete [] buf;
 
-    ASSERT_NE(0UL, nowSize);
+    ASSERT_NE(0UL, nowSpamSize);
 
+    // Determine if we have the spam filter enabled
     int sock = socket_local_client("logd",
                                    ANDROID_SOCKET_NAMESPACE_RESERVED,
                                    SOCK_STREAM);
+
+    ASSERT_TRUE(sock >= 0);
+
+    static const char getPruneList[] = "getPruneList";
+    if (write(sock, getPruneList, sizeof(getPruneList)) > 0) {
+        char buffer[80];
+        memset(buffer, 0, sizeof(buffer));
+        read(sock, buffer, sizeof(buffer));
+        char *cp = strchr(buffer, '\n');
+        if (!cp || (cp[1] != '~') || (cp[2] != '!')) {
+            close(sock);
+            fprintf(stderr,
+                    "WARNING: "
+                    "Logger has SPAM filtration turned off \"%s\"\n", buffer);
+            return;
+        }
+    } else {
+        int save_errno = errno;
+        close(sock);
+        FAIL() << "Can not send " << getPruneList << " to logger -- " << strerror(save_errno);
+    }
+
     static const unsigned long expected_absolute_minimum_log_size = 65536UL;
     unsigned long totalSize = expected_absolute_minimum_log_size;
-    if (sock >= 0) {
-        static const char getSize[] = {
-            'g', 'e', 't', 'L', 'o', 'g', 'S', 'i', 'z', 'e', ' ',
-            LOG_ID_MAIN + '0', '\0'
-        };
-        if (write(sock, getSize, sizeof(getSize)) > 0) {
-            char buffer[80];
-            memset(buffer, 0, sizeof(buffer));
-            read(sock, buffer, sizeof(buffer));
-            totalSize = atol(buffer);
-            if (totalSize < expected_absolute_minimum_log_size) {
-                totalSize = expected_absolute_minimum_log_size;
-            }
+    static const char getSize[] = {
+        'g', 'e', 't', 'L', 'o', 'g', 'S', 'i', 'z', 'e', ' ',
+        LOG_ID_MAIN + '0', '\0'
+    };
+    if (write(sock, getSize, sizeof(getSize)) > 0) {
+        char buffer[80];
+        memset(buffer, 0, sizeof(buffer));
+        read(sock, buffer, sizeof(buffer));
+        totalSize = atol(buffer);
+        if (totalSize < expected_absolute_minimum_log_size) {
+            fprintf(stderr,
+                    "WARNING: "
+                    "Logger had unexpected referenced size \"%s\"\n", buffer);
+            totalSize = expected_absolute_minimum_log_size;
         }
-        close(sock);
     }
+    close(sock);
+
     // logd allows excursions to 110% of total size
     totalSize = (totalSize * 11 ) / 10;
 
     // 50% threshold for SPAM filter (<20% typical, lots of engineering margin)
-    ASSERT_GT(totalSize, nowSize * 2);
+    ASSERT_GT(totalSize, nowSpamSize * 2);
 }