1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <string>
16
17 #include "AidlClient.h"
18
19 #include <aidl/android/automotive/computepipe/registry/IPipeRegistration.h>
20 #include <android/binder_manager.h>
21 #include <android-base/logging.h>
22
23 #include <thread>
24
25 #include "types/GraphState.h"
26
27 namespace android {
28 namespace automotive {
29 namespace computepipe {
30 namespace runner {
31 namespace client_interface {
32 namespace aidl_client {
33
34 using ::aidl::android::automotive::computepipe::registry::IPipeRegistration;
35 using ::ndk::ScopedAStatus;
36
37 namespace {
38 constexpr char kRegistryInterfaceName[] = "router";
39 constexpr int kMaxRouterConnectionAttempts = 10;
40 constexpr int kRouterConnectionAttemptIntervalSeconds = 2;
41
deathNotifier(void * cookie)42 void deathNotifier(void* cookie) {
43 CHECK(cookie);
44 AidlClient* runnerIface = static_cast<AidlClient*>(cookie);
45 runnerIface->routerDied();
46 }
47
48 } // namespace
49
dispatchPacketToClient(int32_t streamId,const std::shared_ptr<MemHandle> packet)50 Status AidlClient::dispatchPacketToClient(int32_t streamId,
51 const std::shared_ptr<MemHandle> packet) {
52 if (!mPipeRunner) {
53 return Status::ILLEGAL_STATE;
54 }
55 return mPipeRunner->dispatchPacketToClient(streamId, packet);
56 }
57
activate()58 Status AidlClient::activate() {
59 if (mPipeRunner) {
60 return Status::ILLEGAL_STATE;
61 }
62
63 mPipeRunner = ndk::SharedRefBase::make<AidlClientImpl>(mGraphOptions, mRunnerEngine);
64 mPipeDebugger = ndk::SharedRefBase::make<DebuggerImpl>(mGraphOptions, mRunnerEngine);
65 mPipeRunner->setPipeDebugger(mPipeDebugger);
66
67 std::thread t(&AidlClient::tryRegisterPipeRunner, this);
68 t.detach();
69 return Status::SUCCESS;
70 }
71
deliverGraphDebugInfo(const std::string & debugData)72 Status AidlClient::deliverGraphDebugInfo(const std::string& debugData) {
73 if (mPipeDebugger) {
74 return mPipeDebugger->deliverGraphDebugInfo(debugData);
75 }
76 return Status::SUCCESS;
77 }
78
routerDied()79 void AidlClient::routerDied() {
80 std::thread t(&AidlClient::tryRegisterPipeRunner, this);
81 t.detach();
82 }
83
tryRegisterPipeRunner()84 void AidlClient::tryRegisterPipeRunner() {
85 if (!mPipeRunner) {
86 LOG(ERROR) << "Init must be called before attempting to connect to router.";
87 return;
88 }
89
90 const std::string instanceName =
91 std::string() + IPipeRegistration::descriptor + "/" + kRegistryInterfaceName;
92
93 for (int i =0; i < kMaxRouterConnectionAttempts; i++) {
94 if (i != 0) {
95 sleep(kRouterConnectionAttemptIntervalSeconds);
96 }
97
98 ndk::SpAIBinder binder(AServiceManager_getService(instanceName.c_str()));
99 if (binder.get() == nullptr) {
100 LOG(ERROR) << "Failed to connect to router service";
101 continue;
102 }
103
104 // Connected to router registry, register the runner and dealth callback.
105 std::shared_ptr<IPipeRegistration> registryService = IPipeRegistration::fromBinder(binder);
106 ndk::ScopedAStatus status =
107 registryService->registerPipeRunner(mGraphOptions.graph_name().c_str(), mPipeRunner);
108
109 if (!status.isOk()) {
110 LOG(ERROR) << "Failed to register runner instance at router registy.";
111 continue;
112 }
113
114 AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(&deathNotifier);
115 AIBinder_linkToDeath(registryService->asBinder().get(), recipient, this);
116 LOG(ERROR) << "Runner was registered at router registry.";
117 return;
118 }
119
120 LOG(ERROR) << "Max connection attempts reached, router connection attempts failed.";
121 return;
122 }
123
handleResetPhase(const RunnerEvent & e)124 Status AidlClient::handleResetPhase(const RunnerEvent& e) {
125 if (!mPipeRunner) {
126 return Status::ILLEGAL_STATE;
127 }
128 if (e.isTransitionComplete()) {
129 mPipeRunner->stateUpdateNotification(GraphState::RESET);
130 }
131
132 if (mPipeDebugger) {
133 mPipeDebugger->handleResetPhase(e);
134 }
135 return SUCCESS;
136 }
137
handleConfigPhase(const ClientConfig & e)138 Status AidlClient::handleConfigPhase(const ClientConfig& e) {
139 if (!mPipeRunner) {
140 return Status::ILLEGAL_STATE;
141 }
142 if (e.isTransitionComplete()) {
143 mPipeRunner->stateUpdateNotification(GraphState::CONFIG_DONE);
144 } else if (e.isAborted()) {
145 mPipeRunner->stateUpdateNotification(GraphState::ERR_HALT);
146 }
147 if (mPipeDebugger) {
148 mPipeDebugger->handleConfigPhase(e);
149 }
150
151 return SUCCESS;
152 }
153
handleExecutionPhase(const RunnerEvent & e)154 Status AidlClient::handleExecutionPhase(const RunnerEvent& e) {
155 if (!mPipeRunner) {
156 return Status::ILLEGAL_STATE;
157 }
158 if (e.isTransitionComplete()) {
159 mPipeRunner->stateUpdateNotification(GraphState::RUNNING);
160 } else if (e.isAborted()) {
161 mPipeRunner->stateUpdateNotification(GraphState::ERR_HALT);
162 }
163 if (mPipeDebugger) {
164 mPipeDebugger->handleExecutionPhase(e);
165 }
166 return SUCCESS;
167 }
168
handleStopWithFlushPhase(const RunnerEvent & e)169 Status AidlClient::handleStopWithFlushPhase(const RunnerEvent& e) {
170 if (!mPipeRunner) {
171 return Status::ILLEGAL_STATE;
172 }
173 if (e.isTransitionComplete()) {
174 mPipeRunner->stateUpdateNotification(GraphState::DONE);
175 }
176 if (mPipeDebugger) {
177 mPipeDebugger->handleStopWithFlushPhase(e);
178 }
179 return SUCCESS;
180 }
181
handleStopImmediatePhase(const RunnerEvent & e)182 Status AidlClient::handleStopImmediatePhase(const RunnerEvent& e) {
183 if (!mPipeRunner) {
184 return Status::ILLEGAL_STATE;
185 }
186 if (e.isTransitionComplete()) {
187 mPipeRunner->stateUpdateNotification(GraphState::ERR_HALT);
188 }
189 if (mPipeDebugger) {
190 mPipeDebugger->handleStopImmediatePhase(e);
191 }
192 return SUCCESS;
193 }
194
195 } // namespace aidl_client
196 } // namespace client_interface
197 } // namespace runner
198 } // namespace computepipe
199 } // namespace automotive
200 } // namespace android
201