Merge "[gatekeeperd] verify a password after enrolling successfully" into mnc-dev
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 909592d..fd9953c 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -146,6 +146,13 @@
         "  adb reverse --remove-all     - remove all reversed socket connections from device\n"
         "  adb jdwp                     - list PIDs of processes hosting a JDWP transport\n"
         "  adb install [-lrtsdg] <file>\n"
+        "                               - push this package file to the device and install it\n"
+        "                                 (-l: forward lock application)\n"
+        "                                 (-r: replace existing application)\n"
+        "                                 (-t: allow test packages)\n"
+        "                                 (-s: install application on sdcard)\n"
+        "                                 (-d: allow version code downgrade)\n"
+        "                                 (-g: grant all runtime permissions)\n"
         "  adb install-multiple [-lrtsdpg] <file...>\n"
         "                               - push this package file to the device and install it\n"
         "                                 (-l: forward lock application)\n"
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
index 95cd4d1..2714d93 100644
--- a/libbacktrace/BacktraceCurrent.cpp
+++ b/libbacktrace/BacktraceCurrent.cpp
@@ -96,7 +96,7 @@
 static void SignalHandler(int, siginfo_t*, void* sigcontext) {
   ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false);
   if (!entry) {
-    BACK_LOGW("Unable to find pid %d tid %d information", getpid(), gettid());
+    BACK_LOGE("pid %d, tid %d entry not found", getpid(), gettid());
     return;
   }
 
@@ -109,9 +109,14 @@
   // the thread run ahead causing problems.
   // The number indicates that we are waiting for the second Wake() call
   // overall which is made by the thread requesting an unwind.
-  entry->Wait(2);
-
-  ThreadEntry::Remove(entry);
+  if (entry->Wait(2)) {
+    // Do not remove the entry here because that can result in a deadlock
+    // if the code cannot properly send a signal to the thread under test.
+    entry->Wake();
+  } else {
+    // At this point, it is possible that entry has been freed, so just exit.
+    BACK_LOGE("Timed out waiting for unwind thread to indicate it completed.");
+  }
 }
 
 bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) {
@@ -128,17 +133,15 @@
   act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
   sigemptyset(&act.sa_mask);
   if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) {
-    BACK_LOGW("sigaction failed %s", strerror(errno));
-    entry->Unlock();
+    BACK_LOGE("sigaction failed: %s", strerror(errno));
     ThreadEntry::Remove(entry);
     pthread_mutex_unlock(&g_sigaction_mutex);
     return false;
   }
 
   if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) {
-    BACK_LOGW("tgkill %d failed: %s", Tid(), strerror(errno));
+    BACK_LOGE("tgkill %d failed: %s", Tid(), strerror(errno));
     sigaction(THREAD_SIGNAL, &oldact, nullptr);
-    entry->Unlock();
     ThreadEntry::Remove(entry);
     pthread_mutex_unlock(&g_sigaction_mutex);
     return false;
@@ -146,17 +149,30 @@
 
   // Wait for the thread to get the ucontext. The number indicates
   // that we are waiting for the first Wake() call made by the thread.
-  entry->Wait(1);
+  bool wait_completed = entry->Wait(1);
 
   // After the thread has received the signal, allow other unwinders to
   // continue.
   sigaction(THREAD_SIGNAL, &oldact, nullptr);
   pthread_mutex_unlock(&g_sigaction_mutex);
 
-  bool unwind_done = UnwindFromContext(num_ignore_frames, entry->GetUcontext());
+  bool unwind_done = false;
+  if (wait_completed) {
+    unwind_done = UnwindFromContext(num_ignore_frames, entry->GetUcontext());
 
-  // Tell the signal handler to exit and release the entry.
-  entry->Wake();
+    // Tell the signal handler to exit and release the entry.
+    entry->Wake();
+
+    // Wait for the thread to indicate it is done with the ThreadEntry.
+    if (!entry->Wait(3)) {
+      // Send a warning, but do not mark as a failure to unwind.
+      BACK_LOGW("Timed out waiting for signal handler to indicate it finished.");
+    }
+  } else {
+    BACK_LOGE("Timed out waiting for signal handler to get ucontext data.");
+  }
+
+  ThreadEntry::Remove(entry);
 
   return unwind_done;
 }
