Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43564fd8 authored by Steven Moreland's avatar Steven Moreland
Browse files

binderStabilityTest: rewrite pieces w/ no AIDL

Since AIDL sets interface stability now, we can't use AIDL interfaces in
this test. A custom C++/NDK interface has instead been written there so
that we can set different stability levels in the same compilation unit.
Writing custom interfaces like this is strongly discouraged and is not
supported. However, in order to test different stability levels in the
same module, we need to be able to do this, and android testing
infrastructure doesn't easily support running things in multiple
compilation contexts yet.

Bug: 138467287
Test: binderStabilityTest
Change-Id: I4461b82baf4c9850cfb4c32d7b0c5ca82fa83a74
parent a9860b6d
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -142,7 +142,6 @@ aidl_interface {
    name: "binderStabilityTestIface",
    name: "binderStabilityTestIface",
    srcs: [
    srcs: [
        "IBinderStabilityTest.aidl",
        "IBinderStabilityTest.aidl",
        "IBinderStabilityTestSub.aidl",
    ],
    ],
}
}


+6 −8
Original line number Original line Diff line number Diff line
@@ -14,34 +14,32 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


import IBinderStabilityTestSub;

// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// THIS IS ONLY FOR TESTING!
// THIS IS ONLY FOR TESTING!
interface IBinderStabilityTest {
interface IBinderStabilityTest {
    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // THIS IS ONLY FOR TESTING!
    // THIS IS ONLY FOR TESTING!
    void sendBinder(IBinderStabilityTestSub binder);
    void sendBinder(IBinder binder);


    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // THIS IS ONLY FOR TESTING!
    // THIS IS ONLY FOR TESTING!
    void sendAndCallBinder(IBinderStabilityTestSub binder);
    void sendAndCallBinder(IBinder binder);


    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // THIS IS ONLY FOR TESTING!
    // THIS IS ONLY FOR TESTING!
    IBinderStabilityTestSub returnNoStabilityBinder();
    IBinder returnNoStabilityBinder();


    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // THIS IS ONLY FOR TESTING!
    // THIS IS ONLY FOR TESTING!
    IBinderStabilityTestSub returnLocalStabilityBinder();
    IBinder returnLocalStabilityBinder();


    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // THIS IS ONLY FOR TESTING!
    // THIS IS ONLY FOR TESTING!
    IBinderStabilityTestSub returnVintfStabilityBinder();
    IBinder returnVintfStabilityBinder();


    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
    // THIS IS ONLY FOR TESTING!
    // THIS IS ONLY FOR TESTING!
    IBinderStabilityTestSub returnVendorStabilityBinder();
    IBinder returnVendorStabilityBinder();
}
}
// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// DO NOT EVER IN A MILLION YEARS WRITE AN INTERFACE LIKE THIS!
// THIS IS ONLY FOR TESTING!
// THIS IS ONLY FOR TESTING!
+0 −19
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

interface IBinderStabilityTestSub {
    void userDefinedTransaction();
}
+145 −105
Original line number Original line Diff line number Diff line
@@ -26,9 +26,7 @@


#include <sys/prctl.h>
#include <sys/prctl.h>


#include "aidl/BnBinderStabilityTestSub.h"
#include "aidl/BnBinderStabilityTest.h"
#include "aidl/BnBinderStabilityTest.h"
#include "BnBinderStabilityTestSub.h"
#include "BnBinderStabilityTest.h"
#include "BnBinderStabilityTest.h"


using namespace android;
using namespace android;
@@ -36,167 +34,217 @@ using namespace ndk;
using android::binder::Status;
using android::binder::Status;
using android::internal::Stability; // for testing only!
using android::internal::Stability; // for testing only!


const String16 kNoStabilityServer = String16("binder_stability_test_service_low");
const String16 kSystemStabilityServer = String16("binder_stability_test_service_system");
const String16 kCompilationUnitServer = String16("binder_stability_test_service_compl");
const String16 kVintfServer = String16("binder_stability_test_service_vintf");


