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 "Device.h"
18
19 #include <android-base/file.h>
20 #include <android-base/properties.h>
21 #include <json/json.h>
22
23 #include "ClientFrameComposer.h"
24 #include "FrameComposer.h"
25 #include "GuestFrameComposer.h"
26 #include "HostFrameComposer.h"
27 #include "NoOpFrameComposer.h"
28
29 ANDROID_SINGLETON_STATIC_INSTANCE(aidl::android::hardware::graphics::composer3::impl::Device);
30
31 namespace aidl::android::hardware::graphics::composer3::impl {
32 namespace {
33
shouldUseGuestComposer()34 bool shouldUseGuestComposer() {
35 return ::android::base::GetProperty("ro.hardware.vulkan", "") == "pastel";
36 }
37
getPmemPath()38 std::string getPmemPath() { return ::android::base::GetProperty("ro.vendor.hwcomposer.pmem", ""); }
39
loadPersistentKeyValues(Json::Value * dictionary)40 HWC3::Error loadPersistentKeyValues(Json::Value* dictionary) {
41 *dictionary = Json::Value(Json::ValueType::objectValue);
42
43 const std::string path = getPmemPath();
44 if (path.empty()) {
45 ALOGE("%s: persistent key-value store path not available.", __FUNCTION__);
46 return HWC3::Error::NoResources;
47 }
48
49 std::string content;
50 if (!::android::base::ReadFileToString(path, &content)) {
51 ALOGE("%s: failed to read key-value store from %s", __FUNCTION__, path.c_str());
52 return HWC3::Error::NoResources;
53 }
54
55 if (content.empty() || content[0] == '\0') {
56 return HWC3::Error::None;
57 }
58
59 Json::Reader reader;
60 if (!reader.parse(content, *dictionary)) {
61 const std::string error = reader.getFormattedErrorMessages();
62 ALOGE("%s: failed to parse key-value store from %s:%s", __FUNCTION__, path.c_str(),
63 error.c_str());
64 return HWC3::Error::NoResources;
65 }
66
67 return HWC3::Error::None;
68 }
69
savePersistentKeyValues(const Json::Value & dictionary)70 HWC3::Error savePersistentKeyValues(const Json::Value& dictionary) {
71 const std::string path = getPmemPath();
72 if (path.empty()) {
73 ALOGE("%s: persistent key-value store path not available.", __FUNCTION__);
74 return HWC3::Error::NoResources;
75 }
76
77 const std::string contents = dictionary.toStyledString();
78 if (!::android::base::WriteStringToFile(contents, path)) {
79 ALOGE("%s: failed to write key-value store to %s", __FUNCTION__, path.c_str());
80 return HWC3::Error::NoResources;
81 }
82
83 return HWC3::Error::None;
84 }
85
86 } // namespace
87
getComposer(FrameComposer ** outComposer)88 HWC3::Error Device::getComposer(FrameComposer** outComposer) {
89 std::unique_lock<std::mutex> lock(mMutex);
90
91 if (mComposer == nullptr) {
92 if (IsInNoOpCompositionMode()) {
93 DEBUG_LOG("%s: using NoOpFrameComposer", __FUNCTION__);
94 mComposer = std::make_unique<NoOpFrameComposer>();
95 } else if (IsInClientCompositionMode()) {
96 DEBUG_LOG("%s: using ClientFrameComposer", __FUNCTION__);
97 mComposer = std::make_unique<ClientFrameComposer>();
98 } else if (shouldUseGuestComposer()) {
99 DEBUG_LOG("%s: using GuestFrameComposer", __FUNCTION__);
100 mComposer = std::make_unique<GuestFrameComposer>();
101 } else {
102 DEBUG_LOG("%s: using HostFrameComposer", __FUNCTION__);
103 mComposer = std::make_unique<HostFrameComposer>();
104 }
105 if (!mComposer) {
106 ALOGE("%s failed to allocate FrameComposer", __FUNCTION__);
107 return HWC3::Error::NoResources;
108 }
109
110 HWC3::Error error = mComposer->init();
111 if (error != HWC3::Error::None) {
112 ALOGE("%s failed to init FrameComposer", __FUNCTION__);
113 return error;
114 }
115 }
116
117 *outComposer = mComposer.get();
118 return HWC3::Error::None;
119 }
120
getPersistentKeyValue(const std::string & key,const std::string & defaultValue,std::string * outValue)121 HWC3::Error Device::getPersistentKeyValue(const std::string& key, const std::string& defaultValue,
122 std::string* outValue) {
123 std::unique_lock<std::mutex> lock(mMutex);
124
125 Json::Value dictionary;
126
127 HWC3::Error error = loadPersistentKeyValues(&dictionary);
128 if (error != HWC3::Error::None) {
129 ALOGE("%s: failed to load pmem json", __FUNCTION__);
130 return error;
131 }
132
133 if (!dictionary.isMember(key)) {
134 *outValue = defaultValue;
135 return HWC3::Error::None;
136 }
137
138 *outValue = defaultValue;
139
140 return HWC3::Error::None;
141 }
142
setPersistentKeyValue(const std::string & key,const std::string & value)143 HWC3::Error Device::setPersistentKeyValue(const std::string& key, const std::string& value) {
144 std::unique_lock<std::mutex> lock(mMutex);
145
146 Json::Value dictionary;
147
148 HWC3::Error error = loadPersistentKeyValues(&dictionary);
149 if (error != HWC3::Error::None) {
150 ALOGE("%s: failed to load pmem json", __FUNCTION__);
151 return error;
152 }
153
154 dictionary[key] = value;
155
156 error = savePersistentKeyValues(dictionary);
157 if (error != HWC3::Error::None) {
158 ALOGE("%s: failed to save pmem json", __FUNCTION__);
159 return error;
160 }
161
162 return HWC3::Error::None;
163 }
164
persistentKeyValueEnabled() const165 bool Device::persistentKeyValueEnabled() const { return !getPmemPath().empty(); }
166 } // namespace aidl::android::hardware::graphics::composer3::impl
167