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/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