diff --git a/wifi/java/android/net/wifi/RttManager.aidl b/wifi/java/android/net/wifi/RttManager.aidl index 5c6d44710ea5c..9479cf0b936e9 100644 --- a/wifi/java/android/net/wifi/RttManager.aidl +++ b/wifi/java/android/net/wifi/RttManager.aidl @@ -15,4 +15,7 @@ */ package android.net.wifi; -parcelable RttManager.RttCapabilities; \ No newline at end of file + +parcelable RttManager.RttCapabilities; +parcelable RttManager.ParcelableRttResults; +parcelable RttManager.ParcelableRttParams; diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java index 590ff1b1bfaa4..c6f1f6819669c 100644 --- a/wifi/java/android/net/wifi/RttManager.java +++ b/wifi/java/android/net/wifi/RttManager.java @@ -472,6 +472,34 @@ public class RttManager { preamble = PREAMBLE_HT; bandwidth = RTT_BW_20_SUPPORT; } + + /** + * {@hide} + */ + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("deviceType=" + deviceType); + sb.append(", requestType=" + requestType); + sb.append(", secure=" + secure); + sb.append(", bssid=" + bssid); + sb.append(", frequency=" + frequency); + sb.append(", channelWidth=" + channelWidth); + sb.append(", centerFreq0=" + centerFreq0); + sb.append(", centerFreq1=" + centerFreq1); + sb.append(", num_samples=" + num_samples); + sb.append(", num_retries=" + num_retries); + sb.append(", numberBurst=" + numberBurst); + sb.append(", interval=" + interval); + sb.append(", numSamplesPerBurst=" + numSamplesPerBurst); + sb.append(", numRetriesPerMeasurementFrame=" + numRetriesPerMeasurementFrame); + sb.append(", numRetriesPerFTMR=" + numRetriesPerFTMR); + sb.append(", LCIRequest=" + LCIRequest); + sb.append(", LCRRequest=" + LCRRequest); + sb.append(", burstTimeout=" + burstTimeout); + sb.append(", preamble=" + preamble); + sb.append(", bandwidth=" + bandwidth); + return sb.toString(); + } } /** pseudo-private class used to parcel arguments */ @@ -727,6 +755,51 @@ public class RttManager { mResults = results; } + /** + * {@hide} + */ + public String toString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < mResults.length; ++i) { + sb.append("[" + i + "]: "); + sb.append("bssid=" + mResults[i].bssid); + sb.append(", burstNumber=" + mResults[i].burstNumber); + sb.append(", measurementFrameNumber=" + mResults[i].measurementFrameNumber); + sb.append(", successMeasurementFrameNumber=" + + mResults[i].successMeasurementFrameNumber); + sb.append(", frameNumberPerBurstPeer=" + mResults[i].frameNumberPerBurstPeer); + sb.append(", status=" + mResults[i].status); + sb.append(", requestType=" + mResults[i].requestType); + sb.append(", measurementType=" + mResults[i].measurementType); + sb.append(", retryAfterDuration=" + mResults[i].retryAfterDuration); + sb.append(", ts=" + mResults[i].ts); + sb.append(", rssi=" + mResults[i].rssi); + sb.append(", rssi_spread=" + mResults[i].rssi_spread); + sb.append(", rssiSpread=" + mResults[i].rssiSpread); + sb.append(", tx_rate=" + mResults[i].tx_rate); + sb.append(", txRate=" + mResults[i].txRate); + sb.append(", rxRate=" + mResults[i].rxRate); + sb.append(", rtt_ns=" + mResults[i].rtt_ns); + sb.append(", rtt=" + mResults[i].rtt); + sb.append(", rtt_sd_ns=" + mResults[i].rtt_sd_ns); + sb.append(", rttStandardDeviation=" + mResults[i].rttStandardDeviation); + sb.append(", rtt_spread_ns=" + mResults[i].rtt_spread_ns); + sb.append(", rttSpread=" + mResults[i].rttSpread); + sb.append(", distance_cm=" + mResults[i].distance_cm); + sb.append(", distance=" + mResults[i].distance); + sb.append(", distance_sd_cm=" + mResults[i].distance_sd_cm); + sb.append(", distanceStandardDeviation=" + mResults[i].distanceStandardDeviation); + sb.append(", distance_spread_cm=" + mResults[i].distance_spread_cm); + sb.append(", distanceSpread=" + mResults[i].distanceSpread); + sb.append(", burstDuration=" + mResults[i].burstDuration); + sb.append(", negotiatedBurstNum=" + mResults[i].negotiatedBurstNum); + sb.append(", LCI=" + mResults[i].LCI); + sb.append(", LCR=" + mResults[i].LCR); + sb.append(", secure=" + mResults[i].secure); + } + return sb.toString(); + } + /** Implement the Parcelable interface {@hide} */ @Override public int describeContents() { @@ -1295,4 +1368,3 @@ public class RttManager { } } - diff --git a/wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl b/wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl index 556877a9e3a7d..b95140e88ae79 100644 --- a/wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl +++ b/wifi/java/android/net/wifi/nan/IWifiNanEventCallback.aidl @@ -17,6 +17,7 @@ package android.net.wifi.nan; import android.net.wifi.nan.ConfigRequest; +import android.net.wifi.RttManager; /** * Callback interface that WifiNanManager implements @@ -28,4 +29,8 @@ oneway interface IWifiNanEventCallback void onConnectSuccess(); void onConnectFail(int reason); void onIdentityChanged(); + + void onRangingSuccess(int rangingId, in RttManager.ParcelableRttResults results); + void onRangingFailure(int rangingId, int reason, in String description); + void onRangingAborted(int rangingId); } diff --git a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl index ea7906c4982e1..aaf43e53914d2 100644 --- a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl +++ b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl @@ -23,6 +23,7 @@ import android.net.wifi.nan.IWifiNanEventCallback; import android.net.wifi.nan.IWifiNanSessionCallback; import android.net.wifi.nan.PublishConfig; import android.net.wifi.nan.SubscribeConfig; +import android.net.wifi.RttManager; /** * Interface that WifiNanService implements @@ -51,4 +52,5 @@ interface IWifiNanManager void sendMessage(int clientId, int sessionId, int peerId, in byte[] message, int messageLength, int messageId); void terminateSession(int clientId, int sessionId); + int startRanging(int clientId, int sessionId, in RttManager.ParcelableRttParams parms); } diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/nan/WifiNanManager.java index b7eb5a6ecb39b..0505291acb2c6 100644 --- a/wifi/java/android/net/wifi/nan/WifiNanManager.java +++ b/wifi/java/android/net/wifi/nan/WifiNanManager.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.net.wifi.RttManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; @@ -28,10 +29,12 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.util.Log; +import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import java.lang.ref.WeakReference; +import java.util.Arrays; /** * This class provides the primary API for managing Wi-Fi NAN operation: @@ -91,7 +94,7 @@ public class WifiNanManager { private final IWifiNanManager mService; - private Object mLock = new Object(); // lock access to the following vars + private final Object mLock = new Object(); // lock access to the following vars @GuardedBy("mLock") private final IBinder mBinder = new Binder(); @@ -102,6 +105,9 @@ public class WifiNanManager { @GuardedBy("mLock") private Looper mLooper; + @GuardedBy("mLock") + private SparseArray mRangingListeners = new SparseArray<>(); + /** * {@hide} */ @@ -237,6 +243,7 @@ public class WifiNanManager { @Override protected void finalize() throws Throwable { disconnect(); + super.finalize(); } /** @@ -415,12 +422,63 @@ public class WifiNanManager { } } + /** + * {@hide} + */ + public void startRanging(int sessionId, RttManager.RttParams[] params, + RttManager.RttListener listener) { + if (VDBG) { + Log.v(TAG, "startRanging: sessionId=" + sessionId + ", " + "params=" + + Arrays.toString(params) + ", listener=" + listener); + } + + int clientId; + synchronized (mLock) { + if (mClientId == INVALID_CLIENT_ID) { + Log.e(TAG, "startRanging(): called with invalid client ID - not connected first?"); + return; + } + + clientId = mClientId; + } + + int rangingKey = 0; + try { + rangingKey = mService.startRanging(clientId, sessionId, + new RttManager.ParcelableRttParams(params)); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + + synchronized (mLock) { + mRangingListeners.put(rangingKey, listener); + } + } + private static class WifiNanEventCallbackProxy extends IWifiNanEventCallback.Stub { private static final int CALLBACK_CONNECT_SUCCESS = 0; private static final int CALLBACK_CONNECT_FAIL = 1; private static final int CALLBACK_IDENTITY_CHANGED = 2; + private static final int CALLBACK_RANGING_SUCCESS = 3; + private static final int CALLBACK_RANGING_FAILURE = 4; + private static final int CALLBACK_RANGING_ABORTED = 5; private final Handler mHandler; + private final WeakReference mNanManager; + + RttManager.RttListener getAndRemoveRangingListener(int rangingId) { + WifiNanManager mgr = mNanManager.get(); + if (mgr == null) { + Log.w(TAG, "getAndRemoveRangingListener: called post GC"); + return null; + } + + synchronized (mgr.mLock) { + RttManager.RttListener listener = mgr.mRangingListeners.get(rangingId); + mgr.mRangingListeners.delete(rangingId); + return listener; + } + } /** * Constructs a {@link WifiNanEventCallback} using the specified looper. @@ -430,7 +488,7 @@ public class WifiNanManager { */ WifiNanEventCallbackProxy(WifiNanManager mgr, Looper looper, final WifiNanEventCallback originalCallback) { - final WeakReference nanManager = new WeakReference(mgr); + mNanManager = new WeakReference<>(mgr); if (VDBG) Log.v(TAG, "WifiNanEventCallbackProxy ctor: looper=" + looper); mHandler = new Handler(looper) { @@ -440,7 +498,7 @@ public class WifiNanManager { Log.d(TAG, "WifiNanEventCallbackProxy: What=" + msg.what + ", msg=" + msg); } - WifiNanManager mgr = nanManager.get(); + WifiNanManager mgr = mNanManager.get(); if (mgr == null) { Log.w(TAG, "WifiNanEventCallbackProxy: handleMessage post GC"); return; @@ -455,12 +513,43 @@ public class WifiNanManager { mgr.mLooper = null; mgr.mClientId = INVALID_CLIENT_ID; } - nanManager.clear(); + mNanManager.clear(); originalCallback.onConnectFail(msg.arg1); break; case CALLBACK_IDENTITY_CHANGED: originalCallback.onIdentityChanged(); break; + case CALLBACK_RANGING_SUCCESS: { + RttManager.RttListener listener = getAndRemoveRangingListener(msg.arg1); + if (listener == null) { + Log.e(TAG, "CALLBACK_RANGING_SUCCESS rangingId=" + msg.arg1 + + ": no listener registered (anymore)"); + } else { + listener.onSuccess( + ((RttManager.ParcelableRttResults) msg.obj).mResults); + } + break; + } + case CALLBACK_RANGING_FAILURE: { + RttManager.RttListener listener = getAndRemoveRangingListener(msg.arg1); + if (listener == null) { + Log.e(TAG, "CALLBACK_RANGING_SUCCESS rangingId=" + msg.arg1 + + ": no listener registered (anymore)"); + } else { + listener.onFailure(msg.arg2, (String) msg.obj); + } + break; + } + case CALLBACK_RANGING_ABORTED: { + RttManager.RttListener listener = getAndRemoveRangingListener(msg.arg1); + if (listener == null) { + Log.e(TAG, "CALLBACK_RANGING_SUCCESS rangingId=" + msg.arg1 + + ": no listener registered (anymore)"); + } else { + listener.onAborted(); + } + break; + } } } }; @@ -490,6 +579,43 @@ public class WifiNanManager { Message msg = mHandler.obtainMessage(CALLBACK_IDENTITY_CHANGED); mHandler.sendMessage(msg); } + + @Override + public void onRangingSuccess(int rangingId, RttManager.ParcelableRttResults results) { + if (VDBG) { + Log.v(TAG, "onRangingSuccess: rangingId=" + rangingId + ", results=" + results); + } + + Message msg = mHandler.obtainMessage(CALLBACK_RANGING_SUCCESS); + msg.arg1 = rangingId; + msg.obj = results; + mHandler.sendMessage(msg); + } + + @Override + public void onRangingFailure(int rangingId, int reason, String description) { + if (VDBG) { + Log.v(TAG, "onRangingSuccess: rangingId=" + rangingId + ", reason=" + reason + + ", description=" + description); + } + + Message msg = mHandler.obtainMessage(CALLBACK_RANGING_FAILURE); + msg.arg1 = rangingId; + msg.arg2 = reason; + msg.obj = description; + mHandler.sendMessage(msg); + + } + + @Override + public void onRangingAborted(int rangingId) { + if (VDBG) Log.v(TAG, "onRangingAborted: rangingId=" + rangingId); + + Message msg = mHandler.obtainMessage(CALLBACK_RANGING_ABORTED); + msg.arg1 = rangingId; + mHandler.sendMessage(msg); + + } } private static class WifiNanSessionCallbackProxy extends IWifiNanSessionCallback.Stub { diff --git a/wifi/java/android/net/wifi/nan/WifiNanSession.java b/wifi/java/android/net/wifi/nan/WifiNanSession.java index 890f757d6391e..32872ba8dc6a8 100644 --- a/wifi/java/android/net/wifi/nan/WifiNanSession.java +++ b/wifi/java/android/net/wifi/nan/WifiNanSession.java @@ -16,6 +16,7 @@ package android.net.wifi.nan; +import android.net.wifi.RttManager; import android.util.Log; import java.lang.ref.WeakReference; @@ -97,6 +98,7 @@ public class WifiNanSession { + "terminated so step should be done explicitly"); terminate(); } + super.finalize(); } /** @@ -130,4 +132,31 @@ public class WifiNanSession { mgr.sendMessage(mSessionId, peerId, message, messageLength, messageId); } } + + /** + * Start a ranging operation with the specified peers. The peer IDs are obtained from an + * {@link WifiNanSessionCallback#onMatch(int, byte[], int, byte[], int)} or + * {@link WifiNanSessionCallback#onMessageReceived(int, byte[], int)} operation - i.e. can only + * range devices which are part of an ongoing discovery session. + * + * @param params RTT parameters - each corresponding to a specific peer ID (the array sizes + * must be identical). The + * {@link android.net.wifi.RttManager.RttParams#bssid} member must be set to + * a peer ID - not to a MAC address. + * @param listener The listener to receive the results of the ranging session. + */ + public void startRanging(RttManager.RttParams[] params, RttManager.RttListener listener) { + if (mTerminated) { + Log.w(TAG, "startRanging: called on terminated session"); + return; + } else { + WifiNanManager mgr = mMgr.get(); + if (mgr == null) { + Log.w(TAG, "startRanging: called post GC on WifiNanManager"); + return; + } + + mgr.startRanging(mSessionId, params, listener); + } + } }