WifiRttManager.java revision 4250e786ad80007024640abbc03d8d3e1186fdb6
117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenpackage android.net.wifi.rtt; 217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport static android.Manifest.permission.ACCESS_COARSE_LOCATION; 417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport static android.Manifest.permission.ACCESS_WIFI_STATE; 517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport static android.Manifest.permission.CHANGE_WIFI_STATE; 64250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohenimport static android.Manifest.permission.LOCATION_HARDWARE; 717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.Nullable; 917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.RequiresPermission; 1058019f524f8180423a6e46b83fa3564267612e39Etan Cohenimport android.annotation.SdkConstant; 114250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohenimport android.annotation.SystemApi; 1217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.SystemService; 1317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.content.Context; 1417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.Binder; 1517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.Handler; 1617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.Looper; 1717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.RemoteException; 184250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohenimport android.os.WorkSource; 1917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.util.Log; 2017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 2117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport java.util.List; 2217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 2317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen/** 2417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * This class provides the primary API for measuring distance (range) to other devices using the 2517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * IEEE 802.11mc Wi-Fi Round Trip Time (RTT) technology. 2617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <p> 2717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * The devices which can be ranged include: 2817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <li>Access Points (APs) 2958019f524f8180423a6e46b83fa3564267612e39Etan Cohen * <li>Wi-Fi Aware peers 3017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <p> 3117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * Ranging requests are triggered using 3217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * {@link #startRanging(RangingRequest, RangingResultCallback, Handler)}. Results (in case of 3317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * successful operation) are returned in the {@link RangingResultCallback#onRangingResults(List)} 3417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * callback. 3558019f524f8180423a6e46b83fa3564267612e39Etan Cohen * <p> 3658019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Wi-Fi RTT may not be usable at some points, e.g. when Wi-Fi is disabled. To validate that 3758019f524f8180423a6e46b83fa3564267612e39Etan Cohen * the functionality is available use the {@link #isAvailable()} function. To track 3858019f524f8180423a6e46b83fa3564267612e39Etan Cohen * changes in RTT usability register for the {@link #ACTION_WIFI_RTT_STATE_CHANGED} 3958019f524f8180423a6e46b83fa3564267612e39Etan Cohen * broadcast. Note that this broadcast is not sticky - you should register for it and then 4058019f524f8180423a6e46b83fa3564267612e39Etan Cohen * check the above API to avoid a race condition. 4117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * 4217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * @hide RTT_API 4317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen */ 4417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen@SystemService(Context.WIFI_RTT2_SERVICE) 4517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenpublic class WifiRttManager { 4617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private static final String TAG = "WifiRttManager"; 4717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private static final boolean VDBG = true; 4817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 4917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private final Context mContext; 5017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private final IWifiRttManager mService; 5117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 5258019f524f8180423a6e46b83fa3564267612e39Etan Cohen /** 5358019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Broadcast intent action to indicate that the state of Wi-Fi RTT availability has changed. 5458019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Use the {@link #isAvailable()} to query the current status. 5558019f524f8180423a6e46b83fa3564267612e39Etan Cohen * This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering 5658019f524f8180423a6e46b83fa3564267612e39Etan Cohen * the broadcast to check the current state of Wi-Fi RTT. 5758019f524f8180423a6e46b83fa3564267612e39Etan Cohen * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 5858019f524f8180423a6e46b83fa3564267612e39Etan Cohen * components will be launched. 5958019f524f8180423a6e46b83fa3564267612e39Etan Cohen */ 6058019f524f8180423a6e46b83fa3564267612e39Etan Cohen @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 6158019f524f8180423a6e46b83fa3564267612e39Etan Cohen public static final String ACTION_WIFI_RTT_STATE_CHANGED = 6258019f524f8180423a6e46b83fa3564267612e39Etan Cohen "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED"; 6358019f524f8180423a6e46b83fa3564267612e39Etan Cohen 6417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen /** @hide */ 6517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen public WifiRttManager(Context context, IWifiRttManager service) { 6617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mContext = context; 6717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mService = service; 6817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 6917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 7017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen /** 7158019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Returns the current status of RTT API: whether or not RTT is available. To track 7258019f524f8180423a6e46b83fa3564267612e39Etan Cohen * changes in the state of RTT API register for the 7358019f524f8180423a6e46b83fa3564267612e39Etan Cohen * {@link #ACTION_WIFI_RTT_STATE_CHANGED} broadcast. 7458019f524f8180423a6e46b83fa3564267612e39Etan Cohen * 7558019f524f8180423a6e46b83fa3564267612e39Etan Cohen * @return A boolean indicating whether the app can use the RTT API at this time (true) or 7658019f524f8180423a6e46b83fa3564267612e39Etan Cohen * not (false). 7758019f524f8180423a6e46b83fa3564267612e39Etan Cohen */ 7858019f524f8180423a6e46b83fa3564267612e39Etan Cohen public boolean isAvailable() { 7958019f524f8180423a6e46b83fa3564267612e39Etan Cohen try { 8058019f524f8180423a6e46b83fa3564267612e39Etan Cohen return mService.isAvailable(); 8158019f524f8180423a6e46b83fa3564267612e39Etan Cohen } catch (RemoteException e) { 8258019f524f8180423a6e46b83fa3564267612e39Etan Cohen throw e.rethrowFromSystemServer(); 8358019f524f8180423a6e46b83fa3564267612e39Etan Cohen } 8458019f524f8180423a6e46b83fa3564267612e39Etan Cohen } 8558019f524f8180423a6e46b83fa3564267612e39Etan Cohen 8658019f524f8180423a6e46b83fa3564267612e39Etan Cohen /** 8717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * Initiate a request to range to a set of devices specified in the {@link RangingRequest}. 8817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * Results will be returned in the {@link RangingResultCallback} set of callbacks. 8917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * 9017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * @param request A request specifying a set of devices whose distance measurements are 9117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * requested. 9217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * @param callback A callback for the result of the ranging request. 9317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * @param handler The Handler on whose thread to execute the callbacks of the {@code 9417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * callback} object. If a null is provided then the application's main thread 9517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * will be used. 9617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen */ 9717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE}) 9817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen public void startRanging(RangingRequest request, RangingResultCallback callback, 9917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen @Nullable Handler handler) { 1004250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen startRanging(null, request, callback, handler); 1014250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen } 1024250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen 1034250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen /** 1044250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * Initiate a request to range to a set of devices specified in the {@link RangingRequest}. 1054250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * Results will be returned in the {@link RangingResultCallback} set of callbacks. 1064250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * 1074250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * @param workSource A mechanism to specify an alternative work-source for the request. 1084250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * @param request A request specifying a set of devices whose distance measurements are 1094250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * requested. 1104250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * @param callback A callback for the result of the ranging request. 1114250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * @param handler The Handler on whose thread to execute the callbacks of the {@code 1124250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * callback} object. If a null is provided then the application's main thread 1134250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * will be used. 1144250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * 1154250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * @hide (@SystemApi) 1164250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen */ 1174250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE, 1184250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen ACCESS_WIFI_STATE}) 1194250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen public void startRanging(@Nullable WorkSource workSource, RangingRequest request, 1204250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen RangingResultCallback callback, @Nullable Handler handler) { 12117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen if (VDBG) { 1224250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen Log.v(TAG, "startRanging: workSource=" + workSource + ", request=" + request 1234250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen + ", callback=" + callback + ", handler=" + handler); 12417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 12517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 12617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper(); 12717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen Binder binder = new Binder(); 12817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen try { 1294250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen mService.startRanging(binder, mContext.getOpPackageName(), workSource, request, 13017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen new RttCallbackProxy(looper, callback)); 13117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } catch (RemoteException e) { 1324250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen throw e.rethrowFromSystemServer(); 1334250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen } 1344250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen } 1354250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen 1364250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen /** 1374250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * Cancel all ranging requests for the specified work sources. The requests have been requested 1384250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * using {@link #startRanging(WorkSource, RangingRequest, RangingResultCallback, Handler)}. 1394250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * 1404250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * @param workSource The work-sources of the requesters. 1414250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * 1424250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * @hide (@SystemApi) 1434250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen */ 1444250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen @RequiresPermission(allOf = {LOCATION_HARDWARE}) 1454250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen public void cancelRanging(WorkSource workSource) { 1464250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen if (VDBG) { 1474250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen Log.v(TAG, "cancelRanging: workSource=" + workSource); 1484250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen } 1494250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen 1504250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen try { 1514250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen mService.cancelRanging(workSource); 1524250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen } catch (RemoteException e) { 15317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen throw e.rethrowFromSystemServer(); 15417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 15517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 15617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 15717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private static class RttCallbackProxy extends IRttCallback.Stub { 15817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private final Handler mHandler; 15917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private final RangingResultCallback mCallback; 16017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 16117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen RttCallbackProxy(Looper looper, RangingResultCallback callback) { 16217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mHandler = new Handler(looper); 16317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mCallback = callback; 16417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 16517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 16617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen @Override 167210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen public void onRangingFailure(int status) throws RemoteException { 168210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen if (VDBG) Log.v(TAG, "RttCallbackProxy: onRangingFailure: status=" + status); 16917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mHandler.post(() -> { 170210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen mCallback.onRangingFailure(status); 171210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen }); 172210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen } 173210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen 174210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen @Override 175210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen public void onRangingResults(List<RangingResult> results) throws RemoteException { 176210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen if (VDBG) Log.v(TAG, "RttCallbackProxy: onRanginResults: results=" + results); 177210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen mHandler.post(() -> { 178210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen mCallback.onRangingResults(results); 17917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen }); 18017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 18117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 18217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen} 183