Merge "Fix support for negatively Z-ordered SubWindows."
diff --git a/Android.bp b/Android.bp
index 2ea4894..d8027c1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -65,6 +65,7 @@
                 "core/proto/android/os/procrank.proto",
                 "core/proto/android/os/system_properties.proto",
                 "core/proto/android/service/graphicsstats.proto",
+                "libs/incident/proto/android/privacy.proto",
                 "tools/streaming_proto/stream.proto",
             ],
             shared: {
diff --git a/cmds/incidentd/src/Privacy.cpp b/cmds/incidentd/src/Privacy.cpp
index 140b12c..5db2239 100644
--- a/cmds/incidentd/src/Privacy.cpp
+++ b/cmds/incidentd/src/Privacy.cpp
@@ -16,37 +16,18 @@
 
 #include "Privacy.h"
 
+#include <android/os/IncidentReportArgs.h>
 #include <stdlib.h>
 
-// DESTINATION enum value
-const uint8_t DEST_LOCAL = 0;
-const uint8_t DEST_EXPLICIT = 1;
-const uint8_t DEST_AUTOMATIC = 2;
+uint64_t encode_field_id(const Privacy* p) { return (uint64_t)p->type << 32 | p->field_id; }
 
-// type of the field, identitical to protobuf definition
-const uint8_t TYPE_STRING = 9;
-const uint8_t TYPE_MESSAGE = 11;
-
-bool
-Privacy::IsMessageType() const { return type == TYPE_MESSAGE; }
-
-uint64_t
-Privacy::EncodedFieldId() const { return (uint64_t)type << 32 | field_id; }
-
-bool
-Privacy::IsStringType() const { return type == TYPE_STRING; }
-
-bool
-Privacy::HasChildren() const { return children != NULL && children[0] != NULL; }
-
-const Privacy*
-Privacy::lookup(uint32_t fieldId) const
+const Privacy* lookup(const Privacy* p, uint32_t fieldId)
 {
-    if (children == NULL) return NULL;
-    for (int i=0; children[i] != NULL; i++) {
-        if (children[i]->field_id == fieldId) return children[i];
-        // This assumes the list's field id is in ascending order and must be true.
-        if (children[i]->field_id > fieldId) return NULL;
+    if (p->children == NULL) return NULL;
+    for (int i=0; p->children[i] != NULL; i++) { // NULL-terminated.
+        if (p->children[i]->field_id == fieldId) return p->children[i];
+        // Incident section gen tool guarantees field ids in ascending order.
+        if (p->children[i]->field_id > fieldId) return NULL;
     }
     return NULL;
 }
@@ -54,11 +35,14 @@
 static bool allowDest(const uint8_t dest, const uint8_t policy)
 {
     switch (policy) {
-    case DEST_LOCAL:
-        return dest == DEST_LOCAL;
-    case DEST_EXPLICIT:
-        return dest == DEST_LOCAL || dest == DEST_EXPLICIT;
-    case DEST_AUTOMATIC:
+    case android::os::DEST_LOCAL:
+        return dest == android::os::DEST_LOCAL;
+    case android::os::DEST_EXPLICIT:
+    case DEST_UNSET:
+        return dest == android::os::DEST_LOCAL ||
+            dest == android::os::DEST_EXPLICIT ||
+            dest == DEST_UNSET;
+    case android::os::DEST_AUTOMATIC:
         return true;
     default:
         return false;
@@ -72,18 +56,19 @@
 }
 
 bool
-PrivacySpec::CheckPremission(const Privacy* privacy) const
+PrivacySpec::CheckPremission(const Privacy* privacy, const uint8_t defaultDest) const
 {
-    uint8_t policy = privacy == NULL ? DEST_DEFAULT_VALUE : privacy->dest;
+    uint8_t policy = privacy != NULL ? privacy->dest : defaultDest;
     return allowDest(dest, policy);
 }
 
 bool
-PrivacySpec::RequireAll() const { return dest == DEST_LOCAL; }
+PrivacySpec::RequireAll() const { return dest == android::os::DEST_LOCAL; }
 
-PrivacySpec new_spec_from_args(int dest) {
+PrivacySpec new_spec_from_args(int dest)
+{
   if (dest < 0) return PrivacySpec();
   return PrivacySpec(dest);
 }
 
-PrivacySpec get_default_dropbox_spec() { return PrivacySpec(DEST_AUTOMATIC); }
\ No newline at end of file
+PrivacySpec get_default_dropbox_spec() { return PrivacySpec(android::os::DEST_AUTOMATIC); }
\ No newline at end of file
diff --git a/cmds/incidentd/src/Privacy.h b/cmds/incidentd/src/Privacy.h
index f514f19..9e15ff4 100644
--- a/cmds/incidentd/src/Privacy.h
+++ b/cmds/incidentd/src/Privacy.h
@@ -19,35 +19,46 @@
 
 #include <stdint.h>
 
-// This is the default value of DEST enum
-const uint8_t DEST_DEFAULT_VALUE = 1;
+// This is the default value of DEST enum, sync with privacy.proto
+const uint8_t DEST_UNSET = 255; // DEST_UNSET is not exposed to libincident
+const uint8_t DEST_DEFAULT_VALUE = DEST_UNSET;
 
 /*
- * In order not to depend on libprotobuf-cpp-full nor libplatformprotos in incidentd,
- * privacy options's data structure are explicitly redefined in this file.
+ * In order to NOT auto-generate large chuck of code by proto compiler in incidentd,
+ * privacy options's data structure are explicitly redefined here and
+ * the values are populated by incident_section_gen tool.
+ *
+ * Each proto field will have a Privacy when it is different from its parent, otherwise
+ * it uses its parent's tag. A message type will have an array of Privacy.
  */
 struct Privacy {
+    // The field number
     uint32_t field_id;
+
+    // The field type, see external/protobuf/src/google/protobuf/descriptor.h
     uint8_t type;
-    // ignore parent's privacy flags if children are set, NULL-terminated
+
+    // If children is null, it is a primitive field,
+    // otherwise it is a message field which could have overridden privacy tags here.
+    // This array is NULL-terminated.
     Privacy** children;
 
-    // the following fields are identitical to
-    // frameworks/base/libs/incident/proto/android/privacy.proto
+    // DESTINATION Enum in frameworks/base/libs/incident/proto/android/privacy.proto.
     uint8_t dest;
-    const char** patterns; // only set when type is string
-
-    bool IsMessageType() const;
-    bool IsStringType() const;
-    bool HasChildren() const;
-    uint64_t EncodedFieldId() const;
-
-    const Privacy* lookup(uint32_t fieldId) const;
+    // A list of regexp rules for stripping string fields in proto.
+    const char** patterns;
 };
 
+// Encode field id used by ProtoOutputStream.
+uint64_t encode_field_id(const Privacy* p);
+
+// Look up the child with given fieldId, if not found, return NULL.
+const Privacy* lookup(const Privacy* p, uint32_t fieldId);
+
 /**
  * PrivacySpec defines the request has what level of privacy authorization.
  * For example, a device without user consent should only be able to upload AUTOMATIC fields.
+ * DEST_UNSET are treated as DEST_EXPLICIT.
  */
 class PrivacySpec {
 public:
@@ -58,7 +69,10 @@
 
     bool operator<(const PrivacySpec& other) const;
 
-    bool CheckPremission(const Privacy* privacy) const;
+    // check permission of a policy, if returns true, don't strip the data.
+    bool CheckPremission(const Privacy* privacy, const uint8_t defaultDest = DEST_DEFAULT_VALUE) const;
+
+    // if returns true, no data need to be stripped.
     bool RequireAll() const;
 };
 
diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp
index 77ae1a7..03faa92 100644
--- a/cmds/incidentd/src/PrivacyBuffer.cpp
+++ b/cmds/incidentd/src/PrivacyBuffer.cpp
@@ -14,15 +14,18 @@
  * limitations under the License.
  */
 
-
+#define LOG_TAG "incidentd"
 
 #include "PrivacyBuffer.h"
 #include "io_util.h"
 
 #include <android/util/protobuf.h>
+#include <cutils/log.h>
 
 using namespace android::util;
 
+const bool DEBUG = false;
+
 /**
  * Write the field to buf based on the wire type, iterator will point to next field.
  * If skip is set to true, no data will be written to buf. Return number of bytes written.
@@ -30,6 +33,9 @@
 void
 PrivacyBuffer::writeFieldOrSkip(uint32_t fieldTag, bool skip)
 {
+    if (DEBUG) ALOGD("%s field %d (wiretype = %d)", skip ? "skip" : "write",
+        read_field_id(fieldTag), read_wire_type(fieldTag));
+
     uint8_t wireType = read_wire_type(fieldTag);
     size_t bytesToWrite = 0;
     uint32_t varint = 0;
@@ -55,6 +61,7 @@
             bytesToWrite = 4;
             break;
     }
+    if (DEBUG) ALOGD("%s %d bytes of data", skip ? "skip" : "write", (int)bytesToWrite);
     if (skip) {
         mData.rp()->move(bytesToWrite);
     } else {
@@ -76,10 +83,13 @@
 {
     if (!mData.hasNext() || parentPolicy == NULL) return BAD_VALUE;
     uint32_t fieldTag = mData.readRawVarint();
-    const Privacy* policy = parentPolicy->lookup(read_field_id(fieldTag));
+    const Privacy* policy = lookup(parentPolicy, read_field_id(fieldTag));
 
-    if (policy == NULL || !policy->IsMessageType() || !policy->HasChildren()) {
-        bool skip = !spec.CheckPremission(policy);
+    if (policy == NULL || policy->children == NULL) {
+        if (DEBUG) ALOGD("Not a message field %d: dest(%d)", read_field_id(fieldTag),
+            policy != NULL ? policy->dest : parentPolicy->dest);
+
+        bool skip = !spec.CheckPremission(policy, parentPolicy->dest);
         // iterator will point to head of next field
         writeFieldOrSkip(fieldTag, skip);
         return NO_ERROR;
@@ -87,7 +97,7 @@
     // current field is message type and its sub-fields have extra privacy policies
     uint32_t msgSize = mData.readRawVarint();
     EncodedBuffer::Pointer start = mData.rp()->copy();
-    long long token = mProto.start(policy->EncodedFieldId());
+    long long token = mProto.start(encode_field_id(policy));
     while (mData.rp()->pos() - start.pos() != msgSize) {
         status_t err = stripField(policy, spec);
         if (err != NO_ERROR) return err;
@@ -112,8 +122,9 @@
 status_t
 PrivacyBuffer::strip(const PrivacySpec& spec)
 {
+    if (DEBUG) ALOGD("Strip with spec %d", spec.dest);
     // optimization when no strip happens
-    if (mPolicy == NULL || !mPolicy->HasChildren() || spec.RequireAll()) {
+    if (mPolicy == NULL || mPolicy->children == NULL || spec.RequireAll()) {
         if (spec.CheckPremission(mPolicy)) mSize = mData.size();
         return NO_ERROR;
     }
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index c08b9ea..1bf795b 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -210,9 +210,9 @@
 {
     for (ReportRequestSet::iterator it=requests->begin(); it!=requests->end(); it++) {
         const sp<ReportRequest> request = *it;
-        const vector<vector<int8_t>>& headers = request->args.headers();
+        const vector<vector<uint8_t>>& headers = request->args.headers();
 
-        for (vector<vector<int8_t>>::const_iterator buf=headers.begin(); buf!=headers.end(); buf++) {
+        for (vector<vector<uint8_t>>::const_iterator buf=headers.begin(); buf!=headers.end(); buf++) {
             if (buf->empty()) continue;
 
             // So the idea is only requests with negative fd are written to dropbox file.
diff --git a/cmds/incidentd/src/io_util.cpp b/cmds/incidentd/src/io_util.cpp
index f043d36..af4a35c 100644
--- a/cmds/incidentd/src/io_util.cpp
+++ b/cmds/incidentd/src/io_util.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "incidentd"
+
 #include "io_util.h"
 
 #include <unistd.h>
diff --git a/cmds/incidentd/tests/PrivacyBuffer_test.cpp b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
index ca94623..32b9e42 100644
--- a/cmds/incidentd/tests/PrivacyBuffer_test.cpp
+++ b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
@@ -12,27 +12,27 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#define LOG_TAG "incidentd"
+
 #include "FdBuffer.h"
 #include "PrivacyBuffer.h"
 
 #include <android-base/file.h>
 #include <android-base/test_utils.h>
+#include <android/os/IncidentReportArgs.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <string.h>
 
 using namespace android;
 using namespace android::base;
+using namespace android::os;
 using namespace std;
 using ::testing::StrEq;
 using ::testing::Test;
 using ::testing::internal::CaptureStdout;
 using ::testing::internal::GetCapturedStdout;
 
-const uint8_t LOCAL = 0;
-const uint8_t EXPLICIT = 1;
-const uint8_t AUTOMATIC = 2;
-
 const uint8_t OTHER_TYPE = 1;
 const uint8_t STRING_TYPE = 9;
 const uint8_t MESSAGE_TYPE = 11;
@@ -109,21 +109,11 @@
         p->field_id = field_id;
         p->type = MESSAGE_TYPE;
         p->children = children;
-        p->dest = EXPLICIT;
+        p->dest = DEST_DEFAULT_VALUE;
         p->patterns = NULL;
         return p;
     }
 
-    Privacy* create_string_privacy(uint32_t field_id, uint8_t dest, const char** patterns) {
-        Privacy* p = new_uninit_privacy();
-        p->field_id = field_id;
-        p->type = STRING_TYPE;
-        p->children = NULL;
-        p->dest = dest;
-        p->patterns = patterns;
-        return p;
-    }
-
     FdBuffer buffer;
 private:
     TemporaryFile tf;
@@ -138,103 +128,103 @@
     }
 };
 
-TEST_F(PrivacyBufferTest, NullFieldPolicy) {
+TEST_F(PrivacyBufferTest, NullPolicy) {
     writeToFdBuffer(STRING_FIELD_0);
-    assertStrip(EXPLICIT, STRING_FIELD_0, create_string_privacy(300, AUTOMATIC, NULL));
+    assertStrip(DEST_EXPLICIT, STRING_FIELD_0, NULL);
 }
 
-TEST_F(PrivacyBufferTest, StripSpecNotAllowed) {
+TEST_F(PrivacyBufferTest, StripUnsetField) {
     writeToFdBuffer(STRING_FIELD_0);
-    assertStripByFields(AUTOMATIC, "", 1, create_privacy(0, STRING_TYPE, EXPLICIT));
+    assertStripByFields(DEST_AUTOMATIC, "", 1, create_privacy(0, STRING_TYPE, DEST_UNSET));
 }
 
 TEST_F(PrivacyBufferTest, StripVarintField) {
     writeToFdBuffer(VARINT_FIELD_1);
-    assertStripByFields(EXPLICIT, "", 1, create_privacy(1, OTHER_TYPE, LOCAL));
+    assertStripByFields(DEST_EXPLICIT, "", 1, create_privacy(1, OTHER_TYPE, DEST_LOCAL));
 }
 
 TEST_F(PrivacyBufferTest, StripLengthDelimitedField_String) {
     writeToFdBuffer(STRING_FIELD_2);
-    assertStripByFields(EXPLICIT, "", 1, create_privacy(2, STRING_TYPE, LOCAL));
+    assertStripByFields(DEST_EXPLICIT, "", 1, create_privacy(2, STRING_TYPE, DEST_LOCAL));
 }
 
 TEST_F(PrivacyBufferTest, StripFixed64Field) {
     writeToFdBuffer(FIX64_FIELD_3);
-    assertStripByFields(EXPLICIT, "", 1, create_privacy(3, OTHER_TYPE, LOCAL));
+    assertStripByFields(DEST_EXPLICIT, "", 1, create_privacy(3, OTHER_TYPE, DEST_LOCAL));
 }
 
 TEST_F(PrivacyBufferTest, StripFixed32Field) {
     writeToFdBuffer(FIX32_FIELD_4);
-    assertStripByFields(EXPLICIT, "", 1, create_privacy(4, OTHER_TYPE, LOCAL));
+    assertStripByFields(DEST_EXPLICIT, "", 1, create_privacy(4, OTHER_TYPE, DEST_LOCAL));
 }
 
 TEST_F(PrivacyBufferTest, StripLengthDelimitedField_Message) {
     writeToFdBuffer(MESSAGE_FIELD_5);
-    assertStripByFields(EXPLICIT, "", 1, create_privacy(5, MESSAGE_TYPE, LOCAL));
+    assertStripByFields(DEST_EXPLICIT, "", 1, create_privacy(5, MESSAGE_TYPE, DEST_LOCAL));
 }
 
 TEST_F(PrivacyBufferTest, NoStripVarintField) {
     writeToFdBuffer(VARINT_FIELD_1);
-    assertStripByFields(EXPLICIT, VARINT_FIELD_1, 1, create_privacy(1, OTHER_TYPE, AUTOMATIC));
+    assertStripByFields(DEST_EXPLICIT, VARINT_FIELD_1, 1, create_privacy(1, OTHER_TYPE, DEST_AUTOMATIC));
 }
 
 TEST_F(PrivacyBufferTest, NoStripLengthDelimitedField_String) {
     writeToFdBuffer(STRING_FIELD_2);
-    assertStripByFields(EXPLICIT, STRING_FIELD_2, 1, create_privacy(2, STRING_TYPE, AUTOMATIC));
+    assertStripByFields(DEST_EXPLICIT, STRING_FIELD_2, 1, create_privacy(2, STRING_TYPE, DEST_AUTOMATIC));
 }
 
 TEST_F(PrivacyBufferTest, NoStripFixed64Field) {
     writeToFdBuffer(FIX64_FIELD_3);
-    assertStripByFields(EXPLICIT, FIX64_FIELD_3, 1, create_privacy(3, OTHER_TYPE, AUTOMATIC));
+    assertStripByFields(DEST_EXPLICIT, FIX64_FIELD_3, 1, create_privacy(3, OTHER_TYPE, DEST_AUTOMATIC));
 }
 
 TEST_F(PrivacyBufferTest, NoStripFixed32Field) {
     writeToFdBuffer(FIX32_FIELD_4);
-    assertStripByFields(EXPLICIT, FIX32_FIELD_4, 1, create_privacy(4, OTHER_TYPE, AUTOMATIC));
+    assertStripByFields(DEST_EXPLICIT, FIX32_FIELD_4, 1, create_privacy(4, OTHER_TYPE, DEST_AUTOMATIC));
 }
 
 TEST_F(PrivacyBufferTest, NoStripLengthDelimitedField_Message) {
     writeToFdBuffer(MESSAGE_FIELD_5);
-    assertStripByFields(EXPLICIT, MESSAGE_FIELD_5, 1, create_privacy(5, MESSAGE_TYPE, AUTOMATIC));
+    assertStripByFields(DEST_EXPLICIT, MESSAGE_FIELD_5, 1, create_privacy(5, MESSAGE_TYPE, DEST_AUTOMATIC));
 }
 
 TEST_F(PrivacyBufferTest, StripVarintAndString) {
     writeToFdBuffer(STRING_FIELD_0 + VARINT_FIELD_1 + STRING_FIELD_2
             + FIX64_FIELD_3 + FIX32_FIELD_4);
     string expected = STRING_FIELD_0 + FIX64_FIELD_3 + FIX32_FIELD_4;
-    assertStripByFields(EXPLICIT, expected, 2,
-            create_privacy(1, OTHER_TYPE, LOCAL), create_privacy(2, STRING_TYPE, LOCAL));
+    assertStripByFields(DEST_EXPLICIT, expected, 2,
+            create_privacy(1, OTHER_TYPE, DEST_LOCAL), create_privacy(2, STRING_TYPE, DEST_LOCAL));
 }
 
 TEST_F(PrivacyBufferTest, StripVarintAndFixed64) {
     writeToFdBuffer(STRING_FIELD_0 + VARINT_FIELD_1 + STRING_FIELD_2
             + FIX64_FIELD_3 + FIX32_FIELD_4);
     string expected = STRING_FIELD_0 + STRING_FIELD_2 + FIX32_FIELD_4;
-    assertStripByFields(EXPLICIT, expected, 2,
-            create_privacy(1, OTHER_TYPE, LOCAL), create_privacy(3, OTHER_TYPE, LOCAL));
+    assertStripByFields(DEST_EXPLICIT, expected, 2,
+            create_privacy(1, OTHER_TYPE, DEST_LOCAL), create_privacy(3, OTHER_TYPE, DEST_LOCAL));
 }
 
 TEST_F(PrivacyBufferTest, StripVarintInNestedMessage) {
     writeToFdBuffer(STRING_FIELD_0 + MESSAGE_FIELD_5);
-    Privacy* list[] = { create_privacy(1, OTHER_TYPE, LOCAL), NULL };
+    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
     string expected = STRING_FIELD_0 + "\x2a\xd" + STRING_FIELD_2;
-    assertStripByFields(EXPLICIT, expected, 1, create_message_privacy(5, list));
+    assertStripByFields(DEST_EXPLICIT, expected, 1, create_message_privacy(5, list));
 }
 
 TEST_F(PrivacyBufferTest, StripFix64AndVarintInNestedMessage) {
     writeToFdBuffer(STRING_FIELD_0 + FIX64_FIELD_3 + MESSAGE_FIELD_5);
-    Privacy* list[] = { create_privacy(1, OTHER_TYPE, LOCAL), NULL };
+    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
     string expected = STRING_FIELD_0 + "\x2a\xd" + STRING_FIELD_2;
-    assertStripByFields(EXPLICIT, expected, 2, create_privacy(3, OTHER_TYPE, LOCAL), create_message_privacy(5, list));
+    assertStripByFields(DEST_EXPLICIT, expected, 2, create_privacy(3, OTHER_TYPE, DEST_LOCAL), create_message_privacy(5, list));
 }
 
 TEST_F(PrivacyBufferTest, ClearAndStrip) {
     string data = STRING_FIELD_0 + VARINT_FIELD_1;
     writeToFdBuffer(data);
-    Privacy* list[] = { create_privacy(1, OTHER_TYPE, LOCAL), NULL };
+    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
     EncodedBuffer::iterator bufData = buffer.data();
     PrivacyBuffer privacyBuf(create_message_privacy(300, list), bufData);
-    PrivacySpec spec1(EXPLICIT), spec2(LOCAL);
+    PrivacySpec spec1(DEST_EXPLICIT), spec2(DEST_LOCAL);
 
     ASSERT_EQ(privacyBuf.strip(spec1), NO_ERROR);
     assertBuffer(privacyBuf, STRING_FIELD_0);
@@ -244,7 +234,7 @@
 
 TEST_F(PrivacyBufferTest, BadDataInFdBuffer) {
     writeToFdBuffer("iambaddata");
-    Privacy* list[] = { create_privacy(4, OTHER_TYPE, AUTOMATIC), NULL };
+    Privacy* list[] = { create_privacy(4, OTHER_TYPE, DEST_AUTOMATIC), NULL };
     EncodedBuffer::iterator bufData = buffer.data();
     PrivacyBuffer privacyBuf(create_message_privacy(300, list), bufData);
     PrivacySpec spec;
@@ -253,7 +243,7 @@
 
 TEST_F(PrivacyBufferTest, BadDataInNestedMessage) {
     writeToFdBuffer(STRING_FIELD_0 + MESSAGE_FIELD_5 + "aoeoe");
-    Privacy* list[] = { create_privacy(1, OTHER_TYPE, LOCAL), NULL };
+    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
     Privacy* field5[] = { create_message_privacy(5, list), NULL };
     EncodedBuffer::iterator bufData = buffer.data();
     PrivacyBuffer privacyBuf(create_message_privacy(300, field5), bufData);
@@ -265,8 +255,17 @@
     string input = "\x2a\"" + VARINT_FIELD_1 + STRING_FIELD_2 + MESSAGE_FIELD_5;
     writeToFdBuffer(input);
     Privacy* field5 = create_message_privacy(5, NULL);
-    Privacy* list[] = { create_privacy(1, OTHER_TYPE, LOCAL), field5, NULL };
+    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), field5, NULL };
     field5->children = list;
     string expected = "\x2a\x1c" + STRING_FIELD_2 + "\x2a\xd" + STRING_FIELD_2;
-    assertStrip(EXPLICIT, expected, field5);
+    assertStrip(DEST_EXPLICIT, expected, field5);
 }
+
+TEST_F(PrivacyBufferTest, AutoMessage) {
+    writeToFdBuffer(STRING_FIELD_2 + MESSAGE_FIELD_5);
+    Privacy* list[] = { create_privacy(1, OTHER_TYPE, DEST_LOCAL), NULL };
+    Privacy* autoMsg = create_privacy(5, MESSAGE_TYPE, DEST_AUTOMATIC);
+    autoMsg->children = list;
+    string expected = "\x2a\xd" + STRING_FIELD_2;
+    assertStripByFields(DEST_AUTOMATIC, expected, 1, autoMsg);
+}
\ No newline at end of file
diff --git a/cmds/incidentd/tests/Reporter_test.cpp b/cmds/incidentd/tests/Reporter_test.cpp
index 8d99fc7..531c9f2 100644
--- a/cmds/incidentd/tests/Reporter_test.cpp
+++ b/cmds/incidentd/tests/Reporter_test.cpp
@@ -141,7 +141,7 @@
     IncidentReportArgs args1, args2;
     args1.addSection(1);
     args2.addSection(2);
-    std::vector<int8_t> header {'a', 'b', 'c', 'd', 'e'};
+    std::vector<uint8_t> header {'a', 'b', 'c', 'd', 'e'};
     args2.addHeader(header);
     sp<ReportRequest> r1 = new ReportRequest(args1, l, tf.fd);
     sp<ReportRequest> r2 = new ReportRequest(args2, l, tf.fd);
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index 649e908..0c7876c 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -66,12 +66,12 @@
     args1.addSection(2);
     args2.setAll(true);
 
-    vector<int8_t> head1;
+    vector<uint8_t> head1;
     head1.push_back('a');
     head1.push_back('x');
     head1.push_back('e');
 
-    vector<int8_t> head2;
+    vector<uint8_t> head2;
     head2.push_back('p');
     head2.push_back('u');
     head2.push_back('p');
diff --git a/cmds/incidentd/tests/section_list.cpp b/cmds/incidentd/tests/section_list.cpp
index 4acc429..1d6213f 100644
--- a/cmds/incidentd/tests/section_list.cpp
+++ b/cmds/incidentd/tests/section_list.cpp
@@ -5,20 +5,16 @@
     NULL
 };
 
-const uint8_t LOCAL = 0;
-const uint8_t EXPLICIT = 1;
-const uint8_t AUTOMATIC = 2;
-
-Privacy sub_field_1 { 1, 1, NULL, LOCAL, NULL };
-Privacy sub_field_2 { 2, 9, NULL, AUTOMATIC, NULL };
+Privacy sub_field_1 { 1, 1, NULL, DEST_LOCAL, NULL };
+Privacy sub_field_2 { 2, 9, NULL, DEST_AUTOMATIC, NULL };
 
 Privacy* list[] = {
     &sub_field_1,
     &sub_field_2,
     NULL };
 
-Privacy field_0 { 0, 11, list, EXPLICIT, NULL };
-Privacy field_1 { 1, 9, NULL, AUTOMATIC, NULL };
+Privacy field_0 { 0, 11, list, DEST_EXPLICIT, NULL };
+Privacy field_1 { 1, 9, NULL, DEST_AUTOMATIC, NULL };
 
 Privacy* final_list[] = {
     &field_0,
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 068f5f7..01fe5bf 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -680,6 +680,26 @@
      * as the user moves between applications and doesn't require a special permission.
      * </p>
      *
+     * <p>
+     * Recommended naming conventions for tags to make debugging easier:
+     * <ul>
+     * <li>use a unique prefix delimited by a colon for your app/library (e.g.
+     * gmail:mytag) to make it easier to understand where the wake locks comes
+     * from. This namespace will also avoid collision for tags inside your app
+     * coming from different libraries which will make debugging easier.
+     * <li>use constants (e.g. do not include timestamps in the tag) to make it
+     * easier for tools to aggregate similar wake locks. When collecting
+     * debugging data, the platform only monitors a finite number of tags,
+     * using constants will help tools to provide better debugging data.
+     * <li>avoid using Class#getName() or similar method since this class name
+     * can be transformed by java optimizer and obfuscator tools.
+     * <li>avoid wrapping the tag or a prefix to avoid collision with wake lock
+     * tags from the platform (e.g. *alarm*).
+     * <li>never include personnally identifiable information for privacy
+     * reasons.
+     * </ul>
+     * </p>
+     *
      * @param levelAndFlags Combination of wake lock level and flag values defining
      * the requested behavior of the WakeLock.
      * @param tag Your class name (or other tag) for debugging purposes.
@@ -1509,6 +1529,13 @@
          * cost of that work can be accounted to the application.
          * </p>
          *
+         * <p>
+         * Make sure to follow the tag naming convention when using WorkSource
+         * to make it easier for app developers to understand wake locks
+         * attributed to them. See {@link PowerManager#newWakeLock(int, String)}
+         * documentation.
+         * </p>
+         *
          * @param ws The work source, or null if none.
          */
         public void setWorkSource(WorkSource ws) {
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 17c7ebd..7635a72 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -81,6 +81,7 @@
     private int mCollapsibleHeightReserved;
 
     private int mTopOffset;
+    private boolean mShowAtTop;
 
     private boolean mIsDragging;
     private boolean mOpenOnClick;
@@ -134,6 +135,7 @@
         mMaxCollapsedHeightSmall = a.getDimensionPixelSize(
                 R.styleable.ResolverDrawerLayout_maxCollapsedHeightSmall,
                 mMaxCollapsedHeight);
+        mShowAtTop = a.getBoolean(R.styleable.ResolverDrawerLayout_showAtTop, false);
         a.recycle();
 
         mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
@@ -162,6 +164,16 @@
         return mCollapseOffset > 0;
     }
 
+    public void setShowAtTop(boolean showOnTop) {
+        mShowAtTop = showOnTop;
+        invalidate();
+        requestLayout();
+    }
+
+    public boolean getShowAtTop() {
+        return mShowAtTop;
+    }
+
     public void setCollapsed(boolean collapsed) {
         if (!isLaidOut()) {
             mOpenOnLayout = collapsed;
@@ -206,6 +218,12 @@
             return false;
         }
 
+        if (getShowAtTop()) {
+            // Keep the drawer fully open.
+            mCollapseOffset = 0;
+            return false;
+        }
+
         if (isLaidOut()) {
             final boolean isCollapsedOld = mCollapseOffset != 0;
             if (remainClosed && (oldCollapsibleHeight < mCollapsibleHeight
@@ -372,14 +390,23 @@
                 mVelocityTracker.computeCurrentVelocity(1000);
                 final float yvel = mVelocityTracker.getYVelocity(mActivePointerId);
                 if (Math.abs(yvel) > mMinFlingVelocity) {
-                    if (isDismissable()
-                            && yvel > 0 && mCollapseOffset > mCollapsibleHeight) {
-                        smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, yvel);
-                        mDismissOnScrollerFinished = true;
+                    if (getShowAtTop()) {
+                        if (isDismissable() && yvel < 0) {
+                            abortAnimation();
+                            dismiss();
+                        } else {
+                            smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel);
+                        }
                     } else {
-                        smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel);
+                        if (isDismissable()
+                                && yvel > 0 && mCollapseOffset > mCollapsibleHeight) {
+                            smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, yvel);
+                            mDismissOnScrollerFinished = true;
+                        } else {
+                            smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel);
+                        }
                     }
-                } else {
+                }else {
                     smoothScrollTo(
                             mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0);
                 }
@@ -421,6 +448,11 @@
         mVelocityTracker.clear();
     }
 
+    private void dismiss() {
+        mRunOnDismissedListener = new RunOnDismissedListener();
+        post(mRunOnDismissedListener);
+    }
+
     @Override
     public void computeScroll() {
         super.computeScroll();
@@ -430,8 +462,7 @@
             if (keepGoing) {
                 postInvalidateOnAnimation();
             } else if (mDismissOnScrollerFinished && mOnDismissedListener != null) {
-                mRunOnDismissedListener = new RunOnDismissedListener();
-                post(mRunOnDismissedListener);
+                dismiss();
             }
         }
     }
@@ -443,6 +474,10 @@
     }
 
     private float performDrag(float dy) {
+        if (getShowAtTop()) {
+            return 0;
+        }
+
         final float newPos = Math.max(0, Math.min(mCollapseOffset + dy,
                 mCollapsibleHeight + mUncollapsibleHeight));
         if (newPos != mCollapseOffset) {
@@ -656,7 +691,7 @@
 
     @Override
     public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
-        if (velocityY > mMinFlingVelocity && mCollapseOffset != 0) {
+        if (!getShowAtTop() && velocityY > mMinFlingVelocity && mCollapseOffset != 0) {
             smoothScrollTo(0, velocityY);
             return true;
         }
@@ -666,12 +701,21 @@
     @Override
     public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
         if (!consumed && Math.abs(velocityY) > mMinFlingVelocity) {
-            if (isDismissable()
-                    && velocityY < 0 && mCollapseOffset > mCollapsibleHeight) {
-                smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, velocityY);
-                mDismissOnScrollerFinished = true;
+            if (getShowAtTop()) {
+                if (isDismissable() && velocityY > 0) {
+                    abortAnimation();
+                    dismiss();
+                } else {
+                    smoothScrollTo(velocityY < 0 ? mCollapsibleHeight : 0, velocityY);
+                }
             } else {
-                smoothScrollTo(velocityY > 0 ? 0 : mCollapsibleHeight, velocityY);
+                if (isDismissable()
+                        && velocityY < 0 && mCollapseOffset > mCollapsibleHeight) {
+                    smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, velocityY);
+                    mDismissOnScrollerFinished = true;
+                } else {
+                    smoothScrollTo(velocityY > 0 ? 0 : mCollapsibleHeight, velocityY);
+                }
             }
             return true;
         }
@@ -794,7 +838,11 @@
 
         updateCollapseOffset(oldCollapsibleHeight, !isDragging());
 
-        mTopOffset = Math.max(0, heightSize - heightUsed) + (int) mCollapseOffset;
+        if (getShowAtTop()) {
+            mTopOffset = 0;
+        } else {
+            mTopOffset = Math.max(0, heightSize - heightUsed) + (int) mCollapseOffset;
+        }
 
         setMeasuredDimension(sourceWidth, heightSize);
     }
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 73a9fbb..8ed958d 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -18,8 +18,6 @@
 option java_multiple_files = true;
 option java_outer_classname = "IncidentProtoMetadata";
 
-import "frameworks/base/libs/incident/proto/android/privacy.proto";
-import "frameworks/base/libs/incident/proto/android/section.proto";
 import "frameworks/base/core/proto/android/os/cpufreq.proto";
 import "frameworks/base/core/proto/android/os/cpuinfo.proto";
 import "frameworks/base/core/proto/android/os/incidentheader.proto";
@@ -42,6 +40,8 @@
 import "frameworks/base/core/proto/android/service/package.proto";
 import "frameworks/base/core/proto/android/service/print.proto";
 import "frameworks/base/core/proto/android/service/procstats.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+import "frameworks/base/libs/incident/proto/android/section.proto";
 
 package android.os;
 
diff --git a/core/proto/android/os/procrank.proto b/core/proto/android/os/procrank.proto
index 9945f2e..f684c84 100644
--- a/core/proto/android/os/procrank.proto
+++ b/core/proto/android/os/procrank.proto
@@ -18,12 +18,15 @@
 option java_multiple_files = true;
 option java_outer_classname = "ProcrankProto";
 
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
 import "frameworks/base/tools/streaming_proto/stream.proto";
 
 package android.os;
 
 //Memory usage of running processes
 message Procrank {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     // Currently running process
     repeated ProcessProto processes = 1;
 
@@ -34,6 +37,7 @@
 // Next Tag: 11
 message ProcessProto {
     option (stream_proto.stream_msg).enable_fields_mapping = true;
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     // ID of the process
     optional int32 pid = 1;
@@ -68,6 +72,8 @@
 
 // Next Tag: 3
 message SummaryProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional ProcessProto total = 1;
 
     optional ZramProto zram = 2;
@@ -77,9 +83,13 @@
 
 // TODO: sync on how to use these values
 message ZramProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional string raw_text = 1;
 }
 
 message RamProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
     optional string raw_text = 1;
 }
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index da8a9cc..3b49d9d 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8538,6 +8538,8 @@
         <attr name="maxWidth" />
         <attr name="maxCollapsedHeight" format="dimension" />
         <attr name="maxCollapsedHeightSmall" format="dimension" />
+        <!-- Whether the Drawer should be positioned at the top rather than at the bottom. -->
+        <attr name="showAtTop" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="MessagingLinearLayout">
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index 55e804b..9fcb06e 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.R;
 import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
+import com.android.internal.widget.ResolverDrawerLayout;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -33,6 +34,8 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.widget.RelativeLayout;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -100,6 +103,34 @@
     }
 
     @Test
+    public void setShowAtTopToTrue() throws Exception {
+        Intent sendIntent = createSendImageIntent();
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+        waitForIdle();
+
+        final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+        final View resolverList = activity.findViewById(R.id.resolver_list);
+        final RelativeLayout profileView =
+            (RelativeLayout) activity.findViewById(R.id.profile_button).getParent();
+        assertThat("Drawer should show at bottom by default",
+                profileView.getBottom() == resolverList.getTop() && profileView.getTop() > 0);
+
+        activity.runOnUiThread(() -> {
+            ResolverDrawerLayout layout = (ResolverDrawerLayout)
+                    activity.findViewById(
+                            R.id.contentPanel);
+            layout.setShowAtTop(true);
+        });
+        waitForIdle();
+        assertThat("Drawer should show at top with new attribute",
+            profileView.getBottom() == resolverList.getTop() && profileView.getTop() == 0);
+    }
+
+    @Test
     public void hasLastChosenActivity() throws Exception {
         Intent sendIntent = createSendImageIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
@@ -283,4 +314,4 @@
     private void waitForIdle() {
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
-}
\ No newline at end of file
+}
diff --git a/libs/incident/include/android/os/IncidentReportArgs.h b/libs/incident/include/android/os/IncidentReportArgs.h
index da80989..2849d58 100644
--- a/libs/incident/include/android/os/IncidentReportArgs.h
+++ b/libs/incident/include/android/os/IncidentReportArgs.h
@@ -29,6 +29,12 @@
 
 using namespace std;
 
+// DESTINATION enum value, sync with proto/android/privacy.proto
+const uint8_t DEST_LOCAL = 0;
+const uint8_t DEST_EXPLICIT = 100;
+const uint8_t DEST_AUTOMATIC = 200;
+
+
 class IncidentReportArgs : public Parcelable {
 public:
     IncidentReportArgs();
@@ -41,19 +47,19 @@
     void setAll(bool all);
     void setDest(int dest);
     void addSection(int section);
-    void addHeader(const vector<int8_t>& header);
+    void addHeader(const vector<uint8_t>& header);
 
     inline bool all() const { return mAll; }
     bool containsSection(int section) const;
     inline int dest() const { return mDest; }
     inline const set<int>& sections() const { return mSections; }
-    inline const vector<vector<int8_t>>& headers() const { return mHeaders; }
+    inline const vector<vector<uint8_t>>& headers() const { return mHeaders; }
 
     void merge(const IncidentReportArgs& that);
 
 private:
     set<int> mSections;
-    vector<vector<int8_t>> mHeaders;
+    vector<vector<uint8_t>> mHeaders;
     bool mAll;
     int mDest;
 };
diff --git a/libs/incident/proto/android/privacy.proto b/libs/incident/proto/android/privacy.proto
index 5fd75d6..7590b22 100644
--- a/libs/incident/proto/android/privacy.proto
+++ b/libs/incident/proto/android/privacy.proto
@@ -34,21 +34,23 @@
 
     // Fields or messages annotated with DEST_EXPLICIT can be sent
     // off the device with an explicit user action.
-    DEST_EXPLICIT = 1;
+    DEST_EXPLICIT = 100;
 
     // Fields or messages annotated with DEST_AUTOMATIC can be sent by
     // automatic means, without per-sending user consent. The user
     // still must have previously accepted a consent to share this
     // information.
-    DEST_AUTOMATIC = 2;
+    DEST_AUTOMATIC = 200;
 
-    // There is no more permissive option than DEST_AUTOMATIC.
+    // This is the default value, which could be overridden by other values.
+    // The reason to pick 255 is it fits into one byte.
+    DEST_UNSET = 255;
+
+    // Currently use 0, 100, 200 and 255, values in between are reserved for futures.
 }
 
 message PrivacyFlags {
-  optional Destination dest = 1  [
-      default = DEST_EXPLICIT
-  ];
+  optional Destination dest = 1 [ default = DEST_UNSET ];
 
   // regex to filter pii sensitive info from a string field type
   repeated string patterns = 2;
@@ -58,3 +60,8 @@
     // Flags for automatically filtering statistics
     optional PrivacyFlags privacy = 102672883;
 }
