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