Lógica de Threads para HAL usando AIDL

Cenário 2: Chamadas sincronizadas sequenciais a partir de uma única thread do cliente

Quando uma única thread de um processo cliente invoca a mesma interface sincronizada do servidor múltiplas vezes em sequência, o resultado é uma serialização natural das requisições no servidor. A thread do cliente é bloqueada até que cada chamada anterior seja concluída, garantindo a ordem de execução.

using aidl::android::hardware::meuhal::IMeuHal;

int main() { const std::string servico = std::string() + IMeuHal::descriptor + "/padrao"; LOG(INFO) << "Obtendo proxy para: " << servico;

ndk::SpAIBinder vinculo(AServiceManager_getService(servico.c_str()));
if (vinculo.get() == nullptr) {
    LOG(ERROR) << "Serviço indisponível.";
    return 1;
}

auto halProxy = IMeuHal::fromBinder(vinculo);
if (!halProxy) {
    LOG(ERROR) << "Falha ao obter interface.";
    return 1;
}

// Chamadas sequenciais do mesmo ponto da execução
ndk::ScopedAStatus resultado;
for (int i = 0; i < 5; ++i) {
    resultado = halProxy->executarAcao();
    if (!resultado.isOk()) {
        LOG(ERROR) << "Chamada " << i << " falhou.";
        break;
    }
}

LOG(INFO) << "Operações concluídas.";
return 0;

}


</div>### Cenário 1: Chamadas sincronizadas concorrentes a partir de múltiplas threads do cliente

Quando múltiplas threads dentro do mesmo processo cliente chamam a interface sincronizada simultaneamente, o comportamento no servidor depende de sua implementação de pool de threads. Se o servidor possuir múltiplas threads de despacho, as chamadas podem ser executadas de forma concorrente, não serial.

<div class="code-example">```
#include <aidl/android/hardware/meuhal/IMeuHal.h>
#include <android/binder_manager.h>
#include <android-base/logging.h>
#include <thread>
#include <vector>

using aidl::android::hardware::meuhal::IMeuHal;

void invocarServico(std::shared_ptr<IMeuHal> servico, int idThread) {
    LOG(ERROR) << "Thread " << idThread << " iniciando.";
    auto status = servico->executarAcao();
    LOG(ERROR) << "Thread " << idThread << " finalizou. Status: "
               << (status.isOk() ? "OK" : "FALHA");
}

int main() {
    const std::string nomeInstancia = std::string() + IMeuHal::descriptor + "/padrao";
    ndk::SpAIBinder binder(AServiceManager_getService(nomeInstancia.c_str()));
    auto halInterface = IMeuHal::fromBinder(binder);

    const int NUM_THREADS = 4;
    std::vector<std::thread> poolDeThreads;

    for (int i = 0; i < NUM_THREADS; ++i) {
        poolDeThreads.emplace_back(invocarServico, halInterface, i + 1);
    }

    for (auto& t : poolDeThreads) {
        t.join();
    }

    return 0;
}

O método no servidor HAL pode conter operações de longa duração. Sua execução pode ocorrer em threads diferentes do pool do Binder, indicando potencial concorrência.

namespace aidl::android::hardware::meuhal {

::ndk::ScopedAStatus MeuHal::executarAcao() { LOG(ERROR) << "Método 'executarAcao' iniciado. ThreadID: " << std::this_thread::get_id(); // Simula trabalho std::this_thread::sleep_for(std::chrono::seconds(1)); LOG(ERROR) << "Método finalizado. ThreadID: " << std::this_thread::get_id(); return ndk::ScopedAStatus::ok(); }

} // namespace aidl::android::hardware::meuhal


</div>### Observações sobre Serialização

A serialização automática no servider não é garantida pelo AIDL em si. Para forçar a execução serial de todos os métodos, uma implementação de mutex ou fila de comandos é necessária dentro do código do servidor. A arquitetura do Binder e a configuração do pool de threads determinam o comportamento de concorrência.

</div>

Tags: aidl HAL binder-ndk android-threads Concurrency

Publicado em 6-30 01:50