HardwareBase.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * Copyright (C) 2019 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. #pragma once
  17. #include <list>
  18. #include <map>
  19. #include <sstream>
  20. #include <string>
  21. #include <android-base/unique_fd.h>
  22. #include <log/log.h>
  23. #include <sys/epoll.h>
  24. #include <utils/Trace.h>
  25. #include "utils.h"
  26. namespace aidl {
  27. namespace android {
  28. namespace hardware {
  29. namespace vibrator {
  30. using ::android::base::unique_fd;
  31. class HwApiBase {
  32. private:
  33. using NamesMap = std::map<const std::ios *, std::string>;
  34. class RecordInterface {
  35. public:
  36. virtual std::string toString(const NamesMap &names) = 0;
  37. virtual ~RecordInterface() {}
  38. };
  39. template <typename T>
  40. class Record : public RecordInterface {
  41. public:
  42. Record(const char *func, const T &value, const std::ios *stream)
  43. : mFunc(func), mValue(value), mStream(stream) {}
  44. std::string toString(const NamesMap &names) override;
  45. private:
  46. const char *mFunc;
  47. const T mValue;
  48. const std::ios *mStream;
  49. };
  50. using Records = std::list<std::unique_ptr<RecordInterface>>;
  51. static constexpr uint32_t RECORDS_SIZE = 32;
  52. public:
  53. HwApiBase();
  54. void debug(int fd);
  55. protected:
  56. void saveName(const std::string &name, const std::ios *stream);
  57. template <typename T>
  58. void open(const std::string &name, T *stream);
  59. bool has(const std::ios &stream);
  60. template <typename T>
  61. bool get(T *value, std::istream *stream);
  62. template <typename T>
  63. bool set(const T &value, std::ostream *stream);
  64. template <typename T>
  65. bool poll(const T &value, std::istream *stream, const int32_t timeout = -1);
  66. template <typename T>
  67. void record(const char *func, const T &value, const std::ios *stream);
  68. private:
  69. std::string mPathPrefix;
  70. NamesMap mNames;
  71. Records mRecords{RECORDS_SIZE};
  72. std::mutex mRecordsMutex;
  73. std::mutex mIoMutex;
  74. };
  75. #define HWAPI_RECORD(args...) HwApiBase::record(__FUNCTION__, ##args)
  76. template <typename T>
  77. void HwApiBase::open(const std::string &name, T *stream) {
  78. saveName(name, stream);
  79. utils::openNoCreate(mPathPrefix + name, stream);
  80. }
  81. template <typename T>
  82. bool HwApiBase::get(T *value, std::istream *stream) {
  83. ATRACE_NAME("HwApi::get");
  84. std::scoped_lock ioLock{mIoMutex};
  85. bool ret;
  86. stream->seekg(0);
  87. *stream >> *value;
  88. if (!(ret = !!*stream)) {
  89. ALOGE("Failed to read %s (%d): %s", mNames[stream].c_str(), errno, strerror(errno));
  90. }
  91. stream->clear();
  92. HWAPI_RECORD(*value, stream);
  93. return ret;
  94. }
  95. template <typename T>
  96. bool HwApiBase::set(const T &value, std::ostream *stream) {
  97. ATRACE_NAME("HwApi::set");
  98. using utils::operator<<;
  99. std::scoped_lock ioLock{mIoMutex};
  100. bool ret;
  101. *stream << value << std::endl;
  102. if (!(ret = !!*stream)) {
  103. ALOGE("Failed to write %s (%d): %s", mNames[stream].c_str(), errno, strerror(errno));
  104. stream->clear();
  105. }
  106. HWAPI_RECORD(value, stream);
  107. return ret;
  108. }
  109. template <typename T>
  110. bool HwApiBase::poll(const T &value, std::istream *stream, const int32_t timeoutMs) {
  111. ATRACE_NAME("HwApi::poll");
  112. auto path = mPathPrefix + mNames[stream];
  113. unique_fd fileFd{::open(path.c_str(), O_RDONLY)};
  114. unique_fd epollFd{epoll_create(1)};
  115. epoll_event event = {
  116. .events = EPOLLPRI | EPOLLET,
  117. };
  118. T actual;
  119. bool ret;
  120. int epollRet;
  121. if (timeoutMs < -1) {
  122. ALOGE("Invalid polling timeout!");
  123. return false;
  124. }
  125. if (epoll_ctl(epollFd, EPOLL_CTL_ADD, fileFd, &event)) {
  126. ALOGE("Failed to poll %s (%d): %s", mNames[stream].c_str(), errno, strerror(errno));
  127. return false;
  128. }
  129. while ((ret = get(&actual, stream)) && (actual != value)) {
  130. epollRet = epoll_wait(epollFd, &event, 1, timeoutMs);
  131. if (epollRet <= 0) {
  132. ALOGE("Polling error or timeout! (%d)", epollRet);
  133. return false;
  134. }
  135. }
  136. HWAPI_RECORD(value, stream);
  137. return ret;
  138. }
  139. template <typename T>
  140. void HwApiBase::record(const char *func, const T &value, const std::ios *stream) {
  141. std::lock_guard<std::mutex> lock(mRecordsMutex);
  142. mRecords.emplace_back(std::make_unique<Record<T>>(func, value, stream));
  143. mRecords.pop_front();
  144. }
  145. template <typename T>
  146. std::string HwApiBase::Record<T>::toString(const NamesMap &names) {
  147. using utils::operator<<;
  148. std::stringstream ret;
  149. ret << mFunc << " '" << names.at(mStream) << "' = '" << mValue << "'";
  150. return ret.str();
  151. }
  152. class HwCalBase {
  153. public:
  154. HwCalBase();
  155. void debug(int fd);
  156. protected:
  157. template <typename T>
  158. bool getProperty(const char *key, T *value, const T defval);
  159. template <typename T>
  160. bool getPersist(const char *key, T *value);
  161. private:
  162. std::string mPropertyPrefix;
  163. std::map<std::string, std::string> mCalData;
  164. };
  165. template <typename T>
  166. bool HwCalBase::getProperty(const char *key, T *outval, const T defval) {
  167. ATRACE_NAME("HwCal::getProperty");
  168. *outval = utils::getProperty(mPropertyPrefix + key, defval);
  169. return true;
  170. }
  171. template <typename T>
  172. bool HwCalBase::getPersist(const char *key, T *value) {
  173. ATRACE_NAME("HwCal::getPersist");
  174. auto it = mCalData.find(key);
  175. if (it == mCalData.end()) {
  176. ALOGE("Missing %s config!", key);
  177. return false;
  178. }
  179. std::stringstream stream{it->second};
  180. utils::unpack(stream, value);
  181. if (!stream || !stream.eof()) {
  182. ALOGE("Invalid %s config!", key);
  183. return false;
  184. }
  185. return true;
  186. }
  187. } // namespace vibrator
  188. } // namespace hardware
  189. } // namespace android
  190. } // namespace aidl