/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wifi.hal; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.hardware.wifi.WifiStatusCode; import android.net.wifi.CoexUnsafeChannel; import android.net.wifi.OuiKeyedData; import android.net.wifi.WifiAvailableChannel; import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; import android.util.Log; import com.android.server.wifi.SarInfo; import com.android.server.wifi.SsidTranslator; import com.android.server.wifi.WifiNative; import com.android.server.wifi.WlanWakeReasonAndCounts; import com.android.server.wifi.util.GeneralUtil.Mutable; import com.android.server.wifi.util.NativeUtil; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.function.Supplier; /** * Wrapper around a WifiChip. * May be initialized using a HIDL or AIDL WifiChip. */ public class WifiChip { public static final String TAG = "WifiChip"; private IWifiChip mWifiChip; /** * Interface concurrency types used in reporting device concurrency capabilities. */ public static final int IFACE_CONCURRENCY_TYPE_STA = 0; public static final int IFACE_CONCURRENCY_TYPE_AP = 1; public static final int IFACE_CONCURRENCY_TYPE_AP_BRIDGED = 2; public static final int IFACE_CONCURRENCY_TYPE_P2P = 3; public static final int IFACE_CONCURRENCY_TYPE_NAN = 4; @IntDef(prefix = { "IFACE_CONCURRENCY_TYPE_" }, value = { IFACE_CONCURRENCY_TYPE_STA, IFACE_CONCURRENCY_TYPE_AP, IFACE_CONCURRENCY_TYPE_AP_BRIDGED, IFACE_CONCURRENCY_TYPE_P2P, IFACE_CONCURRENCY_TYPE_NAN, }) @Retention(RetentionPolicy.SOURCE) public @interface IfaceConcurrencyType {} /** * Supported interface types. */ public static final int IFACE_TYPE_STA = 0; public static final int IFACE_TYPE_AP = 1; public static final int IFACE_TYPE_P2P = 2; public static final int IFACE_TYPE_NAN = 3; @IntDef(prefix = { "IFACE_TYPE_" }, value = { IFACE_TYPE_STA, IFACE_TYPE_AP, IFACE_TYPE_P2P, IFACE_TYPE_NAN, }) @Retention(RetentionPolicy.SOURCE) public @interface IfaceType {} /** * Antenna configurations. */ public static final int WIFI_ANTENNA_MODE_UNSPECIFIED = 0; public static final int WIFI_ANTENNA_MODE_1X1 = 1; public static final int WIFI_ANTENNA_MODE_2X2 = 2; public static final int WIFI_ANTENNA_MODE_3X3 = 3; public static final int WIFI_ANTENNA_MODE_4X4 = 4; @IntDef(prefix = { "WIFI_ANTENNA_MODE_" }, value = { WIFI_ANTENNA_MODE_UNSPECIFIED, WIFI_ANTENNA_MODE_1X1, WIFI_ANTENNA_MODE_2X2, WIFI_ANTENNA_MODE_3X3, WIFI_ANTENNA_MODE_4X4, }) @Retention(RetentionPolicy.SOURCE) public @interface WifiAntennaMode {} /** * Supported VoIP mode. */ public static final int WIFI_VOIP_MODE_OFF = 0; public static final int WIFI_VOIP_MODE_VOICE = 1; @IntDef(prefix = { "WIFI_VOIP_MODE_" }, value = { WIFI_VOIP_MODE_OFF, WIFI_VOIP_MODE_VOICE, }) @Retention(RetentionPolicy.SOURCE) public @interface WifiVoipMode {} /** * Response containing a value and a status code. * * @param Type of value that should be returned. */ public static class Response { private Mutable mMutable; private int mStatusCode; public Response(T initialValue) { mMutable = new Mutable<>(initialValue); mStatusCode = WifiHal.WIFI_STATUS_ERROR_UNKNOWN; } public void setValue(T value) { mMutable.value = value; } public T getValue() { return mMutable.value; } public void setStatusCode(@WifiHal.WifiStatusCode int statusCode) { mStatusCode = statusCode; } public @WifiHal.WifiStatusCode int getStatusCode() { return mStatusCode; } } /** * Set of interface concurrency types, along with the maximum number of interfaces that can have * one of the specified concurrency types for a given ChipConcurrencyCombination. See * ChipConcurrencyCombination below for examples. */ public static class ChipConcurrencyCombinationLimit { public final int maxIfaces; public final @IfaceConcurrencyType List types; public ChipConcurrencyCombinationLimit(int inMaxIfaces, @IfaceConcurrencyType List inTypes) { maxIfaces = inMaxIfaces; types = inTypes; } @Override public String toString() { return "{maxIfaces=" + maxIfaces + ", types=" + types + "}"; } } /** * Set of interfaces that can operate concurrently when in a given mode. * * For example: * [{STA} <= 2] * At most two STA interfaces are supported * [], [STA], [STA+STA] * * [{STA} <= 1, {NAN} <= 1, {AP_BRIDGED} <= 1] * Any combination of STA, NAN, AP_BRIDGED * [], [STA], [NAN], [AP_BRIDGED], [STA+NAN], [STA+AP_BRIDGED], [NAN+AP_BRIDGED], * [STA+NAN+AP_BRIDGED] * * [{STA} <= 1, {NAN,P2P} <= 1] * Optionally a STA and either NAN or P2P * [], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P] * Not included [NAN+P2P], [STA+NAN+P2P] * * [{STA} <= 1, {STA,NAN} <= 1] * Optionally a STA and either a second STA or a NAN * [], [STA], [STA+NAN], [STA+STA], [NAN] * Not included [STA+STA+NAN] */ public static class ChipConcurrencyCombination { public final List limits; public ChipConcurrencyCombination(List inLimits) { limits = inLimits; } @Override public String toString() { return "{limits=" + limits + "}"; } } /** * A mode that the chip can be put in. A mode defines a set of constraints on * the interfaces that can exist while in that mode. Modes define a unit of * configuration where all interfaces must be torn down to switch to a * different mode. Some HALs may only have a single mode, but an example where * multiple modes would be required is if a chip has different firmwares with * different capabilities. * * When in a mode, it must be possible to perform any combination of creating * and removing interfaces as long as at least one of the * ChipConcurrencyCombinations is satisfied. This means that if a chip has two * available combinations, [{STA} <= 1] and [{AP_BRIDGED} <= 1] then it is expected * that exactly one STA type or one AP_BRIDGED type can be created, but it * is not expected that both a STA and AP_BRIDGED type could be created. If it * was then there would be a single available combination * [{STA} <=1, {AP_BRIDGED} <= 1]. * * When switching between two available combinations it is expected that * interfaces only supported by the initial combination must be removed until * the target combination is also satisfied. At that point new interfaces * satisfying only the target combination can be added (meaning the initial * combination limits will no longer satisfied). The addition of these new * interfaces must not impact the existence of interfaces that satisfy both * combinations. * * For example, a chip with available combinations: * [{STA} <= 2, {NAN} <=1] and [{STA} <=1, {NAN} <= 1, {AP_BRIDGED} <= 1}] * If the chip currently has 3 interfaces STA, STA and NAN and wants to add an * AP_BRIDGED interface in place of one of the STAs, then one of the STA interfaces * must be removed first, and then the AP interface can be created after * the STA has been torn down. During this process the remaining STA and NAN * interfaces must not be removed/recreated. * * If a chip does not support this kind of reconfiguration in this mode then * the combinations must be separated into two separate modes. Before * switching modes, all interfaces must be torn down, the mode switch must be * enacted, and when it completes the new interfaces must be brought up. */ public static class ChipMode { public final int id; public final List availableCombinations; public ChipMode(int inId, List inAvailableCombinations) { id = inId; availableCombinations = inAvailableCombinations; } @Override public String toString() { return "{id=" + id + ", availableCombinations=" + availableCombinations + "}"; } } /** * Wifi radio configuration. */ public static class WifiRadioConfiguration { public final @WifiScanner.WifiBand int bandInfo; public final @WifiAntennaMode int antennaMode; public WifiRadioConfiguration(int inBandInfo, int inAntennaMode) { bandInfo = inBandInfo; antennaMode = inAntennaMode; } @Override public String toString() { return "{bandInfo=" + bandInfo + ", antennaMode=" + antennaMode + "}"; } } /** * Wifi radio combination. */ public static class WifiRadioCombination { public final List radioConfigurations; public WifiRadioCombination(List inRadioConfigurations) { radioConfigurations = inRadioConfigurations; } @Override public String toString() { return "{radioConfigurations=" + radioConfigurations + "}"; } } /** * AFC channel allowance. */ public static class AfcChannelAllowance { /** * AFC max permissible information queried from AFC server based on frequency. */ public List availableAfcFrequencyInfos; /** * AFC max permissible information queried from AFC server based on channel number. */ public List availableAfcChannelInfos; /** * The time in UTC at which this information expires, as the difference, measured in * milliseconds, between the expiration time and midnight, January 1, 1970 UTC. */ public long availabilityExpireTimeMs; } /** * Available AFC frequency info. */ public static class AvailableAfcFrequencyInfo { public int startFrequencyMhz = 0; public int endFrequencyMhz = 0; public int maxPsdDbmPerMhz = 0; } /** * Available AFC channel info. */ public static class AvailableAfcChannelInfo { public int globalOperatingClass = 0; public int channelCfi = 0; public int maxEirpDbm = 0; } /** * Wifi Chip capabilities. */ public static class WifiChipCapabilities { /** * Maximum number of links supported by the chip for MLO association. * * Note: This is a static configuration of the chip. */ public final int maxMloAssociationLinkCount; /** * Maximum number of STR links used in Multi-Link Operation. The maximum * number of STR links used for MLO can be different from the number of * radios supported by the chip. * * Note: This is a static configuration of the chip. */ public final int maxMloStrLinkCount; /** * Maximum number of concurrent TDLS sessions that can be enabled * by framework via * {@link android.hardware.wifi.supplicant.ISupplicantStaIface#initiateTdlsSetup(byte[])}. */ public final int maxConcurrentTdlsSessionCount; public WifiChipCapabilities(int maxMloAssociationLinkCount, int maxMloStrLinkCount, int maxConcurrentTdlsSessionCount) { this.maxMloAssociationLinkCount = maxMloAssociationLinkCount; this.maxMloStrLinkCount = maxMloStrLinkCount; this.maxConcurrentTdlsSessionCount = maxConcurrentTdlsSessionCount; } @Override public String toString() { return "{maxMloAssociationLinkCount=" + maxMloAssociationLinkCount + ", maxMloStrLinkCount=" + maxMloStrLinkCount + ", maxConcurrentTdlsSessionCount=" + maxConcurrentTdlsSessionCount + "}"; } } /** * Information about the version of the driver and firmware running this chip. * * The information in these ASCII strings are vendor specific and does not * need to follow any particular format. It may be dumped as part of the bug * report. */ public static class ChipDebugInfo { public final String driverDescription; public final String firmwareDescription; public ChipDebugInfo(String inDriverDescription, String inFirmwareDescription) { driverDescription = inDriverDescription; firmwareDescription = inFirmwareDescription; } } /** * State of an iface operating on the radio chain (hardware MAC) on the device. */ public static class IfaceInfo { public final String name; public final int channel; public IfaceInfo(String inName, int inChannel) { name = inName; channel = inChannel; } } /** * State of a hardware radio chain (hardware MAC) on the device. */ public static class RadioModeInfo { public final int radioId; public final @WifiScanner.WifiBand int bandInfo; public final List ifaceInfos; public RadioModeInfo(int inRadioId, @WifiScanner.WifiBand int inBandInfo, List inIfaceInfos) { radioId = inRadioId; bandInfo = inBandInfo; ifaceInfos = inIfaceInfos; } } /** * Framework callback object. Will get called when the equivalent events are received * from the HAL. */ public interface Callback { /** * Indicates that a chip reconfiguration failed. This is a fatal * error and any iface objects available previously must be considered * invalid. The client can attempt to recover by trying to reconfigure the * chip again using {@link IWifiChip#configureChip(int)}. * * @param status Failure reason code. */ void onChipReconfigureFailure(int status); /** * Indicates that the chip has been reconfigured successfully. At * this point, the interfaces available in the mode must be able to be * configured. When this is called, any previous iface objects must be * considered invalid. * * @param modeId The mode that the chip switched to, corresponding to the id * property of the target ChipMode. */ void onChipReconfigured(int modeId); /** * Indicates that the chip has encountered a fatal error. * Client must not attempt to parse either the errorCode or debugData. * Must only be captured in a bugreport. * * @param errorCode Vendor defined error code. * @param debugData Vendor defined data used for debugging. */ void onDebugErrorAlert(int errorCode, byte[] debugData); /** * Reports debug ring buffer data. * * The ring buffer data collection is event based: * - Driver calls this callback when new records are available, the * |WifiDebugRingBufferStatus| passed up to framework in the callback * indicates to framework if more data is available in the ring buffer. * It is not expected that driver will necessarily always empty the ring * immediately as data is available. Instead the driver will report data * every X seconds, or if N bytes are available, based on the parameters * set via |startLoggingToDebugRingBuffer|. * - In the case where a bug report has to be captured, the framework will * require driver to upload all data immediately. This is indicated to * driver when framework calls |forceDumpToDebugRingBuffer|. The driver * will start sending all available data in the indicated ring by repeatedly * invoking this callback. * * @param status Status of the corresponding ring buffer. This should * contain the name of the ring buffer on which the data is * available. * @param data Raw bytes of data sent by the driver. Must be dumped * out to a bugreport and post processed. */ void onDebugRingBufferDataAvailable(WifiNative.RingBufferStatus status, byte[] data); /** * Indicates that a new iface has been added to the chip. * * @param type Type of iface added. * @param name Name of iface added. */ void onIfaceAdded(@IfaceType int type, String name); /** * Indicates that an existing iface has been removed from the chip. * * @param type Type of iface removed. * @param name Name of iface removed. */ void onIfaceRemoved(@IfaceType int type, String name); /** * Indicates a radio mode change. * Radio mode change could be a result of: * a) Bringing up concurrent interfaces (ex. STA + AP). * b) Change in operating band of one of the concurrent interfaces * (ex. STA connection moved from 2.4G to 5G) * * @param radioModeInfos List of RadioModeInfo structures for each * radio chain (hardware MAC) on the device. */ void onRadioModeChange(List radioModeInfos); } public WifiChip(@NonNull android.hardware.wifi.V1_0.IWifiChip chip, @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { mWifiChip = createWifiChipHidlImplMockable(chip, context, ssidTranslator); } public WifiChip(@NonNull android.hardware.wifi.IWifiChip chip, @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { mWifiChip = createWifiChipAidlImplMockable(chip, context, ssidTranslator); } protected WifiChipHidlImpl createWifiChipHidlImplMockable( @NonNull android.hardware.wifi.V1_0.IWifiChip chip, @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { return new WifiChipHidlImpl(chip, context, ssidTranslator); } protected WifiChipAidlImpl createWifiChipAidlImplMockable( @NonNull android.hardware.wifi.IWifiChip chip, @NonNull Context context, @NonNull SsidTranslator ssidTranslator) { return new WifiChipAidlImpl(chip, context, ssidTranslator); } private T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier supplier) { if (mWifiChip == null) { Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiChip is null"); return defaultVal; } return supplier.get(); } /** * See comments for {@link IWifiChip#configureChip(int)} */ public boolean configureChip(int modeId) { return validateAndCall("configureChip", false, () -> mWifiChip.configureChip(modeId)); } /** * See comments for {@link IWifiChip#createApIface(List)} */ @Nullable public WifiApIface createApIface(@NonNull List vendorData) { if (vendorData == null) { Log.e(TAG, "createApIface received null vendorData"); return null; } return validateAndCall("createApIface", null, () -> mWifiChip.createApIface(vendorData)); } /** * See comments for {@link IWifiChip#createBridgedApIface(List)} */ @Nullable public WifiApIface createBridgedApIface(@NonNull List vendorData) { if (vendorData == null) { Log.e(TAG, "createBridgedApIface received null vendorData"); return null; } return validateAndCall("createBridgedApIface", null, () -> mWifiChip.createBridgedApIface(vendorData)); } /** * See comments for {@link IWifiChip#createNanIface()} */ @Nullable public WifiNanIface createNanIface() { return validateAndCall("createNanIface", null, () -> mWifiChip.createNanIface()); } /** * See comments for {@link IWifiChip#createP2pIface()} */ @Nullable public WifiP2pIface createP2pIface() { return validateAndCall("createP2pIface", null, () -> mWifiChip.createP2pIface()); } /** * See comments for {@link IWifiChip#createRttController()} */ @Nullable public WifiRttController createRttController() { return validateAndCall("createRttController", null, () -> mWifiChip.createRttController()); } /** * See comments for {@link IWifiChip#createStaIface()} */ @Nullable public WifiStaIface createStaIface() { return validateAndCall("createStaIface", null, () -> mWifiChip.createStaIface()); } /** * See comments for {@link IWifiChip#enableDebugErrorAlerts(boolean)} */ public boolean enableDebugErrorAlerts(boolean enable) { return validateAndCall("enableDebugErrorAlerts", false, () -> mWifiChip.enableDebugErrorAlerts(enable)); } /** * See comments for {@link IWifiChip#flushRingBufferToFile()} */ public boolean flushRingBufferToFile() { return validateAndCall("flushRingBufferToFile", false, () -> mWifiChip.flushRingBufferToFile()); } /** * See comments for {@link IWifiChip#forceDumpToDebugRingBuffer(String)} */ public boolean forceDumpToDebugRingBuffer(String ringName) { return validateAndCall("forceDumpToDebugRingBuffer", false, () -> mWifiChip.forceDumpToDebugRingBuffer(ringName)); } /** * See comments for {@link IWifiChip#getApIface(String)} */ @Nullable public WifiApIface getApIface(String ifaceName) { return validateAndCall("getApIface", null, () -> mWifiChip.getApIface(ifaceName)); } /** * See comments for {@link IWifiChip#getApIfaceNames()} */ @Nullable public List getApIfaceNames() { return validateAndCall("getApIfaceNames", null, () -> mWifiChip.getApIfaceNames()); } /** * See comments for {@link IWifiChip#getAvailableModes()} */ @Nullable public List getAvailableModes() { return validateAndCall("getAvailableModes", null, () -> mWifiChip.getAvailableModes()); } /** * See comments for {@link IWifiChip#getCapabilitiesBeforeIfacesExist()} */ public Response getCapabilitiesBeforeIfacesExist() { return validateAndCall("getCapabilitiesBeforeIfacesExist", new Response<>(0L), () -> mWifiChip.getCapabilitiesBeforeIfacesExist()); } /** * See comments for {@link IWifiChip#getCapabilitiesAfterIfacesExist()} */ public Response getCapabilitiesAfterIfacesExist() { return validateAndCall("getCapabilitiesAfterIfacesExist", new Response<>(0L), () -> mWifiChip.getCapabilitiesAfterIfacesExist()); } /** * See comments for {@link IWifiChip#getDebugHostWakeReasonStats()} */ @Nullable public WlanWakeReasonAndCounts getDebugHostWakeReasonStats() { return validateAndCall("getDebugHostWakeReasonStats", null, () -> mWifiChip.getDebugHostWakeReasonStats()); } /** * See comments for {@link IWifiChip#getDebugRingBuffersStatus()} */ @Nullable public List getDebugRingBuffersStatus() { return validateAndCall("getDebugRingBuffersStatus", null, () -> mWifiChip.getDebugRingBuffersStatus()); } /** * See comments for {@link IWifiChip#getId()} */ public int getId() { return validateAndCall("getId", -1, () -> mWifiChip.getId()); } /** * See comments for {@link IWifiChip#getMode()} */ public Response getMode() { return validateAndCall("getMode", new Response<>(0), () -> mWifiChip.getMode()); } /** * See comments for {@link IWifiChip#getNanIface(String)} */ @Nullable public WifiNanIface getNanIface(String ifaceName) { return validateAndCall("getNanIface", null, () -> mWifiChip.getNanIface(ifaceName)); } /** * See comments for {@link IWifiChip#getNanIfaceNames()} */ @Nullable public List getNanIfaceNames() { return validateAndCall("getNanIfaceNames", null, () -> mWifiChip.getNanIfaceNames()); } /** * See comments for {@link IWifiChip#getP2pIface(String)} */ @Nullable public WifiP2pIface getP2pIface(String ifaceName) { return validateAndCall("getP2pIface", null, () -> mWifiChip.getP2pIface(ifaceName)); } /** * See comments for {@link IWifiChip#getP2pIfaceNames()} */ @Nullable public List getP2pIfaceNames() { return validateAndCall("getP2pIfaceNames", null, () -> mWifiChip.getP2pIfaceNames()); } /** * See comments for {@link IWifiChip#getStaIface(String)} */ @Nullable public WifiStaIface getStaIface(String ifaceName) { return validateAndCall("getStaIface", null, () -> mWifiChip.getStaIface(ifaceName)); } /** * See comments for {@link IWifiChip#getStaIfaceNames()} */ @Nullable public List getStaIfaceNames() { return validateAndCall("getStaIfaceNames", null, () -> mWifiChip.getStaIfaceNames()); } /** * See comments for {@link IWifiChip#getSupportedRadioCombinations()} */ @Nullable public List getSupportedRadioCombinations() { return validateAndCall("getSupportedRadioCombinations", null, () -> mWifiChip.getSupportedRadioCombinations()); } /** * See comments for {@link IWifiChip#getWifiChipCapabilities()} */ @Nullable public WifiChipCapabilities getWifiChipCapabilities() { return validateAndCall("getWifiChipCapabilities", null, () -> mWifiChip.getWifiChipCapabilities()); } /** * See comments for {@link IWifiChip#getUsableChannels(int, int, int)} */ @Nullable public List getUsableChannels(@WifiScanner.WifiBand int band, @WifiAvailableChannel.OpMode int mode, @WifiAvailableChannel.Filter int filter) { return validateAndCall("getUsableChannels", null, () -> mWifiChip.getUsableChannels(band, mode, filter)); } /** * See comments for {@link IWifiChip#registerCallback(Callback)} */ public boolean registerCallback(WifiChip.Callback callback) { return validateAndCall("registerCallback", false, () -> mWifiChip.registerCallback(callback)); } /** * See comments for {@link IWifiChip#removeApIface(String)} */ public boolean removeApIface(String ifaceName) { return validateAndCall("removeApIface", false, () -> mWifiChip.removeApIface(ifaceName)); } /** * See comments for {@link IWifiChip#removeIfaceInstanceFromBridgedApIface(String, String)} */ public boolean removeIfaceInstanceFromBridgedApIface(String brIfaceName, String ifaceName) { return validateAndCall("removeIfaceInstanceFromBridgedApIface", false, () -> mWifiChip.removeIfaceInstanceFromBridgedApIface(brIfaceName, ifaceName)); } /** * See comments for {@link IWifiChip#removeNanIface(String)} */ public boolean removeNanIface(String ifaceName) { return validateAndCall("removeNanIface", false, () -> mWifiChip.removeNanIface(ifaceName)); } /** * See comments for {@link IWifiChip#removeP2pIface(String)} */ public boolean removeP2pIface(String ifaceName) { return validateAndCall("removeP2pIface", false, () -> mWifiChip.removeP2pIface(ifaceName)); } /** * See comments for {@link IWifiChip#removeStaIface(String)} */ public boolean removeStaIface(String ifaceName) { return validateAndCall("removeStaIface", false, () -> mWifiChip.removeStaIface(ifaceName)); } /** * See comments for {@link IWifiChip#requestChipDebugInfo()} */ @Nullable public WifiChip.ChipDebugInfo requestChipDebugInfo() { return validateAndCall("requestChipDebugInfo", null, () -> mWifiChip.requestChipDebugInfo()); } /** * See comments for {@link IWifiChip#requestDriverDebugDump()} */ @Nullable public byte[] requestDriverDebugDump() { return validateAndCall("requestDriverDebugDump", null, () -> mWifiChip.requestDriverDebugDump()); } /** * See comments for {@link IWifiChip#requestFirmwareDebugDump()} */ @Nullable public byte[] requestFirmwareDebugDump() { return validateAndCall("requestFirmwareDebugDump", null, () -> mWifiChip.requestFirmwareDebugDump()); } /** * See comments for {@link IWifiChip#selectTxPowerScenario(SarInfo)} */ public boolean selectTxPowerScenario(SarInfo sarInfo) { return validateAndCall("selectTxPowerScenario", false, () -> mWifiChip.selectTxPowerScenario(sarInfo)); } /** * See comments for {@link IWifiChip#setCoexUnsafeChannels(List, int)} */ public boolean setCoexUnsafeChannels(List unsafeChannels, int restrictions) { return validateAndCall("setCoexUnsafeChannels", false, () -> mWifiChip.setCoexUnsafeChannels(unsafeChannels, restrictions)); } /** * See comments for {@link IWifiChip#setCountryCode(byte[])} */ public boolean setCountryCode(String countryCode) { if (countryCode == null || countryCode.length() != 2) { Log.e(TAG, "Invalid country code " + countryCode); return false; } try { final byte[] code = NativeUtil.stringToByteArray(countryCode); return validateAndCall("setCountryCode", false, () -> mWifiChip.setCountryCode(code)); } catch (IllegalArgumentException e) { Log.e(TAG, "Invalid country code " + countryCode + ", error: " + e); return false; } } /** * See comments for {@link IWifiChip#setLowLatencyMode(boolean)} */ public boolean setLowLatencyMode(boolean enable) { return validateAndCall("setLowLatencyMode", false, () -> mWifiChip.setLowLatencyMode(enable)); } /** * See comments for {@link IWifiChip#setMultiStaPrimaryConnection(String)} */ public boolean setMultiStaPrimaryConnection(String ifaceName) { return validateAndCall("setMultiStaPrimaryConnection", false, () -> mWifiChip.setMultiStaPrimaryConnection(ifaceName)); } /** * See comments for {@link IWifiChip#setMultiStaUseCase(int)} */ public boolean setMultiStaUseCase(@WifiNative.MultiStaUseCase int useCase) { return validateAndCall("setMultiStaUseCase", false, () -> mWifiChip.setMultiStaUseCase(useCase)); } /** * See comments for {@link IWifiChip#startLoggingToDebugRingBuffer(String, int, int, int)} */ public boolean startLoggingToDebugRingBuffer(String ringName, int verboseLevel, int maxIntervalInSec, int minDataSizeInBytes) { return validateAndCall("startLoggingToDebugRingBuffer", false, () -> mWifiChip.startLoggingToDebugRingBuffer(ringName, verboseLevel, maxIntervalInSec, minDataSizeInBytes)); } /** * See comments for {@link IWifiChip#stopLoggingToDebugRingBuffer()} */ public boolean stopLoggingToDebugRingBuffer() { return validateAndCall("stopLoggingToDebugRingBuffer", false, () -> mWifiChip.stopLoggingToDebugRingBuffer()); } /** * See comments for {@link IWifiChip#triggerSubsystemRestart()} */ public boolean triggerSubsystemRestart() { return validateAndCall("triggerSubsystemRestart", false, () -> mWifiChip.triggerSubsystemRestart()); } /** * See comments for {@link IWifiChip#setMloMode(int)}. */ public @WifiStatusCode int setMloMode(@WifiManager.MloMode int mode) { return validateAndCall("setMloMode", WifiStatusCode.ERROR_NOT_STARTED, () -> mWifiChip.setMloMode(mode)); } /** * See comments for {@link IWifiChip#enableStaChannelForPeerNetwork(boolean, boolean)} */ public boolean enableStaChannelForPeerNetwork(boolean enableIndoorChannel, boolean enableDfsChannel) { return validateAndCall("enableStaChannelForPeerNetwork", false, () -> mWifiChip.enableStaChannelForPeerNetwork(enableIndoorChannel, enableDfsChannel)); } /** * See comments for {@link IWifiChip#setAfcChannelAllowance(AfcChannelAllowance)} */ public boolean setAfcChannelAllowance(AfcChannelAllowance afcChannelAllowance) { if (afcChannelAllowance == null) return false; return validateAndCall("setAfcChannelAllowance", false, () -> mWifiChip.setAfcChannelAllowance(afcChannelAllowance)); } /** * See comments for {@link IWifiChip#setVoipMode(int)} */ public boolean setVoipMode(@WifiVoipMode int mode) { return validateAndCall("setVoipMode", false, () -> mWifiChip.setVoipMode(mode)); } }