1 /*
2  * Copyright (C) 2022 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 "AidlDisplay.h"
18 
19 #include "utils/include/Utils.h"
20 
21 #include <aidl/android/hardware/automotive/evs/Rotation.h>
22 #include <android-base/logging.h>
23 #include <ui/DisplayMode.h>
24 #include <ui/DisplayState.h>
25 
26 namespace aidl::android::automotive::evs::implementation {
27 
28 namespace hidlevs = ::android::hardware::automotive::evs;
29 
30 using ::aidl::android::hardware::automotive::evs::BufferDesc;
31 using ::aidl::android::hardware::automotive::evs::DisplayDesc;
32 using ::aidl::android::hardware::automotive::evs::DisplayState;
33 using ::aidl::android::hardware::automotive::evs::EvsResult;
34 using ::aidl::android::hardware::automotive::evs::Rotation;
35 using ::ndk::ScopedAStatus;
36 
~AidlDisplay()37 AidlDisplay::~AidlDisplay() {
38     // simply release a shared pointer to remote display object.
39     mHidlDisplay = nullptr;
40 }
41 
42 /**
43  * Gets basic display information from a hardware display object and returns.
44  */
getDisplayInfo(DisplayDesc * _aidl_return)45 ScopedAStatus AidlDisplay::getDisplayInfo(DisplayDesc* _aidl_return) {
46     if (!mHidlDisplay) {
47         return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
48     }
49 
50     mHidlDisplay->getDisplayInfo([_aidl_return](const hidlevs::V1_0::DisplayDesc& info) {
51         _aidl_return->id = info.displayId;
52         _aidl_return->vendorFlags = info.vendorFlags;
53     });
54 
55     auto halV1_1 = hidlevs::V1_1::IEvsDisplay::castFrom(mHidlDisplay).withDefault(nullptr);
56     if (!halV1_1) {
57         // Additional display information is not available if the system runs
58         // HIDL EVS v1.0 implementation.
59         return ScopedAStatus::ok();
60     }
61 
62     halV1_1->getDisplayInfo_1_1([_aidl_return](const auto& hidlMode, const auto& hidlState) {
63         const ::android::ui::DisplayMode* pMode =
64                 reinterpret_cast<const ::android::ui::DisplayMode*>(hidlMode.data());
65         const ::android::ui::DisplayState* pState =
66                 reinterpret_cast<const ::android::ui::DisplayState*>(hidlState.data());
67         _aidl_return->width = pMode->resolution.getWidth();
68         _aidl_return->height = pMode->resolution.getHeight();
69         _aidl_return->orientation = static_cast<Rotation>(pState->orientation);
70     });
71     return ScopedAStatus::ok();
72 }
73 
74 /**
75  * Gets current display state from a hardware display object and return.
76  */
getDisplayState(DisplayState * _aidl_return)77 ScopedAStatus AidlDisplay::getDisplayState(DisplayState* _aidl_return) {
78     if (!mHidlDisplay) {
79         return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
80     }
81 
82     *_aidl_return = std::move(Utils::makeFromHidl(mHidlDisplay->getDisplayState()));
83     return ScopedAStatus::ok();
84 }
85 
86 /**
87  * Returns a handle to a frame buffer associated with the display.
88  */
getTargetBuffer(BufferDesc * _aidl_return)89 ScopedAStatus AidlDisplay::getTargetBuffer(BufferDesc* _aidl_return) {
90     if (!mHidlDisplay) {
91         return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
92     }
93 
94     mHidlDisplay->getTargetBuffer([this, _aidl_return](auto& hidlBuffer) {
95         *_aidl_return = std::move(Utils::makeFromHidl(hidlBuffer, /* doDup= */ true));
96         mHeldBuffer = std::move(hidlBuffer);
97     });
98     return ScopedAStatus::ok();
99 }
100 
101 /**
102  * Notifies the display that the buffer is ready to be used.
103  */
returnTargetBufferForDisplay(const BufferDesc & buffer)104 ScopedAStatus AidlDisplay::returnTargetBufferForDisplay(const BufferDesc& buffer) {
105     if (!mHidlDisplay) {
106         return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
107     }
108 
109     if (buffer.bufferId != mHeldBuffer.bufferId) {
110         LOG(WARNING) << "Ignores a request to return a buffer " << buffer.bufferId << "; a buffer "
111                      << mHeldBuffer.bufferId << " is held.";
112         return ScopedAStatus::ok();
113     }
114 
115     return Utils::buildScopedAStatusFromEvsResult(
116             mHidlDisplay->returnTargetBufferForDisplay(mHeldBuffer));
117 }
118 
119 /**
120  * Sets the display state as what the clients wants.
121  */
setDisplayState(DisplayState state)122 ScopedAStatus AidlDisplay::setDisplayState(DisplayState state) {
123     if (!mHidlDisplay) {
124         return Utils::buildScopedAStatusFromEvsResult(EvsResult::RESOURCE_NOT_AVAILABLE);
125     }
126 
127     return Utils::buildScopedAStatusFromEvsResult(
128             mHidlDisplay->setDisplayState(std::move(Utils::makeToHidl(state))));
129 }
130 
131 }  // namespace aidl::android::automotive::evs::implementation
132