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