+
+extend google.protobuf.MessageOptions {
+    // Flags used to annotate a message which all its unset primitive types inhert this tag.
+    optional PrivacyFlags msg_privacy = 102672883;
+}
diff --git a/libs/incident/src/IncidentReportArgs.cpp b/libs/incident/src/IncidentReportArgs.cpp
index e628722..bd9c8ee 100644
--- a/libs/incident/src/IncidentReportArgs.cpp
+++ b/libs/incident/src/IncidentReportArgs.cpp
@@ -69,7 +69,7 @@
         return err;
     }
 
-    for (vector<vector<int8_t>>::const_iterator it = mHeaders.begin(); it != mHeaders.end(); it++) {
+    for (vector<vector<uint8_t>>::const_iterator it = mHeaders.begin(); it != mHeaders.end(); it++) {
         err = out->writeByteVector(*it);
         if (err != NO_ERROR) {
             return err;
@@ -161,7 +161,7 @@
 }
 
 void
-IncidentReportArgs::addHeader(const vector<int8_t>& header)
+IncidentReportArgs::addHeader(const vector<uint8_t>& header)
 {
     mHeaders.push_back(header);
 }
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index f20ca43..f4238f2 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -282,6 +282,7 @@
         mBoundUserId = UserHandle.USER_NULL;
         if (component != null) {
             if (D) Log.d(mTag, "unbinding " + component);
+            mBoundService = null;
             mContext.unbindService(this);
         }
     }
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index 674bee1..7650795 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -59,24 +59,31 @@
  *
  * #include "section_list.h"
  * ...
- * Privacy WindowState_state { 1, 9, NULL, LOCAL, NULL }; // first two integers are values for field id and proto type.
- * Privacy WindowState_child_windows { 3, 11, NULL, DEFAULT, NULL }; // reserved for WindowState_LIST
- * Privacy* WindowState_MSG_[] = {
+ * Privacy WindowState__state { 1, 9, NULL, LOCAL, NULL }; // first two integers are values for field id and proto type.
+ * Privacy WindowState__child_windows { 3, 11, NULL, UNSET, NULL }; // reserved for WindowState_LIST
+ * Privacy* WindowState__MSG__UNSET[] = {
  *     &WindowState_state,
  *     // display id is default, nothing is generated.
  *     &WindowState_child_windows,
  *     NULL  // terminator of the array
  * };
- * Privacy WindowState_my_window { 1, 11, WindowState_my_window_LIST, DEFAULT, NULL };
+ * Privacy WindowState__my_window { 1, 11, WindowState__MSG__UNSET, UNSET, NULL };
  *
  * createList() {
  *    ...
- *    WindowState_child_windows.children = WindowState_my_window_LIST; // point to its own definition after the list is defined.
+ *    WindowState_child_windows.children = WindowState__MSG_UNSET; // point to its own definition after the list is defined.
  *    ...
  * }
  *
  * const Privacy** PRIVACY_POLICY_LIST = createList();
  * const int PRIVACY_POLICY_COUNT = 1;
+ *
+ * Privacy Value Inheritance rules:
+ * 1. Both field and message can be tagged with DESTINATION: LOCAL(L), EXPLICIT(E), AUTOMATIC(A).
+ * 2. Primitives inherits containing message's tag unless defined explicitly.
+ * 3. Containing message's tag doesn't apply to message fields, even when unset (in this case, uses its default message tag).
+ * 4. Message field tag overrides its default message tag.
+ * 5. UNSET tag defaults to EXPLICIT.
  */
 
 // The assignments will be called when constructs PRIVACY_POLICY_LIST, has to be global variable
@@ -164,14 +171,13 @@
     return result;
 }
 
-static string getFieldName(const FieldDescriptor* field) {
-    return replaceAll(field->full_name(), '.', "__");
+static inline void printPrivacy(const string& name, const FieldDescriptor* field, const string& children,
+        const Destination dest, const string& patterns, const string& comments = "") {
+    printf("Privacy %s = { %d, %d, %s, %d, %s };%s\n", name.c_str(), field->number(), field->type(),
+        children.c_str(), dest, patterns.c_str(), comments.c_str());
 }
 
-static string getMessageTypeName(const Descriptor* descriptor) {
-    return replaceAll(descriptor->full_name(), '.', "_") + "_MSG_";
-}
-
+// Get Custom Options ================================================================================
 static inline SectionFlags getSectionFlags(const FieldDescriptor* field) {
     return field->options().GetExtension(section);
 }
@@ -180,24 +186,64 @@
     return field->options().GetExtension(privacy);
 }
 
-static inline bool isDefaultField(const FieldDescriptor* field) {
-    return getPrivacyFlags(field).dest() == PrivacyFlags::default_instance().dest();
+static inline PrivacyFlags getPrivacyFlags(const Descriptor* descriptor) {
+    return descriptor->options().GetExtension(msg_privacy);
 }
 
-static bool isDefaultMessageImpl(const Descriptor* descriptor, set<string>* parents) {
-    int N = descriptor->field_count();
+// Get Destinations ===================================================================================
+static inline Destination getMessageDest(const Descriptor* descriptor, const Destination overridden) {
+    return overridden != DEST_UNSET ? overridden : getPrivacyFlags(descriptor).dest();
+}
+
+// Returns field's own dest, when it is a message field, uses its message default tag if unset.
+static inline Destination getFieldDest(const FieldDescriptor* field) {
+    Destination fieldDest = getPrivacyFlags(field).dest();
+    return field->type() != FieldDescriptor::TYPE_MESSAGE ? fieldDest :
+            getMessageDest(field->message_type(), fieldDest);
+}
+
+// Get Names ===========================================================================================
+static inline string getFieldName(const FieldDescriptor* field) {
+    // replace . with double underscores to avoid name conflicts since fields use snake naming convention
+    return replaceAll(field->full_name(), '.', "__");
+}
+
+
+static inline string getMessageName(const Descriptor* descriptor, const Destination overridden) {
+    // replace . with one underscore since messages use camel naming convention
+    return replaceAll(descriptor->full_name(), '.', "_") + "__MSG__" +
+            to_string(getMessageDest(descriptor, overridden));
+}
+
+// IsDefault ============================================================================================
+// Returns true if a field is default. Default is defined as this field has same dest as its containing message.
+// For message fields, it only looks at its field tag and own default mesaage tag, doesn't recursively go deeper.
+static inline bool isDefaultField(const FieldDescriptor* field, const Destination containerDest) {
+    Destination fieldDest = getFieldDest(field);
+    if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
+        return fieldDest == containerDest || (fieldDest == DEST_UNSET);
+    } else {
+        return fieldDest == containerDest ||
+            (containerDest == DEST_UNSET && fieldDest == DEST_EXPLICIT) ||
+            (containerDest == DEST_EXPLICIT && fieldDest == DEST_UNSET);
+    }
+}
+
+static bool isDefaultMessageImpl(const Descriptor* descriptor, const Destination dest, set<string>* parents) {
+    const int N = descriptor->field_count();
+    const Destination messageDest = getMessageDest(descriptor, dest);
     parents->insert(descriptor->full_name());
     for (int i=0; i<N; ++i) {
         const FieldDescriptor* field = descriptor->field(i);
-        // look at if the current field is default or not, return false immediately
-        if (!isDefaultField(field)) return false;
-
+        const Destination fieldDest = getFieldDest(field);
+        // If current field is not default, return false immediately
+        if (!isDefaultField(field, messageDest)) return false;
         switch (field->type()) {
             case FieldDescriptor::TYPE_MESSAGE:
                 // if self recursion, don't go deep.
                 if (parents->find(field->message_type()->full_name()) != parents->end()) break;
                 // if is a default message, just continue
-                if (isDefaultMessageImpl(field->message_type(), parents)) break;
+                if (isDefaultMessageImpl(field->message_type(), fieldDest, parents)) break;
                 // sub message is not default, so this message is always not default
                 return false;
             case FieldDescriptor::TYPE_STRING:
@@ -210,106 +256,118 @@
     return true;
 }
 
-static bool isDefaultMessage(const Descriptor* descriptor) {
+// Recursively look at if this message is default, meaning all its fields and sub-messages
+// can be described by the same dest.
+static bool isDefaultMessage(const Descriptor* descriptor, const Destination dest) {
     set<string> parents;
-    return isDefaultMessageImpl(descriptor, &parents);
+    return isDefaultMessageImpl(descriptor, dest, &parents);
 }
 
-// This function is called for looking at privacy tags for a message type and recursively its sub-messages
-// It prints out each fields's privacy tags and a List of Privacy of the message itself (don't print default values)
-// Returns false if the descriptor doesn't have any non default privacy flags set, including its submessages
-static bool generatePrivacyFlags(const Descriptor* descriptor, map<string, bool> &msgNames, set<string>* parents) {
-    bool hasDefaultFlags[descriptor->field_count()];
+// ===============================================================================================================
+static bool numberInOrder(const FieldDescriptor* f1, const FieldDescriptor* f2) {
+    return f1->number() < f2->number();
+}
 
-    string messageTypeName = getMessageTypeName(descriptor);
-    // if the message is already defined, skip it.
-    if (msgNames.find(messageTypeName) != msgNames.end()) {
-        bool hasDefault = msgNames[messageTypeName];
-        return !hasDefault; // don't generate if it has default privacy.
+// field numbers are possibly out of order, sort them here.
+static vector<const FieldDescriptor*> sortFields(const Descriptor* descriptor) {
+    vector<const FieldDescriptor*> fields;
+    fields.reserve(descriptor->field_count());
+    for (int i=0; i<descriptor->field_count(); i++) {
+        fields.push_back(descriptor->field(i));
+    }
+    std::sort(fields.begin(), fields.end(), numberInOrder);
+    return fields;
+}
+
+// This function looks for privacy tags of a message type and recursively its sub-messages.
+// It generates Privacy objects for each non-default fields including non-default sub-messages.
+// And if the message has Privacy objects generated, it returns a list of them.
+// Returns false if the descriptor doesn't have any non default privacy flags set, including its submessages
+static bool generatePrivacyFlags(const Descriptor* descriptor, const Destination overridden,
+        map<string, bool> &variableNames, set<string>* parents) {
+    const string messageName = getMessageName(descriptor, overridden);
+    const Destination messageDest = getMessageDest(descriptor, overridden);
+
+    if (variableNames.find(messageName) != variableNames.end()) {
+        bool hasDefault = variableNames[messageName];
+        return !hasDefault; // if has default, then don't generate privacy flags.
     }
     // insert the message type name so sub-message will figure out if self-recursion occurs
-    parents->insert(messageTypeName);
+    parents->insert(messageName);
 
-    // iterate though its field and generate sub flags first
-    for (int i=0; i<descriptor->field_count(); i++) {
-        hasDefaultFlags[i] = true; // set default to true
-
-        const FieldDescriptor* field = descriptor->field(i);
+    // sort fields based on number, iterate though them and generate sub flags first
+    vector<const FieldDescriptor*> fieldsInOrder = sortFields(descriptor);
+    bool hasDefaultFlags[fieldsInOrder.size()];
+    for (size_t i=0; i<fieldsInOrder.size(); i++) {
+        const FieldDescriptor* field = fieldsInOrder[i];
         const string fieldName = getFieldName(field);
-        // check if the same field name is already defined.
-        if (msgNames.find(fieldName) != msgNames.end()) {
-            hasDefaultFlags[i] = msgNames[fieldName];
-            continue;
-        };
+        const Destination fieldDest = getFieldDest(field);
 
-        PrivacyFlags p = getPrivacyFlags(field);
+        if (variableNames.find(fieldName) != variableNames.end()) {
+            hasDefaultFlags[i] = variableNames[fieldName];
+            continue;
+        }
+        hasDefaultFlags[i] = isDefaultField(field, messageDest);
+
         string fieldMessageName;
+        PrivacyFlags p = getPrivacyFlags(field);
         switch (field->type()) {
             case FieldDescriptor::TYPE_MESSAGE:
-                fieldMessageName = getMessageTypeName(field->message_type());
+                fieldMessageName = getMessageName(field->message_type(), fieldDest);
                 if (parents->find(fieldMessageName) != parents->end()) { // Self-Recursion proto definition
-                    if (isDefaultField(field)) {
-                        hasDefaultFlags[i] = isDefaultMessage(field->message_type());
-                    } else {
-                        hasDefaultFlags[i] = false;
+                    if (hasDefaultFlags[i]) {
+                        hasDefaultFlags[i] = isDefaultMessage(field->message_type(), fieldDest);
                     }
                     if (!hasDefaultFlags[i]) {
-                        printf("Privacy %s = { %d, %d, NULL, %d, NULL }; // self recursion field of %s\n",
-                                fieldName.c_str(), field->number(), field->type(), p.dest(), fieldMessageName.c_str());
+                        printPrivacy(fieldName, field, "NULL", fieldDest, "NULL",
+                            " // self recursion field of " + fieldMessageName);
                         // generate the assignment and used to construct createList function later on.
                         gSelfRecursionAssignments.push_back(fieldName + ".children = " + fieldMessageName);
                     }
-                    break;
-                } else if (generatePrivacyFlags(field->message_type(), msgNames, parents)) {
-                    printf("Privacy %s = { %d, %d, %s, %d, NULL };\n", fieldName.c_str(), field->number(),
-                            field->type(), fieldMessageName.c_str(), p.dest());
-                } else if (isDefaultField(field)) {
-                    // don't create a new privacy if the value is default.
-                    break;
-                } else {
-                    printf("Privacy %s = { %d, %d, NULL, %d, NULL };\n", fieldName.c_str(), field->number(),
-                            field->type(), p.dest());
+                } else if (generatePrivacyFlags(field->message_type(), p.dest(), variableNames, parents)) {
+                    if (variableNames.find(fieldName) == variableNames.end()) {
+                        printPrivacy(fieldName, field, fieldMessageName, fieldDest, "NULL");
+                    }
+                    hasDefaultFlags[i] = false;
+                } else if (!hasDefaultFlags[i]) {
+                    printPrivacy(fieldName, field, "NULL", fieldDest, "NULL");
                 }
-                hasDefaultFlags[i] = false;
                 break;
             case FieldDescriptor::TYPE_STRING:
-                if (isDefaultField(field) && p.patterns_size() == 0) break;
-
-                printf("const char* %s_patterns[] = {\n", fieldName.c_str());
-                for (int i=0; i<p.patterns_size(); i++) {
-                    // the generated string need to escape backslash as well, need to dup it here
-                    printf("    \"%s\",\n", replaceAll(p.patterns(i), '\\', "\\\\").c_str());
+                if (p.patterns_size() != 0) { // if patterns are specified
+                    if (hasDefaultFlags[i]) break;
+                    printf("const char* %s_patterns[] = {\n", fieldName.c_str());
+                    for (int j=0; j<p.patterns_size(); j++) {
+                        // generated string needs to escape backslash too, duplicate it to allow escape again.
+                        printf("    \"%s\",\n", replaceAll(p.patterns(j), '\\', "\\\\").c_str());
+                    }
+                    printf("    NULL };\n");
+                    printPrivacy(fieldName, field, "NULL", fieldDest, fieldName + "_patterns");
+                    break;
                 }
-                printf("    NULL };\n");
-                printf("Privacy %s = { %d, %d, NULL, %d, %s_patterns };\n", fieldName.c_str(), field->number(),
-                        field->type(), p.dest(), fieldName.c_str());
-                hasDefaultFlags[i] = false;
-                break;
+                // else treat string field as primitive field and goes to default
             default:
-                if (isDefaultField(field)) break;
-                printf("Privacy %s = { %d, %d, NULL, %d, NULL };\n", fieldName.c_str(), field->number(),
-                        field->type(), p.dest());
-                hasDefaultFlags[i] = false;
+                if (!hasDefaultFlags[i]) printPrivacy(fieldName, field, "NULL", fieldDest, "NULL");
         }
-        // add the field name to message map, true means it has default flags
-        msgNames[fieldName] = hasDefaultFlags[i];
+        // Don't generate a variable twice
+        if (!hasDefaultFlags[i]) variableNames[fieldName] = false;
     }
 
     bool allDefaults = true;
-    for (int i=0; i<descriptor->field_count(); i++) {
+    for (size_t i=0; i<fieldsInOrder.size(); i++) {
         allDefaults &= hasDefaultFlags[i];
     }
 
-    parents->erase(messageTypeName); // erase the message type name when exit the message.
-    msgNames[messageTypeName] = allDefaults; // store the privacy tags of the message here to avoid overhead.
+    parents->erase(messageName); // erase the message type name when exit the message.
+    variableNames[messageName] = allDefaults; // store the privacy tags of the message here to avoid overhead.
 
     if (allDefaults) return false;
 
     emptyline();
     int policyCount = 0;
-    printf("Privacy* %s[] = {\n", messageTypeName.c_str());
-    for (int i=0; i<descriptor->field_count(); i++) {
-        const FieldDescriptor* field = descriptor->field(i);
+    printf("Privacy* %s[] = {\n", messageName.c_str());
+    for (size_t i=0; i<fieldsInOrder.size(); i++) {
+        const FieldDescriptor* field = fieldsInOrder[i];
         if (hasDefaultFlags[i]) continue;
         printf("    &%s,\n", getFieldName(field).c_str());
         policyCount++;
@@ -359,29 +417,30 @@
 
     // generates PRIVACY_POLICY_LIST
     printf("// Generate PRIVACY_POLICY_LIST.\n\n");
-    map<string, bool> messageNames;
+    map<string, bool> variableNames;
     set<string> parents;
-    bool skip[descriptor->field_count()];
+    vector<const FieldDescriptor*> fieldsInOrder = sortFields(descriptor);
+    bool skip[fieldsInOrder.size()];
+    const Destination incidentDest = getPrivacyFlags(descriptor).dest();
 
-    for (int i=0; i<descriptor->field_count(); i++) {
-        const FieldDescriptor* field = descriptor->field(i);
+    for (size_t i=0; i<fieldsInOrder.size(); i++) {
+        const FieldDescriptor* field = fieldsInOrder[i];
         const string fieldName = getFieldName(field);
-        PrivacyFlags p = getPrivacyFlags(field);
+        const Destination fieldDest = getFieldDest(field);
+        const string fieldMessageName = getMessageName(field->message_type(), fieldDest);
 
         skip[i] = true;
 
         if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
             continue;
         }
-        // generate privacy flags for each field.
-        if (generatePrivacyFlags(field->message_type(), messageNames, &parents)) {
-            printf("Privacy %s { %d, %d, %s, %d, NULL };\n", fieldName.c_str(), field->number(),
-                    field->type(), getMessageTypeName(field->message_type()).c_str(), p.dest());
-        } else if (isDefaultField(field)) {
+        // generate privacy flags for each section.
+        if (generatePrivacyFlags(field->message_type(), fieldDest, variableNames, &parents)) {
+            printPrivacy(fieldName, field, fieldMessageName, fieldDest, "NULL");
+        } else if (isDefaultField(field, incidentDest)) {
             continue; // don't create a new privacy if the value is default.
         } else {
-            printf("Privacy %s { %d, %d, NULL, %d, NULL };\n", fieldName.c_str(), field->number(),
-                    field->type(), p.dest());
+            printPrivacy(fieldName, field, "NULL", fieldDest, "NULL");
         }
         skip[i] = false;
     }
@@ -391,16 +450,16 @@
     int policyCount = 0;
     if (gSelfRecursionAssignments.empty()) {
         printf("Privacy* privacyArray[] = {\n");
-        for (int i=0; i<descriptor->field_count(); i++) {
+        for (size_t i=0; i<fieldsInOrder.size(); i++) {
             if (skip[i]) continue;
-            printf("    &%s,\n", getFieldName(descriptor->field(i)).c_str());
+            printf("    &%s,\n", getFieldName(fieldsInOrder[i]).c_str());
             policyCount++;
         }
         printf("};\n\n");
         printf("const Privacy** PRIVACY_POLICY_LIST = const_cast<const Privacy**>(privacyArray);\n\n");
         printf("const int PRIVACY_POLICY_COUNT = %d;\n", policyCount);
     } else {
-        for (int i=0; i<descriptor->field_count(); i++) {
+        for (size_t i=0; i<fieldsInOrder.size(); i++) {
             if (!skip[i]) policyCount++;
         }
 
@@ -410,9 +469,9 @@
         }
         printf("    Privacy** privacyArray = (Privacy**)malloc(%d * sizeof(Privacy**));\n", policyCount);
         policyCount = 0; // reset
-        for (int i=0; i<descriptor->field_count(); i++) {
+        for (size_t i=0; i<fieldsInOrder.size(); i++) {
             if (skip[i]) continue;
-            printf("    privacyArray[%d] = &%s;\n", policyCount++, getFieldName(descriptor->field(i)).c_str());
+            printf("    privacyArray[%d] = &%s;\n", policyCount++, getFieldName(fieldsInOrder[i]).c_str());
         }
         printf("    return const_cast<const Privacy**>(privacyArray);\n");
         printf("}\n\n");