const String16 kCompilationUnitNdkServer = String16("binder_stability_test_service_compl");
// This is handwritten so that we can test different stability levels w/o having the AIDL

// compiler assign them. Hand-writing binder interfaces is considered a bad practice
class BadStabilityTestSub : public BnBinderStabilityTestSub {
// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!
class BadStableBinder : public BBinder {
public:
public:
    Status userDefinedTransaction() {
    static constexpr uint32_t USER_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION;
        return Status::ok();
    static String16 kDescriptor;

    bool gotUserTransaction = false;

    static status_t doUserTransaction(const sp<IBinder>& binder) {
        Parcel data, reply;
        data.writeInterfaceToken(kDescriptor);
        return binder->transact(USER_TRANSACTION, data, &reply, 0/*flags*/);
    }

    status_t onTransact(uint32_t code,
            const Parcel& data, Parcel* reply, uint32_t flags) override {
        if (code == USER_TRANSACTION) {
            // not interested in this kind of stability. Make sure
            // we have a test failure
            LOG_ALWAYS_FATAL_IF(!data.enforceInterface(kDescriptor));

            gotUserTransaction = true;

            ALOGE("binder stability: Got user transaction");
            return OK;
        }
        return BBinder::onTransact(code, data, reply, flags);
    }
    }


    static sp<IBinderStabilityTestSub> system() {
    static sp<BadStableBinder> undef() {
        sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
        sp<BadStableBinder> iface = new BadStableBinder();
        // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
        // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
        Stability::markCompilationUnit(iface.get()); // <- BAD, NO! DO NOT COPY
        return iface;
        return iface;
    }
    }


    static sp<IBinderStabilityTestSub> vintf() {
    static sp<BadStableBinder> system() {
        sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
        sp<BadStableBinder> iface = new BadStableBinder();
        // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
        Stability::markCompilationUnit(iface.get()); // <- for test only
        // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
        Stability::markVintf(iface.get()); // <- BAD, NO! DO NOT COPY
        return iface;
        return iface;
    }
    }


    static sp<IBinderStabilityTestSub> vendor() {
    static sp<BadStableBinder> vintf() {
        sp<BnBinderStabilityTestSub> iface = new BadStabilityTestSub();
        sp<BadStableBinder> iface = new BadStableBinder();
        // NO! NO! NO! NO! DO NOT EVERY DO SOMETHING LIKE THIS?
        Stability::markVintf(iface.get()); // <- for test only
        // WHAT ARE YOU CRAZY? IT'S VERY DANGEROUS
        return iface;
        Stability::markVndk(iface.get()); // <- BAD, NO! DO NOT COPY
    }

    static sp<BadStableBinder> vendor() {
        sp<BadStableBinder> iface = new BadStableBinder();
        Stability::markVndk(iface.get()); // <- for test only
        return iface;
        return iface;
    }
    }
};
};
String16 BadStableBinder::kDescriptor = String16("BadStableBinder.test");


