WifiRttManager.java revision 58019f524f8180423a6e46b83fa3564267612e39
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; 617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.Nullable; 817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.RequiresPermission; 958019f524f8180423a6e46b83fa3564267612e39Etan Cohenimport android.annotation.SdkConstant; 1017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.annotation.SystemService; 1117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.content.Context; 1217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.Binder; 1317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.Handler; 1417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.Looper; 1517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.os.RemoteException; 1617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport android.util.Log; 1717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 1817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenimport java.util.List; 1917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 2017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen/** 2117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * This class provides the primary API for measuring distance (range) to other devices using the 2217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * IEEE 802.11mc Wi-Fi Round Trip Time (RTT) technology. 2317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <p> 2417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * The devices which can be ranged include: 2517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <li>Access Points (APs) 2658019f524f8180423a6e46b83fa3564267612e39Etan Cohen * <li>Wi-Fi Aware peers 2717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * <p> 2817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * Ranging requests are triggered using 2917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * {@link #startRanging(RangingRequest, RangingResultCallback, Handler)}. Results (in case of 3017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * successful operation) are returned in the {@link RangingResultCallback#onRangingResults(List)} 3117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * callback. 3258019f524f8180423a6e46b83fa3564267612e39Etan Cohen * <p> 3358019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Wi-Fi RTT may not be usable at some points, e.g. when Wi-Fi is disabled. To validate that 3458019f524f8180423a6e46b83fa3564267612e39Etan Cohen * the functionality is available use the {@link #isAvailable()} function. To track 3558019f524f8180423a6e46b83fa3564267612e39Etan Cohen * changes in RTT usability register for the {@link #ACTION_WIFI_RTT_STATE_CHANGED} 3658019f524f8180423a6e46b83fa3564267612e39Etan Cohen * broadcast. Note that this broadcast is not sticky - you should register for it and then 3758019f524f8180423a6e46b83fa3564267612e39Etan Cohen * check the above API to avoid a race condition. 3817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * 3917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * @hide RTT_API 4017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen */ 4117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen@SystemService(Context.WIFI_RTT2_SERVICE) 4217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohenpublic class WifiRttManager { 4317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private static final String TAG = "WifiRttManager"; 4417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private static final boolean VDBG = true; 4517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 4617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private final Context mContext; 4717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private final IWifiRttManager mService; 4817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 4958019f524f8180423a6e46b83fa3564267612e39Etan Cohen /** 5058019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Broadcast intent action to indicate that the state of Wi-Fi RTT availability has changed. 5158019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Use the {@link #isAvailable()} to query the current status. 5258019f524f8180423a6e46b83fa3564267612e39Etan Cohen * This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering 5358019f524f8180423a6e46b83fa3564267612e39Etan Cohen * the broadcast to check the current state of Wi-Fi RTT. 5458019f524f8180423a6e46b83fa3564267612e39Etan Cohen * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 5558019f524f8180423a6e46b83fa3564267612e39Etan Cohen * components will be launched. 5658019f524f8180423a6e46b83fa3564267612e39Etan Cohen */ 5758019f524f8180423a6e46b83fa3564267612e39Etan Cohen @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 5858019f524f8180423a6e46b83fa3564267612e39Etan Cohen public static final String ACTION_WIFI_RTT_STATE_CHANGED = 5958019f524f8180423a6e46b83fa3564267612e39Etan Cohen "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED"; 6058019f524f8180423a6e46b83fa3564267612e39Etan Cohen 6117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen /** @hide */ 6217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen public WifiRttManager(Context context, IWifiRttManager service) { 6317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mContext = context; 6417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mService = service; 6517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 6617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 6717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen /** 6858019f524f8180423a6e46b83fa3564267612e39Etan Cohen * Returns the current status of RTT API: whether or not RTT is available. To track 6958019f524f8180423a6e46b83fa3564267612e39Etan Cohen * changes in the state of RTT API register for the 7058019f524f8180423a6e46b83fa3564267612e39Etan Cohen * {@link #ACTION_WIFI_RTT_STATE_CHANGED} broadcast. 7158019f524f8180423a6e46b83fa3564267612e39Etan Cohen * 7258019f524f8180423a6e46b83fa3564267612e39Etan Cohen * @return A boolean indicating whether the app can use the RTT API at this time (true) or 7358019f524f8180423a6e46b83fa3564267612e39Etan Cohen * not (false). 7458019f524f8180423a6e46b83fa3564267612e39Etan Cohen */ 7558019f524f8180423a6e46b83fa3564267612e39Etan Cohen public boolean isAvailable() { 7658019f524f8180423a6e46b83fa3564267612e39Etan Cohen try { 7758019f524f8180423a6e46b83fa3564267612e39Etan Cohen return mService.isAvailable(); 7858019f524f8180423a6e46b83fa3564267612e39Etan Cohen } catch (RemoteException e) { 7958019f524f8180423a6e46b83fa3564267612e39Etan Cohen throw e.rethrowFromSystemServer(); 8058019f524f8180423a6e46b83fa3564267612e39Etan Cohen } 8158019f524f8180423a6e46b83fa3564267612e39Etan Cohen } 8258019f524f8180423a6e46b83fa3564267612e39Etan Cohen 8358019f524f8180423a6e46b83fa3564267612e39Etan Cohen /** 8417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * Initiate a request to range to a set of devices specified in the {@link RangingRequest}. 8517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * Results will be returned in the {@link RangingResultCallback} set of callbacks. 8617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * 8717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * @param request A request specifying a set of devices whose distance measurements are 8817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * requested. 8917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * @param callback A callback for the result of the ranging request. 9017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * @param handler The Handler on whose thread to execute the callbacks of the {@code 9117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * callback} object. If a null is provided then the application's main thread 9217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen * will be used. 9317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen */ 9417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE}) 9517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen public void startRanging(RangingRequest request, RangingResultCallback callback, 9617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen @Nullable Handler handler) { 9717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen if (VDBG) { 9817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen Log.v(TAG, "startRanging: request=" + request + ", callback=" + callback + ", handler=" 9917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen + handler); 10017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 10117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 10217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper(); 10317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen Binder binder = new Binder(); 10417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen try { 10517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mService.startRanging(binder, mContext.getOpPackageName(), request, 10617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen new RttCallbackProxy(looper, callback)); 10717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } catch (RemoteException e) { 10817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen throw e.rethrowFromSystemServer(); 10917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 11017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 11117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 11217ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private static class RttCallbackProxy extends IRttCallback.Stub { 11317ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private final Handler mHandler; 11417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen private final RangingResultCallback mCallback; 11517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 11617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen RttCallbackProxy(Looper looper, RangingResultCallback callback) { 11717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mHandler = new Handler(looper); 11817ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mCallback = callback; 11917ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 12017ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen 12117ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen @Override 122210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen public void onRangingFailure(int status) throws RemoteException { 123210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen if (VDBG) Log.v(TAG, "RttCallbackProxy: onRangingFailure: status=" + status); 12417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen mHandler.post(() -> { 125210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen mCallback.onRangingFailure(status); 126210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen }); 127210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen } 128210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen 129210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen @Override 130210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen public void onRangingResults(List<RangingResult> results) throws RemoteException { 131210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen if (VDBG) Log.v(TAG, "RttCallbackProxy: onRanginResults: results=" + results); 132210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen mHandler.post(() -> { 133210da15b9f195c045b34ce0b125a431f394edce0Etan Cohen mCallback.onRangingResults(results); 13417ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen }); 13517ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 13617ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen } 13717ba47254ceabc27c3c8ebc8728fa6c0d55975bcEtan Cohen} 138