diff --git a/automotive/evs/1.1/Android.bp b/automotive/evs/1.1/Android.bp index c850c91b21..17f31e4dd0 100644 --- a/automotive/evs/1.1/Android.bp +++ b/automotive/evs/1.1/Android.bp @@ -10,9 +10,11 @@ hidl_interface { "types.hal", "IEvsCamera.hal", "IEvsCameraStream.hal", + "IEvsDisplay.hal", "IEvsEnumerator.hal", ], interfaces: [ + "android.frameworks.automotive.display@1.0", "android.hardware.automotive.evs@1.0", "android.hardware.camera.device@3.2", "android.hardware.graphics.common@1.0", diff --git a/automotive/evs/1.1/IEvsDisplay.hal b/automotive/evs/1.1/IEvsDisplay.hal new file mode 100644 index 0000000000..38da536189 --- /dev/null +++ b/automotive/evs/1.1/IEvsDisplay.hal @@ -0,0 +1,35 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.automotive.evs@1.1; + +import @1.0::IEvsDisplay; +import @1.0::EvsResult; +import android.frameworks.automotive.display@1.0::HwDisplayConfig; +import android.frameworks.automotive.display@1.0::HwDisplayState; + +/** + * Represents a single display. + */ +interface IEvsDisplay extends @1.0::IEvsDisplay { + /** + * Returns the description of this display. + * + * @return cfg Current configuration of this display. + * @return state Current state of this display. + */ + getDisplayInfo_1_1() generates (HwDisplayConfig cfg, HwDisplayState state); +}; diff --git a/automotive/evs/1.1/IEvsEnumerator.hal b/automotive/evs/1.1/IEvsEnumerator.hal index 7752b0e330..84dd21f92a 100644 --- a/automotive/evs/1.1/IEvsEnumerator.hal +++ b/automotive/evs/1.1/IEvsEnumerator.hal @@ -17,6 +17,7 @@ package android.hardware.automotive.evs@1.1; import IEvsCamera; +import IEvsDisplay; import @1.0::IEvsEnumerator; import @1.0::EvsResult; import android.hardware.camera.device@3.2::Stream; @@ -54,4 +55,25 @@ interface IEvsEnumerator extends @1.0::IEvsEnumerator { * @return result False for EVS manager implementations and true for all others. */ isHardware() generates (bool result); + + /** + * Returns a list of all EVS displays available to the system + * + * @return displayIds Identifiers of available displays. + */ + getDisplayIdList() generates (vec displayIds); + + /** + * Get exclusive access to IEvsDisplay for the system + * + * There can be more than one EVS display objects for the system and this function + * requests access to the display identified by a given ID. If the target EVS display + * is not available or is already in use the old instance shall be closed and give + * the new caller exclusive access. + * When done using the display, the caller may release it by calling closeDisplay(). + * + * @param id Target display identifier. + * @return display EvsDisplay object to be used. + */ + openDisplay_1_1(uint8_t id) generates (IEvsDisplay display); }; diff --git a/automotive/evs/1.1/default/Android.bp b/automotive/evs/1.1/default/Android.bp index a7c7b4282b..a35c9db254 100644 --- a/automotive/evs/1.1/default/Android.bp +++ b/automotive/evs/1.1/default/Android.bp @@ -27,6 +27,10 @@ cc_binary { "libutils", "libcamera_metadata", "libtinyxml2", + "android.hidl.token@1.0-utils", + "android.frameworks.automotive.display@1.0", + "android.hardware.graphics.bufferqueue@1.0", + "android.hardware.graphics.bufferqueue@2.0", ], cflags: [ diff --git a/automotive/evs/1.1/default/EvsCamera.cpp b/automotive/evs/1.1/default/EvsCamera.cpp index b7e4efac02..f9cdb881d8 100644 --- a/automotive/evs/1.1/default/EvsCamera.cpp +++ b/automotive/evs/1.1/default/EvsCamera.cpp @@ -280,7 +280,7 @@ Return EvsCamera::setMaster() { return EvsResult::OK; } -Return EvsCamera::forceMaster(const sp& ) { +Return EvsCamera::forceMaster(const sp& ) { // Default implementation does not expect multiple subscribers and therefore // return a success code always. return EvsResult::OK; diff --git a/automotive/evs/1.1/default/EvsCamera.h b/automotive/evs/1.1/default/EvsCamera.h index 72a1b5776b..a49db46521 100644 --- a/automotive/evs/1.1/default/EvsCamera.h +++ b/automotive/evs/1.1/default/EvsCamera.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -33,7 +33,8 @@ using IEvsCameraStream_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCam using IEvsCameraStream_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCameraStream; using ::android::hardware::automotive::evs::V1_0::EvsResult; using ::android::hardware::automotive::evs::V1_0::CameraDesc; -using ::android::hardware::automotive::evs::V1_0::IEvsDisplay; +using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay; +using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay; namespace android { @@ -68,7 +69,7 @@ public: Return resumeVideoStream() override; Return doneWithFrame_1_1(const hidl_vec& buffer) override; Return setMaster() override; - Return forceMaster(const sp& display) override; + Return forceMaster(const sp& display) override; Return unsetMaster() override; Return getParameterList(getParameterList_cb _hidl_cb) override; Return getIntParameterRange(CameraParam id, diff --git a/automotive/evs/1.1/default/EvsDisplay.cpp b/automotive/evs/1.1/default/EvsDisplay.cpp index 74c099ac30..2b5a4a977c 100644 --- a/automotive/evs/1.1/default/EvsDisplay.cpp +++ b/automotive/evs/1.1/default/EvsDisplay.cpp @@ -21,6 +21,8 @@ #include #include +using ::android::frameworks::automotive::display::V1_0::HwDisplayConfig; +using ::android::frameworks::automotive::display::V1_0::HwDisplayState; namespace android { namespace hardware { @@ -31,6 +33,13 @@ namespace implementation { EvsDisplay::EvsDisplay() { + EvsDisplay(nullptr, 0); +} + + +EvsDisplay::EvsDisplay(sp pDisplayProxy, uint64_t displayId) + : mDisplayProxy(pDisplayProxy), + mDisplayId(displayId) { ALOGD("EvsDisplay instantiated"); // Set up our self description @@ -327,6 +336,18 @@ Return EvsDisplay::returnTargetBufferForDisplay(const BufferDesc_1_0& } +Return EvsDisplay::getDisplayInfo_1_1(getDisplayInfo_1_1_cb _info_cb) { + if (mDisplayProxy != nullptr) { + return mDisplayProxy->getDisplayInfo(mDisplayId, _info_cb); + } else { + HwDisplayConfig nullConfig; + HwDisplayState nullState; + _info_cb(nullConfig, nullState); + return Void(); + } +} + + } // namespace implementation } // namespace V1_1 } // namespace evs diff --git a/automotive/evs/1.1/default/EvsDisplay.h b/automotive/evs/1.1/default/EvsDisplay.h index 2a5653500f..9b2ed90128 100644 --- a/automotive/evs/1.1/default/EvsDisplay.h +++ b/automotive/evs/1.1/default/EvsDisplay.h @@ -17,14 +17,16 @@ #ifndef ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSDISPLAY_H #define ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSDISPLAY_H -#include +#include +#include #include -using ::android::hardware::automotive::evs::V1_0::IEvsDisplay; +using ::android::hardware::automotive::evs::V1_1::IEvsDisplay; using ::android::hardware::automotive::evs::V1_0::DisplayDesc; using ::android::hardware::automotive::evs::V1_0::DisplayState; using ::android::hardware::automotive::evs::V1_0::EvsResult; using BufferDesc_1_0 = ::android::hardware::automotive::evs::V1_0::BufferDesc; +using android::frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService; namespace android { namespace hardware { @@ -43,9 +45,12 @@ public: Return getTargetBuffer(getTargetBuffer_cb _hidl_cb) override; Return returnTargetBufferForDisplay(const BufferDesc_1_0& buffer) override; + // Methods from ::android::hardware::automotive::evs::V1_1::IEvsDisplay follow. + Return getDisplayInfo_1_1(getDisplayInfo_1_1_cb _info_cb) override; // Implementation details EvsDisplay(); + EvsDisplay(sp pDisplayProxy, uint64_t displayId); virtual ~EvsDisplay() override; void forceShutdown(); // This gets called if another caller "steals" ownership of the display @@ -60,6 +65,9 @@ private: DisplayState mRequestedState = DisplayState::NOT_VISIBLE; std::mutex mAccessLock; + + sp mDisplayProxy; + uint64_t mDisplayId; }; } // namespace implementation diff --git a/automotive/evs/1.1/default/EvsEnumerator.cpp b/automotive/evs/1.1/default/EvsEnumerator.cpp index cb7403a7da..0319560ee6 100644 --- a/automotive/evs/1.1/default/EvsEnumerator.cpp +++ b/automotive/evs/1.1/default/EvsEnumerator.cpp @@ -34,18 +34,38 @@ namespace implementation { std::list EvsEnumerator::sCameraList; wp EvsEnumerator::sActiveDisplay; unique_ptr EvsEnumerator::sConfigManager; +sp EvsEnumerator::sDisplayProxyService; +std::unordered_map EvsEnumerator::sDisplayPortList; -EvsEnumerator::EvsEnumerator() { +EvsEnumerator::EvsEnumerator(sp windowService) { ALOGD("EvsEnumerator created"); // Add sample camera data to our list of cameras // In a real driver, this would be expected to can the available hardware sConfigManager = ConfigManager::Create("/vendor/etc/automotive/evs/evs_default_configuration.xml"); + + // Add available cameras for (auto v : sConfigManager->getCameraList()) { sCameraList.emplace_back(v.c_str()); } + + if (sDisplayProxyService == nullptr) { + /* sets a car-window service handle */ + sDisplayProxyService = windowService; + } + + // Add available displays + if (sDisplayProxyService != nullptr) { + // Get a display ID list. + sDisplayProxyService->getDisplayIdList([](const auto& displayIds) { + for (const auto& id : displayIds) { + const auto port = id & 0xF; + sDisplayPortList.insert_or_assign(port, id); + } + }); + } } @@ -165,7 +185,7 @@ Return EvsEnumerator::closeCamera(const ::android::sp& pCa } -Return> EvsEnumerator::openDisplay() { +Return> EvsEnumerator::openDisplay() { ALOGD("openDisplay"); // If we already have a display active, then we need to shut it down so we can @@ -185,7 +205,42 @@ Return> EvsEnumerator::openDisplay() { } -Return EvsEnumerator::closeDisplay(const ::android::sp& pDisplay) { +Return EvsEnumerator::getDisplayIdList(getDisplayIdList_cb _list_cb) { + hidl_vec ids; + + ids.resize(sDisplayPortList.size()); + unsigned i = 0; + for (const auto& [port, id] : sDisplayPortList) { + ids[i++] = port; + } + + _list_cb(ids); + return Void(); +} + + +Return> EvsEnumerator::openDisplay_1_1(uint8_t port) { + ALOGD("%s", __FUNCTION__); + + // If we already have a display active, then we need to shut it down so we can + // give exclusive access to the new caller. + sp pActiveDisplay = sActiveDisplay.promote(); + if (pActiveDisplay != nullptr) { + ALOGW("Killing previous display because of new caller"); + closeDisplay(pActiveDisplay); + } + + // Create a new display interface and return it + pActiveDisplay = new EvsDisplay(sDisplayProxyService, sDisplayPortList[port]); + sActiveDisplay = pActiveDisplay; + + ALOGD("Returning new EvsDisplay object %p", pActiveDisplay.get()); + return pActiveDisplay; +} + + + +Return EvsEnumerator::closeDisplay(const ::android::sp& pDisplay) { ALOGD("closeDisplay"); // Do we still have a display object we think should be active? diff --git a/automotive/evs/1.1/default/EvsEnumerator.h b/automotive/evs/1.1/default/EvsEnumerator.h index ca35dc6f8a..9415953a27 100644 --- a/automotive/evs/1.1/default/EvsEnumerator.h +++ b/automotive/evs/1.1/default/EvsEnumerator.h @@ -19,19 +19,22 @@ #include #include +#include +#include #include #include "ConfigManager.h" using ::android::hardware::automotive::evs::V1_0::EvsResult; -using ::android::hardware::automotive::evs::V1_0::IEvsDisplay; using ::android::hardware::automotive::evs::V1_0::DisplayState; using IEvsCamera_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCamera; using IEvsCamera_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCamera; using CameraDesc_1_0 = ::android::hardware::automotive::evs::V1_0::CameraDesc; using CameraDesc_1_1 = ::android::hardware::automotive::evs::V1_1::CameraDesc; - +using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay; +using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay; +using android::frameworks::automotive::display::V1_0::IAutomotiveDisplayProxyService; namespace android { namespace hardware { @@ -51,8 +54,8 @@ public: Return getCameraList(getCameraList_cb _hidl_cb) override; Return> openCamera(const hidl_string& cameraId) override; Return closeCamera(const ::android::sp& carCamera) override; - Return> openDisplay() override; - Return closeDisplay(const ::android::sp& display) override; + Return> openDisplay() override; + Return closeDisplay(const ::android::sp& display) override; Return getDisplayState() override; // Methods from ::android::hardware::automotive::evs::V1_1::IEvsEnumerator follow. @@ -60,9 +63,11 @@ public: Return> openCamera_1_1(const hidl_string& cameraId, const Stream& streamCfg) override; Return isHardware() override { return true; } + Return getDisplayIdList(getDisplayIdList_cb _list_cb) override; + Return> openDisplay_1_1(uint8_t port) override; // Implementation details - EvsEnumerator(); + EvsEnumerator(sp windowService = nullptr); private: // NOTE: All members values are static so that all clients operate on the same state @@ -83,6 +88,10 @@ private: static wp sActiveDisplay; static unique_ptr sConfigManager; + + static sp sDisplayProxyService; + static std::unordered_map sDisplayPortList; }; } // namespace implementation diff --git a/automotive/evs/1.1/default/service.cpp b/automotive/evs/1.1/default/service.cpp index 5135864e88..374b646812 100644 --- a/automotive/evs/1.1/default/service.cpp +++ b/automotive/evs/1.1/default/service.cpp @@ -34,7 +34,6 @@ using android::hardware::joinRpcThreadpool; // Generated HIDL files using android::hardware::automotive::evs::V1_1::IEvsEnumerator; -using android::hardware::automotive::evs::V1_0::IEvsDisplay; // The namespace in which all our implementation code lives using namespace android::hardware::automotive::evs::V1_1::implementation; diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp index 1a622452da..ce02973ac2 100644 --- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp +++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp @@ -54,9 +54,11 @@ static const float kNanoToSeconds = 0.000000001f; #include #include #include -#include +#include #include #include +#include +#include #include #include @@ -76,6 +78,8 @@ using ::android::hardware::automotive::evs::V1_0::DisplayState; using ::android::hardware::graphics::common::V1_0::PixelFormat; using IEvsCamera_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCamera; using IEvsCamera_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCamera; +using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay; +using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay; /* * Plese note that this is different from what is defined in @@ -567,9 +571,30 @@ TEST_F(EvsHidlTest, CameraToDisplayRoundTrip) { // output format. Stream nullCfg = {}; - // Request exclusive access to the EVS display - sp pDisplay = pEnumerator->openDisplay(); + // Request available display IDs + uint8_t targetDisplayId = 0; + pEnumerator->getDisplayIdList([&targetDisplayId](auto ids) { + ASSERT_GT(ids.size(), 0); + targetDisplayId = ids[0]; + }); + + // Request exclusive access to the first EVS display + sp pDisplay = pEnumerator->openDisplay_1_1(targetDisplayId); ASSERT_NE(pDisplay, nullptr); + ALOGI("Display %d is in use.", targetDisplayId); + + // Get the display descriptor + pDisplay->getDisplayInfo_1_1([](const auto& config, const auto& state) { + android::DisplayConfig* pConfig = (android::DisplayConfig*)config.data(); + const auto width = pConfig->resolution.getWidth(); + const auto height = pConfig->resolution.getHeight(); + ALOGI(" Resolution: %dx%d", width, height); + ASSERT_GT(width, 0); + ASSERT_GT(height, 0); + + android::ui::DisplayState* pState = (android::ui::DisplayState*)state.data(); + ASSERT_NE(pState->layerStack, -1); + }); // Test each reported camera for (auto&& cam: cameraInfo) { @@ -1556,7 +1581,7 @@ TEST_F(EvsHidlTest, HighPriorityCameraClient) { Stream nullCfg = {}; // Request exclusive access to the EVS display - sp pDisplay = pEnumerator->openDisplay(); + sp pDisplay = pEnumerator->openDisplay(); ASSERT_NE(pDisplay, nullptr); // Test each reported camera @@ -1920,7 +1945,7 @@ TEST_F(EvsHidlTest, CameraUseStreamConfigToDisplay) { loadCameraList(); // Request exclusive access to the EVS display - sp pDisplay = pEnumerator->openDisplay(); + sp pDisplay = pEnumerator->openDisplay(); ASSERT_NE(pDisplay, nullptr); // Test each reported camera