HalGroup.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Copyright (C) 2017 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. #ifndef ANDROID_VINTF_HAL_GROUP_H
  17. #define ANDROID_VINTF_HAL_GROUP_H
  18. #include <map>
  19. #include <set>
  20. #include "MapValueIterator.h"
  21. #include "Version.h"
  22. namespace android {
  23. namespace vintf {
  24. // A HalGroup is a wrapped multimap from name to Hal.
  25. // Hal.getName() must return a string indicating the name.
  26. template <typename Hal>
  27. struct HalGroup {
  28. using InstanceType = typename Hal::InstanceType;
  29. public:
  30. virtual ~HalGroup() {}
  31. // Move all hals from another HalGroup to this.
  32. bool addAllHals(HalGroup* other, std::string* error = nullptr) {
  33. for (auto& pair : other->mHals) {
  34. if (!add(std::move(pair.second))) {
  35. if (error) {
  36. *error = "HAL \"" + pair.first + "\" has a conflict.";
  37. }
  38. return false;
  39. }
  40. }
  41. other->mHals.clear();
  42. return true;
  43. }
  44. // Add an hal to this HalGroup so that it can be constructed programatically.
  45. virtual bool add(Hal&& hal) { return addInternal(std::move(hal)) != nullptr; }
  46. protected:
  47. // Get all hals with the given name (e.g "android.hardware.camera").
  48. // There could be multiple hals that matches the same given name.
  49. std::vector<const Hal*> getHals(const std::string& name) const {
  50. std::vector<const Hal*> ret;
  51. auto range = mHals.equal_range(name);
  52. for (auto it = range.first; it != range.second; ++it) {
  53. ret.push_back(&it->second);
  54. }
  55. return ret;
  56. }
  57. // Get all hals with the given name (e.g "android.hardware.camera").
  58. // There could be multiple hals that matches the same given name.
  59. // Non-const version of the above getHals() method.
  60. std::vector<Hal*> getHals(const std::string& name) {
  61. std::vector<Hal*> ret;
  62. auto range = mHals.equal_range(name);
  63. for (auto it = range.first; it != range.second; ++it) {
  64. ret.push_back(&it->second);
  65. }
  66. return ret;
  67. }
  68. public:
  69. // Apply func to all instances.
  70. bool forEachInstance(const std::function<bool(const InstanceType&)>& func) const {
  71. for (const auto& hal : getHals()) {
  72. bool cont = hal.forEachInstance(func);
  73. if (!cont) return false;
  74. }
  75. return true;
  76. }
  77. bool forEachInstanceOfPackage(const std::string& package,
  78. const std::function<bool(const InstanceType&)>& func) const {
  79. for (const auto* hal : getHals(package)) {
  80. if (!hal->forEachInstance(func)) {
  81. return false;
  82. }
  83. }
  84. return true;
  85. }
  86. // Apply func to all instances of package@expectVersion::*/*.
  87. // For example, if [email protected]::IFoo/default is in "this" and getFqInstances
  88. // is called with [email protected], then [email protected]::IFoo/default is returned.
  89. virtual bool forEachInstanceOfVersion(
  90. const std::string& package, const Version& expectVersion,
  91. const std::function<bool(const InstanceType&)>& func) const = 0;
  92. // Apply func to instances of package@expectVersion::interface/*.
  93. // For example, if [email protected]::IFoo/default is in "this" and getFqInstances
  94. // is called with [email protected]::IFoo, then [email protected]::IFoo/default is returned.
  95. bool forEachInstanceOfInterface(const std::string& package, const Version& expectVersion,
  96. const std::string& interface,
  97. const std::function<bool(const InstanceType&)>& func) const {
  98. return forEachInstanceOfVersion(package, expectVersion,
  99. [&func, &interface](const InstanceType& e) {
  100. if (e.interface() == interface) {
  101. return func(e);
  102. }
  103. return true;
  104. });
  105. }
  106. // Alternative to forEachInstanceOfInterface if you need a vector instead.
  107. // If interface is empty, returns all instances of package@version;
  108. // else return all instances of package@version::interface.
  109. std::vector<InstanceType> getFqInstances(const std::string& package,
  110. const Version& expectVersion,
  111. const std::string& interface = "") const {
  112. std::vector<InstanceType> v;
  113. auto mapToVector = [&v](const auto& e) {
  114. v.push_back(e);
  115. return true;
  116. };
  117. if (interface.empty()) {
  118. (void)forEachInstanceOfVersion(package, expectVersion, mapToVector);
  119. } else {
  120. (void)forEachInstanceOfInterface(package, expectVersion, interface, mapToVector);
  121. }
  122. return v;
  123. }
  124. protected:
  125. // sorted map from component name to the component.
  126. // The component name looks like: android.hardware.foo
  127. std::multimap<std::string, Hal> mHals;
  128. // override this to filter for add.
  129. virtual bool shouldAdd(const Hal&) const { return true; }
  130. // Return an iterable to all Hal objects. Call it as follows:
  131. // for (const auto& e : vm.getHals()) { }
  132. ConstMultiMapValueIterable<std::string, Hal> getHals() const { return iterateValues(mHals); }
  133. // Return an iterable to all Hal objects. Call it as follows:
  134. // for (const auto& e : vm.getHals()) { }
  135. MultiMapValueIterable<std::string, Hal> getHals() { return iterateValues(mHals); }
  136. // Get any HAL component based on the component name. Return any one
  137. // if multiple. Return nullptr if the component does not exist. This is only
  138. // for creating objects programatically.
  139. // The component name looks like:
  140. // android.hardware.foo
  141. Hal* getAnyHal(const std::string& name) {
  142. auto it = mHals.find(name);
  143. if (it == mHals.end()) {
  144. return nullptr;
  145. }
  146. return &(it->second);
  147. }
  148. Hal* addInternal(Hal&& hal) {
  149. if (!shouldAdd(hal)) {
  150. return nullptr;
  151. }
  152. std::string name = hal.getName();
  153. auto it = mHals.emplace(std::move(name), std::move(hal)); // always succeeds
  154. return &it->second;
  155. }
  156. };
  157. } // namespace vintf
  158. } // namespace android
  159. #endif // ANDROID_VINTF_HAL_GROUP_H