// NO! NO! NO! Do not even think of doing something like this!
// NO! NO! NO! Do not even think of doing something like this!
// This is for testing! If a class like this was actually used in production,
// This is for testing! If a class like this was actually used in production,
// it would ruin everything!
// it would ruin everything!
class BadStabilityTester : public BnBinderStabilityTest {
class MyBinderStabilityTest : public BnBinderStabilityTest {
public:
public:
    Status sendBinder(const sp<IBinderStabilityTestSub>& /*binder*/) override {
    Status sendBinder(const sp<IBinder>& /*binder*/) override {
        return Status::ok();
        return Status::ok();
    }
    }
    Status sendAndCallBinder(const sp<IBinderStabilityTestSub>& binder) override {
    Status sendAndCallBinder(const sp<IBinder>& binder) override {
        Stability::debugLogStability("sendAndCallBinder got binder", IInterface::asBinder(binder));
        Stability::debugLogStability("sendAndCallBinder got binder", binder);
        return binder->userDefinedTransaction();
        return Status::fromExceptionCode(BadStableBinder::doUserTransaction(binder));
    }
    }
    Status returnNoStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
    Status returnNoStabilityBinder(sp<IBinder>* _aidl_return) override {
        *_aidl_return = new BadStabilityTestSub();
        *_aidl_return = BadStableBinder::undef();
        return Status::ok();
        return Status::ok();
    }
    }
    Status returnLocalStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
    Status returnLocalStabilityBinder(sp<IBinder>* _aidl_return) override {
        *_aidl_return = BadStabilityTestSub::system();
        *_aidl_return = BadStableBinder::system();
        return Status::ok();
        return Status::ok();
    }
    }
    Status returnVintfStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
    Status returnVintfStabilityBinder(sp<IBinder>* _aidl_return) override {
        *_aidl_return = BadStabilityTestSub::vintf();
        *_aidl_return = BadStableBinder::vintf();
        return Status::ok();
        return Status::ok();
    }
    }
    Status returnVendorStabilityBinder(sp<IBinderStabilityTestSub>* _aidl_return) override {
    Status returnVendorStabilityBinder(sp<IBinder>* _aidl_return) override {
        *_aidl_return = BadStabilityTestSub::vendor();
        *_aidl_return = BadStableBinder::vendor();
        return Status::ok();
        return Status::ok();
    }
    }
};
};


void checkSystemStabilityBinder(const sp<IBinderStabilityTest>& complServer) {
TEST(BinderStability, CantCallVendorBinderInSystemContext) {
    EXPECT_TRUE(complServer->sendBinder(new BadStabilityTestSub()).isOk());
    sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer);
    EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::system()).isOk());
    auto server = interface_cast<IBinderStabilityTest>(serverBinder);
    EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::vintf()).isOk());

    EXPECT_TRUE(complServer->sendBinder(BadStabilityTestSub::vendor()).isOk());
    ASSERT_NE(nullptr, server.get());
    ASSERT_NE(nullptr, IInterface::asBinder(server)->remoteBinder());


    EXPECT_TRUE(complServer->sendAndCallBinder(new BadStabilityTestSub()).isOk());
    EXPECT_TRUE(server->sendBinder(BadStableBinder::undef()).isOk());
    EXPECT_TRUE(complServer->sendAndCallBinder(BadStabilityTestSub::system()).isOk());
    EXPECT_TRUE(server->sendBinder(BadStableBinder::system()).isOk());
    EXPECT_TRUE(complServer->sendAndCallBinder(BadStabilityTestSub::vintf()).isOk());
    EXPECT_TRUE(server->sendBinder(BadStableBinder::vintf()).isOk());
    EXPECT_TRUE(server->sendBinder(BadStableBinder::vendor()).isOk());


    {
        sp<BadStableBinder> binder = BadStableBinder::undef();
        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
        EXPECT_TRUE(binder->gotUserTransaction);
    }
    {
        sp<BadStableBinder> binder = BadStableBinder::system();
        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
        EXPECT_TRUE(binder->gotUserTransaction);
    }
    {
        sp<BadStableBinder> binder = BadStableBinder::vintf();
        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
        EXPECT_TRUE(binder->gotUserTransaction);
    }
    {
        // !!! user-defined transaction may not be stable for remote server !!!
        // !!! user-defined transaction may not be stable for remote server !!!
    EXPECT_FALSE(complServer->sendAndCallBinder(BadStabilityTestSub::vendor()).isOk());
        // !!! so, it does not work !!!
        sp<BadStableBinder> binder = BadStableBinder::vendor();
        EXPECT_EQ(BAD_TYPE, server->sendAndCallBinder(binder).exceptionCode());
        EXPECT_FALSE(binder->gotUserTransaction);
    }


    sp<IBinderStabilityTestSub> out;
    sp<IBinder> out;
    EXPECT_TRUE(complServer->returnNoStabilityBinder(&out).isOk());
    EXPECT_TRUE(server->returnNoStabilityBinder(&out).isOk());
    ASSERT_NE(nullptr, out.get());
    ASSERT_NE(nullptr, out.get());
    EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder());
    EXPECT_EQ(OK, out->pingBinder());
    EXPECT_TRUE(out->userDefinedTransaction().isOk());
    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));


    EXPECT_TRUE(complServer->returnLocalStabilityBinder(&out).isOk());
    EXPECT_TRUE(server->returnLocalStabilityBinder(&out).isOk());
    ASSERT_NE(nullptr, out.get());
    ASSERT_NE(nullptr, out.get());
    EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder());
    EXPECT_EQ(OK, out->pingBinder());
    EXPECT_TRUE(out->userDefinedTransaction().isOk());
    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));


    EXPECT_TRUE(complServer->returnVintfStabilityBinder(&out).isOk());
    EXPECT_TRUE(server->returnVintfStabilityBinder(&out).isOk());
    ASSERT_NE(nullptr, out.get());
    ASSERT_NE(nullptr, out.get());
    EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder());
    EXPECT_EQ(OK, out->pingBinder());
    EXPECT_TRUE(out->userDefinedTransaction().isOk());
    EXPECT_EQ(OK, BadStableBinder::doUserTransaction(out));


    EXPECT_TRUE(complServer->returnVendorStabilityBinder(&out).isOk());
    EXPECT_TRUE(server->returnVendorStabilityBinder(&out).isOk());
    ASSERT_NE(nullptr, out.get());
    ASSERT_NE(nullptr, out.get());


    // !!! libbinder-defined transaction works !!!
    // !!! libbinder-defined transaction works !!!
    EXPECT_EQ(OK, IInterface::asBinder(out)->pingBinder());
    EXPECT_EQ(OK, out->pingBinder());


    // !!! user-defined transaction may not be stable !!!
    // !!! user-defined transaction may not be stable !!!
    EXPECT_FALSE(out->userDefinedTransaction().isOk());
    // !!! so, it does not work !!!
    EXPECT_EQ(BAD_TYPE, BadStableBinder::doUserTransaction(out));
}
}


