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