1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "EVSAPP"
18
19 #include <stdio.h>
20
21 #include <hidl/HidlTransportSupport.h>
22 #include <utils/Errors.h>
23 #include <utils/StrongPointer.h>
24 #include <utils/Log.h>
25
26 #include "android-base/macros.h" // arraysize
27
28 #include <android/hardware/automotive/evs/1.0/IEvsEnumerator.h>
29 #include <android/hardware/automotive/evs/1.0/IEvsDisplay.h>
30
31 #include <hwbinder/ProcessState.h>
32
33 #include "EvsStateControl.h"
34 #include "EvsVehicleListener.h"
35 #include "ConfigManager.h"
36
37
38 // libhidl:
39 using android::hardware::configureRpcThreadpool;
40 using android::hardware::joinRpcThreadpool;
41
42
43 // TODO: Should this somehow be a shared definition with the module itself?
44 const static char kEvsServiceName[] = "EvsSharedEnumerator";
45
46
47 // Main entry point
main(int,char **)48 int main(int /* argc */, char** /* argv */)
49 {
50 printf("EVS app starting\n");
51
52 // Load our configuration information
53 ConfigManager config;
54 config.initialize("config.json");
55
56 // Set thread pool size to one to avoid concurrent events from the HAL.
57 // This pool will handle the EvsCameraStream callbacks.
58 // Note: This _will_ run in parallel with the EvsListener run() loop below which
59 // runs the application logic that reacts to the async events.
60 configureRpcThreadpool(1, false /* callerWillJoin */);
61
62 // Construct our async helper object
63 sp<EvsVehicleListener> pEvsListener = new EvsVehicleListener();
64
65 // Get the EVS manager service
66 ALOGI("Acquiring EVS Enumerator");
67 android::sp<IEvsEnumerator> pEvs = IEvsEnumerator::getService(kEvsServiceName);
68 if (pEvs.get() == nullptr) {
69 ALOGE("getService returned NULL. Exiting.");
70 return 1;
71 }
72
73 // Request exclusive access to the EVS display
74 ALOGI("Acquiring EVS Display");
75 android::sp <IEvsDisplay> pDisplay;
76 pDisplay = pEvs->openDisplay();
77 if (pDisplay.get() == nullptr) {
78 ALOGE("EVS Display unavailable. Exiting.");
79 return 1;
80 }
81
82 // Connect to the Vehicle HAL so we can monitor state
83 ALOGI("Connecting to Vehicle HAL");
84 android::sp <IVehicle> pVnet = IVehicle::getService();
85 if (pVnet.get() == nullptr) {
86 #if 0
87 ALOGE("Vehicle HAL getService returned NULL. Exiting.");
88 return 1;
89 #else
90 // While testing, at least, we want to be able to run without a vehicle
91 ALOGE("getService returned NULL, but we're in test, so we'll pretend to be in reverse");
92 #endif
93 } else {
94 // Register for vehicle state change callbacks we care about
95 // Changes in these values are what will trigger a reconfiguration of the EVS pipeline
96 SubscribeOptions optionsData[2] = {
97 {
98 .propId = static_cast<int32_t>(VehicleProperty::GEAR_SELECTION),
99 .flags = SubscribeFlags::DEFAULT
100 },
101 {
102 .propId = static_cast<int32_t>(VehicleProperty::TURN_SIGNAL_STATE),
103 .flags = SubscribeFlags::DEFAULT
104 },
105 };
106 hidl_vec<SubscribeOptions> options;
107 options.setToExternal(optionsData, arraysize(optionsData));
108 StatusCode status = pVnet->subscribe(pEvsListener, options);
109 if (status != StatusCode::OK) {
110 ALOGE("Subscription to vehicle notifications failed with code %d. Exiting.", status);
111 return 1;
112 }
113 }
114
115 // Configure ourselves for the current vehicle state at startup
116 ALOGI("Constructing state controller");
117 EvsStateControl *pStateController = new EvsStateControl(pVnet, pEvs, pDisplay, config);
118 if (!pStateController->configureForVehicleState()) {
119 ALOGE("Initial configuration failed. Exiting.");
120 return 1;
121 } else {
122 // Run forever, reacting to events as necessary
123 ALOGI("Entering running state");
124 pEvsListener->run(pStateController);
125 }
126
127 // In normal operation, we expect to run forever, but in some error conditions we'll quit.
128 // One known example is if another process preempts our registration for our service name.
129 printf("EVS Listener stopped. Exiting.\n");
130 return 0;
131 }
132