TEST(BinderStability, RemoteNoStabilityServer) {
// This is handwritten so that we can test different stability levels w/o having the AIDL
    sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kNoStabilityServer);
// compiler assign them. Hand-writing binder interfaces is considered a bad practice
    auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder);
// sanity reasons. YOU SHOULD DEFINE AN AIDL INTERFACE INSTEAD!


    ASSERT_NE(nullptr, remoteServer.get());
struct NdkBinderStable_DataClass {
    ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder());
    bool gotUserTransaction = false;

};
    checkSystemStabilityBinder(remoteServer);
void* NdkBadStableBinder_Class_onCreate(void* args) {
    LOG_ALWAYS_FATAL_IF(args != nullptr, "Takes no args");
    return static_cast<void*>(new NdkBinderStable_DataClass);
}
}

void NdkBadStableBinder_Class_onDestroy(void* userData) {
TEST(BinderStability, RemoteLowStabilityServer) {
    delete static_cast<NdkBinderStable_DataClass*>(userData);
    sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kCompilationUnitServer);
    auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder);

    ASSERT_NE(nullptr, remoteServer.get());
    ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder());

    checkSystemStabilityBinder(remoteServer);
}
}
NdkBinderStable_DataClass* NdkBadStableBinder_getUserData(AIBinder* binder) {
    LOG_ALWAYS_FATAL_IF(binder == nullptr);
    void* userData = AIBinder_getUserData(binder);
    LOG_ALWAYS_FATAL_IF(userData == nullptr, "null data - binder is remote?");


TEST(BinderStability, RemoteVintfServer) {
    return static_cast<NdkBinderStable_DataClass*>(userData);
    sp<IBinder> remoteBinder = android::defaultServiceManager()->getService(kVintfServer);
}
    auto remoteServer = interface_cast<IBinderStabilityTest>(remoteBinder);
binder_status_t NdkBadStableBinder_Class_onTransact(

    AIBinder* binder, transaction_code_t code, const AParcel* /*in*/, AParcel* /*out*/) {
    ASSERT_NE(nullptr, remoteServer.get());
    ASSERT_NE(nullptr, IInterface::asBinder(remoteServer)->remoteBinder());


    checkSystemStabilityBinder(remoteServer);
    if (code == BadStableBinder::USER_TRANSACTION) {
        ALOGE("ndk binder stability: Got user transaction");
        NdkBadStableBinder_getUserData(binder)->gotUserTransaction = true;
        return STATUS_OK;
    }
    }


class NdkBadStabilityTestSub : public aidl::BnBinderStabilityTestSub {
    return STATUS_UNKNOWN_TRANSACTION;
    ScopedAStatus userDefinedTransaction() {
        return ScopedAStatus::ok();
}
}
};

