Copy queries synchronously in DnsTlsSocket

Prior to this change, each outgoing query was copied only once,
on the DnsTlsSocket's loop thread.  This could create a problem
if a misbehaving server sent an erroneous response with a
colliding ID number after the query was given to DnsTlsSocket
but before the copy was made.  The erroneous response would
complete the query, causing the caller to deallocate the backing
buffer, resulting in a segfault on copy.

This change moves the copy earlier, onto the calling thread, thus
ensuring that the backing buffer cannot have been deallocated.
Instead of sending the network thread pointers to query buffers,
copies of queries are stored in a shared queue, and the network
thread is notified of new queries on an eventfd socket.

Bug: 122133500
Test: Integrations tests pass, manual tests good.  No regression test.
Change-Id: Ia4e72da561aeef69a17e87bfdc7aa04340c12fd0
diff --git a/resolv/LockedQueue.h b/resolv/LockedQueue.h
new file mode 100644
index 0000000..0481eda
--- /dev/null
+++ b/resolv/LockedQueue.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DNS_LOCKED_QUEUE_H
+#define _DNS_LOCKED_QUEUE_H
+
+#include <algorithm>
+#include <deque>
+#include <mutex>
+
+#include <android-base/thread_annotations.h>
+
+namespace android {
+namespace net {
+
+template <typename T>
+class LockedQueue {
+  public:
+    // Push an item onto the queue.
+    void push(T item) {
+        std::lock_guard guard(mLock);
+        mQueue.push_front(std::move(item));
+    }
+
+    // Swap out the contents of the queue
+    void swap(std::deque<T>& other) {
+        std::lock_guard guard(mLock);
+        mQueue.swap(other);
+    }
+
+  private:
+    std::mutex mLock;
+    std::deque<T> mQueue GUARDED_BY(mLock);
+};
+
+}  // end of namespace net
+}  // end of namespace android
+
+#endif  // _DNS_LOCKEDQUEUE_H