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 #pragma once
18 
19 #include <android-base/logging.h>
20 #include <cstdint>
21 #include <iostream>
22 #include <map>
23 #include <optional>
24 #include <sstream>
25 #include <string>
26 #include <variant>
27 #include <vector>
28 
29 namespace aidl::android::hardware::biometrics {
30 
31 using OptBool = std::optional<bool>;
32 using OptInt32 = std::optional<std::int32_t>;
33 using OptInt64 = std::optional<std::int64_t>;
34 using OptString = std::optional<std::string>;
35 using OptIntVec = std::vector<std::optional<std::int32_t>>;
36 
37 using ConfigValue = std::variant<OptBool, OptInt32, OptInt64, OptString, OptIntVec>;
38 
39 class Config {
40   public:
41     struct Data {
42         std::string name;
43         ConfigValue (*getter)();
44         bool (*setter)(const ConfigValue&);
45         ConfigValue (Config::*parser)(const std::string&);
46         std::string defaultValue;
47         ConfigValue value;
48     };
49     enum class ConfigSourceType { SOURCE_SYSPROP, SOURCE_AIDL, SOURCE_FILE };
50 
51   public:
52     Config();
53     virtual ~Config() = default;
54 
55     template <typename T>
get(const std::string & name)56     T get(const std::string& name) {
57         CHECK(mMap.count(name) > 0) << " biometric/config get invalid name: " << name;
58         std::optional<T> optval = std::get<std::optional<T>>(getInternal(name));
59         if (!optval) optval = std::get<std::optional<T>>(getDefault(name));
60         if (optval) return optval.value();
61         return T();
62     }
63     template <typename T>
set(const std::string & name,const T & val)64     bool set(const std::string& name, const T& val) {
65         CHECK(mMap.count(name) > 0) << " biometric/config set invalid name: " << name;
66         std::optional<T> aval(val);
67         ConfigValue cval(aval);
68         return setInternal(name, cval);
69     }
70     template <typename T>
getopt(const std::string & name)71     T getopt(const std::string& name) {
72         CHECK(mMap.count(name) > 0) << " biometric/config get invalid name: " << name;
73         return std::get<T>(getInternal(name));
74     }
75     template <typename T>
setopt(const std::string & name,const T & val)76     bool setopt(const std::string& name, const T& val) {
77         CHECK(mMap.count(name) > 0) << " biometric/config set invalid name: " << name;
78         ConfigValue cval(val);
79         return setInternal(name, cval);
80     }
81 
82     void init();
83 
84     virtual Config::Data* getConfigData(int* size) = 0;
85     bool setParam(const std::string& name, const std::string& value);
86 
sourcedFromAidl()87     void sourcedFromAidl() { mSource = ConfigSourceType::SOURCE_AIDL; }
toString(const ConfigValue & v)88     std::string toString(const ConfigValue& v) const {
89         std::ostringstream os;
90         if (std::holds_alternative<OptInt32>(v)) {
91             OptInt32 ov = std::get<OptInt32>(v);
92             if (ov.has_value()) os << ov.value();
93         } else if (std::holds_alternative<OptInt64>(v)) {
94             OptInt64 ov = std::get<OptInt64>(v);
95             if (ov.has_value()) os << ov.value();
96         } else if (std::holds_alternative<OptBool>(v)) {
97             OptBool ov = std::get<OptBool>(v);
98             if (ov.has_value()) os << ov.value();
99             os << std::get<OptBool>(v).value();
100         } else if (std::holds_alternative<OptIntVec>(v)) {
101             for (auto x : std::get<OptIntVec>(v))
102                 if (x.has_value()) os << x.value() << " ";
103         }
104         return os.str();
105     }
toString()106     std::string toString() const {
107         std::ostringstream os;
108         for (auto const& [k, v] : mMap) {
109             os << k << ":" << toString(v.value) << std::endl;
110         }
111         return os.str();
112     }
113 
114     ConfigValue parseBool(const std::string& value);
115     ConfigValue parseString(const std::string& name);
116     ConfigValue parseInt32(const std::string& value);
117     ConfigValue parseInt64(const std::string& value);
118     ConfigValue parseIntVec(const std::string& value);
119 
120   protected:
setConfig(const std::string & name,const Config::Data & value)121     void setConfig(const std::string& name, const Config::Data& value) { mMap[name] = value; }
122 
123   private:
124     ConfigValue getInternal(const std::string& name);
125     bool setInternal(const std::string& name, const ConfigValue& val);
126     ConfigValue getDefault(const std::string& name);
127 
128     Config::ConfigSourceType mSource;
129     std::map<std::string, Config::Data> mMap;
130 };
131 
132 }  // namespace aidl::android::hardware::biometrics
133