static AIBinder_Class* kNdkBadStableBinder =
    AIBinder_Class_define(String8(BadStableBinder::kDescriptor).c_str(),
                          NdkBadStableBinder_Class_onCreate,
                          NdkBadStableBinder_Class_onDestroy,
                          NdkBadStableBinder_Class_onTransact);

// for testing only to get around __ANDROID_VNDK__ guard.
// for testing only to get around __ANDROID_VNDK__ guard.
extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY
extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY


TEST(BinderStability, NdkClientOfRemoteServer) {
TEST(BinderStability, NdkCantCallVendorBinderInSystemContext) {
    SpAIBinder binder = SpAIBinder(AServiceManager_getService(
    SpAIBinder binder = SpAIBinder(AServiceManager_getService(
        String8(kCompilationUnitServer).c_str()));
        String8(kSystemStabilityServer).c_str()));


    std::shared_ptr<aidl::IBinderStabilityTest> remoteServer =
    std::shared_ptr<aidl::IBinderStabilityTest> remoteServer =
        aidl::IBinderStabilityTest::fromBinder(binder);
        aidl::IBinderStabilityTest::fromBinder(binder);


    ASSERT_NE(nullptr, remoteServer.get());
    ASSERT_NE(nullptr, remoteServer.get());


    std::shared_ptr<aidl::IBinderStabilityTestSub> vendor = SharedRefBase::make<NdkBadStabilityTestSub>();
    SpAIBinder comp = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));

    EXPECT_TRUE(remoteServer->sendBinder(comp).isOk());
    // TODO: not ideal: binder must be held once it is marked
    EXPECT_TRUE(remoteServer->sendAndCallBinder(comp).isOk());
    SpAIBinder vendorBinder = vendor->asBinder();
    EXPECT_TRUE(NdkBadStableBinder_getUserData(comp.get())->gotUserTransaction);
    AIBinder_markVendorStability(vendorBinder.get());


    SpAIBinder vendor = SpAIBinder(AIBinder_new(kNdkBadStableBinder, nullptr /*args*/));
    AIBinder_markVendorStability(vendor.get());
    EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk());
    EXPECT_TRUE(remoteServer->sendBinder(vendor).isOk());
    EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk());
    EXPECT_FALSE(remoteServer->sendAndCallBinder(vendor).isOk());
    EXPECT_FALSE(NdkBadStableBinder_getUserData(vendor.get())->gotUserTransaction);
}
}


class MarksStabilityInConstructor : public BBinder {
class MarksStabilityInConstructor : public BBinder {
@@ -234,16 +282,8 @@ int main(int argc, char** argv) {
        // child process
        // child process
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        prctl(PR_SET_PDEATHSIG, SIGHUP);


        sp<IBinder> noStability = new BadStabilityTester;
        sp<IBinder> server = new MyBinderStabilityTest;
        android::defaultServiceManager()->addService(kNoStabilityServer, noStability);
        android::defaultServiceManager()->addService(kSystemStabilityServer, server);

        sp<IBinder> compil = new BadStabilityTester;
        Stability::markCompilationUnit(compil.get());
        android::defaultServiceManager()->addService(kCompilationUnitServer, compil);

        sp<IBinder> vintf = new BadStabilityTester;
        Stability::markVintf(vintf.get());
        android::defaultServiceManager()->addService(kVintfServer, vintf);


        IPCThreadState::self()->joinThreadPool(true);
        IPCThreadState::self()->joinThreadPool(true);
        exit(1);  // should not reach
        exit(1);  // should not reach