libbinder: binders hold wire protocol version

The libbinder wire protocol version is currently unstable, but we may
stablize it. This adds a version field in the stability token which is
passed around with binder objects, so it doesn't require additional
memory.

Future consideration/direction:
- when starting a transaction, attach a binder to a Parcel object
- when parceling, parcel according to the maximum of (locally
  understood wire protocol, binder wire protocol)
- verify in transact the data parcel has the corresponding binder
- when the server creates a reply parcel, note version which is the
  same as the version used in the data Parcel (we know that whoever
  wrote this transaction can understand this level).
- save binary blobs of known write*/read* data flows, and test that
  Parcel can understand and recreate these blobs after it is versioned.

Bug: 167966510
Test: 'atest binderStabilityTest' - verifies behavior
Test: internally checks version is always set
Change-Id: I9bb5be5b5b7d7255f8387cf690d86a055102f95d
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index c183d29..8264154 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -223,13 +223,14 @@
         if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
             using android::internal::Stability;
 
-            auto stability = Stability::get(this);
-            auto required = privateVendor ? Stability::VENDOR : Stability::getLocalStability();
+            auto category = Stability::getCategory(this);
+            Stability::Level required = privateVendor ? Stability::VENDOR
+                : Stability::getLocalLevel();
 
-            if (CC_UNLIKELY(!Stability::check(stability, required))) {
+            if (CC_UNLIKELY(!Stability::check(category, required))) {
                 ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
-                    Stability::stabilityString(stability).c_str(),
-                    Stability::stabilityString(required).c_str());
+                    category.debugString().c_str(),
+                    Stability::levelString(required).c_str());
                 return BAD_TYPE;
             }
         }
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index feeb819..cc30fa8 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -171,7 +171,8 @@
     if (status != OK) return status;
 
     internal::Stability::tryMarkCompilationUnit(binder.get());
