1dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph/*
2dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph * Copyright (C) 2016 The Android Open Source Project
3dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph *
4dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph * Licensed under the Apache License, Version 2.0 (the "License");
5dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph * you may not use this file except in compliance with the License.
6dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph * You may obtain a copy of the License at
7dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph *
8dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph *      http://www.apache.org/licenses/LICENSE-2.0
9dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph *
10dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph * Unless required by applicable law or agreed to in writing, software
11dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph * distributed under the License is distributed on an "AS IS" BASIS,
12dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph * See the License for the specific language governing permissions and
14dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph * limitations under the License.
15dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph */
16dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph#include "EvsStateControl.h"
17150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph#include "RenderDirectView.h"
184a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph#include "RenderTopView.h"
19dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
20dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph#include <stdio.h>
21dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph#include <string.h>
22dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
2326cc755123e4867612f8f668e0424305f593aedbSteven Moreland#include <log/log.h>
24dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
25dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
26dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph// TODO:  Seems like it'd be nice if the Vehicle HAL provided such helpers (but how & where?)
27dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolphinline constexpr VehiclePropertyType getPropType(VehicleProperty prop) {
28dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    return static_cast<VehiclePropertyType>(
29dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph            static_cast<int32_t>(prop)
30dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph            & static_cast<int32_t>(VehiclePropertyType::MASK));
31dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph}
32dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
33dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
34dcc3534f0f7523e4ee7285522586d6e2827aa407Scott RandolphEvsStateControl::EvsStateControl(android::sp <IVehicle>       pVnet,
35dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                                 android::sp <IEvsEnumerator> pEvs,
36da289be96177f528495cc660f83472ade76c5918Scott Randolph                                 android::sp <IEvsDisplay>    pDisplay,
37da289be96177f528495cc660f83472ade76c5918Scott Randolph                                 const ConfigManager&         config) :
38dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    mVehicle(pVnet),
39dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    mEvs(pEvs),
40dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    mDisplay(pDisplay),
414a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph    mConfig(config),
42dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    mCurrentState(OFF) {
43dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
44dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    // Initialize the property value containers we'll be updating (they'll be zeroed by default)
45dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    static_assert(getPropType(VehicleProperty::GEAR_SELECTION) == VehiclePropertyType::INT32,
46dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                  "Unexpected type for GEAR_SELECTION property");
47dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    static_assert(getPropType(VehicleProperty::TURN_SIGNAL_STATE) == VehiclePropertyType::INT32,
48dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                  "Unexpected type for TURN_SIGNAL_STATE property");
49dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
502fb838823ed3783fd93de6bc7a3b8e27c03fcf46Pavel Maltsev    mGearValue.prop       = static_cast<int32_t>(VehicleProperty::GEAR_SELECTION);
512fb838823ed3783fd93de6bc7a3b8e27c03fcf46Pavel Maltsev    mTurnSignalValue.prop = static_cast<int32_t>(VehicleProperty::TURN_SIGNAL_STATE);
52dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
534a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph#if 0 // This way we only ever deal with cameras which exist in the system
54dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    // Build our set of cameras for the states we support
55dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    ALOGD("Requesting camera list");
564a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph    mEvs->getCameraList([this, &config](hidl_vec<CameraDesc> cameraList) {
57dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                            ALOGI("Camera list callback received %zu cameras",
58dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                                  cameraList.size());
59da289be96177f528495cc660f83472ade76c5918Scott Randolph                            for (auto&& cam: cameraList) {
60da289be96177f528495cc660f83472ade76c5918Scott Randolph                                ALOGD("Found camera %s", cam.cameraId.c_str());
61da289be96177f528495cc660f83472ade76c5918Scott Randolph                                bool cameraConfigFound = false;
62da289be96177f528495cc660f83472ade76c5918Scott Randolph
63da289be96177f528495cc660f83472ade76c5918Scott Randolph                                // Check our configuration for information about this camera
64da289be96177f528495cc660f83472ade76c5918Scott Randolph                                // Note that a camera can have a compound function string
65da289be96177f528495cc660f83472ade76c5918Scott Randolph                                // such that a camera can be "right/reverse" and be used for both.
664a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                // If more than one camera is listed for a given function, we'll
674a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                // list all of them and let the UX/rendering logic use one, some
684a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                // or all of them as appropriate.
69da289be96177f528495cc660f83472ade76c5918Scott Randolph                                for (auto&& info: config.getCameras()) {
70da289be96177f528495cc660f83472ade76c5918Scott Randolph                                    if (cam.cameraId == info.cameraId) {
71da289be96177f528495cc660f83472ade76c5918Scott Randolph                                        // We found a match!
72da289be96177f528495cc660f83472ade76c5918Scott Randolph                                        if (info.function.find("reverse") != std::string::npos) {
734a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                            mCameraList[State::REVERSE].push_back(info);
74da289be96177f528495cc660f83472ade76c5918Scott Randolph                                        }
75da289be96177f528495cc660f83472ade76c5918Scott Randolph                                        if (info.function.find("right") != std::string::npos) {
764a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                            mCameraList[State::RIGHT].push_back(info);
77da289be96177f528495cc660f83472ade76c5918Scott Randolph                                        }
78da289be96177f528495cc660f83472ade76c5918Scott Randolph                                        if (info.function.find("left") != std::string::npos) {
794a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                            mCameraList[State::LEFT].push_back(info);
804a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                        }
814a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                        if (info.function.find("park") != std::string::npos) {
824a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                            mCameraList[State::PARKING].push_back(info);
83da289be96177f528495cc660f83472ade76c5918Scott Randolph                                        }
84da289be96177f528495cc660f83472ade76c5918Scott Randolph                                        cameraConfigFound = true;
85da289be96177f528495cc660f83472ade76c5918Scott Randolph                                        break;
86da289be96177f528495cc660f83472ade76c5918Scott Randolph                                    }
87dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                                }
88da289be96177f528495cc660f83472ade76c5918Scott Randolph                                if (!cameraConfigFound) {
89da289be96177f528495cc660f83472ade76c5918Scott Randolph                                    ALOGW("No config information for hardware camera %s",
90da289be96177f528495cc660f83472ade76c5918Scott Randolph                                          cam.cameraId.c_str());
91dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                                }
92dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                            }
93dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                        }
94dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    );
954a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph#else // This way we use placeholders for cameras in the configuration but not reported by EVS
964a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph    // Build our set of cameras for the states we support
974a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph    ALOGD("Requesting camera list");
984a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph    for (auto&& info: config.getCameras()) {
994a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        if (info.function.find("reverse") != std::string::npos) {
1004a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph            mCameraList[State::REVERSE].push_back(info);
1014a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        }
1024a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        if (info.function.find("right") != std::string::npos) {
1034a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph            mCameraList[State::RIGHT].push_back(info);
1044a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        }
1054a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        if (info.function.find("left") != std::string::npos) {
1064a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph            mCameraList[State::LEFT].push_back(info);
1074a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        }
1084a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        if (info.function.find("park") != std::string::npos) {
1094a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph            mCameraList[State::PARKING].push_back(info);
1104a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        }
1114a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph    }
1124a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph#endif
1134a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph
114dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    ALOGD("State controller ready");
115dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph}
116dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
117dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
118150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolphbool EvsStateControl::startUpdateLoop() {
119150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    // Create the thread and report success if it gets started
120150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    mRenderThread = std::thread([this](){ updateLoop(); });
121150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    return mRenderThread.joinable();
122150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph}
123150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
124150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
125150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolphvoid EvsStateControl::postCommand(const Command& cmd) {
126150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    // Push the command onto the queue watched by updateLoop
127150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    mLock.lock();
128150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    mCommandQueue.push(cmd);
129150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    mLock.unlock();
130150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
131150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    // Send a signal to wake updateLoop in case it is asleep
132150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    mWakeSignal.notify_all();
133150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph}
134150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
135150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
136150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolphvoid EvsStateControl::updateLoop() {
137150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    ALOGD("Starting EvsStateControl update loop");
138150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
139150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    bool run = true;
140150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    while (run) {
141150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        // Process incoming commands
142150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        {
143150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            std::lock_guard <std::mutex> lock(mLock);
144150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            while (!mCommandQueue.empty()) {
145150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                const Command& cmd = mCommandQueue.front();
146150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                switch (cmd.operation) {
147150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                case Op::EXIT:
148150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                    run = false;
149150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                    break;
150150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                case Op::CHECK_VEHICLE_STATE:
151150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                    // Just running selectStateForCurrentConditions below will take care of this
152150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                    break;
153150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                case Op::TOUCH_EVENT:
154150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                    // TODO:  Implement this given the x/y location of the touch event
155150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                    // Ignore for now
156150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                    break;
157150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                }
158150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                mCommandQueue.pop();
159150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            }
160150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        }
161150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
162150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        // Review vehicle state and choose an appropriate renderer
163150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        if (!selectStateForCurrentConditions()) {
164150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            ALOGE("selectStateForCurrentConditions failed so we're going to die");
165150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            break;
166150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        }
167150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
168150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        // If we have an active renderer, give it a chance to draw
169150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        if (mCurrentRenderer) {
170150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            // Get the output buffer we'll use to display the imagery
171150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            BufferDesc tgtBuffer = {};
172150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            mDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc& buff) {
173150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                                          tgtBuffer = buff;
174150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                                      }
175150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            );
176150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
177150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            if (tgtBuffer.memHandle == nullptr) {
178150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                ALOGE("Didn't get requested output buffer -- skipping this frame.");
179150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            } else {
180150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                // Generate our output image
181150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                if (!mCurrentRenderer->drawFrame(tgtBuffer)) {
182150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                    // If drawing failed, we want to exit quickly so an app restart can happen
183150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                    run = false;
184150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                }
185150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
186150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                // Send the finished image back for display
187150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                mDisplay->returnTargetBufferForDisplay(tgtBuffer);
188150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            }
189150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        } else {
190150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            // No active renderer, so sleep until somebody wakes us with another command
191150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            std::unique_lock<std::mutex> lock(mLock);
192150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            mWakeSignal.wait(lock);
193150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        }
194150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    }
195150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
196150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    ALOGW("EvsStateControl update loop ending");
197150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
198150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    // TODO:  Fix it so we can exit cleanly from the main thread instead
199150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    printf("Shutting down app due to state control loop ending\n");
200150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    ALOGE("KILLING THE APP FROM THE EvsStateControl LOOP ON DRAW FAILURE!!!");
201150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    exit(1);
202150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph}
203150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
204150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph
205150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolphbool EvsStateControl::selectStateForCurrentConditions() {
20629803803b299652fc219713774181dd9a7dd8decScott Randolph    static int32_t sDummyGear   = int32_t(VehicleGear::GEAR_REVERSE);
20729803803b299652fc219713774181dd9a7dd8decScott Randolph    static int32_t sDummySignal = int32_t(VehicleTurnSignal::NONE);
20829803803b299652fc219713774181dd9a7dd8decScott Randolph
209dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    if (mVehicle != nullptr) {
210dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        // Query the car state
211dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        if (invokeGet(&mGearValue) != StatusCode::OK) {
212dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph            ALOGE("GEAR_SELECTION not available from vehicle.  Exiting.");
213dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph            return false;
214dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        }
215c529bcba1d63acbdf6ba2dce9eeafa6600667c55Scott Randolph        if ((mTurnSignalValue.prop == 0) || (invokeGet(&mTurnSignalValue) != StatusCode::OK)) {
21629803803b299652fc219713774181dd9a7dd8decScott Randolph            // Silently treat missing turn signal state as no turn signal active
21729803803b299652fc219713774181dd9a7dd8decScott Randolph            mTurnSignalValue.value.int32Values.setToExternal(&sDummySignal, 1);
218c529bcba1d63acbdf6ba2dce9eeafa6600667c55Scott Randolph            mTurnSignalValue.prop = 0;
219dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        }
220dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    } else {
221dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        // While testing without a vehicle, behave as if we're in reverse for the first 20 seconds
222dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        static const int kShowTime = 20;    // seconds
223dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
224dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        // See if it's time to turn off the default reverse camera
225dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        static std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
226dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
227dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        if (std::chrono::duration_cast<std::chrono::seconds>(now - start).count() > kShowTime) {
228dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph            // Switch to drive (which should turn off the reverse camera)
229dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph            sDummyGear = int32_t(VehicleGear::GEAR_DRIVE);
230dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        }
231dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
232dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        // Build the dummy vehicle state values (treating single values as 1 element vectors)
233dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        mGearValue.value.int32Values.setToExternal(&sDummyGear, 1);
234dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        mTurnSignalValue.value.int32Values.setToExternal(&sDummySignal, 1);
235dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    }
236dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
237dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    // Choose our desired EVS state based on the current car state
238c529bcba1d63acbdf6ba2dce9eeafa6600667c55Scott Randolph    // TODO:  Update this logic, and consider user input when choosing if a view should be presented
239dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    State desiredState = OFF;
240dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    if (mGearValue.value.int32Values[0] == int32_t(VehicleGear::GEAR_REVERSE)) {
241dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        desiredState = REVERSE;
242dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    } else if (mTurnSignalValue.value.int32Values[0] == int32_t(VehicleTurnSignal::RIGHT)) {
243dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        desiredState = RIGHT;
244dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    } else if (mTurnSignalValue.value.int32Values[0] == int32_t(VehicleTurnSignal::LEFT)) {
245dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        desiredState = LEFT;
2464a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph    } else if (mGearValue.value.int32Values[0] == int32_t(VehicleGear::GEAR_PARK)) {
2474a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        desiredState = PARKING;
248dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    }
249dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
250150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    // Apply the desire state
251150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    return configureEvsPipeline(desiredState);
252dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph}
253dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
254dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
255dcc3534f0f7523e4ee7285522586d6e2827aa407Scott RandolphStatusCode EvsStateControl::invokeGet(VehiclePropValue *pRequestedPropValue) {
256dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    StatusCode status = StatusCode::TRY_AGAIN;
257dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
258dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    // Call the Vehicle HAL, which will block until the callback is complete
259dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    mVehicle->get(*pRequestedPropValue,
260150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph                  [pRequestedPropValue, &status]
261dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                  (StatusCode s, const VehiclePropValue& v) {
262dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                       status = s;
263c529bcba1d63acbdf6ba2dce9eeafa6600667c55Scott Randolph                       if (s == StatusCode::OK) {
264c529bcba1d63acbdf6ba2dce9eeafa6600667c55Scott Randolph                           *pRequestedPropValue = v;
265c529bcba1d63acbdf6ba2dce9eeafa6600667c55Scott Randolph                       }
266dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph                  }
267dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    );
268dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
269dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    return status;
270dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph}
271dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
272dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
273dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolphbool EvsStateControl::configureEvsPipeline(State desiredState) {
274dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    if (mCurrentState == desiredState) {
275dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        // Nothing to do here...
276dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        return true;
277dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    }
278dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
279c529bcba1d63acbdf6ba2dce9eeafa6600667c55Scott Randolph    ALOGD("Switching to state %d.", desiredState);
2804a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph    ALOGD("  Current state %d has %zu cameras", mCurrentState,
2814a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph          mCameraList[mCurrentState].size());
2824a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph    ALOGD("  Desired state %d has %zu cameras", desiredState,
2834a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph          mCameraList[desiredState].size());
284dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
285150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    // Since we're changing states, shut down the current renderer
286150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    if (mCurrentRenderer != nullptr) {
287150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        mCurrentRenderer->deactivate();
288150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        mCurrentRenderer = nullptr; // It's a smart pointer, so destructs on assignment to null
289150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    }
290dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
291150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    // Do we need a new direct view renderer?
2924a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph    if (mCameraList[desiredState].size() > 1 || desiredState == PARKING) {
2934a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        // TODO:  DO we want other kinds of compound view or else sequentially selected views?
2944a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        mCurrentRenderer = std::make_unique<RenderTopView>(mEvs,
2954a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                                           mCameraList[desiredState],
2964a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                                           mConfig);
2974a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        if (!mCurrentRenderer) {
2984a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph            ALOGE("Failed to construct top view renderer.  Skipping state change.");
2994a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph            return false;
3004a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        }
3014a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph    } else if (mCameraList[desiredState].size() == 1) {
302150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        // We have a camera assigned to this state for direct view
3034a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph        mCurrentRenderer = std::make_unique<RenderDirectView>(mEvs,
3044a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph                                                              mCameraList[desiredState][0]);
305150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        if (!mCurrentRenderer) {
3064a83b5dba29eceaf43c4ff7d5c184463949174ccScott Randolph            ALOGE("Failed to construct direct renderer.  Skipping state change.");
307150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            return false;
308dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        }
309150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    }
310dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
311150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    // Now set the display state based on whether we have a video feed to show
312150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    if (mCurrentRenderer == nullptr) {
313150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        ALOGD("Turning off the display");
314150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        mDisplay->setDisplayState(DisplayState::NOT_VISIBLE);
315150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph    } else {
316150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        // Start the camera stream
317150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        ALOGD("Starting camera stream");
318150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        if (!mCurrentRenderer->activate()) {
319150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            ALOGE("New renderer failed to activate");
320150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            return false;
321150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        }
322dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
323150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        // Activate the display
324150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        ALOGD("Arming the display");
325150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        Return<EvsResult> result = mDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME);
326150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph        if (result != EvsResult::OK) {
327150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            ALOGE("setDisplayState returned an error (%d)", (EvsResult)result);
328150c580464a7a4d6b0ad3362f23f790ded65e7abScott Randolph            return false;
329dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph        }
330dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    }
331dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
332dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    // Record our current state
333dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    ALOGI("Activated state %d.", desiredState);
334dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    mCurrentState = desiredState;
335dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph
336dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph    return true;
337dcc3534f0f7523e4ee7285522586d6e2827aa407Scott Randolph}
338