1 /*
2 * Copyright (C) 2016 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 #include <string>
18
19 #include <android-base/logging.h>
20 #include <cutils/properties.h>
21
22 #include "wifi_feature_flags.h"
23
24 namespace android {
25 namespace hardware {
26 namespace wifi {
27 namespace V1_5 {
28 namespace implementation {
29 namespace feature_flags {
30
31 using V1_0::ChipModeId;
32 using V1_0::IfaceType;
33 using V1_0::IWifiChip;
34
35 /* The chip may either have a single mode supporting any number of combinations,
36 * or a fixed dual-mode (so it involves firmware loading to switch between
37 * modes) setting. If there is a need to support more modes, it needs to be
38 * implemented manually in WiFi HAL (see changeFirmwareMode in
39 * WifiChip::handleChipConfiguration).
40 *
41 * Supported combinations are defined in device's makefile, for example:
42 * WIFI_HAL_INTERFACE_COMBINATIONS := {{{STA, AP}, 1}, {{P2P, NAN}, 1}},
43 * WIFI_HAL_INTERFACE_COMBINATIONS += {{{STA}, 1}, {{AP}, 2}}
44 * What means:
45 * Interface combination 1: 1 STA or AP and 1 P2P or NAN concurrent iface
46 * operations.
47 * Interface combination 2: 1 STA and 2 AP concurrent iface operations.
48 *
49 * For backward compatibility, the following makefile flags can be used to
50 * generate combinations list:
51 * - WIFI_HIDL_FEATURE_DUAL_INTERFACE
52 * - WIFI_HIDL_FEATURE_DISABLE_AP
53 * - WIFI_HIDL_FEATURE_AWARE
54 * However, they are ignored if WIFI_HAL_INTERFACE_COMBINATIONS was provided.
55 * With WIFI_HIDL_FEATURE_DUAL_INTERFACE flag set, there is a single mode with
56 * two interface combinations:
57 * Interface Combination 1: Will support 1 STA and 1 P2P or NAN (optional)
58 * concurrent iface operations.
59 * Interface Combination 2: Will support 1 STA and 1 AP concurrent
60 * iface operations.
61 *
62 * The only dual-mode configuration supported is for alternating STA and AP
63 * mode, that may involve firmware reloading. In such case, there are 2 separate
64 * modes of operation with 1 interface combination each:
65 * Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN (optional)
66 * concurrent iface operations.
67 * Mode 2 (AP mode): Will support 1 AP iface operation.
68 *
69 * If Aware is enabled, the iface combination will be modified to support either
70 * P2P or NAN in place of just P2P.
71 */
72 // clang-format off
73 #ifdef WIFI_HAL_INTERFACE_COMBINATIONS
74 constexpr ChipModeId kMainModeId = chip_mode_ids::kV3;
75 #elif defined(WIFI_HIDL_FEATURE_DUAL_INTERFACE)
76 // former V2 (fixed dual interface) setup expressed as V3
77 constexpr ChipModeId kMainModeId = chip_mode_ids::kV3;
78 # ifdef WIFI_HIDL_FEATURE_DISABLE_AP
79 # ifdef WIFI_HIDL_FEATURE_AWARE
80 // 1 STA + 1 of (P2P or NAN)
81 # define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}}
82 # else
83 // 1 STA + 1 P2P
84 # define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}}
85 # endif
86 # else
87 # ifdef WIFI_HIDL_FEATURE_AWARE
88 // (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
89 # define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
90 {{{STA}, 1}, {{P2P, NAN}, 1}}
91 # else
92 // (1 STA + 1 AP) or (1 STA + 1 P2P)
93 # define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
94 {{{STA}, 1}, {{P2P}, 1}}
95 # endif
96 # endif
97 #else
98 // V1 (fixed single interface, dual-mode chip)
99 constexpr ChipModeId kMainModeId = chip_mode_ids::kV1Sta;
100 # ifdef WIFI_HIDL_FEATURE_AWARE
101 // 1 STA + 1 of (P2P or NAN)
102 # define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}}
103 # else
104 // 1 STA + 1 P2P
105 # define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}}
106 # endif
107
108 # ifndef WIFI_HIDL_FEATURE_DISABLE_AP
109 # define WIFI_HAL_INTERFACE_COMBINATIONS_AP {{{AP}, 1}}
110 # endif
111 #endif
112 // clang-format on
113
114 /**
115 * Helper class to convert a collection of combination limits to a combination.
116 *
117 * The main point here is to simplify the syntax required by
118 * WIFI_HAL_INTERFACE_COMBINATIONS.
119 */
120 struct ChipIfaceCombination
121 : public hidl_vec<IWifiChip::ChipIfaceCombinationLimit> {
ChipIfaceCombinationandroid::hardware::wifi::V1_5::implementation::feature_flags::ChipIfaceCombination122 ChipIfaceCombination(
123 const std::initializer_list<IWifiChip::ChipIfaceCombinationLimit> list)
124 : hidl_vec(list) {}
125
126 operator IWifiChip::ChipIfaceCombination() const { return {*this}; }
127
make_vecandroid::hardware::wifi::V1_5::implementation::feature_flags::ChipIfaceCombination128 static hidl_vec<IWifiChip::ChipIfaceCombination> make_vec(
129 const std::initializer_list<ChipIfaceCombination> list) {
130 return hidl_vec<IWifiChip::ChipIfaceCombination>( //
131 std::begin(list), std::end(list));
132 }
133 };
134
135 #define STA IfaceType::STA
136 #define AP IfaceType::AP
137 #define P2P IfaceType::P2P
138 #define NAN IfaceType::NAN
139 static const std::vector<IWifiChip::ChipMode> kChipModesPrimary{
140 {kMainModeId,
141 ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS})},
142 #ifdef WIFI_HAL_INTERFACE_COMBINATIONS_AP
143 {chip_mode_ids::kV1Ap,
144 ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_AP})},
145 #endif
146 };
147
148 static const std::vector<IWifiChip::ChipMode> kChipModesSecondary{
149 #ifdef WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP
150 {chip_mode_ids::kV3, ChipIfaceCombination::make_vec(
151 {WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP})},
152 #endif
153 };
154
155 constexpr char kDebugPresetInterfaceCombinationIdxProperty[] =
156 "persist.vendor.debug.wifi.hal.preset_interface_combination_idx";
157 // List of pre-defined interface combinations that can be enabled at runtime via
158 // setting the property: "kDebugPresetInterfaceCombinationIdxProperty" to the
159 // corresponding index value.
160 static const std::vector<
161 std::pair<std::string, std::vector<IWifiChip::ChipMode>>>
162 kDebugChipModes{
163 // Legacy combination - No STA/AP concurrencies.
164 // 0 - (1 AP) or (1 STA + 1 of (P2P or NAN))
165 {"No STA/AP Concurrency",
166 {{kMainModeId,
167 ChipIfaceCombination::make_vec(
168 {{{{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
169
170 // STA + AP concurrency
171 // 1 - (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
172 {"STA + AP Concurrency",
173 {{kMainModeId,
174 ChipIfaceCombination::make_vec(
175 {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
176
177 // STA + STA concurrency
178 // 2 - (1 STA + 1 AP) or (2 STA + 1 of (P2P or NAN))
179 {"Dual STA Concurrency",
180 {{kMainModeId,
181 ChipIfaceCombination::make_vec(
182 {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}},
183
184 // AP + AP + STA concurrency
185 // 3 - (1 STA + 2 AP) or (1 STA + 1 of (P2P or NAN))
186 {"Dual AP Concurrency",
187 {{kMainModeId,
188 ChipIfaceCombination::make_vec(
189 {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
190
191 // STA + STA concurrency and AP + AP + STA concurrency
192 // 4 - (1 STA + 2 AP) or (2 STA + 1 of (P2P or NAN))
193 {"Dual STA & Dual AP Concurrency",
194 {{kMainModeId,
195 ChipIfaceCombination::make_vec(
196 {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}}};
197
198 #undef STA
199 #undef AP
200 #undef P2P
201 #undef NAN
202
203 #ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
204 #pragma message \
205 "WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION is deprecated; override " \
206 "'config_wifi_ap_randomization_supported' in " \
207 "frameworks/base/core/res/res/values/config.xml in the device overlay " \
208 "instead"
209 #endif // WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
210
WifiFeatureFlags()211 WifiFeatureFlags::WifiFeatureFlags() {}
212
getChipModesForPrimary()213 std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModesForPrimary() {
214 std::array<char, PROPERTY_VALUE_MAX> buffer;
215 auto res = property_get(kDebugPresetInterfaceCombinationIdxProperty,
216 buffer.data(), nullptr);
217 // Debug propety not set, use the device preset interface combination.
218 if (res <= 0) return kChipModesPrimary;
219
220 // Debug propety set, use one of the debug preset interface combination.
221 unsigned long idx = std::stoul(buffer.data());
222 if (idx >= kDebugChipModes.size()) {
223 LOG(ERROR) << "Invalid index set in property: "
224 << kDebugPresetInterfaceCombinationIdxProperty;
225 return kChipModesPrimary;
226 }
227 std::string name;
228 std::vector<IWifiChip::ChipMode> chip_modes;
229 std::tie(name, chip_modes) = kDebugChipModes[idx];
230 LOG(INFO) << "Using debug chip mode: <" << name << "> set via property: "
231 << kDebugPresetInterfaceCombinationIdxProperty;
232 return chip_modes;
233 }
234
getChipModes(bool is_primary)235 std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModes(
236 bool is_primary) {
237 return (is_primary) ? getChipModesForPrimary() : kChipModesSecondary;
238 }
239
240 } // namespace feature_flags
241 } // namespace implementation
242 } // namespace V1_5
243 } // namespace wifi
244 } // namespace hardware
245 } // namespace android
246