-    return writeInt32(internal::Stability::get(binder.get()));
+    auto category = internal::Stability::getCategory(binder.get());
+    return writeInt32(category.repr());
 }
 
 status_t Parcel::finishUnflattenBinder(
@@ -181,7 +182,7 @@
     status_t status = readInt32(&stability);
     if (status != OK) return status;
 
-    status = internal::Stability::set(binder.get(), stability, true /*log*/);
+    status = internal::Stability::setRepr(binder.get(), stability, true /*log*/);
     if (status != OK) return status;
 
     *out = binder;
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
index 6115aec..339c538 100644
--- a/libs/binder/Stability.cpp
+++ b/libs/binder/Stability.cpp
@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "Stability"
+
 #include <binder/Stability.h>
 
 #include <binder/BpBinder.h>
@@ -21,34 +23,59 @@
 namespace android {
 namespace internal {
 
+// the libbinder parcel format is currently unstable
+
+// oldest version which is supported
+constexpr uint8_t kBinderWireFormatOldest = 1;
+// current version
+constexpr uint8_t kBinderWireFormatVersion = 1;
+
+Stability::Category Stability::Category::currentFromLevel(Level level) {
+    return {
+        .version = kBinderWireFormatVersion,
+        .reserved = {0},
+        .level = level,
+    };
+}
+
+std::string Stability::Category::debugString() {
+    return levelString(level) + " wire protocol version "
+        + std::to_string(version);
+}
+
 void Stability::markCompilationUnit(IBinder* binder) {
-    status_t result = set(binder, getLocalStability(), true /*log*/);
+    auto stability = Category::currentFromLevel(getLocalLevel());
+    status_t result = setRepr(binder, stability.repr(), true /*log*/);
     LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
 }
 
 void Stability::markVintf(IBinder* binder) {
-    status_t result = set(binder, Level::VINTF, true /*log*/);
+    auto stability = Category::currentFromLevel(Level::VINTF);
+    status_t result = setRepr(binder, stability.repr(), true /*log*/);
     LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
 }
 
 void Stability::debugLogStability(const std::string& tag, const sp<IBinder>& binder) {
-    ALOGE("%s: stability is %s", tag.c_str(), stabilityString(get(binder.get())).c_str());
+    auto stability = getCategory(binder.get());
+    ALOGE("%s: stability is %s", tag.c_str(), stability.debugString().c_str());
 }
 
 void Stability::markVndk(IBinder* binder) {
-    status_t result = set(binder, Level::VENDOR, true /*log*/);
+    auto stability = Category::currentFromLevel(Level::VENDOR);
+    status_t result = setRepr(binder, stability.repr(), true /*log*/);
     LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
 }
 
 bool Stability::requiresVintfDeclaration(const sp<IBinder>& binder) {
-    return check(get(binder.get()), Level::VINTF);
+    return check(getCategory(binder.get()), Level::VINTF);
 }
 
 void Stability::tryMarkCompilationUnit(IBinder* binder) {
-    (void) set(binder, getLocalStability(), false /*log*/);
+    auto stability = Category::currentFromLevel(getLocalLevel());
+    (void) setRepr(binder, stability.repr(), false /*log*/);
 }
 
-Stability::Level Stability::getLocalStability() {
+Stability::Level Stability::getLocalLevel() {
 #ifdef __ANDROID_VNDK__
     #ifdef __ANDROID_APEX__
         // TODO(b/142684679) avoid use_vendor on system APEXes
@@ -67,65 +94,81 @@
 #endif
 }
 
-status_t Stability::set(IBinder* binder, int32_t stability, bool log) {
-    Level currentStability = get(binder);
+status_t Stability::setRepr(IBinder* binder, int32_t representation, bool log) {
+    auto current = getCategory(binder);
+    auto setting = Category::fromRepr(representation);
+
+    // If we have ahold of a binder with a newer declared version, then it
+    // should support older versions, and we will simply write our parcels with
+    // the current wire parcel format.
+    if (setting.version < kBinderWireFormatOldest) {
+        // always log, because this shouldn't happen
+        ALOGE("Cannot accept binder with older binder wire protocol version "
+              "%u. Versions less than %u are unsupported.", setting.version,
+               kBinderWireFormatOldest);
+        return BAD_TYPE;
+    }
 
     // null binder is always written w/ 'UNDECLARED' stability
     if (binder == nullptr) {
-        if (stability == UNDECLARED) {
+        if (setting.level == UNDECLARED) {
             return OK;
         } else {
             if (log) {
                 ALOGE("Null binder written with stability %s.",
-                    stabilityString(stability).c_str());
+                    levelString(setting.level).c_str());
             }
             return BAD_TYPE;
         }
     }
 
-    if (!isDeclaredStability(stability)) {
+    if (!isDeclaredLevel(setting.level)) {
         if (log) {
-            ALOGE("Can only set known stability, not %d.", stability);
+            ALOGE("Can only set known stability, not %u.", setting.level);
         }
         return BAD_TYPE;
     }
 
-    if (currentStability != Level::UNDECLARED && currentStability != stability) {
+    if (current.repr() != 0 && current != setting) {
         if (log) {
-            ALOGE("Interface being set with %s but it is already marked as %s.",
-                stabilityString(stability).c_str(), stabilityString(currentStability).c_str());
+            ALOGE("Interface being set with %s but it is already marked as %s",
+                  setting.debugString().c_str(),
+                  current.debugString().c_str());
         }
         return BAD_TYPE;
     }
 
-    if (currentStability == stability) return OK;
+    if (current == setting) return OK;
 
     BBinder* local = binder->localBinder();
     if (local != nullptr) {
-        local->mStability = static_cast<int32_t>(stability);
+        local->mStability = setting.repr();
     } else {
-        binder->remoteBinder()->mStability = static_cast<int32_t>(stability);
+        binder->remoteBinder()->mStability = setting.repr();
     }
 
     return OK;
 }
 
-Stability::Level Stability::get(IBinder* binder) {
-    if (binder == nullptr) return UNDECLARED;
+Stability::Category Stability::getCategory(IBinder* binder) {
+    if (binder == nullptr) {
+        return Category::currentFromLevel(Level::UNDECLARED);
+    }
 
     BBinder* local = binder->localBinder();
     if (local != nullptr) {
-        return static_cast<Stability::Level>(local->mStability);
+        return Category::fromRepr(local->mStability);
     }
 
-    return static_cast<Stability::Level>(binder->remoteBinder()->mStability);
+    return Category::fromRepr(binder->remoteBinder()->mStability);
 }
 
-bool Stability::check(int32_t provided, Level required) {
-    bool stable = (provided & required) == required;
+bool Stability::check(Category provided, Level required) {
+    bool stable = (provided.level & required) == required;
 
-    if (!isDeclaredStability(provided) && provided != UNDECLARED) {
-        ALOGE("Unknown stability when checking interface stability %d.", provided);
+    if (provided.level != UNDECLARED && !isDeclaredLevel(provided.level)) {
+        ALOGE("Unknown stability when checking interface stability %d.",
+              provided.level);
 
         stable = false;
     }
@@ -133,18 +176,18 @@
     return stable;
 }
 
-bool Stability::isDeclaredStability(int32_t stability) {
+bool Stability::isDeclaredLevel(Level stability) {
     return stability == VENDOR || stability == SYSTEM || stability == VINTF;
 }
 
-std::string Stability::stabilityString(int32_t stability) {
-    switch (stability) {
+std::string Stability::levelString(Level level) {
+    switch (level) {
         case Level::UNDECLARED: return "undeclared stability";
         case Level::VENDOR: return "vendor stability";
         case Level::SYSTEM: return "system stability";
         case Level::VINTF: return "vintf stability";
     }
-    return "unknown stability " + std::to_string(stability);
+    return "unknown stability " + std::to_string(level);
 }
 
 }  // namespace internal
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index 6566285..12272ba 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -26,6 +26,29 @@
 
 namespace internal {
 
+// Stability encodes how a binder changes over time. There are two levels of
+// stability:
+// 1). the interface stability - this is how a particular set of API calls (a
+//   particular ordering of things like writeInt32/readInt32) are changed over
+//   time. If one release, we have 'writeInt32' and the next release, we have
+//   'writeInt64', then this interface doesn't have a very stable
+//   Stability::Level. Usually this ordering is controlled by a .aidl file.
+// 2). the wire format stability - this is how these API calls map to actual
+//   bytes that are written to the wire (literally, this is how they are written
+//   to the kernel inside of IBinder::transact, but it may be expanded to other
+//   wires in the future). For instance, writeInt32 in binder translates to
+//   writing a 4-byte little-endian integer in two's complement. You can imagine
+//   in the future, we change writeInt32/readInt32 to instead write 8-bytes with
+//   that integer and some check bits. In this case, the wire format changes,
+//   but as long as a client libbinder knows to keep on writing a 4-byte value
+//   to old servers, and new servers know how to interpret the 8-byte result,
+//   they can still communicate.
+//
+// Every binder object has a stability level associated with it, and when
+// communicating with a binder, we make sure that the command we sent is one
+// that it knows how to process. The summary of stability of a binder is
+// represented by a Stability::Category object.
+
 // WARNING: These APIs are only ever expected to be called by auto-generated code.
 //     Instead of calling them, you should set the stability of a .aidl interface
 class Stability final {
@@ -73,7 +96,7 @@
 
     static void tryMarkCompilationUnit(IBinder* binder);
 
-    enum Level : int32_t {
+    enum Level : uint8_t {
         UNDECLARED = 0,
 
         VENDOR = 0b000011,
@@ -81,19 +104,54 @@
         VINTF = 0b111111,
     };
 
+    // This is the format of stability passed on the wire.
+    struct Category {
+        static inline Category fromRepr(int32_t representation) {
+            return *reinterpret_cast<Category*>(&representation);
+        }
+        int32_t repr() const {
+            return *reinterpret_cast<const int32_t*>(this);
+        }
+        static inline Category currentFromLevel(Level level);
+
+        bool operator== (const Category& o) const {
+            return repr() == o.repr();
+        }
+        bool operator!= (const Category& o) const {
+            return !(*this == o);
+        }
+
+        std::string debugString();
+
+        // This is the version of the wire protocol associated with the host
+        // process of a particular binder. As the wire protocol changes, if
+        // sending a transaction to a binder with an old version, the Parcel
+        // class must write parcels according to the version documented here.
+        uint8_t version;
+
+        uint8_t reserved[2];
+
+        // bitmask of Stability::Level
+        Level level;
+    };
+    static_assert(sizeof(Category) == sizeof(int32_t));
+
     // returns the stability according to how this was built
-    static Level getLocalStability();
+    static Level getLocalLevel();
 
     // applies stability to binder if stability level is known
     __attribute__((warn_unused_result))
-    static status_t set(IBinder* binder, int32_t stability, bool log);
+    static status_t setRepr(IBinder* binder, int32_t representation, bool log);
 
-    static Level get(IBinder* binder);
+    // get stability information as encoded on the wire
+    static Category getCategory(IBinder* binder);
 
-    static bool check(int32_t provided, Level required);
+    // whether a transaction on binder is allowed, if the transaction
+    // is done from a context with a specific stability level
+    static bool check(Category provided, Level required);
 
-    static bool isDeclaredStability(int32_t stability);
-    static std::string stabilityString(int32_t stability);
+    static bool isDeclaredLevel(Level level);
+    static std::string levelString(Level level);
 
     Stability();
 };