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