1 /*
2  * Copyright (C) 2024 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 "FileNode.h"
18 
19 #include <log/log.h>
20 #include <sstream>
21 
22 namespace android {
23 
24 ANDROID_SINGLETON_STATIC_INSTANCE(hardware::graphics::composer::FileNodeManager);
25 
26 namespace hardware::graphics::composer {
27 
FileNode(const std::string & nodePath)28 FileNode::FileNode(const std::string& nodePath) : mNodePath(nodePath) {}
29 
~FileNode()30 FileNode::~FileNode() {
31     for (auto& fd : mFds) {
32         close(fd.second);
33     }
34 }
35 
dump()36 std::string FileNode::dump() {
37     std::ostringstream os;
38     os << "FileNode: root path: " << mNodePath << std::endl;
39     for (const auto& item : mFds) {
40         auto lastWrittenValue = getLastWrittenValue(item.first);
41         os << "FileNode: sysfs node = " << item.first << ", last written value = 0x" << std::setw(8)
42            << std::setfill('0') << std::hex << lastWrittenValue << std::endl;
43     }
44     return os.str();
45 }
46 
getLastWrittenValue(const std::string & nodeName)47 uint32_t FileNode::getLastWrittenValue(const std::string& nodeName) {
48     int fd = getFileHandler(nodeName);
49     if ((fd < 0) || (mLastWrittenValue.count(fd) <= 0)) return 0;
50     return mLastWrittenValue[fd];
51 }
52 
readString(const std::string & nodeName)53 std::optional<std::string> FileNode::readString(const std::string& nodeName) {
54     std::string fullPath = mNodePath + nodeName;
55     std::ifstream ifs(fullPath);
56     if (ifs) {
57         std::ostringstream os;
58         os << ifs.rdbuf(); // reading data
59         return os.str();
60     }
61     return std::nullopt;
62 }
63 
WriteUint32(const std::string & nodeName,uint32_t value)64 bool FileNode::WriteUint32(const std::string& nodeName, uint32_t value) {
65     int fd = getFileHandler(nodeName);
66     if (fd >= 0) {
67         std::string cmdString = std::to_string(value);
68         int ret = write(fd, cmdString.c_str(), std::strlen(cmdString.c_str()));
69         if (ret < 0) {
70             ALOGE("Write 0x%x to file node %s%s failed, ret = %d errno = %d", value,
71                   mNodePath.c_str(), nodeName.c_str(), ret, errno);
72             return false;
73         }
74     } else {
75         ALOGE("Write to invalid file node %s%s", mNodePath.c_str(), nodeName.c_str());
76         return false;
77     }
78     mLastWrittenValue[fd] = value;
79     return true;
80 }
81 
getFileHandler(const std::string & nodeName)82 int FileNode::getFileHandler(const std::string& nodeName) {
83     if (mFds.count(nodeName) > 0) {
84         return mFds[nodeName];
85     }
86     std::string fullPath = mNodePath + nodeName;
87     int fd = open(fullPath.c_str(), O_WRONLY, 0);
88     if (fd < 0) {
89         ALOGE("Open file node %s failed, fd = %d", fullPath.c_str(), fd);
90         return fd;
91     }
92     mFds[nodeName] = fd;
93     return fd;
94 }
95 
96 }; // namespace hardware::graphics::composer
97 }; // namespace android
98