blob: 73543aec970938ccdc5bc3b33a0fdec70cf2af36 [file] [log] [blame]
// 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.
#include <string>
#include "AidlClient.h"
#include <aidl/android/automotive/computepipe/registry/IPipeRegistration.h>
#include <android/binder_manager.h>
#include <android-base/logging.h>
#include <thread>
#include "types/GraphState.h"
namespace android {
namespace automotive {
namespace computepipe {
namespace runner {
namespace client_interface {
namespace aidl_client {
using ::aidl::android::automotive::computepipe::registry::IPipeRegistration;
using ::ndk::ScopedAStatus;
namespace {
constexpr char kRegistryInterfaceName[] = "router";
constexpr int kMaxRouterConnectionAttempts = 10;
constexpr int kRouterConnectionAttemptIntervalSeconds = 2;
void deathNotifier(void* cookie) {
CHECK(cookie);
AidlClient* runnerIface = static_cast<AidlClient*>(cookie);
runnerIface->routerDied();
}
} // namespace
Status AidlClient::dispatchPacketToClient(int32_t streamId,
const std::shared_ptr<MemHandle> packet) {
if (!mPipeRunner) {
return Status::ILLEGAL_STATE;
}
return mPipeRunner->dispatchPacketToClient(streamId, packet);
}
Status AidlClient::activate() {
if (mPipeRunner) {
return Status::ILLEGAL_STATE;
}
mPipeRunner = ndk::SharedRefBase::make<AidlClientImpl>(mGraphOptions, mRunnerEngine);
mPipeDebugger = ndk::SharedRefBase::make<DebuggerImpl>(mGraphOptions, mRunnerEngine);
mPipeRunner->setPipeDebugger(mPipeDebugger);
std::thread t(&AidlClient::tryRegisterPipeRunner, this);
t.detach();
return Status::SUCCESS;
}
Status AidlClient::deliverGraphDebugInfo(const std::string& debugData) {
if (mPipeDebugger) {
return mPipeDebugger->deliverGraphDebugInfo(debugData);
}
return Status::SUCCESS;
}
void AidlClient::routerDied() {
std::thread t(&AidlClient::tryRegisterPipeRunner, this);
t.detach();
}
void AidlClient::tryRegisterPipeRunner() {
if (!mPipeRunner) {
LOG(ERROR) << "Init must be called before attempting to connect to router.";
return;
}
const std::string instanceName =
std::string() + IPipeRegistration::descriptor + "/" + kRegistryInterfaceName;
for (int i =0; i < kMaxRouterConnectionAttempts; i++) {
if (i != 0) {
sleep(kRouterConnectionAttemptIntervalSeconds);
}
ndk::SpAIBinder binder(AServiceManager_getService(instanceName.c_str()));
if (binder.get() == nullptr) {
LOG(ERROR) << "Failed to connect to router service";
continue;
}
// Connected to router registry, register the runner and dealth callback.
std::shared_ptr<IPipeRegistration> registryService = IPipeRegistration::fromBinder(binder);
ndk::ScopedAStatus status =
registryService->registerPipeRunner(mGraphOptions.graph_name().c_str(), mPipeRunner);
if (!status.isOk()) {
LOG(ERROR) << "Failed to register runner instance at router registy.";
continue;
}
AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(&deathNotifier);
AIBinder_linkToDeath(registryService->asBinder().get(), recipient, this);
LOG(ERROR) << "Runner was registered at router registry.";
return;
}
LOG(ERROR) << "Max connection attempts reached, router connection attempts failed.";
return;
}
Status AidlClient::handleResetPhase(const RunnerEvent& e) {
if (!mPipeRunner) {
return Status::ILLEGAL_STATE;
}
if (e.isTransitionComplete()) {
mPipeRunner->stateUpdateNotification(GraphState::RESET);
}
if (mPipeDebugger) {
mPipeDebugger->handleResetPhase(e);
}
return SUCCESS;
}
Status AidlClient::handleConfigPhase(const ClientConfig& e) {
if (!mPipeRunner) {
return Status::ILLEGAL_STATE;
}
if (e.isTransitionComplete()) {
mPipeRunner->stateUpdateNotification(GraphState::CONFIG_DONE);
} else if (e.isAborted()) {
mPipeRunner->stateUpdateNotification(GraphState::ERR_HALT);
}
if (mPipeDebugger) {
mPipeDebugger->handleConfigPhase(e);
}
return SUCCESS;
}
Status AidlClient::handleExecutionPhase(const RunnerEvent& e) {
if (!mPipeRunner) {
return Status::ILLEGAL_STATE;
}
if (e.isTransitionComplete()) {
mPipeRunner->stateUpdateNotification(GraphState::RUNNING);
} else if (e.isAborted()) {
mPipeRunner->stateUpdateNotification(GraphState::ERR_HALT);
}
if (mPipeDebugger) {
mPipeDebugger->handleExecutionPhase(e);
}
return SUCCESS;
}
Status AidlClient::handleStopWithFlushPhase(const RunnerEvent& e) {
if (!mPipeRunner) {
return Status::ILLEGAL_STATE;
}
if (e.isTransitionComplete()) {
mPipeRunner->stateUpdateNotification(GraphState::DONE);
}
if (mPipeDebugger) {
mPipeDebugger->handleStopWithFlushPhase(e);
}
return SUCCESS;
}
Status AidlClient::handleStopImmediatePhase(const RunnerEvent& e) {
if (!mPipeRunner) {
return Status::ILLEGAL_STATE;
}
if (e.isTransitionComplete()) {
mPipeRunner->stateUpdateNotification(GraphState::ERR_HALT);
}
if (mPipeDebugger) {
mPipeDebugger->handleStopImmediatePhase(e);
}
return SUCCESS;
}
} // namespace aidl_client
} // namespace client_interface
} // namespace runner
} // namespace computepipe
} // namespace automotive
} // namespace android