diff --git a/libbacktrace/BacktraceLog.h b/libbacktrace/BacktraceLog.h
index 1632ec2..5c39f1c 100644
--- a/libbacktrace/BacktraceLog.h
+++ b/libbacktrace/BacktraceLog.h
@@ -25,4 +25,7 @@
 #define BACK_LOGW(format, ...) \
   ALOGW("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__)
 
+#define BACK_LOGE(format, ...) \
+  ALOGE("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__)
+
 #endif // _LIBBACKTRACE_BACKTRACE_LOG_H
diff --git a/libbacktrace/ThreadEntry.cpp b/libbacktrace/ThreadEntry.cpp
index e8b60c8..084c1aa 100644
--- a/libbacktrace/ThreadEntry.cpp
+++ b/libbacktrace/ThreadEntry.cpp
@@ -69,7 +69,7 @@
 }
 
 void ThreadEntry::Remove(ThreadEntry* entry) {
-  pthread_mutex_unlock(&entry->mutex_);
+  entry->Unlock();
 
   pthread_mutex_lock(&ThreadEntry::list_mutex_);
   if (--entry->ref_count_ == 0) {
@@ -96,20 +96,24 @@
   pthread_cond_destroy(&wait_cond_);
 }
 
-void ThreadEntry::Wait(int value) {
+bool ThreadEntry::Wait(int value) {
   timespec ts;
   clock_gettime(CLOCK_MONOTONIC, &ts);
-  ts.tv_sec += 10;
+  ts.tv_sec += 5;
 
+  bool wait_completed = true;
   pthread_mutex_lock(&wait_mutex_);
   while (wait_value_ != value) {
     int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts);
     if (ret != 0) {
-      BACK_LOGW("pthread_cond_timedwait failed: %s", strerror(ret));
+      BACK_LOGW("pthread_cond_timedwait for value %d failed: %s", value, strerror(ret));
+      wait_completed = false;
       break;
     }
   }
   pthread_mutex_unlock(&wait_mutex_);
+
+  return wait_completed;
 }
 
 void ThreadEntry::Wake() {
diff --git a/libbacktrace/ThreadEntry.h b/libbacktrace/ThreadEntry.h
index 94becf2..11924a3 100644
--- a/libbacktrace/ThreadEntry.h
+++ b/libbacktrace/ThreadEntry.h
@@ -29,7 +29,7 @@
 
   void Wake();
 
-  void Wait(int);
+  bool Wait(int);
 
   void CopyUcontextFromSigcontext(void*);
 
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 8c0a0be..1da52d8 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -388,7 +388,6 @@
         bool kick = false;
         bool leading = true;
         LogBufferElementLast last;
-        log_time start(log_time::EPOCH);
         for(it = mLogElements.begin(); it != mLogElements.end();) {
             LogBufferElement *e = *it;
 
@@ -417,8 +416,6 @@
                 continue;
             }
 
-            leading = false;
-
             if (hasBlacklist && mPrune.naughty(e)) {
                 last.clear(e);
                 it = erase(it);
@@ -448,29 +445,24 @@
             }
 
             if (e->getUid() != worst) {
-                if (start != log_time::EPOCH) {
+                if (leading) {
                     static const timespec too_old = {
                         EXPIRE_HOUR_THRESHOLD * 60 * 60, 0
                     };
-                    start = e->getRealTime() + too_old;
+                    LogBufferElementCollection::iterator last;
+                    last = mLogElements.end();
+                    --last;
+                    if ((e->getRealTime() < ((*last)->getRealTime() - too_old))
+                            || (e->getRealTime() > (*last)->getRealTime())) {
+                        break;
+                    }
                 }
+                leading = false;
                 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;
@@ -479,15 +471,21 @@
             kick = true;
 
             unsigned short len = e->getMsgLen();
-            stats.drop(e);
-            e->setDropped(1);
-            if (last.merge(e, 1)) {
-                it = mLogElements.erase(it);
-                stats.erase(e);
-                delete e;
+
+            // do not create any leading drops
+            if (leading) {
+                it = erase(it);
             } else {
-                last.add(e);
-                ++it;
+                stats.drop(e);
+                e->setDropped(1);
+                if (last.merge(e, 1)) {
+                    it = mLogElements.erase(it);
+                    stats.erase(e);
+                    delete e;
+                } else {
+                    last.add(e);
+                    ++it;
+                }
             }
             if (worst_sizes < second_worst_sizes) {
                 break;
@@ -526,7 +524,7 @@
             break;
         }
 
-        if (hasWhitelist && mPrune.nice(e)) { // WhiteListed
+        if (hasWhitelist && !e->getDropped() && mPrune.nice(e)) { // WhiteListed
             whitelist = true;
             it++;
             continue;
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 46bd9c0..3266360 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -93,53 +93,42 @@
 static char *find_benchmark_spam(char *cp)
 {
     // liblog_benchmarks has been run designed to SPAM.  The signature of
-    // a noisiest UID statistics is one of the following:
+    // a noisiest UID statistics is:
     //
-    // main: UID/PID Total size/num   Now          UID/PID[?]  Total
-    // 0           7500306/304207     71608/3183   0/4225?     7454388/303656
-    //    <wrap>                                                     93432/1012
-    // -or-
-    // 0/gone      7454388/303656     93432/1012
+    // Chattiest UIDs in main log buffer:                           Size Pruned
+    // UID   PACKAGE                                                BYTES LINES
+    // 0     root                                                  54164 147569
     //
-    // basically if we see a *large* number of 0/????? entries
-    unsigned long value;
+    char *benchmark = NULL;
     do {
-        char *benchmark = strstr(cp, " 0/");
-        char *benchmark_newline = strstr(cp, "\n0/");
+        static const char signature[] = "\n0     root ";
+
+        benchmark = strstr(cp, signature);
         if (!benchmark) {
-            benchmark = benchmark_newline;
-        }
-        if (benchmark_newline && (benchmark > benchmark_newline)) {
-            benchmark = benchmark_newline;
-        }
-        cp = benchmark;
-        if (!cp) {
             break;
         }
-        cp += 3;
-        while (isdigit(*cp) || (*cp == 'g') || (*cp == 'o') || (*cp == 'n')) {
+        cp = benchmark + sizeof(signature);
+        while (isspace(*cp)) {
             ++cp;
         }
-        value = 0;
-        // ###? or gone
-        if ((*cp == '?') || (*cp == 'e')) {
-            while (*++cp == ' ');
-            while (isdigit(*cp)) {
-                value = value * 10ULL + *cp - '0';
-                ++cp;
-            }
-            if (*cp != '/') {
-                value = 0;
-                continue;
-            }
-            while (isdigit(*++cp));
-            while (*cp == ' ') ++cp;
-            if (!isdigit(*cp)) {
-                value = 0;
-            }
+        benchmark = cp;
+        while (isdigit(*cp)) {
+            ++cp;
         }
-    } while ((value < 900000ULL) && *cp);
-    return cp;
+        while (isspace(*cp)) {
+            ++cp;
+        }
+        unsigned long value = 0;
+        while (isdigit(*cp)) {
+            value = value * 10ULL + *cp - '0';
+            ++cp;
+        }
+        if (value > 100000UL) {
+            break;
+        }
+        benchmark = NULL;
+    } while (*cp);
+    return benchmark;
 }
 
 TEST(logd, statistics) {
@@ -179,16 +168,16 @@
     EXPECT_EQ(0, truncated);
 
 #ifdef TARGET_USES_LOGD
-    char *main_logs = strstr(cp, "\nmain:");
+    char *main_logs = strstr(cp, "\nChattiest UIDs in main ");
     EXPECT_TRUE(NULL != main_logs);
 
-    char *radio_logs = strstr(cp, "\nradio:");
+    char *radio_logs = strstr(cp, "\nChattiest UIDs in radio ");
     EXPECT_TRUE(NULL != radio_logs);
 
-    char *system_logs = strstr(cp, "\nsystem:");
+    char *system_logs = strstr(cp, "\nChattiest UIDs in system ");
     EXPECT_TRUE(NULL != system_logs);
 
-    char *events_logs = strstr(cp, "\nevents:");
+    char *events_logs = strstr(cp, "\nChattiest UIDs in events ");
     EXPECT_TRUE(NULL != events_logs);
 #endif
 
@@ -431,13 +420,13 @@
     }
 
 #ifdef TARGET_USES_LOGD
-    EXPECT_GE(100000UL, ns[log_maximum_retry]); // 42777 user
+    EXPECT_GE(200000UL, ns[log_maximum_retry]); // 104734 user
 #else
     EXPECT_GE(10000UL, ns[log_maximum_retry]); // 5636 kernel
 #endif
 
 #ifdef TARGET_USES_LOGD
-    EXPECT_GE(30000UL, ns[log_maximum]); // 27305 user
+    EXPECT_GE(90000UL, ns[log_maximum]); // 46913 user
 #else
     EXPECT_GE(10000UL, ns[log_maximum]); // 5637 kernel
 #endif
@@ -445,13 +434,13 @@
     EXPECT_GE(4096UL, ns[clock_overhead]); // 4095
 
 #ifdef TARGET_USES_LOGD
-    EXPECT_GE(250000UL, ns[log_overhead]); // 121876 user
+    EXPECT_GE(250000UL, ns[log_overhead]); // 126886 user
 #else
     EXPECT_GE(100000UL, ns[log_overhead]); // 50945 kernel
 #endif
 
 #ifdef TARGET_USES_LOGD
-    EXPECT_GE(7500UL, ns[log_latency]); // 3718 user space
+    EXPECT_GE(10000UL, ns[log_latency]); // 5669 user space
 #else
     EXPECT_GE(500000UL, ns[log_latency]); // 254200 kernel
 #endif
@@ -483,8 +472,7 @@
     ASSERT_TRUE(benchmark_statistics_found != NULL);
 
     // Check how effective the SPAM filter is, parse out Now size.
-    //             Total               Now
-    // 0/4225?     7454388/303656      31488/755
+    // 0     root                      54164 147569
     //                                 ^-- benchmark_statistics_found
 
     unsigned long nowSpamSize = atol(benchmark_statistics_found);