javed.attari
javed.attari

Reputation: 31

Native binder callback is hanging

I am working on AOSP code base with NXP EVK. I have a binder interface which receive callback. There are two kinds of clients which can connect to service. One client produces data and the other is the consumer of the data. The consumer receives the data through IMyServiceListener and the produces gets notification of the new client connection through IMyClientListener. What happens is in my implementation of the service connect function, i try to call the callback of the producer (onNewClient) but it hangs and never comeback. Producer and consumer both runs in different processes. Consumer has similar implementation as producer, its just subsribe to IMyClientListener callback instead of IMyServiceListener.

Scenario:

  1. Service Starts
  2. Producer starts
  3. Producer calls connect
  4. Producer subsribes to IMyClientListener
  5. Producer waits for callback
  6. Consumer starts
  7. Consumer call connects
  8. In the service connect function, service calls the callback for IMyClientListener and hangs forever.

I tried step 8 using threads buts still that thread hangs forever.

// AIDL interfaces

interface IMyServiceListener {
    boolean onData(in byte[] data);
}

interface IMyClientListener {
    boolean onNewClient();
}

interface IMyService  {
    boolean connect();
    boolean subscribeToClientListener(IMyClientListener listener);
    boolean subscribeToListener(IMyServiceListener listener);
}

//////////Service code using platform c++ binder

class CMyService : public BnMyService
{
    sp<IMyClientListener> mClientListener = nullptr;
    sp<IMyListener> mListener = nullptr;
public:

    static void instantiate() {
        defaultServiceManager()->addService(
                String16("com.my.service"), new CMyService());
    }
   
    binder::Status connect(bool* _aidl_return)
    {

       //blah blah other code to connect
       
       if (mClientListener != nullptr)
       {
           mClientListener->onNewClient();
           // Above code hangs
       }
    }
    
    binder::Status subscribeToClientListener(const sp<IMyClientListener>& listener, bool* _aidl_return)
    {
        mClientListener = listener;
        *_aidl_return = true;
    }
    
    binder::Status subscribeToListener(const sp<IMyListener>& listener, bool* _aidl_return)
    {
        mListener = listener;
        *_aidl_return = true;
    }   
    
}



/////////Producer code using NDK binder

struct CClientListenerData
{
    void* mUserData = nullptr;
};


class CMyClientListener : public aidl::com::my::BpMyClientListener
{
private:
    CClientListenerData* mListener = nullptr;
public:
    explicit CMyClientListener(const ::ndk::SpAIBinder& binder, CClientListenerData* listener) : BpMyClientListener(binder) {mListener = listener;}
    virtual ~CMyClientListener() = default;
    virtual ::ndk::ScopedAStatus onNewClient(bool* _aidl_return) override;
};

::ndk::ScopedAStatus CMyClientListener::onNewClient(bool* _aidl_return)
{
    // Got the callback

    return ndk::ScopedAStatus::ok();
}


class CMyProducer
{
private:
    std::shared_ptr<aidl::com::my::IMyService> mMyServiceInterface;
    std::shared_ptr<::aidl::com::my::IMyClientListener> mMyClientListener;
    ::ndk::SpAIBinder mNewBinder = ::ndk::SpAIBinder(CreateBinder::NewBinder());
    CClientListenerData mListener;
    CMyClientListener mCMyClientListener = CMyClientListener(mNewBinder, &mListener);
public:


    CMyProducer()
    {
        mMyClientListener = std::shared_ptr<::aidl::com::my::IMyClientListener>(&mCMyClientListener);
    }

    bool Connect() {
        ::ndk::SpAIBinder binder(AServiceManager_getService("com.my.service"));
        mMyServiceInterface = aidl::com::my::IMyService::fromBinder(binder);
        bool ret = false;
        mMyServiceInterface->connect(&ret);
        return ret;
    }
   
    bool SubscribeToClient(bool* _aidl_return))
    {
        mMyServiceInterface->subscribeToClientListener(mMyClientListener, &ret);
    }

};

Upvotes: 0

Views: 577

Answers (1)

Alvin Chang
Alvin Chang

Reputation: 1

I encountered this issue before. I think it could be solved by adding ABinderProcess_startThreadPool() at the start of CMyProducer.

Upvotes: 0

Related Questions