2

Sorry if this is a dumb question. I'm very new to Android.

I have written a library that uses a library that uses a binder service. That is, my library has a class that derives from a library class which uses binder.

My library is intended to provide that data via an API in a platform-independent way (it can't expose a binder dependency). For this discussion, let's say it has a "Start" and "Stop" function. Start spins up the service if the ref-count is zero, and increments the ref count. Stop decrements the ref count, and when the ref count goes to zero I want to shut everything down, run clean-up code, etc.

All the documentation I can find says I have to call startThreadPool and joinThreadPool to receive binder events. But joinThreadPool blocks, so the Start function never returns.

This means binder subscription needs to happen in a thread. But even if I put the call to joinThreadPool in its own thread I don't know how to make joinThreadPool cleanly exit so I can clean up.

So I tried creating a thread that just calls startThreadPool and spins in a sleep loop while an atomic is set; Stop clears the atomic. This works in theory, but my debugging seems to show that if I try to end the process that is using my API I get a "binder exited" event before my cleanup code can execute.

The basic question is: how do I use binder in a non-blocking way, and then leave binder and clean up?

Onik
  • 19,396
  • 14
  • 68
  • 91

1 Answers1

0

answer here i translate to english https://blog.csdn.net/gaosiniquanjia/article/details/123659277

There are many sayings on the Internet that the last call seems redundant; the reason is that it can be executed normally after being removed; but it is not.

In my opinion; the purpose of calling IPCThread::self()->joinThreadPool() in the main thread is to ensure that the thread generated by the previous call will not be forced to exit because the execution reaches the end of the main function; because ProcessState: :self()->startThreadPool() will not cause the main thread to block; and IPCThread::self()->joinThreadPool() call will cause the main thread to block and they provide the same function; it can handle some requests or return values sent by the Binder driver; further improving the throughput of Binder command processing. Of course; if the code that blocks the main thread is added between them, the last function call can be omitted; otherwise, it cannot be omitted.

example code:

static pthread_mutex_t  s_work_lock;
static pthread_cond_t   s_work_cond;
status_t AddBindService::onTransact(uint32_t        code,
                                    const Parcel&   data,
                                    Parcel*         reply,
                                    uint32_t        flags)
{
    status_t    rv(0);

    // Perform the requested operation
    switch (code) {
        case BINDER_EXIT:
            cout << "server BINDER_EXIT called" << endl;
            reply->writeInt32(0); //before ending signal
            pthread_cond_signal(&s_work_cond);
            break;

        default:
            cout << "server onTransact unknown code, code: " << code << endl;
            break;
    }

    return rv;
}

void main()
{
    String16    serviceName_server("test.binder_tmp_server"); //register token name
    pthread_mutex_init(&s_work_lock, NULL);
    pthread_cond_init(&s_work_cond,  NULL);

    // Add the service
    sp<ProcessState>    proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    if ((rv = sm->addService(serviceName_server, new AddBindService())) != 0) {
        cerr << "addService " << serviceName_server << " failed, rv: " << rv << " errno: " << errno << endl;
    }
    // Start threads to handle server work
    proc->startThreadPool();

    /*...........your code here*/

    //wait signal to exit
    pthread_mutex_lock(&s_work_lock);
    pthread_cond_wait(&s_work_cond, &s_work_lock);
    pthread_mutex_unlock(&s_work_lock);

    pthread_cond_destroy(&s_work_cond);
    pthread_mutex_destroy(&s_work_lock);
}

refer to:

  1. https://android.googlesource.com/platform/frameworks/native/+/refs/tags/android-9.0.0_r60/services/surfaceflinger/main_surfaceflinger.cpp

  2. https://android.googlesource.com/platform/system/extras/+/refs/tags/android-9.0.0_r60/tests/binder/benchmarks/binderAddInts.cpp