From d71b53361125ea4f7340426c5e6c90bb10561dab Mon Sep 17 00:00:00 2001 From: Etan Cohen Date: Wed, 22 Aug 2018 08:51:37 -0700 Subject: [RTT] Handle HAL concurrencly limitations on RTT availability The chip may not support RTT in all modes. The change handles this correctly: whenever the HAL cannot support RTT (e.g. for multi-mode chips + switching to AP mode only) the framework will be notified and can dispatch RTT availability notification to app (both when becoming non-available and then when becoming available again). This notification on exact status also fixes the following: - Initialization is precise: i.e. won't try to execute RTT commands on an as yet uninitialized chip - Can revert an early "hack" which re-tried creating a new RTT controller if the previous one simply stopped working Bug: 79565105 Bug: 111218083 Test: unit tests (new ones) Test: ACTS RangeApSupporting11McTest:test_rtt_in_and_after_softap_mode Change-Id: Ib9ef75bb679cdb0f49384260112c06684f52c693 --- .../com/android/server/wifi/HalDeviceManager.java | 242 +++++++-- .../java/com/android/server/wifi/WifiNative.java | 55 --- .../com/android/server/wifi/WifiVendorHal.java | 546 --------------------- .../com/android/server/wifi/rtt/RttNative.java | 96 ++-- 4 files changed, 254 insertions(+), 685 deletions(-) (limited to 'service') diff --git a/service/java/com/android/server/wifi/HalDeviceManager.java b/service/java/com/android/server/wifi/HalDeviceManager.java index 3c61217d7..2acdc03e4 100644 --- a/service/java/com/android/server/wifi/HalDeviceManager.java +++ b/service/java/com/android/server/wifi/HalDeviceManager.java @@ -383,6 +383,49 @@ public class HalDeviceManager { } } + /** + * Register a callback object for RTT life-cycle events. The callback object registration + * indicates that an RTT controller should be created whenever possible. The callback object + * will be called with a new RTT controller whenever it is created (or at registration time + * if an RTT controller already exists). The callback object will also be triggered whenever + * an existing RTT controller is destroyed (the previous copies must be discarded by the + * recipient). + * + * @param callback InterfaceRttControllerLifecycleCallback object. + * @param handler Handler on which to dispatch callback + */ + public void registerRttControllerLifecycleCallback( + @NonNull InterfaceRttControllerLifecycleCallback callback, @NonNull Handler handler) { + if (VDBG) { + Log.d(TAG, "registerRttControllerLifecycleCallback: callback=" + callback + ", handler=" + + handler); + } + + if (callback == null || handler == null) { + Log.wtf(TAG, "registerRttControllerLifecycleCallback with nulls!? callback=" + callback + + ", handler=" + handler); + return; + } + + synchronized (mLock) { + InterfaceRttControllerLifecycleCallbackProxy proxy = + new InterfaceRttControllerLifecycleCallbackProxy(callback, handler); + if (!mRttControllerLifecycleCallbacks.add(proxy)) { + Log.d(TAG, + "registerRttControllerLifecycleCallback: registering an existing callback=" + + callback); + return; + } + + if (mIWifiRttController == null) { + mIWifiRttController = createRttControllerIfPossible(); + } + if (mIWifiRttController != null) { + proxy.onNewRttController(mIWifiRttController); + } + } + } + /** * Return the name of the input interface or null on error. */ @@ -437,49 +480,31 @@ public class HalDeviceManager { } /** - * Creates a IWifiRttController. A direct match to the IWifiChip.createRttController() method. + * Called on RTT controller lifecycle events. RTT controller is a singleton which will be + * created when possible (after first lifecycle registration) and destroyed if necessary. * - * Returns the created IWifiRttController or a null on error. + * Determination of availability is determined by the HAL. Creation attempts (if requested + * by registration of interface) will be done on any mode changes. */ - public IWifiRttController createRttController() { - if (VDBG) Log.d(TAG, "createRttController"); - synchronized (mLock) { - if (mWifi == null) { - Log.e(TAG, "createRttController: null IWifi"); - return null; - } - - WifiChipInfo[] chipInfos = getAllChipInfo(); - if (chipInfos == null) { - Log.e(TAG, "createRttController: no chip info found"); - stopWifi(); // major error: shutting down - return null; - } - - for (WifiChipInfo chipInfo : chipInfos) { - Mutable rttResp = new Mutable<>(); - try { - chipInfo.chip.createRttController(null, - (WifiStatus status, IWifiRttController rtt) -> { - if (status.code == WifiStatusCode.SUCCESS) { - rttResp.value = rtt; - } else { - Log.e(TAG, - "IWifiChip.createRttController failed: " + statusString( - status)); - } - }); - } catch (RemoteException e) { - Log.e(TAG, "IWifiChip.createRttController exception: " + e); - } - if (rttResp.value != null) { - return rttResp.value; - } - } + public interface InterfaceRttControllerLifecycleCallback { + /** + * Called when an RTT controller was created (or for newly registered listeners - if it + * was already available). The controller provided by this callback may be destroyed by + * the HAL at which point the {@link #onRttControllerDestroyed()} will be called. + * + * Note: this callback can be triggered to replace an existing controller (instead of + * calling the Destroyed callback in between). + * + * @param controller The RTT controller object. + */ + void onNewRttController(@NonNull IWifiRttController controller); - Log.e(TAG, "createRttController: not available from any of the chips"); - return null; - } + /** + * Called when the previously provided RTT controller is destroyed. Clients must discard + * their copy. A new copy may be provided later by + * {@link #onNewRttController(IWifiRttController)}. + */ + void onRttControllerDestroyed(); } // internal state @@ -496,8 +521,11 @@ public class HalDeviceManager { private IServiceManager mServiceManager; private IWifi mWifi; + private IWifiRttController mIWifiRttController; private final WifiEventCallback mWifiEventCallback = new WifiEventCallback(); private final Set mManagerStatusListeners = new HashSet<>(); + private final Set + mRttControllerLifecycleCallbacks = new HashSet<>(); private final SparseArray> mInterfaceAvailableForRequestListeners = new SparseArray<>(); private final SparseArray mDebugCallbacks = new SparseArray<>(); @@ -594,6 +622,10 @@ public class HalDeviceManager { mInterfaceAvailableForRequestListeners.get(IfaceType.AP).clear(); mInterfaceAvailableForRequestListeners.get(IfaceType.P2P).clear(); mInterfaceAvailableForRequestListeners.get(IfaceType.NAN).clear(); + + mIWifiRttController = null; + dispatchRttControllerLifecycleOnDestroyed(); + mRttControllerLifecycleCallbacks.clear(); } private final HwRemoteBinder.DeathRecipient mServiceManagerDeathRecipient = @@ -1787,6 +1819,7 @@ public class HalDeviceManager { WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip( ifaceCreationData.chipModeId); + updateRttControllerOnModeChange(); if (status.code != WifiStatusCode.SUCCESS) { Log.e(TAG, "executeChipReconfiguration: configureChip error: " + statusString(status)); @@ -2077,6 +2110,135 @@ public class HalDeviceManager { } } + private class InterfaceRttControllerLifecycleCallbackProxy implements + InterfaceRttControllerLifecycleCallback { + private InterfaceRttControllerLifecycleCallback mCallback; + private Handler mHandler; + + InterfaceRttControllerLifecycleCallbackProxy( + InterfaceRttControllerLifecycleCallback callback, Handler handler) { + mCallback = callback; + mHandler = handler; + } + + // override equals & hash to make sure that the container HashSet is unique with respect to + // the contained listener + @Override + public boolean equals(Object obj) { + return mCallback == ((InterfaceRttControllerLifecycleCallbackProxy) obj).mCallback; + } + + @Override + public int hashCode() { + return mCallback.hashCode(); + } + + @Override + public void onNewRttController(IWifiRttController controller) { + mHandler.post(() -> mCallback.onNewRttController(controller)); + } + + @Override + public void onRttControllerDestroyed() { + mHandler.post(() -> mCallback.onRttControllerDestroyed()); + } + } + + private void dispatchRttControllerLifecycleOnNew() { + if (VDBG) { + Log.v(TAG, "dispatchRttControllerLifecycleOnNew: # cbs=" + + mRttControllerLifecycleCallbacks.size()); + } + for (InterfaceRttControllerLifecycleCallbackProxy cbp : mRttControllerLifecycleCallbacks) { + cbp.onNewRttController(mIWifiRttController); + } + } + + private void dispatchRttControllerLifecycleOnDestroyed() { + for (InterfaceRttControllerLifecycleCallbackProxy cbp : mRttControllerLifecycleCallbacks) { + cbp.onRttControllerDestroyed(); + } + } + + + /** + * Updates the RttController when the chip mode is changed: + * - Handles callbacks to registered listeners + * - Handles creation of new RttController + */ + private void updateRttControllerOnModeChange() { + synchronized (mLock) { + boolean controllerDestroyed = mIWifiRttController != null; + mIWifiRttController = null; + if (mRttControllerLifecycleCallbacks.size() == 0) { + Log.d(TAG, "updateRttController: no one is interested in RTT controllers"); + return; + } + + IWifiRttController newRttController = createRttControllerIfPossible(); + if (newRttController == null) { + if (controllerDestroyed) { + dispatchRttControllerLifecycleOnDestroyed(); + } + } else { + mIWifiRttController = newRttController; + dispatchRttControllerLifecycleOnNew(); + } + } + } + + /** + * Try to create a new RttController. + * + * @return The new RttController - or null on failure. + */ + private IWifiRttController createRttControllerIfPossible() { + synchronized (mLock) { + if (!isWifiStarted()) { + Log.d(TAG, "createRttControllerIfPossible: Wifi is not started"); + return null; + } + + WifiChipInfo[] chipInfos = getAllChipInfo(); + if (chipInfos == null) { + Log.d(TAG, "createRttControllerIfPossible: no chip info found - most likely chip " + + "not up yet"); + return null; + } + + for (WifiChipInfo chipInfo : chipInfos) { + if (!chipInfo.currentModeIdValid) { + if (VDBG) { + Log.d(TAG, "createRttControllerIfPossible: chip not configured yet: " + + chipInfo); + } + continue; + } + + Mutable rttResp = new Mutable<>(); + try { + chipInfo.chip.createRttController(null, + (WifiStatus status, IWifiRttController rtt) -> { + if (status.code == WifiStatusCode.SUCCESS) { + rttResp.value = rtt; + } else { + Log.e(TAG, "IWifiChip.createRttController failed: " + + statusString(status)); + } + }); + } catch (RemoteException e) { + Log.e(TAG, "IWifiChip.createRttController exception: " + e); + } + if (rttResp.value != null) { + return rttResp.value; + } + } + } + + Log.w(TAG, "createRttControllerIfPossible: not available from any of the chips"); + return null; + } + // general utilities private static String statusString(WifiStatus status) { diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index 7351b720a..29b38aed7 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -18,13 +18,10 @@ package com.android.server.wifi; import android.annotation.IntDef; import android.annotation.NonNull; -import android.annotation.Nullable; import android.net.InterfaceConfiguration; import android.net.MacAddress; import android.net.TrafficStats; import android.net.apf.ApfCapabilities; -import android.net.wifi.RttManager; -import android.net.wifi.RttManager.ResponderConfig; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiScanner; @@ -2303,51 +2300,6 @@ public class WifiNative { return mWifiVendorHal.getSupportedFeatureSet(ifaceName); } - public static interface RttEventHandler { - void onRttResults(RttManager.RttResult[] result); - } - - /** - * Starts a new rtt request - * - * @param params RTT request params. Refer to {@link RttManager#RttParams}. - * @param handler Callback to be invoked to notify any results. - * @return true if the request was successful, false otherwise. - */ - public boolean requestRtt( - RttManager.RttParams[] params, RttEventHandler handler) { - return mWifiVendorHal.requestRtt(params, handler); - } - - /** - * Cancels an outstanding rtt request - * - * @param params RTT request params. Refer to {@link RttManager#RttParams} - * @return true if there was an outstanding request and it was successfully cancelled - */ - public boolean cancelRtt(RttManager.RttParams[] params) { - return mWifiVendorHal.cancelRtt(params); - } - - /** - * Enable RTT responder role on the device. Returns {@link ResponderConfig} if the responder - * role is successfully enabled, {@code null} otherwise. - * - * @param timeoutSeconds timeout to use for the responder. - */ - @Nullable - public ResponderConfig enableRttResponder(int timeoutSeconds) { - return mWifiVendorHal.enableRttResponder(timeoutSeconds); - } - - /** - * Disable RTT responder role. Returns {@code true} if responder role is successfully disabled, - * {@code false} otherwise. - */ - public boolean disableRttResponder() { - return mWifiVendorHal.disableRttResponder(); - } - /** * Set the MAC OUI during scanning. * An OUI {Organizationally Unique Identifier} is a 24-bit number that @@ -2361,13 +2313,6 @@ public class WifiNative { return mWifiVendorHal.setScanningMacOui(ifaceName, oui); } - /** - * RTT (Round Trip Time) measurement capabilities of the device. - */ - public RttManager.RttCapabilities getRttCapabilities() { - return mWifiVendorHal.getRttCapabilities(); - } - /** * Get the APF (Android Packet Filter) capabilities of the device * @param ifaceName Name of the interface. diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java index 5666dd386..77da7667f 100644 --- a/service/java/com/android/server/wifi/WifiVendorHal.java +++ b/service/java/com/android/server/wifi/WifiVendorHal.java @@ -20,18 +20,9 @@ import android.hardware.wifi.V1_0.IWifiApIface; import android.hardware.wifi.V1_0.IWifiChip; import android.hardware.wifi.V1_0.IWifiChipEventCallback; import android.hardware.wifi.V1_0.IWifiIface; -import android.hardware.wifi.V1_0.IWifiRttController; -import android.hardware.wifi.V1_0.IWifiRttControllerEventCallback; import android.hardware.wifi.V1_0.IWifiStaIface; import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback; import android.hardware.wifi.V1_0.IfaceType; -import android.hardware.wifi.V1_0.RttBw; -import android.hardware.wifi.V1_0.RttConfig; -import android.hardware.wifi.V1_0.RttPeerType; -import android.hardware.wifi.V1_0.RttPreamble; -import android.hardware.wifi.V1_0.RttResponder; -import android.hardware.wifi.V1_0.RttResult; -import android.hardware.wifi.V1_0.RttType; import android.hardware.wifi.V1_0.StaBackgroundScanBucketEventReportSchemeMask; import android.hardware.wifi.V1_0.StaBackgroundScanBucketParameters; import android.hardware.wifi.V1_0.StaBackgroundScanParameters; @@ -44,7 +35,6 @@ import android.hardware.wifi.V1_0.StaScanData; import android.hardware.wifi.V1_0.StaScanDataFlagMask; import android.hardware.wifi.V1_0.StaScanResult; import android.hardware.wifi.V1_0.WifiBand; -import android.hardware.wifi.V1_0.WifiChannelWidthInMhz; import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats; import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType; import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags; @@ -58,8 +48,6 @@ import android.hardware.wifi.V1_0.WifiStatus; import android.hardware.wifi.V1_0.WifiStatusCode; import android.net.MacAddress; import android.net.apf.ApfCapabilities; -import android.net.wifi.RttManager; -import android.net.wifi.RttManager.ResponderConfig; import android.net.wifi.ScanResult; import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; @@ -247,7 +235,6 @@ public class WifiVendorHal { // Vendor HAL HIDL interface objects. private IWifiChip mIWifiChip; - private IWifiRttController mIWifiRttController; private HashMap mIWifiStaIfaces = new HashMap<>(); private HashMap mIWifiApIfaces = new HashMap<>(); private final HalDeviceManager mHalDeviceManager; @@ -255,7 +242,6 @@ public class WifiVendorHal { private final IWifiStaIfaceEventCallback mIWifiStaIfaceEventCallback; private final ChipEventCallback mIWifiChipEventCallback; private final ChipEventCallbackV12 mIWifiChipEventCallbackV12; - private final RttEventCallback mRttEventCallback; // Plumbing for event handling. // @@ -274,7 +260,6 @@ public class WifiVendorHal { mIWifiStaIfaceEventCallback = new StaIfaceEventCallback(); mIWifiChipEventCallback = new ChipEventCallback(); mIWifiChipEventCallbackV12 = new ChipEventCallbackV12(); - mRttEventCallback = new RttEventCallback(); } public static final Object sLock = new Object(); @@ -427,15 +412,6 @@ public class WifiVendorHal { mLog.err("Failed to register STA iface callback").flush(); return stringResult(null); } - mIWifiRttController = mHalDeviceManager.createRttController(); - if (mIWifiRttController == null) { - mLog.err("Failed to create RTT controller").flush(); - return stringResult(null); - } - if (!registerRttEventCallback()) { - mLog.err("Failed to register RTT controller callback").flush(); - return stringResult(null); - } if (!retrieveWifiChip((IWifiIface) iface)) { mLog.err("Failed to get wifi chip").flush(); return stringResult(null); @@ -600,23 +576,6 @@ public class WifiVendorHal { } } - /** - * Registers RTT event callback. Returns whether the registration is successful. - */ - private boolean registerRttEventCallback() { - synchronized (sLock) { - if (mIWifiRttController == null) return boolResult(false); - if (mRttEventCallback == null) return boolResult(false); - try { - WifiStatus status = mIWifiRttController.registerEventCallback(mRttEventCallback); - return ok(status); - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - /** * Stops the HAL */ @@ -637,7 +596,6 @@ public class WifiVendorHal { mIWifiChip = null; mIWifiStaIfaces.clear(); mIWifiApIfaces.clear(); - mIWifiRttController = null; mDriverDescription = null; mFirmwareDescription = null; } @@ -1247,510 +1205,6 @@ public class WifiVendorHal { return featureSet; } - /* RTT related commands/events */ - - /** - * RTT (Round Trip Time) measurement capabilities of the device. - */ - public RttManager.RttCapabilities getRttCapabilities() { - class AnswerBox { - public RttManager.RttCapabilities value = null; - } - synchronized (sLock) { - if (mIWifiRttController == null) return null; - try { - AnswerBox box = new AnswerBox(); - mIWifiRttController.getCapabilities((status, capabilities) -> { - if (!ok(status)) return; - mVerboseLog.info("rtt capabilites %").c(capabilities.toString()).flush(); - RttManager.RttCapabilities ans = new RttManager.RttCapabilities(); - ans.oneSidedRttSupported = capabilities.rttOneSidedSupported; - ans.twoSided11McRttSupported = capabilities.rttFtmSupported; - ans.lciSupported = capabilities.lciSupported; - ans.lcrSupported = capabilities.lcrSupported; - ans.preambleSupported = frameworkPreambleFromHalPreamble( - capabilities.preambleSupport); - ans.bwSupported = frameworkBwFromHalBw(capabilities.bwSupport); - ans.responderSupported = capabilities.responderSupported; - ans.secureRttSupported = false; - ans.mcVersion = ((int) capabilities.mcVersion) & 0xff; - box.value = ans; - }); - return box.value; - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - } - - private int mRttCmdIdNext = 1; // used to generate new command ids - private int mRttCmdId; // id of currently active request - // Event handler for current active RTT request. - private WifiNative.RttEventHandler mRttEventHandler; - - /** - * Receives a callback from the Hal and passes it along to our client using RttEventHandler - */ - private class RttEventCallback extends IWifiRttControllerEventCallback.Stub { - - @Override - public void onResults(int cmdId, java.util.ArrayList results) { - WifiNative.RttEventHandler eventHandler; - synchronized (sLock) { - if (cmdId != mRttCmdId || mRttEventHandler == null) return; - eventHandler = mRttEventHandler; - // Reset the command id for RTT operations in WifiVendorHal. - WifiVendorHal.this.mRttCmdId = 0; - } - RttManager.RttResult[] rtt = new RttManager.RttResult[results.size()]; - for (int i = 0; i < rtt.length; i++) { - rtt[i] = frameworkRttResultFromHalRttResult(results.get(i)); - } - eventHandler.onRttResults(rtt); - } - } - - /** - * Converts a Hal RttResult to a RttManager.RttResult - */ - @VisibleForTesting - static RttManager.RttResult frameworkRttResultFromHalRttResult(RttResult result) { - RttManager.RttResult ans = new RttManager.RttResult(); - ans.bssid = NativeUtil.macAddressFromByteArray(result.addr); - ans.burstNumber = result.burstNum; - ans.measurementFrameNumber = result.measurementNumber; - ans.successMeasurementFrameNumber = result.successNumber; - ans.frameNumberPerBurstPeer = result.numberPerBurstPeer; - ans.status = result.status; //TODO(b/35138520) - don't assume identity translation - ans.retryAfterDuration = result.retryAfterDuration; - ans.measurementType = result.type; - ans.rssi = result.rssi; - ans.rssiSpread = result.rssiSpread; - //TODO(b/35138520) Fix HAL and framework to use the same units - ans.txRate = result.txRate.bitRateInKbps; - ans.rxRate = result.rxRate.bitRateInKbps; - ans.rtt = result.rtt; - ans.rttStandardDeviation = result.rttSd; - ans.rttSpread = result.rttSpread; - //TODO(b/35138520) These divide-by-10s were in the legacy Hal - ans.distance = result.distanceInMm / 10; // Convert cm to mm - ans.distanceStandardDeviation = result.distanceSdInMm / 10; // Convert cm to mm - ans.distanceSpread = result.distanceSpreadInMm / 10; - - ans.ts = result.timeStampInUs; - ans.burstDuration = result.burstDurationInMs; - ans.negotiatedBurstNum = result.negotiatedBurstNum; - ans.LCI = ieFromHal(result.lci); - ans.LCR = ieFromHal(result.lcr); - ans.secure = false; // Not present in HIDL HAL - return ans; - } - - /** - * Convert a Hal WifiInformationElement to its RttManager equivalent - */ - @VisibleForTesting - static RttManager.WifiInformationElement ieFromHal( - android.hardware.wifi.V1_0.WifiInformationElement ie) { - if (ie == null) return null; - RttManager.WifiInformationElement ans = new RttManager.WifiInformationElement(); - ans.id = ie.id; - ans.data = NativeUtil.byteArrayFromArrayList(ie.data); - return ans; - } - - @VisibleForTesting - static RttConfig halRttConfigFromFrameworkRttParams(RttManager.RttParams params) { - RttConfig rttConfig = new RttConfig(); - if (params.bssid != null) { - byte[] addr = NativeUtil.macAddressToByteArray(params.bssid); - for (int i = 0; i < rttConfig.addr.length; i++) { - rttConfig.addr[i] = addr[i]; - } - } - rttConfig.type = halRttTypeFromFrameworkRttType(params.requestType); - rttConfig.peer = halPeerFromFrameworkPeer(params.deviceType); - rttConfig.channel.width = halChannelWidthFromFrameworkChannelWidth(params.channelWidth); - rttConfig.channel.centerFreq = params.frequency; - rttConfig.channel.centerFreq0 = params.centerFreq0; - rttConfig.channel.centerFreq1 = params.centerFreq1; - rttConfig.burstPeriod = params.interval; // In 100ms units, 0 means no specific - rttConfig.numBurst = params.numberBurst; - rttConfig.numFramesPerBurst = params.numSamplesPerBurst; - rttConfig.numRetriesPerRttFrame = params.numRetriesPerMeasurementFrame; - rttConfig.numRetriesPerFtmr = params.numRetriesPerFTMR; - rttConfig.mustRequestLci = params.LCIRequest; - rttConfig.mustRequestLcr = params.LCRRequest; - rttConfig.burstDuration = params.burstTimeout; - rttConfig.preamble = halPreambleFromFrameworkPreamble(params.preamble); - rttConfig.bw = halBwFromFrameworkBw(params.bandwidth); - return rttConfig; - } - - @VisibleForTesting - static int halRttTypeFromFrameworkRttType(int frameworkRttType) { - switch (frameworkRttType) { - case RttManager.RTT_TYPE_ONE_SIDED: - return RttType.ONE_SIDED; - case RttManager.RTT_TYPE_TWO_SIDED: - return RttType.TWO_SIDED; - default: - throw new IllegalArgumentException("bad " + frameworkRttType); - } - } - - @VisibleForTesting - static int frameworkRttTypeFromHalRttType(int halType) { - switch (halType) { - case RttType.ONE_SIDED: - return RttManager.RTT_TYPE_ONE_SIDED; - case RttType.TWO_SIDED: - return RttManager.RTT_TYPE_TWO_SIDED; - default: - throw new IllegalArgumentException("bad " + halType); - } - } - - @VisibleForTesting - static int halPeerFromFrameworkPeer(int frameworkPeer) { - switch (frameworkPeer) { - case RttManager.RTT_PEER_TYPE_AP: - return RttPeerType.AP; - case RttManager.RTT_PEER_TYPE_STA: - return RttPeerType.STA; - case RttManager.RTT_PEER_P2P_GO: - return RttPeerType.P2P_GO; - case RttManager.RTT_PEER_P2P_CLIENT: - return RttPeerType.P2P_CLIENT; - case RttManager.RTT_PEER_NAN: - return RttPeerType.NAN; - default: - throw new IllegalArgumentException("bad " + frameworkPeer); - } - } - - @VisibleForTesting - static int frameworkPeerFromHalPeer(int halPeer) { - switch (halPeer) { - case RttPeerType.AP: - return RttManager.RTT_PEER_TYPE_AP; - case RttPeerType.STA: - return RttManager.RTT_PEER_TYPE_STA; - case RttPeerType.P2P_GO: - return RttManager.RTT_PEER_P2P_GO; - case RttPeerType.P2P_CLIENT: - return RttManager.RTT_PEER_P2P_CLIENT; - case RttPeerType.NAN: - return RttManager.RTT_PEER_NAN; - default: - throw new IllegalArgumentException("bad " + halPeer); - - } - } - - @VisibleForTesting - static int halChannelWidthFromFrameworkChannelWidth(int frameworkChannelWidth) { - switch (frameworkChannelWidth) { - case ScanResult.CHANNEL_WIDTH_20MHZ: - return WifiChannelWidthInMhz.WIDTH_20; - case ScanResult.CHANNEL_WIDTH_40MHZ: - return WifiChannelWidthInMhz.WIDTH_40; - case ScanResult.CHANNEL_WIDTH_80MHZ: - return WifiChannelWidthInMhz.WIDTH_80; - case ScanResult.CHANNEL_WIDTH_160MHZ: - return WifiChannelWidthInMhz.WIDTH_160; - case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: - return WifiChannelWidthInMhz.WIDTH_80P80; - default: - throw new IllegalArgumentException("bad " + frameworkChannelWidth); - } - } - - @VisibleForTesting - static int frameworkChannelWidthFromHalChannelWidth(int halChannelWidth) { - switch (halChannelWidth) { - case WifiChannelWidthInMhz.WIDTH_20: - return ScanResult.CHANNEL_WIDTH_20MHZ; - case WifiChannelWidthInMhz.WIDTH_40: - return ScanResult.CHANNEL_WIDTH_40MHZ; - case WifiChannelWidthInMhz.WIDTH_80: - return ScanResult.CHANNEL_WIDTH_80MHZ; - case WifiChannelWidthInMhz.WIDTH_160: - return ScanResult.CHANNEL_WIDTH_160MHZ; - case WifiChannelWidthInMhz.WIDTH_80P80: - return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ; - default: - throw new IllegalArgumentException("bad " + halChannelWidth); - } - } - - @VisibleForTesting - static int halPreambleFromFrameworkPreamble(int rttManagerPreamble) { - BitMask checkoff = new BitMask(rttManagerPreamble); - int flags = 0; - if (checkoff.testAndClear(RttManager.PREAMBLE_LEGACY)) { - flags |= RttPreamble.LEGACY; - } - if (checkoff.testAndClear(RttManager.PREAMBLE_HT)) { - flags |= RttPreamble.HT; - } - if (checkoff.testAndClear(RttManager.PREAMBLE_VHT)) { - flags |= RttPreamble.VHT; - } - if (checkoff.value != 0) { - throw new IllegalArgumentException("bad " + rttManagerPreamble); - } - return flags; - } - - @VisibleForTesting - static int frameworkPreambleFromHalPreamble(int halPreamble) { - BitMask checkoff = new BitMask(halPreamble); - int flags = 0; - if (checkoff.testAndClear(RttPreamble.LEGACY)) { - flags |= RttManager.PREAMBLE_LEGACY; - } - if (checkoff.testAndClear(RttPreamble.HT)) { - flags |= RttManager.PREAMBLE_HT; - } - if (checkoff.testAndClear(RttPreamble.VHT)) { - flags |= RttManager.PREAMBLE_VHT; - } - if (checkoff.value != 0) { - throw new IllegalArgumentException("bad " + halPreamble); - } - return flags; - } - - @VisibleForTesting - static int halBwFromFrameworkBw(int rttManagerBandwidth) { - BitMask checkoff = new BitMask(rttManagerBandwidth); - int flags = 0; - if (checkoff.testAndClear(RttManager.RTT_BW_5_SUPPORT)) { - flags |= RttBw.BW_5MHZ; - } - if (checkoff.testAndClear(RttManager.RTT_BW_10_SUPPORT)) { - flags |= RttBw.BW_10MHZ; - } - if (checkoff.testAndClear(RttManager.RTT_BW_20_SUPPORT)) { - flags |= RttBw.BW_20MHZ; - } - if (checkoff.testAndClear(RttManager.RTT_BW_40_SUPPORT)) { - flags |= RttBw.BW_40MHZ; - } - if (checkoff.testAndClear(RttManager.RTT_BW_80_SUPPORT)) { - flags |= RttBw.BW_80MHZ; - } - if (checkoff.testAndClear(RttManager.RTT_BW_160_SUPPORT)) { - flags |= RttBw.BW_160MHZ; - } - if (checkoff.value != 0) { - throw new IllegalArgumentException("bad " + rttManagerBandwidth); - } - return flags; - } - - @VisibleForTesting - static int frameworkBwFromHalBw(int rttBw) { - BitMask checkoff = new BitMask(rttBw); - int flags = 0; - if (checkoff.testAndClear(RttBw.BW_5MHZ)) { - flags |= RttManager.RTT_BW_5_SUPPORT; - } - if (checkoff.testAndClear(RttBw.BW_10MHZ)) { - flags |= RttManager.RTT_BW_10_SUPPORT; - } - if (checkoff.testAndClear(RttBw.BW_20MHZ)) { - flags |= RttManager.RTT_BW_20_SUPPORT; - } - if (checkoff.testAndClear(RttBw.BW_40MHZ)) { - flags |= RttManager.RTT_BW_40_SUPPORT; - } - if (checkoff.testAndClear(RttBw.BW_80MHZ)) { - flags |= RttManager.RTT_BW_80_SUPPORT; - } - if (checkoff.testAndClear(RttBw.BW_160MHZ)) { - flags |= RttManager.RTT_BW_160_SUPPORT; - } - if (checkoff.value != 0) { - throw new IllegalArgumentException("bad " + rttBw); - } - return flags; - } - - @VisibleForTesting - static ArrayList halRttConfigArrayFromFrameworkRttParamsArray( - RttManager.RttParams[] params) { - final int length = params.length; - ArrayList configs = new ArrayList(length); - for (int i = 0; i < length; i++) { - RttConfig config = halRttConfigFromFrameworkRttParams(params[i]); - if (config != null) { - configs.add(config); - } - } - return configs; - } - - /** - * Starts a new rtt request - * - * @param params - * @param handler - * @return success indication - */ - public boolean requestRtt(RttManager.RttParams[] params, WifiNative.RttEventHandler handler) { - ArrayList rttConfigs; - try { - rttConfigs = halRttConfigArrayFromFrameworkRttParamsArray(params); - } catch (IllegalArgumentException e) { - mLog.err("Illegal argument for RTT request").c(e.toString()).flush(); - return false; - } - synchronized (sLock) { - if (mIWifiRttController == null) return boolResult(false); - if (mRttCmdId != 0) return boolResult(false); - mRttCmdId = mRttCmdIdNext++; - mRttEventHandler = handler; - if (mRttCmdIdNext <= 0) mRttCmdIdNext = 1; - try { - WifiStatus status = mIWifiRttController.rangeRequest(mRttCmdId, rttConfigs); - if (ok(status)) return true; - mRttCmdId = 0; - return false; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - /** - * Cancels an outstanding rtt request - * - * @param params - * @return true if there was an outstanding request and it was successfully cancelled - */ - public boolean cancelRtt(RttManager.RttParams[] params) { - ArrayList rttConfigs = halRttConfigArrayFromFrameworkRttParamsArray(params); - synchronized (sLock) { - if (mIWifiRttController == null) return boolResult(false); - if (mRttCmdId == 0) return boolResult(false); - ArrayList addrs = new ArrayList(rttConfigs.size()); - for (RttConfig x : rttConfigs) addrs.add(x.addr); - try { - WifiStatus status = mIWifiRttController.rangeCancel(mRttCmdId, addrs); - mRttCmdId = 0; - if (!ok(status)) return false; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - - private int mRttResponderCmdId = 0; - - /** - * Get RTT responder information e.g. WiFi channel to enable responder on. - * - * @return info Instance of |RttResponder|, or null for error. - */ - private RttResponder getRttResponder() { - class AnswerBox { - public RttResponder value = null; - } - synchronized (sLock) { - if (mIWifiRttController == null) return null; - AnswerBox answer = new AnswerBox(); - try { - mIWifiRttController.getResponderInfo((status, info) -> { - if (!ok(status)) return; - answer.value = info; - }); - return answer.value; - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - } - - /** - * Convert Hal RttResponder to a framework ResponderConfig - * - * @param info Instance of |RttResponder| - * @return framework version of same - */ - private ResponderConfig frameworkResponderConfigFromHalRttResponder(RttResponder info) { - ResponderConfig config = new ResponderConfig(); - config.frequency = info.channel.centerFreq; - config.centerFreq0 = info.channel.centerFreq0; - config.centerFreq1 = info.channel.centerFreq1; - config.channelWidth = frameworkChannelWidthFromHalChannelWidth(info.channel.width); - config.preamble = frameworkPreambleFromHalPreamble(info.preamble); - return config; - } - - /** - * Enables RTT responder role on the device. - * - * @return {@link ResponderConfig} if the responder role is successfully enabled, - * {@code null} otherwise. - */ - public ResponderConfig enableRttResponder(int timeoutSeconds) { - RttResponder info = getRttResponder(); - synchronized (sLock) { - if (mIWifiRttController == null) return null; - if (mRttResponderCmdId != 0) { - mLog.err("responder mode already enabled - this shouldn't happen").flush(); - return null; - } - ResponderConfig config = null; - int id = mRttCmdIdNext++; - if (mRttCmdIdNext <= 0) mRttCmdIdNext = 1; - try { - WifiStatus status = mIWifiRttController.enableResponder( - /* cmdId */id, - /* WifiChannelInfo channelHint */null, - timeoutSeconds, info); - if (ok(status)) { - mRttResponderCmdId = id; - config = frameworkResponderConfigFromHalRttResponder(info); - mVerboseLog.i("enabling rtt " + mRttResponderCmdId); - } - return config; - } catch (RemoteException e) { - handleRemoteException(e); - return null; - } - } - } - - /** - * Disables RTT responder role. - * - * @return {@code true} if responder role is successfully disabled, - * {@code false} otherwise. - */ - public boolean disableRttResponder() { - synchronized (sLock) { - if (mIWifiRttController == null) return boolResult(false); - if (mRttResponderCmdId == 0) return boolResult(false); - try { - WifiStatus status = mIWifiRttController.disableResponder(mRttResponderCmdId); - mRttResponderCmdId = 0; - if (!ok(status)) return false; - return true; - } catch (RemoteException e) { - handleRemoteException(e); - return false; - } - } - } - /** * Set the MAC OUI during scanning. *

