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

Commit e9ed0999 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 7149879 from afa3369b to sc-release

Change-Id: If1a4989b18845885100a2184ef2bd8ce750d0d49
parents f1ae9f80 afa3369b
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -95,4 +95,52 @@ __attribute__((warn_unused_result)) AIBinder* AServiceManager_waitForService(con
 */
bool AServiceManager_isDeclared(const char* instance) __INTRODUCED_IN(31);

/**
 * Prevent lazy services without client from shutting down their process
 *
 * \param persist 'true' if the process should not exit.
 */
void AServiceManager_forceLazyServicesPersist(bool persist) __INTRODUCED_IN(31);

/**
 * Set a callback that is invoked when the active service count (i.e. services with clients)
 * registered with this process drops to zero (or becomes nonzero).
 * The callback takes a boolean argument, which is 'true' if there is
 * at least one service with clients.
 *
 * \param callback function to call when the number of services
 *    with clients changes.
 * \param context opaque pointer passed back as second parameter to the
 * callback.
 *
 * The callback takes two arguments. The first is a boolean that represents if there are
 * services with clients (true) or not (false).
 * The second is the 'context' pointer passed during the registration.
 *
 * Callback return value:
 * - false: Default behavior for lazy services (shut down the process if there
 *          are no clients).
 * - true:  Don't shut down the process even if there are no clients.
 *
 * This callback gives a chance to:
 * 1 - Perform some additional operations before exiting;
 * 2 - Prevent the process from exiting by returning "true" from the callback.
 */
void AServiceManager_setActiveServicesCallback(bool (*callback)(bool, void*), void* context)
        __INTRODUCED_IN(31);

/**
 * Try to unregister all services previously registered with 'registerService'.
 *
 * \return true on success.
 */
bool AServiceManager_tryUnregister() __INTRODUCED_IN(31);

/**
 * Re-register services that were unregistered by 'tryUnregister'.
 * This method should be called in the case 'tryUnregister' fails
 * (and should be called on the same thread).
 */
void AServiceManager_reRegister() __INTRODUCED_IN(31);

__END_DECLS
+4 −0
Original line number Diff line number Diff line
@@ -120,6 +120,10 @@ LIBBINDER_NDK31 { # introduced=31
    AServiceManager_isDeclared; # apex llndk
    AServiceManager_registerLazyService; # llndk
    AServiceManager_waitForService; # apex llndk
    AServiceManager_forceLazyServicesPersist; # llndk
    AServiceManager_setActiveServicesCallback; # llndk
    AServiceManager_tryUnregister; # llndk
    AServiceManager_reRegister; # llndk

    AIBinder_Class_getDescriptor;
    AIBinder_Weak_clone;
+19 −0
Original line number Diff line number Diff line
@@ -92,3 +92,22 @@ bool AServiceManager_isDeclared(const char* instance) {
    sp<IServiceManager> sm = defaultServiceManager();
    return sm->isDeclared(String16(instance));
}
void AServiceManager_forceLazyServicesPersist(bool persist) {
    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
    serviceRegistrar.forcePersist(persist);
}
void AServiceManager_setActiveServicesCallback(bool (*callback)(bool, void*), void* context) {
    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
    std::function<bool(bool)> fn = [=](bool hasClients) -> bool {
        return callback(hasClients, context);
    };
    serviceRegistrar.setActiveServicesCallback(fn);
}
bool AServiceManager_tryUnregister() {
    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
    return serviceRegistrar.tryUnregister();
}
void AServiceManager_reRegister() {
    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
    serviceRegistrar.reRegister();
}
 No newline at end of file
+3 −0
Original line number Diff line number Diff line
@@ -28,4 +28,7 @@ interface IBinderNdkUnitTest {
    void forceFlushCommands();

    boolean getsRequestedSid();

    void forcePersist(boolean persist);
    void setCustomActiveServicesCallback();
}
+106 −2
Original line number Diff line number Diff line
@@ -46,6 +46,11 @@ using namespace android;
constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
constexpr char kLazyBinderNdkUnitTestService[] = "LazyBinderNdkUnitTest";
constexpr char kForcePersistNdkUnitTestService[] = "ForcePersistNdkUnitTestService";
constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestService";

constexpr unsigned int kShutdownWaitTime = 10;
constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;

class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
    ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
@@ -76,6 +81,46 @@ class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
        fsync(out);
        return STATUS_OK;
    }
    ndk::ScopedAStatus forcePersist(bool persist) {
        AServiceManager_forceLazyServicesPersist(persist);
        return ndk::ScopedAStatus::ok();
    }
    ndk::ScopedAStatus setCustomActiveServicesCallback() {
        AServiceManager_setActiveServicesCallback(activeServicesCallback, this);
        return ndk::ScopedAStatus::ok();
    }
    static bool activeServicesCallback(bool hasClients, void* context) {
        if (hasClients) {
            return false;
        }

        // Unregister all services
        if (!AServiceManager_tryUnregister()) {
            // Prevent shutdown (test will fail)
            return false;
        }

        // Re-register all services
        AServiceManager_reRegister();

        // Unregister again before shutdown
        if (!AServiceManager_tryUnregister()) {
            // Prevent shutdown (test will fail)
            return false;
        }

        // Check if the context was passed correctly
        MyBinderNdkUnitTest* service = static_cast<MyBinderNdkUnitTest*>(context);
        if (service->contextTestValue != kContextTestValue) {
            // Prevent shutdown (test will fail)
            return false;
        }

        exit(EXIT_SUCCESS);
        // Unreachable
    }

    uint64_t contextTestValue = kContextTestValue;
};

