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 #ifndef DISPLAY_COLOR_LOADER_H
18 #define DISPLAY_COLOR_LOADER_H
19 
20 #include <dlfcn.h>
21 #include <log/log.h>
22 #include <string>
23 #include <vector>
24 
25 template <typename GsInterfaceType, const char *entry>
26 class DisplayColorLoader {
27     static_assert(entry != nullptr);
28     public:
29       DisplayColorLoader(const DisplayColorLoader &) = delete;
30       DisplayColorLoader& operator=(const DisplayColorLoader &) = delete;
31 
DisplayColorLoader(const std::string & libName)32       DisplayColorLoader(const std::string &libName) {
33           libHandle = dlopen(libName.c_str(), RTLD_LAZY);
34 
35           if (libHandle == nullptr) {
36               ALOGE("%s: failed to load library %s\n", __func__, libName.c_str());
37               getDisplayColor = nullptr;
38               return;
39           }
40 
41           const displaycolor::DisplayColorIntfVer *(*getVersion)();
42           getVersion = reinterpret_cast<decltype(getVersion)>(dlsym(libHandle, "GetInterfaceVersion"));
43           if (getVersion == nullptr) {
44               ALOGE("%s: prebuilt lib is not versioned", __func__);
45               return;
46           }
47 
48           auto intfVer = getVersion();
49 
50           if (intfVer != nullptr &&
51               displaycolor::kInterfaceVersion.Compatible(*intfVer)) {
52               getDisplayColor = reinterpret_cast<decltype(getDisplayColor)>(dlsym(libHandle, entry));
53 
54               if (getDisplayColor == nullptr) {
55                   ALOGE("%s: failed to get %s\n", __func__, entry);
56               } else if (!(displaycolor::kInterfaceVersion == *intfVer)) {
57                   ALOGW("%s: different hwc/displaycolor patch level %u.%u.%u vs .%u",
58                         __func__,
59                         intfVer->major,
60                         intfVer->minor,
61                         displaycolor::kInterfaceVersion.patch,
62                         intfVer->patch);
63               }
64           } else {
65               if (intfVer != nullptr) {
66                   ALOGE("%s: prebuilt lib version %u.%u.%u expected %u.%u.%u",
67                         __func__,
68                         intfVer->major,
69                         intfVer->minor,
70                         intfVer->patch,
71                         displaycolor::kInterfaceVersion.major,
72                         displaycolor::kInterfaceVersion.minor,
73                         displaycolor::kInterfaceVersion.patch);
74               } else {
75                   ALOGE("%s: prebult lib getVersion returns null", __func__);
76               }
77           }
78       }
79 
GetDisplayColor(const std::vector<displaycolor::DisplayInfo> & display_info)80       GsInterfaceType *GetDisplayColor(
81               const std::vector<displaycolor::DisplayInfo> &display_info) {
82           if (getDisplayColor != nullptr) {
83               return getDisplayColor(display_info);
84           }
85 
86           return nullptr;
87       }
88 
~DisplayColorLoader()89       ~DisplayColorLoader() {
90           if (libHandle != nullptr) {
91               dlclose(libHandle);
92           }
93       }
94 
95     private:
96       void *libHandle;
97       GsInterfaceType *(*getDisplayColor)(const std::vector<displaycolor::DisplayInfo> &);
98 };
99 
100 #endif //DISPLAY_COLOR_LOADER_H
101