• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <stdio.h>
18 
19 #include <hidl/HidlTransportSupport.h>
20 #include <utils/Errors.h>
21 #include <utils/StrongPointer.h>
22 #include <utils/Log.h>
23 
24 #include "android-base/macros.h"    // arraysize
25 
26 #include <android/hardware/automotive/evs/1.0/IEvsEnumerator.h>
27 #include <android/hardware/automotive/evs/1.0/IEvsDisplay.h>
28 
29 #include <hwbinder/ProcessState.h>
30 
31 #include "EvsStateControl.h"
32 #include "EvsVehicleListener.h"
33 #include "ConfigManager.h"
34 
35 
36 // libhidl:
37 using android::hardware::configureRpcThreadpool;
38 using android::hardware::joinRpcThreadpool;
39 
40 
41 // Helper to subscribe to VHal notifications
subscribeToVHal(sp<IVehicle> pVnet,sp<IVehicleCallback> listener,VehicleProperty propertyId)42 static bool subscribeToVHal(sp<IVehicle> pVnet,
43                             sp<IVehicleCallback> listener,
44                             VehicleProperty propertyId) {
45     assert(pVnet != nullptr);
46     assert(listener != nullptr);
47 
48     // Register for vehicle state change callbacks we care about
49     // Changes in these values are what will trigger a reconfiguration of the EVS pipeline
50     SubscribeOptions optionsData[] = {
51         {
52             .propId = static_cast<int32_t>(propertyId),
53             .flags  = SubscribeFlags::EVENTS_FROM_CAR
54         },
55     };
56     hidl_vec <SubscribeOptions> options;
57     options.setToExternal(optionsData, arraysize(optionsData));
58     StatusCode status = pVnet->subscribe(listener, options);
59     if (status != StatusCode::OK) {
60         ALOGW("VHAL subscription for property 0x%08X failed with code %d.", propertyId, status);
61         return false;
62     }
63 
64     return true;
65 }
66 
67 
68 // Main entry point
main(int argc,char ** argv)69 int main(int argc, char** argv)
70 {
71     ALOGI("EVS app starting\n");
72 
73     // Set up default behavior, then check for command line options
74     bool useVehicleHal = true;
75     bool printHelp = false;
76     const char* evsServiceName = "default";
77     for (int i=1; i< argc; i++) {
78         if (strcmp(argv[i], "--test") == 0) {
79             useVehicleHal = false;
80         } else if (strcmp(argv[i], "--hw") == 0) {
81             evsServiceName = "EvsEnumeratorHw";
82         } else if (strcmp(argv[i], "--mock") == 0) {
83             evsServiceName = "EvsEnumeratorHw-Mock";
84         } else if (strcmp(argv[i], "--help") == 0) {
85             printHelp = true;
86         } else {
87             printf("Ignoring unrecognized command line arg '%s'\n", argv[i]);
88             printHelp = true;
89         }
90     }
91     if (printHelp) {
92         printf("Options include:\n");
93         printf("  --test   Do not talk to Vehicle Hal, but simulate 'reverse' instead\n");
94         printf("  --hw     Bypass EvsManager by connecting directly to EvsEnumeratorHw\n");
95         printf("  --mock   Connect directly to EvsEnumeratorHw-Mock\n");
96     }
97 
98     // Load our configuration information
99     ConfigManager config;
100     if (!config.initialize("/system/etc/automotive/evs/config.json")) {
101         ALOGE("Missing or improper configuration for the EVS application.  Exiting.");
102         return 1;
103     }
104 
105     // Set thread pool size to one to avoid concurrent events from the HAL.
106     // This pool will handle the EvsCameraStream callbacks.
107     // Note:  This _will_ run in parallel with the EvsListener run() loop below which
108     // runs the application logic that reacts to the async events.
109     configureRpcThreadpool(1, false /* callerWillJoin */);
110 
111     // Construct our async helper object
112     sp<EvsVehicleListener> pEvsListener = new EvsVehicleListener();
113 
114     // Get the EVS manager service
115     ALOGI("Acquiring EVS Enumerator");
116     android::sp<IEvsEnumerator> pEvs = IEvsEnumerator::getService(evsServiceName);
117     if (pEvs.get() == nullptr) {
118         ALOGE("getService(%s) returned NULL.  Exiting.", evsServiceName);
119         return 1;
120     }
121 
122     // Request exclusive access to the EVS display
123     ALOGI("Acquiring EVS Display");
124     android::sp <IEvsDisplay> pDisplay;
125     pDisplay = pEvs->openDisplay();
126     if (pDisplay.get() == nullptr) {
127         ALOGE("EVS Display unavailable.  Exiting.");
128         return 1;
129     }
130 
131     // Connect to the Vehicle HAL so we can monitor state
132     sp<IVehicle> pVnet;
133     if (useVehicleHal) {
134         ALOGI("Connecting to Vehicle HAL");
135         pVnet = IVehicle::getService();
136         if (pVnet.get() == nullptr) {
137             ALOGE("Vehicle HAL getService returned NULL.  Exiting.");
138             return 1;
139         } else {
140             // Register for vehicle state change callbacks we care about
141             // Changes in these values are what will trigger a reconfiguration of the EVS pipeline
142             if (!subscribeToVHal(pVnet, pEvsListener, VehicleProperty::GEAR_SELECTION)) {
143                 ALOGE("Without gear notification, we can't support EVS.  Exiting.");
144                 return 1;
145             }
146             if (!subscribeToVHal(pVnet, pEvsListener, VehicleProperty::TURN_SIGNAL_STATE)) {
147                 ALOGW("Didn't get turn signal notificaitons, so we'll ignore those.");
148             }
149         }
150     } else {
151         ALOGW("Test mode selected, so not talking to Vehicle HAL");
152     }
153 
154     // Configure ourselves for the current vehicle state at startup
155     ALOGI("Constructing state controller");
156     EvsStateControl *pStateController = new EvsStateControl(pVnet, pEvs, pDisplay, config);
157     if (!pStateController->startUpdateLoop()) {
158         ALOGE("Initial configuration failed.  Exiting.");
159         return 1;
160     }
161 
162     // Run forever, reacting to events as necessary
163     ALOGI("Entering running state");
164     pEvsListener->run(pStateController);
165 
166     // In normal operation, we expect to run forever, but in some error conditions we'll quit.
167     // One known example is if another process preempts our registration for our service name.
168     ALOGE("EVS Listener stopped.  Exiting.");
169 
170     return 0;
171 }
172