int generatedService() {
@@ -168,6 +213,16 @@ int lazyService(const char* instance) {
    return 1;  // should not return
}

bool isServiceRunning(const char* serviceName) {
    AIBinder* binder = AServiceManager_checkService(serviceName);
    if (binder == nullptr) {
        return false;
    }
    AIBinder_decStrong(binder);

    return true;
}

TEST(NdkBinder, GetServiceThatDoesntExist) {
    sp<IFoo> foo = IFoo::getService("asdfghkl;");
    EXPECT_EQ(nullptr, foo.get());
@@ -238,10 +293,51 @@ TEST(NdkBinder, CheckLazyServiceShutDown) {
    service = nullptr;
    IPCThreadState::self()->flushCommands();
    // Make sure the service is dead after some time of no use
    sleep(10);
    sleep(kShutdownWaitTime);
    ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService));
}

TEST(NdkBinder, ForcedPersistenceTest) {
    for (int i = 0; i < 2; i++) {
        ndk::SpAIBinder binder(AServiceManager_waitForService(kForcePersistNdkUnitTestService));
        std::shared_ptr<aidl::IBinderNdkUnitTest> service =
                aidl::IBinderNdkUnitTest::fromBinder(binder);
        ASSERT_NE(service, nullptr);
        ASSERT_TRUE(service->forcePersist(i == 0).isOk());

        binder = nullptr;
        service = nullptr;
        IPCThreadState::self()->flushCommands();

        sleep(kShutdownWaitTime);

        bool isRunning = isServiceRunning(kForcePersistNdkUnitTestService);

        if (i == 0) {
            ASSERT_TRUE(isRunning) << "Service shut down when it shouldn't have.";
        } else {
            ASSERT_FALSE(isRunning) << "Service failed to shut down.";
        }
    }
}

TEST(NdkBinder, ActiveServicesCallbackTest) {
    ndk::SpAIBinder binder(AServiceManager_waitForService(kActiveServicesNdkUnitTestService));
    std::shared_ptr<aidl::IBinderNdkUnitTest> service =
            aidl::IBinderNdkUnitTest::fromBinder(binder);
    ASSERT_NE(service, nullptr);
    ASSERT_TRUE(service->setCustomActiveServicesCallback().isOk());

    binder = nullptr;
    service = nullptr;
    IPCThreadState::self()->flushCommands();

    sleep(kShutdownWaitTime);

    ASSERT_FALSE(isServiceRunning(kActiveServicesNdkUnitTestService))
            << "Service failed to shut down.";
}

void LambdaOnDeath(void* cookie) {
    auto onDeath = static_cast<std::function<void(void)>*>(cookie);
    (*onDeath)();
@@ -562,12 +658,20 @@ int main(int argc, char* argv[]) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return lazyService(kLazyBinderNdkUnitTestService);
    }
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return lazyService(kForcePersistNdkUnitTestService);
    }
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return lazyService(kActiveServicesNdkUnitTestService);
    }
    if (fork() == 0) {
        prctl(PR_SET_PDEATHSIG, SIGHUP);
        return generatedService();
    }

    ABinderProcess_setThreadPoolMaxThreadCount(1);  // to recieve death notifications/callbacks
    ABinderProcess_setThreadPoolMaxThreadCount(1);  // to receive death notifications/callbacks
    ABinderProcess_startThreadPool();

    return RUN_ALL_TESTS();
Loading