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