diff --git a/service/java/com/android/server/wifi/rtt/RttNative.java b/service/java/com/android/server/wifi/rtt/RttNative.java index accd1a2f8..29b0a139f 100644 --- a/service/java/com/android/server/wifi/rtt/RttNative.java +++ b/service/java/com/android/server/wifi/rtt/RttNative.java @@ -57,6 +57,40 @@ public class RttNative extends IWifiRttControllerEventCallback.Stub { private volatile IWifiRttController mIWifiRttController; private volatile RttCapabilities mRttCapabilities; + private final HalDeviceManager.InterfaceRttControllerLifecycleCallback mRttLifecycleCb = + new HalDeviceManager.InterfaceRttControllerLifecycleCallback() { + @Override + public void onNewRttController(IWifiRttController controller) { + if (mDbg) Log.d(TAG, "onNewRttController: controller=" + controller); + synchronized (mLock) { + try { + controller.registerEventCallback(RttNative.this); + } catch (RemoteException e) { + Log.e(TAG, "onNewRttController: exception registering callback: " + e); + if (mIWifiRttController != null) { + mIWifiRttController = null; + mRttService.disable(); + } + return; + } + + mIWifiRttController = controller; + mRttService.enableIfPossible(); + updateRttCapabilities(); + } + } + + @Override + public void onRttControllerDestroyed() { + if (mDbg) Log.d(TAG, "onRttControllerDestroyed"); + synchronized (mLock) { + mIWifiRttController = null; + mRttCapabilities = null; + mRttService.disable(); + } + } + }; + public RttNative(RttServiceImpl rttService, HalDeviceManager halDeviceManager) { mRttService = rttService; mHalDeviceManager = halDeviceManager; @@ -70,9 +104,14 @@ public class RttNative extends IWifiRttControllerEventCallback.Stub { mHalDeviceManager.initialize(); mHalDeviceManager.registerStatusListener(() -> { if (VDBG) Log.d(TAG, "hdm.onStatusChanged"); - updateController(); + if (mHalDeviceManager.isStarted()) { + mHalDeviceManager.registerRttControllerLifecycleCallback(mRttLifecycleCb, + handler); + } }, handler); - updateController(); + if (mHalDeviceManager.isStarted()) { + mHalDeviceManager.registerRttControllerLifecycleCallback(mRttLifecycleCb, handler); + } } } @@ -83,67 +122,36 @@ public class RttNative extends IWifiRttControllerEventCallback.Stub { return mIWifiRttController != null; } - private void updateController() { - if (mDbg) Log.v(TAG, "updateController: mIWifiRttController=" + mIWifiRttController); - - // only care about isStarted (Wi-Fi started) not isReady - since if not - // ready then Wi-Fi will also be down. - synchronized (mLock) { - IWifiRttController localWifiRttController = mIWifiRttController; - if (mHalDeviceManager.isStarted()) { - if (localWifiRttController == null) { - localWifiRttController = mHalDeviceManager.createRttController(); - if (localWifiRttController == null) { - Log.e(TAG, "updateController: Failed creating RTT controller - but Wifi is " - + "started!"); - } else { - try { - localWifiRttController.registerEventCallback(this); - } catch (RemoteException e) { - Log.e(TAG, "updateController: exception registering callback: " + e); - localWifiRttController = null; - } - } - } - } else { - localWifiRttController = null; - } - mIWifiRttController = localWifiRttController; - - if (mIWifiRttController == null) { - mRttService.disable(); - } else { - mRttService.enableIfPossible(); - updateRttCapabilities(); - } - } - } - /** * Updates the RTT capabilities. */ void updateRttCapabilities() { + if (mIWifiRttController == null) { + Log.e(TAG, "updateRttCapabilities: but a RTT controll is NULL!?"); + return; + } if (mRttCapabilities != null) { return; } + if (mDbg) Log.v(TAG, "updateRttCapabilities"); synchronized (mLock) { try { mIWifiRttController.getCapabilities( (status, capabilities) -> { if (status.code != WifiStatusCode.SUCCESS) { - Log.e(TAG, - "updateController: error requesting capabilities -- code=" - + status.code); + Log.e(TAG, "updateRttCapabilities: error requesting capabilities " + + "-- code=" + status.code); return; } if (mDbg) { - Log.v(TAG, "updateController: RTT capabilities=" + capabilities); + Log.v(TAG, "updateRttCapabilities: RTT capabilities=" + + capabilities); } mRttCapabilities = capabilities; }); } catch (RemoteException e) { - Log.e(TAG, "updateController: exception requesting capabilities: " + e); + Log.e(TAG, "updateRttCapabilities: exception requesting capabilities: " + e); } if (mRttCapabilities != null && !mRttCapabilities.rttFtmSupported) { @@ -171,12 +179,12 @@ public class RttNative extends IWifiRttControllerEventCallback.Stub { "rangeRequest: cmdId=" + cmdId + ", # of requests=" + request.mRttPeers.size()); } if (VDBG) Log.v(TAG, "rangeRequest: request=" + request); - updateRttCapabilities(); synchronized (mLock) { if (!isReady()) { Log.e(TAG, "rangeRequest: RttController is null"); return false; } + updateRttCapabilities(); ArrayList rttConfig = convertRangingRequestToRttConfigs(request, isCalledFromPrivilegedContext, mRttCapabilities); -- cgit v1.2.3