WifiRttManager.java revision 4250e786ad80007024640abbc03d8d3e1186fdb6
1package android.net.wifi.rtt; 2 3import static android.Manifest.permission.ACCESS_COARSE_LOCATION; 4import static android.Manifest.permission.ACCESS_WIFI_STATE; 5import static android.Manifest.permission.CHANGE_WIFI_STATE; 6import static android.Manifest.permission.LOCATION_HARDWARE; 7 8import android.annotation.Nullable; 9import android.annotation.RequiresPermission; 10import android.annotation.SdkConstant; 11import android.annotation.SystemApi; 12import android.annotation.SystemService; 13import android.content.Context; 14import android.os.Binder; 15import android.os.Handler; 16import android.os.Looper; 17import android.os.RemoteException; 18import android.os.WorkSource; 19import android.util.Log; 20 21import java.util.List; 22 23/** 24 * This class provides the primary API for measuring distance (range) to other devices using the 25 * IEEE 802.11mc Wi-Fi Round Trip Time (RTT) technology. 26 * <p> 27 * The devices which can be ranged include: 28 * <li>Access Points (APs) 29 * <li>Wi-Fi Aware peers 30 * <p> 31 * Ranging requests are triggered using 32 * {@link #startRanging(RangingRequest, RangingResultCallback, Handler)}. Results (in case of 33 * successful operation) are returned in the {@link RangingResultCallback#onRangingResults(List)} 34 * callback. 35 * <p> 36 * Wi-Fi RTT may not be usable at some points, e.g. when Wi-Fi is disabled. To validate that 37 * the functionality is available use the {@link #isAvailable()} function. To track 38 * changes in RTT usability register for the {@link #ACTION_WIFI_RTT_STATE_CHANGED} 39 * broadcast. Note that this broadcast is not sticky - you should register for it and then 40 * check the above API to avoid a race condition. 41 * 42 * @hide RTT_API 43 */ 44@SystemService(Context.WIFI_RTT2_SERVICE) 45public class WifiRttManager { 46 private static final String TAG = "WifiRttManager"; 47 private static final boolean VDBG = true; 48 49 private final Context mContext; 50 private final IWifiRttManager mService; 51 52 /** 53 * Broadcast intent action to indicate that the state of Wi-Fi RTT availability has changed. 54 * Use the {@link #isAvailable()} to query the current status. 55 * This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering 56 * the broadcast to check the current state of Wi-Fi RTT. 57 * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered 58 * components will be launched. 59 */ 60 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 61 public static final String ACTION_WIFI_RTT_STATE_CHANGED = 62 "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED"; 63 64 /** @hide */ 65 public WifiRttManager(Context context, IWifiRttManager service) { 66 mContext = context; 67 mService = service; 68 } 69 70 /** 71 * Returns the current status of RTT API: whether or not RTT is available. To track 72 * changes in the state of RTT API register for the 73 * {@link #ACTION_WIFI_RTT_STATE_CHANGED} broadcast. 74 * 75 * @return A boolean indicating whether the app can use the RTT API at this time (true) or 76 * not (false). 77 */ 78 public boolean isAvailable() { 79 try { 80 return mService.isAvailable(); 81 } catch (RemoteException e) { 82 throw e.rethrowFromSystemServer(); 83 } 84 } 85 86 /** 87 * Initiate a request to range to a set of devices specified in the {@link RangingRequest}. 88 * Results will be returned in the {@link RangingResultCallback} set of callbacks. 89 * 90 * @param request A request specifying a set of devices whose distance measurements are 91 * requested. 92 * @param callback A callback for the result of the ranging request. 93 * @param handler The Handler on whose thread to execute the callbacks of the {@code 94 * callback} object. If a null is provided then the application's main thread 95 * will be used. 96 */ 97 @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE}) 98 public void startRanging(RangingRequest request, RangingResultCallback callback, 99 @Nullable Handler handler) { 100 startRanging(null, request, callback, handler); 101 } 102 103 /** 104 * Initiate a request to range to a set of devices specified in the {@link RangingRequest}. 105 * Results will be returned in the {@link RangingResultCallback} set of callbacks. 106 * 107 * @param workSource A mechanism to specify an alternative work-source for the request. 108 * @param request A request specifying a set of devices whose distance measurements are 109 * requested. 110 * @param callback A callback for the result of the ranging request. 111 * @param handler The Handler on whose thread to execute the callbacks of the {@code 112 * callback} object. If a null is provided then the application's main thread 113 * will be used. 114 * 115 * @hide (@SystemApi) 116 */ 117 @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE, 118 ACCESS_WIFI_STATE}) 119 public void startRanging(@Nullable WorkSource workSource, RangingRequest request, 120 RangingResultCallback callback, @Nullable Handler handler) { 121 if (VDBG) { 122 Log.v(TAG, "startRanging: workSource=" + workSource + ", request=" + request 123 + ", callback=" + callback + ", handler=" + handler); 124 } 125 126 Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper(); 127 Binder binder = new Binder(); 128 try { 129 mService.startRanging(binder, mContext.getOpPackageName(), workSource, request, 130 new RttCallbackProxy(looper, callback)); 131 } catch (RemoteException e) { 132 throw e.rethrowFromSystemServer(); 133 } 134 } 135 136 /** 137 * Cancel all ranging requests for the specified work sources. The requests have been requested 138 * using {@link #startRanging(WorkSource, RangingRequest, RangingResultCallback, Handler)}. 139 * 140 * @param workSource The work-sources of the requesters. 141 * 142 * @hide (@SystemApi) 143 */ 144 @RequiresPermission(allOf = {LOCATION_HARDWARE}) 145 public void cancelRanging(WorkSource workSource) { 146 if (VDBG) { 147 Log.v(TAG, "cancelRanging: workSource=" + workSource); 148 } 149 150 try { 151 mService.cancelRanging(workSource); 152 } catch (RemoteException e) { 153 throw e.rethrowFromSystemServer(); 154 } 155 } 156 157 private static class RttCallbackProxy extends IRttCallback.Stub { 158 private final Handler mHandler; 159 private final RangingResultCallback mCallback; 160 161 RttCallbackProxy(Looper looper, RangingResultCallback callback) { 162 mHandler = new Handler(looper); 163 mCallback = callback; 164 } 165 166 @Override 167 public void onRangingFailure(int status) throws RemoteException { 168 if (VDBG) Log.v(TAG, "RttCallbackProxy: onRangingFailure: status=" + status); 169 mHandler.post(() -> { 170 mCallback.onRangingFailure(status); 171 }); 172 } 173 174 @Override 175 public void onRangingResults(List<RangingResult> results) throws RemoteException { 176 if (VDBG) Log.v(TAG, "RttCallbackProxy: onRanginResults: results=" + results); 177 mHandler.post(() -> { 178 mCallback.onRangingResults(results); 179 }); 180 } 181 } 182} 183