diff options
author | 2021-03-23 01:38:24 +0000 | |
---|---|---|
committer | 2021-03-24 01:18:13 +0000 | |
commit | e35fef3e9f9c93d91b896d83f1e028acb21d4334 (patch) | |
tree | 4b7862f9f21642c5ab0e3b0eb69acf1d9bc236d0 | |
parent | a647f2bc257e4eb59923e097c4e225643ecf38cf (diff) |
libbinder: allow stability downgrade
For instance, use a VINTF interface inside the system image without
adding it to the VINTF manifest (e.g. for testing, in this case, the
interface can't be used between system and vendor).
Bug: 183154648
Test: binderStabilityTest
Change-Id: I38019e226547b2437b920e79c252c7e55c17f7e4
-rw-r--r-- | libs/binder/Stability.cpp | 37 | ||||
-rw-r--r-- | libs/binder/include/binder/Stability.h | 18 | ||||
-rw-r--r-- | libs/binder/tests/binderStabilityTest.cpp | 11 |
3 files changed, 56 insertions, 10 deletions
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp index 339c53833b..06830c027b 100644 --- a/libs/binder/Stability.cpp +++ b/libs/binder/Stability.cpp @@ -38,6 +38,18 @@ Stability::Category Stability::Category::currentFromLevel(Level level) { }; } +void Stability::forceDowngradeCompilationUnit(const sp<IBinder>& binder) { + // Downgrading a remote binder would require also copying the version from + // the binder sent here. In practice though, we don't need to downgrade the + // stability of a remote binder, since this would as an effect only restrict + // what we can do to it. + LOG_ALWAYS_FATAL_IF(!binder || !binder->localBinder(), "Can only downgrade local binder"); + + auto stability = Category::currentFromLevel(getLocalLevel()); + status_t result = setRepr(binder.get(), stability.repr(), REPR_LOG | REPR_ALLOW_DOWNGRADE); + LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); +} + std::string Stability::Category::debugString() { return levelString(level) + " wire protocol version " + std::to_string(version); @@ -45,13 +57,13 @@ std::string Stability::Category::debugString() { void Stability::markCompilationUnit(IBinder* binder) { auto stability = Category::currentFromLevel(getLocalLevel()); - status_t result = setRepr(binder, stability.repr(), true /*log*/); + status_t result = setRepr(binder, stability.repr(), REPR_LOG); LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); } void Stability::markVintf(IBinder* binder) { auto stability = Category::currentFromLevel(Level::VINTF); - status_t result = setRepr(binder, stability.repr(), true /*log*/); + status_t result = setRepr(binder, stability.repr(), REPR_LOG); LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); } @@ -62,7 +74,7 @@ void Stability::debugLogStability(const std::string& tag, const sp<IBinder>& bin void Stability::markVndk(IBinder* binder) { auto stability = Category::currentFromLevel(Level::VENDOR); - status_t result = setRepr(binder, stability.repr(), true /*log*/); + status_t result = setRepr(binder, stability.repr(), REPR_LOG); LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); } @@ -72,7 +84,7 @@ bool Stability::requiresVintfDeclaration(const sp<IBinder>& binder) { void Stability::tryMarkCompilationUnit(IBinder* binder) { auto stability = Category::currentFromLevel(getLocalLevel()); - (void) setRepr(binder, stability.repr(), false /*log*/); + (void) setRepr(binder, stability.repr(), REPR_NONE); } Stability::Level Stability::getLocalLevel() { @@ -94,7 +106,10 @@ Stability::Level Stability::getLocalLevel() { #endif } -status_t Stability::setRepr(IBinder* binder, int32_t representation, bool log) { +status_t Stability::setRepr(IBinder* binder, int32_t representation, uint32_t flags) { + bool log = flags & REPR_LOG; + bool allowDowngrade = flags & REPR_ALLOW_DOWNGRADE; + auto current = getCategory(binder); auto setting = Category::fromRepr(representation); @@ -129,7 +144,11 @@ status_t Stability::setRepr(IBinder* binder, int32_t representation, bool log) { return BAD_TYPE; } - if (current.repr() != 0 && current != setting) { + if (current == setting) return OK; + + bool hasAlreadyBeenSet = current.repr() != 0; + bool isAllowedDowngrade = allowDowngrade && check(current, setting.level); + if (hasAlreadyBeenSet && !isAllowedDowngrade) { if (log) { ALOGE("Interface being set with %s but it is already marked as %s", setting.debugString().c_str(), @@ -138,7 +157,11 @@ status_t Stability::setRepr(IBinder* binder, int32_t representation, bool log) { return BAD_TYPE; } - if (current == setting) return OK; + if (isAllowedDowngrade) { + ALOGI("Interface set with %s downgraded to %s stability", + current.debugString().c_str(), + setting.debugString().c_str()); + } BBinder* local = binder->localBinder(); if (local != nullptr) { diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h index 12272ba652..a09e587f04 100644 --- a/libs/binder/include/binder/Stability.h +++ b/libs/binder/include/binder/Stability.h @@ -49,10 +49,17 @@ namespace internal { // 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 { public: + // Given a binder interface at a certain stability, there may be some + // requirements associated with that higher stability level. For instance, a + // VINTF stability binder is required to be in the VINTF manifest. This API + // can be called to use that same interface within a partition. + static void forceDowngradeCompilationUnit(const sp<IBinder>& binder); + + // WARNING: Below 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 + // WARNING: This is only ever expected to be called by auto-generated code. You likely want to // change or modify the stability class of the interface you are using. // This must be called as soon as the binder in question is constructed. No thread safety @@ -139,9 +146,14 @@ private: // returns the stability according to how this was built static Level getLocalLevel(); + enum { + REPR_NONE = 0, + REPR_LOG = 1, + REPR_ALLOW_DOWNGRADE = 2, + }; // applies stability to binder if stability level is known __attribute__((warn_unused_result)) - static status_t setRepr(IBinder* binder, int32_t representation, bool log); + static status_t setRepr(IBinder* binder, int32_t representation, uint32_t flags); // get stability information as encoded on the wire static Category getCategory(IBinder* binder); diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp index 1f2779abf0..42705401da 100644 --- a/libs/binder/tests/binderStabilityTest.cpp +++ b/libs/binder/tests/binderStabilityTest.cpp @@ -131,6 +131,17 @@ TEST(BinderStability, OnlyVintfStabilityBinderNeedsVintfDeclaration) { EXPECT_TRUE(Stability::requiresVintfDeclaration(BadStableBinder::vintf())); } +TEST(BinderStability, ForceDowngradeStability) { + sp<IBinder> someBinder = BadStableBinder::vintf(); + + EXPECT_TRUE(Stability::requiresVintfDeclaration(someBinder)); + + // silly to do this after already using the binder, but it's for the test + Stability::forceDowngradeCompilationUnit(someBinder); + + EXPECT_FALSE(Stability::requiresVintfDeclaration(someBinder)); +} + TEST(BinderStability, VintfStabilityServerMustBeDeclaredInManifest) { sp<IBinder> vintfServer = BadStableBinder::vintf(); |