// 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 #include "AidlClient.h" #include #include #include #include #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(cookie); runnerIface->routerDied(); } } // namespace Status AidlClient::dispatchPacketToClient(int32_t streamId, const std::shared_ptr 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(mGraphOptions, mRunnerEngine); mPipeDebugger = ndk::SharedRefBase::make(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 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