1a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen/* 2a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * Copyright (C) 2018 The Android Open Source Project 3a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * 4a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * Licensed under the Apache License, Version 2.0 (the "License"); 5a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * you may not use this file except in compliance with the License. 6a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * You may obtain a copy of the License at 7a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * 8a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * http://www.apache.org/licenses/LICENSE-2.0 9a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * 10a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * Unless required by applicable law or agreed to in writing, software 11a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * distributed under the License is distributed on an "AS IS" BASIS, 12a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * See the License for the specific language governing permissions and 14a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * limitations under the License. 15a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen */ 16a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen 1717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenpackage android.net.wifi.rtt; 1817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 19eed77825b2da1b5c4bd4b4df182b89e787456a55Etan Cohenimport static android.Manifest.permission.ACCESS_FINE_LOCATION; 2017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport static android.Manifest.permission.ACCESS_WIFI_STATE; 2117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport static android.Manifest.permission.CHANGE_WIFI_STATE; 224250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohenimport static android.Manifest.permission.LOCATION_HARDWARE; 2317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 2452982a9e40650f75105adf96baf4b072af924e88Etan Cohenimport android.annotation.CallbackExecutor; 25a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohenimport android.annotation.NonNull; 2617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.Nullable; 2717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.RequiresPermission; 2858019f524f8180423a6e46b83fa3564267612e39Etan Cohenimport android.annotation.SdkConstant; 294250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohenimport android.annotation.SystemApi; 3017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.SystemService; 3117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.content.Context; 3217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.Binder; 3317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.RemoteException; 344250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohenimport android.os.WorkSource; 3517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.util.Log; 3617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 3717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport java.util.List; 3852982a9e40650f75105adf96baf4b072af924e88Etan Cohenimport java.util.concurrent.Executor; 3917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 4017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen/** 4117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * This class provides the primary API for measuring distance (range) to other devices using the 4217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * IEEE 802.11mc Wi-Fi Round Trip Time (RTT) technology. 4317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <p> 4417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * The devices which can be ranged include: 4517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <li>Access Points (APs) 4658019f524f8180423a6e46b83fa3564267612e39Etan Cohen * <li>Wi-Fi Aware peers 4717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <p> 4817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * Ranging requests are triggered using 4952982a9e40650f75105adf96baf4b072af924e88Etan Cohen * {@link #startRanging(RangingRequest, Executor, RangingResultCallback)}. Results (in case of 5017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * successful operation) are returned in the {@link RangingResultCallback#onRangingResults(List)} 5117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * callback. 5258019f524f8180423a6e46b83fa3564267612e39Etan Cohen * <p> 5358019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Wi-Fi RTT may not be usable at some points, e.g. when Wi-Fi is disabled. To validate that 5458019f524f8180423a6e46b83fa3564267612e39Etan Cohen * the functionality is available use the {@link #isAvailable()} function. To track 5558019f524f8180423a6e46b83fa3564267612e39Etan Cohen * changes in RTT usability register for the {@link #ACTION_WIFI_RTT_STATE_CHANGED} 5658019f524f8180423a6e46b83fa3564267612e39Etan Cohen * broadcast. Note that this broadcast is not sticky - you should register for it and then 5758019f524f8180423a6e46b83fa3564267612e39Etan Cohen * check the above API to avoid a race condition. 5817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen */ 5946efb4810011e8ce124b01e28f02d4c767658094Etan Cohen@SystemService(Context.WIFI_RTT_RANGING_SERVICE) 6017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenpublic class WifiRttManager { 6117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private static final String TAG = "WifiRttManager"; 629752663e3b0b16a07539ec78183176a3ec4e4efaEtan Cohen private static final boolean VDBG = false; 6317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 6417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private final Context mContext; 6517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private final IWifiRttManager mService; 6617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 6758019f524f8180423a6e46b83fa3564267612e39Etan Cohen /** 6858019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Broadcast intent action to indicate that the state of Wi-Fi RTT availability has changed. 6958019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Use the {@link #isAvailable()} to query the current status. 7058019f524f8180423a6e46b83fa3564267612e39Etan Cohen * This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering 7158019f524f8180423a6e46b83fa3564267612e39Etan Cohen * the broadcast to check the current state of Wi-Fi RTT. 7258019f524f8180423a6e46b83fa3564267612e39Etan Cohen * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 7358019f524f8180423a6e46b83fa3564267612e39Etan Cohen * components will be launched. 7458019f524f8180423a6e46b83fa3564267612e39Etan Cohen */ 7558019f524f8180423a6e46b83fa3564267612e39Etan Cohen @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 7658019f524f8180423a6e46b83fa3564267612e39Etan Cohen public static final String ACTION_WIFI_RTT_STATE_CHANGED = 7758019f524f8180423a6e46b83fa3564267612e39Etan Cohen "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED"; 7858019f524f8180423a6e46b83fa3564267612e39Etan Cohen 7917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen /** @hide */ 8017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen public WifiRttManager(Context context, IWifiRttManager service) { 8117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mContext = context; 8217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mService = service; 8317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 8417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 8517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen /** 8658019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Returns the current status of RTT API: whether or not RTT is available. To track 8758019f524f8180423a6e46b83fa3564267612e39Etan Cohen * changes in the state of RTT API register for the 8858019f524f8180423a6e46b83fa3564267612e39Etan Cohen * {@link #ACTION_WIFI_RTT_STATE_CHANGED} broadcast. 89a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * <p>Note: availability of RTT does not mean that the app can use the API. The app's 90a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * permissions and platform Location Mode are validated at run-time. 9158019f524f8180423a6e46b83fa3564267612e39Etan Cohen * 9258019f524f8180423a6e46b83fa3564267612e39Etan Cohen * @return A boolean indicating whether the app can use the RTT API at this time (true) or 9358019f524f8180423a6e46b83fa3564267612e39Etan Cohen * not (false). 9458019f524f8180423a6e46b83fa3564267612e39Etan Cohen */ 9558019f524f8180423a6e46b83fa3564267612e39Etan Cohen public boolean isAvailable() { 9658019f524f8180423a6e46b83fa3564267612e39Etan Cohen try { 9758019f524f8180423a6e46b83fa3564267612e39Etan Cohen return mService.isAvailable(); 9858019f524f8180423a6e46b83fa3564267612e39Etan Cohen } catch (RemoteException e) { 9958019f524f8180423a6e46b83fa3564267612e39Etan Cohen throw e.rethrowFromSystemServer(); 10058019f524f8180423a6e46b83fa3564267612e39Etan Cohen } 10158019f524f8180423a6e46b83fa3564267612e39Etan Cohen } 10258019f524f8180423a6e46b83fa3564267612e39Etan Cohen 10358019f524f8180423a6e46b83fa3564267612e39Etan Cohen /** 10417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * Initiate a request to range to a set of devices specified in the {@link RangingRequest}. 10517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * Results will be returned in the {@link RangingResultCallback} set of callbacks. 10617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * 10717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * @param request A request specifying a set of devices whose distance measurements are 10817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * requested. 10952982a9e40650f75105adf96baf4b072af924e88Etan Cohen * @param executor The Executor on which to run the callback. 11017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * @param callback A callback for the result of the ranging request. 11117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen */ 112eed77825b2da1b5c4bd4b4df182b89e787456a55Etan Cohen @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE}) 113a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen public void startRanging(@NonNull RangingRequest request, 11452982a9e40650f75105adf96baf4b072af924e88Etan Cohen @NonNull @CallbackExecutor Executor executor, @NonNull RangingResultCallback callback) { 11552982a9e40650f75105adf96baf4b072af924e88Etan Cohen startRanging(null, request, executor, callback); 1164250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen } 1174250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen 1184250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen /** 1194250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * Initiate a request to range to a set of devices specified in the {@link RangingRequest}. 1204250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * Results will be returned in the {@link RangingResultCallback} set of callbacks. 1214250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * 1224250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * @param workSource A mechanism to specify an alternative work-source for the request. 1234250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * @param request A request specifying a set of devices whose distance measurements are 1244250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * requested. 12552982a9e40650f75105adf96baf4b072af924e88Etan Cohen * @param executor The Executor on which to run the callback. 1264250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * @param callback A callback for the result of the ranging request. 1274250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * 128a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * @hide 1294250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen */ 130a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen @SystemApi 131eed77825b2da1b5c4bd4b4df182b89e787456a55Etan Cohen @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_FINE_LOCATION, CHANGE_WIFI_STATE, 1324250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen ACCESS_WIFI_STATE}) 133a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen public void startRanging(@Nullable WorkSource workSource, @NonNull RangingRequest request, 13452982a9e40650f75105adf96baf4b072af924e88Etan Cohen @NonNull @CallbackExecutor Executor executor, @NonNull RangingResultCallback callback) { 13517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen if (VDBG) { 1364250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen Log.v(TAG, "startRanging: workSource=" + workSource + ", request=" + request 13752982a9e40650f75105adf96baf4b072af924e88Etan Cohen + ", callback=" + callback + ", executor=" + executor); 13817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 13917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 14052982a9e40650f75105adf96baf4b072af924e88Etan Cohen if (executor == null) { 14152982a9e40650f75105adf96baf4b072af924e88Etan Cohen throw new IllegalArgumentException("Null executor provided"); 14252982a9e40650f75105adf96baf4b072af924e88Etan Cohen } 143b7abd810ba407ac72dbb1b539925450b4ed2ad23Etan Cohen if (callback == null) { 144b7abd810ba407ac72dbb1b539925450b4ed2ad23Etan Cohen throw new IllegalArgumentException("Null callback provided"); 145b7abd810ba407ac72dbb1b539925450b4ed2ad23Etan Cohen } 146b7abd810ba407ac72dbb1b539925450b4ed2ad23Etan Cohen 14717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen Binder binder = new Binder(); 14817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen try { 1494250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen mService.startRanging(binder, mContext.getOpPackageName(), workSource, request, 15052982a9e40650f75105adf96baf4b072af924e88Etan Cohen new IRttCallback.Stub() { 15152982a9e40650f75105adf96baf4b072af924e88Etan Cohen @Override 15252982a9e40650f75105adf96baf4b072af924e88Etan Cohen public void onRangingFailure(int status) throws RemoteException { 15352982a9e40650f75105adf96baf4b072af924e88Etan Cohen clearCallingIdentity(); 15452982a9e40650f75105adf96baf4b072af924e88Etan Cohen executor.execute(() -> callback.onRangingFailure(status)); 15552982a9e40650f75105adf96baf4b072af924e88Etan Cohen } 15652982a9e40650f75105adf96baf4b072af924e88Etan Cohen 15752982a9e40650f75105adf96baf4b072af924e88Etan Cohen @Override 15852982a9e40650f75105adf96baf4b072af924e88Etan Cohen public void onRangingResults(List<RangingResult> results) 15952982a9e40650f75105adf96baf4b072af924e88Etan Cohen throws RemoteException { 16052982a9e40650f75105adf96baf4b072af924e88Etan Cohen clearCallingIdentity(); 16152982a9e40650f75105adf96baf4b072af924e88Etan Cohen executor.execute(() -> callback.onRangingResults(results)); 16252982a9e40650f75105adf96baf4b072af924e88Etan Cohen } 16352982a9e40650f75105adf96baf4b072af924e88Etan Cohen }); 16417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } catch (RemoteException e) { 1654250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen throw e.rethrowFromSystemServer(); 1664250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen } 1674250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen } 1684250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen 1694250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen /** 1704250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * Cancel all ranging requests for the specified work sources. The requests have been requested 17152982a9e40650f75105adf96baf4b072af924e88Etan Cohen * using {@link #startRanging(WorkSource, RangingRequest, Executor, RangingResultCallback)}. 1724250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * 1734250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * @param workSource The work-sources of the requesters. 1744250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen * 175a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen * @hide 1764250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen */ 177a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen @SystemApi 1784250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen @RequiresPermission(allOf = {LOCATION_HARDWARE}) 179a0688e0321a3c911080d7a5a4ae7bf196198c319Etan Cohen public void cancelRanging(@Nullable WorkSource workSource) { 1804250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen if (VDBG) { 1814250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen Log.v(TAG, "cancelRanging: workSource=" + workSource); 1824250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen } 1834250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen 1844250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen try { 1854250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen mService.cancelRanging(workSource); 1864250e786ad80007024640abbc03d8d3e1186fdb6Etan Cohen } catch (RemoteException e) { 18717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen throw e.rethrowFromSystemServer(); 18817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 18917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 19017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen} 191