• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wifi.hal;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.hardware.wifi.V1_0.IWifiRttControllerEventCallback;
22 import android.hardware.wifi.V1_0.RttConfig;
23 import android.hardware.wifi.V1_0.RttPeerType;
24 import android.hardware.wifi.V1_0.RttResult;
25 import android.hardware.wifi.V1_0.RttStatus;
26 import android.hardware.wifi.V1_0.RttType;
27 import android.hardware.wifi.V1_0.WifiStatus;
28 import android.hardware.wifi.V1_0.WifiStatusCode;
29 import android.hardware.wifi.V1_6.RttBw;
30 import android.hardware.wifi.V1_6.RttPreamble;
31 import android.hardware.wifi.V1_6.WifiChannelWidthInMhz;
32 import android.net.MacAddress;
33 import android.net.wifi.rtt.RangingRequest;
34 import android.net.wifi.rtt.RangingResult;
35 import android.net.wifi.rtt.ResponderConfig;
36 import android.net.wifi.rtt.ResponderLocation;
37 import android.os.RemoteException;
38 import android.util.Log;
39 
40 import com.android.server.wifi.util.GeneralUtil.Mutable;
41 import com.android.server.wifi.util.NativeUtil;
42 
43 import java.io.PrintWriter;
44 import java.util.ArrayList;
45 import java.util.HashSet;
46 import java.util.List;
47 import java.util.Objects;
48 import java.util.Set;
49 import java.util.function.Supplier;
50 
51 /**
52  * HIDL implementation of the IWifiRttController interface.
53  */
54 public class WifiRttControllerHidlImpl implements IWifiRttController {
55     private static final String TAG = "WifiRttControllerHidl";
56     private boolean mVerboseLoggingEnabled = false;
57 
58     private android.hardware.wifi.V1_0.IWifiRttController mWifiRttController;
59     private android.hardware.wifi.V1_4.IWifiRttController mWifiRttController14;
60     private android.hardware.wifi.V1_6.IWifiRttController mWifiRttController16;
61     private final WifiRttControllerEventCallback mWifiRttControllerEventCallback;
62     private final WifiRttControllerEventCallback14 mWifiRttControllerEventCallback14;
63     private final WifiRttControllerEventCallback16 mWifiRttControllerEventCallback16;
64     private WifiRttController.Capabilities mRttCapabilities;
65     private Set<WifiRttController.RttControllerRangingResultsCallback> mRangingResultsCallbacks =
66             new HashSet<>();
67 
WifiRttControllerHidlImpl( @onNull android.hardware.wifi.V1_0.IWifiRttController rttController)68     public WifiRttControllerHidlImpl(
69             @NonNull android.hardware.wifi.V1_0.IWifiRttController rttController) {
70         mWifiRttController = rttController;
71         mWifiRttController14 =
72                 android.hardware.wifi.V1_4.IWifiRttController.castFrom(mWifiRttController);
73         mWifiRttController16 =
74                 android.hardware.wifi.V1_6.IWifiRttController.castFrom(mWifiRttController);
75         mWifiRttControllerEventCallback = new WifiRttControllerEventCallback();
76         mWifiRttControllerEventCallback14 = new WifiRttControllerEventCallback14();
77         mWifiRttControllerEventCallback16 = new WifiRttControllerEventCallback16();
78     }
79 
80     /**
81      * See comments for {@link IWifiRttController#setup()}
82      */
setup()83     public boolean setup() {
84         final String methodStr = "setup";
85         return validateAndCall(methodStr, false,
86                 () -> setupInternal(methodStr));
87     }
88 
89     /**
90      * See comments for {@link IWifiRttController#enableVerboseLogging(boolean)}
91      */
enableVerboseLogging(boolean verbose)92     public void enableVerboseLogging(boolean verbose) {
93         mVerboseLoggingEnabled = verbose;
94     }
95 
96     /**
97      * See comments for {@link IWifiRttController#registerRangingResultsCallback(
98      *                         WifiRttController.RttControllerRangingResultsCallback)}
99      */
registerRangingResultsCallback( WifiRttController.RttControllerRangingResultsCallback callback)100     public void registerRangingResultsCallback(
101             WifiRttController.RttControllerRangingResultsCallback callback) {
102         if (!mRangingResultsCallbacks.add(callback)) {
103             Log.e(TAG, "Ranging results callback was already registered");
104         }
105     }
106 
107     /**
108      * See comments for {@link IWifiRttController#validate()}
109      */
validate()110     public boolean validate() {
111         final String methodStr = "validate";
112         return validateAndCall(methodStr, false,
113                 () -> validateInternal(methodStr));
114     }
115 
116     /**
117      * See comments for {@link IWifiRttController#getRttCapabilities()}
118      */
119     @Nullable
getRttCapabilities()120     public WifiRttController.Capabilities getRttCapabilities() {
121         return mRttCapabilities;
122     }
123 
124     /**
125      * See comments for {@link IWifiRttController#rangeRequest(int, RangingRequest)}
126      */
rangeRequest(int cmdId, RangingRequest request)127     public boolean rangeRequest(int cmdId, RangingRequest request) {
128         final String methodStr = "rangeRequest";
129         return validateAndCall(methodStr, false,
130                 () -> rangeRequestInternal(methodStr, cmdId, request));
131     }
132 
133     /**
134      * See comments for {@link IWifiRttController#rangeCancel(int, List)}
135      */
rangeCancel(int cmdId, List<MacAddress> macAddresses)136     public boolean rangeCancel(int cmdId, List<MacAddress> macAddresses) {
137         final String methodStr = "rangeCancel";
138         return validateAndCall(methodStr, false,
139                 () -> rangeCancelInternal(methodStr, cmdId, macAddresses));
140     }
141 
142     /**
143      * See comments for {@link IWifiRttController#dump(PrintWriter)}
144      */
dump(PrintWriter pw)145     public void dump(PrintWriter pw) {
146         pw.println("WifiRttController:");
147         pw.println("  mIWifiRttController: " + mWifiRttController);
148         pw.println("  mRttCapabilities: " + mRttCapabilities);
149     }
150 
151 
152     // Internal Implementations
153 
setupInternal(String methodStr)154     private boolean setupInternal(String methodStr) {
155         try {
156             if (mWifiRttController16 != null) {
157                 mWifiRttController16.registerEventCallback_1_6(mWifiRttControllerEventCallback16);
158             } else if (mWifiRttController14 != null) {
159                 mWifiRttController14.registerEventCallback_1_4(mWifiRttControllerEventCallback14);
160             } else {
161                 mWifiRttController.registerEventCallback(mWifiRttControllerEventCallback);
162             }
163         } catch (RemoteException e) {
164             handleRemoteException(e, methodStr);
165             return false;
166         }
167         updateRttCapabilities();
168         return true;
169     }
170 
validateInternal(String methodStr)171     private boolean validateInternal(String methodStr) {
172         Mutable<Boolean> isRttControllerValid = new Mutable<>(false);
173         try {
174             mWifiRttController.getBoundIface(
175                     (status, iface) -> {
176                         if (isOk(status, methodStr)) {
177                             isRttControllerValid.value = true;
178                         }
179                     });
180         } catch (RemoteException e) {
181             handleRemoteException(e, methodStr);
182         }
183         return isRttControllerValid.value;
184     }
185 
rangeRequestInternal(String methodStr, int cmdId, RangingRequest request)186     private boolean rangeRequestInternal(String methodStr, int cmdId, RangingRequest request) {
187         if (mVerboseLoggingEnabled) {
188             Log.v(TAG, "rangeRequest: cmdId=" + cmdId + ", # of requests="
189                     + request.mRttPeers.size() + ", request=" + request);
190         }
191 
192         updateRttCapabilities();
193         if (mWifiRttController16 != null) {
194             return sendRangeRequest16(cmdId, request);
195         } else if (mWifiRttController14 != null) {
196             return sendRangeRequest14(cmdId, request);
197         } else {
198             return sendRangeRequest(cmdId, request);
199         }
200     }
201 
sendRangeRequest(int cmdId, RangingRequest request)202     private boolean sendRangeRequest(int cmdId, RangingRequest request) {
203         final String methodStr = "sendRangeRequest";
204         ArrayList<RttConfig> rttConfig =
205                 convertRangingRequestToRttConfigs(request, mRttCapabilities);
206         if (rttConfig == null) {
207             Log.e(TAG, "sendRangeRequest: invalid request parameters");
208             return false;
209         }
210         if (rttConfig.size() == 0) {
211             Log.e(TAG, "sendRangeRequest: all requests invalidated");
212             dispatchOnRangingResults(cmdId, new ArrayList<>());
213             return true;
214         }
215 
216         try {
217             WifiStatus status = mWifiRttController.rangeRequest(cmdId, rttConfig);
218             return isOk(status, methodStr);
219         } catch (RemoteException e) {
220             handleRemoteException(e, methodStr);
221             return false;
222         }
223     }
224 
sendRangeRequest14(int cmdId, RangingRequest request)225     private boolean sendRangeRequest14(int cmdId, RangingRequest request) {
226         final String methodStr = "sendRangeRequest14";
227         ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfig =
228                 convertRangingRequestToRttConfigs14(request, mRttCapabilities);
229         if (rttConfig == null) {
230             Log.e(TAG, "sendRangeRequest14: invalid request parameters");
231             return false;
232         }
233         if (rttConfig.size() == 0) {
234             Log.e(TAG, "sendRangeRequest14: all requests invalidated");
235             dispatchOnRangingResults(cmdId, new ArrayList<>());
236             return true;
237         }
238 
239         try {
240             WifiStatus status = mWifiRttController14.rangeRequest_1_4(cmdId, rttConfig);
241             return isOk(status, methodStr);
242         } catch (RemoteException e) {
243             handleRemoteException(e, methodStr);
244             return false;
245         }
246     }
247 
sendRangeRequest16(int cmdId, RangingRequest request)248     private boolean sendRangeRequest16(int cmdId, RangingRequest request) {
249         final String methodStr = "sendRangeRequest16";
250         ArrayList<android.hardware.wifi.V1_6.RttConfig> rttConfig =
251                 convertRangingRequestToRttConfigs16(request, mRttCapabilities);
252         if (rttConfig == null) {
253             Log.e(TAG, "sendRangeRequest16: invalid request parameters");
254             return false;
255         }
256         if (rttConfig.size() == 0) {
257             Log.e(TAG, "sendRangeRequest16: all requests invalidated");
258             dispatchOnRangingResults(cmdId, new ArrayList<>());
259             return true;
260         }
261 
262         try {
263             WifiStatus status = mWifiRttController16.rangeRequest_1_6(cmdId, rttConfig);
264             return isOk(status, methodStr);
265         } catch (RemoteException e) {
266             handleRemoteException(e, methodStr);
267             return false;
268         }
269     }
270 
rangeCancelInternal(String methodStr, int cmdId, List<MacAddress> macAddresses)271     boolean rangeCancelInternal(String methodStr, int cmdId, List<MacAddress> macAddresses) {
272         if (mVerboseLoggingEnabled) Log.v(TAG, "rangeCancel: cmdId=" + cmdId);
273         try {
274             ArrayList<byte[]> macBytes = new ArrayList<>();
275             for (MacAddress mac : macAddresses) {
276                 macBytes.add(mac.toByteArray());
277             }
278             WifiStatus status = mWifiRttController.rangeCancel(cmdId, macBytes);
279             return isOk(status, methodStr);
280         } catch (RemoteException e) {
281             handleRemoteException(e, methodStr);
282             return false;
283         }
284     }
285 
286     /**
287      *  Callback for HAL events on 1.0 WifiRttController
288      */
289     private class WifiRttControllerEventCallback extends IWifiRttControllerEventCallback.Stub {
290         /**
291          * Callback from the HAL with range results.
292          *
293          * @param cmdId Command ID specified in the original request.
294          * @param halResults A list of range results.
295          */
296         @Override
onResults(int cmdId, ArrayList<RttResult> halResults)297         public void onResults(int cmdId, ArrayList<RttResult> halResults) {
298             if (mVerboseLoggingEnabled) {
299                 int numResults = halResults != null ? halResults.size() : -1;
300                 Log.v(TAG, "onResults: cmdId=" + cmdId + ", # of results=" + numResults);
301             }
302             if (halResults == null) {
303                 halResults = new ArrayList<>();
304             }
305             halResults.removeIf(Objects::isNull);
306             ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults(halResults);
307             dispatchOnRangingResults(cmdId, rangingResults);
308         }
309     }
310 
311     /**
312      *  Callback for HAL events on 1.4 WifiRttController
313      */
314     private class WifiRttControllerEventCallback14 extends
315             android.hardware.wifi.V1_4.IWifiRttControllerEventCallback.Stub {
316         @Override
onResults(int cmdId, ArrayList<RttResult> halResults)317         public void onResults(int cmdId, ArrayList<RttResult> halResults) {
318             // This callback is not supported on this version of the interface.
319             return;
320         }
321 
322         @Override
onResults_1_4(int cmdId, ArrayList<android.hardware.wifi.V1_4.RttResult> halResults)323         public void onResults_1_4(int cmdId,
324                 ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) {
325             if (mVerboseLoggingEnabled) {
326                 int numResults = halResults != null ? halResults.size() : -1;
327                 Log.v(TAG, "onResults_1_4: cmdId=" + cmdId + ", # of results=" + numResults);
328             }
329             if (halResults == null) {
330                 halResults = new ArrayList<>();
331             }
332             halResults.removeIf(Objects::isNull);
333             ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults14(halResults);
334             dispatchOnRangingResults(cmdId, rangingResults);
335         }
336     }
337 
338     /**
339      *  Callback for HAL events on 1.6 WifiRttController
340      */
341     private class WifiRttControllerEventCallback16 extends
342             android.hardware.wifi.V1_6.IWifiRttControllerEventCallback.Stub {
343         @Override
onResults(int cmdId, ArrayList<RttResult> halResults)344         public void onResults(int cmdId, ArrayList<RttResult> halResults) {
345             // This callback is not supported on this version of the interface.
346             return;
347         }
348 
349         @Override
onResults_1_4(int cmdId, ArrayList<android.hardware.wifi.V1_4.RttResult> halResults)350         public void onResults_1_4(int cmdId,
351                 ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) {
352             // This callback is not supported on this version of the interface.
353             return;
354         }
355 
356         @Override
onResults_1_6(int cmdId, ArrayList<android.hardware.wifi.V1_6.RttResult> halResults)357         public void onResults_1_6(int cmdId,
358                 ArrayList<android.hardware.wifi.V1_6.RttResult> halResults) {
359             if (mVerboseLoggingEnabled) {
360                 int numResults = halResults != null ? halResults.size() : -1;
361                 Log.v(TAG, "onResults_1_6: cmdId=" + cmdId + ", # of results=" + numResults);
362             }
363             if (halResults == null) {
364                 halResults = new ArrayList<>();
365             }
366             halResults.removeIf(Objects::isNull);
367             ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults16(halResults);
368             dispatchOnRangingResults(cmdId, rangingResults);
369         }
370     }
371 
372 
373     // Helper Functions
374 
convertHalResultsRangingResults( ArrayList<RttResult> halResults)375     private ArrayList<RangingResult> convertHalResultsRangingResults(
376             ArrayList<RttResult> halResults) {
377         ArrayList<RangingResult> rangingResults = new ArrayList<>();
378         for (RttResult rttResult : halResults) {
379             byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data);
380             byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data);
381             ResponderLocation responderLocation;
382             try {
383                 responderLocation = new ResponderLocation(lci, lcr);
384                 if (!responderLocation.isValid()) {
385                     responderLocation = null;
386                 }
387             } catch (Exception e) {
388                 responderLocation = null;
389                 Log.e(TAG,
390                         "ResponderLocation: lci/lcr parser failed exception -- " + e);
391             }
392             if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) {
393                 if (mVerboseLoggingEnabled) {
394                     Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num "
395                             + "samples!? result=" + rttResult);
396                 }
397                 rttResult.distanceSdInMm = 0;
398             }
399             rangingResults.add(new RangingResult.Builder()
400                     .setStatus(convertHalStatusToFrameworkStatus(rttResult.status))
401                     .setMacAddress(MacAddress.fromBytes(rttResult.addr))
402                     .setDistanceMm(rttResult.distanceInMm)
403                     .setDistanceStdDevMm(rttResult.distanceSdInMm)
404                     .setRssi(rttResult.rssi / -2)
405                     .setNumAttemptedMeasurements(rttResult.numberPerBurstPeer)
406                     .setNumSuccessfulMeasurements(rttResult.successNumber)
407                     .setLci(lci)
408                     .setLcr(lcr)
409                     .setUnverifiedResponderLocation(responderLocation)
410                     .setRangingTimestampMillis(
411                             rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS)
412                     .set80211mcMeasurement(rttResult.type == RttType.TWO_SIDED)
413                     .build());
414         }
415         return rangingResults;
416     }
417 
convertHalResultsRangingResults14( ArrayList<android.hardware.wifi.V1_4.RttResult> halResults)418     private ArrayList<RangingResult> convertHalResultsRangingResults14(
419             ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) {
420         ArrayList<RangingResult> rangingResults = new ArrayList<>();
421         for (android.hardware.wifi.V1_4.RttResult rttResult : halResults) {
422             byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data);
423             byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data);
424             ResponderLocation responderLocation;
425             try {
426                 responderLocation = new ResponderLocation(lci, lcr);
427                 if (!responderLocation.isValid()) {
428                     responderLocation = null;
429                 }
430             } catch (Exception e) {
431                 responderLocation = null;
432                 Log.e(TAG,
433                         "ResponderLocation: lci/lcr parser failed exception -- " + e);
434             }
435             if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) {
436                 if (mVerboseLoggingEnabled) {
437                     Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num "
438                             + "samples!? result=" + rttResult);
439                 }
440                 rttResult.distanceSdInMm = 0;
441             }
442             rangingResults.add(new RangingResult.Builder()
443                     .setStatus(convertHalStatusToFrameworkStatus(rttResult.status))
444                     .setMacAddress(MacAddress.fromBytes(rttResult.addr))
445                     .setDistanceMm(rttResult.distanceInMm)
446                     .setDistanceStdDevMm(rttResult.distanceSdInMm)
447                     .setRssi(rttResult.rssi / -2)
448                     .setNumAttemptedMeasurements(rttResult.numberPerBurstPeer)
449                     .setNumSuccessfulMeasurements(rttResult.successNumber)
450                     .setLci(lci)
451                     .setLcr(lcr)
452                     .setUnverifiedResponderLocation(responderLocation)
453                     .setRangingTimestampMillis(
454                             rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS)
455                     .set80211mcMeasurement(rttResult.type == RttType.TWO_SIDED)
456                     .build());
457         }
458         return rangingResults;
459     }
460 
convertHalResultsRangingResults16( ArrayList<android.hardware.wifi.V1_6.RttResult> halResults)461     private ArrayList<RangingResult> convertHalResultsRangingResults16(
462             ArrayList<android.hardware.wifi.V1_6.RttResult> halResults) {
463         ArrayList<RangingResult> rangingResults = new ArrayList<>();
464         for (android.hardware.wifi.V1_6.RttResult rttResult : halResults) {
465             byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data);
466             byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data);
467             ResponderLocation responderLocation;
468             try {
469                 responderLocation = new ResponderLocation(lci, lcr);
470                 if (!responderLocation.isValid()) {
471                     responderLocation = null;
472                 }
473             } catch (Exception e) {
474                 responderLocation = null;
475                 Log.e(TAG,
476                         "ResponderLocation: lci/lcr parser failed exception -- " + e);
477             }
478             if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) {
479                 if (mVerboseLoggingEnabled) {
480                     Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num "
481                             + "samples!? result=" + rttResult);
482                 }
483                 rttResult.distanceSdInMm = 0;
484             }
485             rangingResults.add(new RangingResult.Builder()
486                     .setStatus(convertHalStatusToFrameworkStatus(rttResult.status))
487                     .setMacAddress(MacAddress.fromBytes(rttResult.addr))
488                     .setDistanceMm(rttResult.distanceInMm)
489                     .setDistanceStdDevMm(rttResult.distanceSdInMm)
490                     .setRssi(rttResult.rssi / -2)
491                     .setNumAttemptedMeasurements(rttResult.numberPerBurstPeer)
492                     .setNumSuccessfulMeasurements(rttResult.successNumber)
493                     .setLci(lci)
494                     .setLcr(lcr)
495                     .setUnverifiedResponderLocation(responderLocation)
496                     .setRangingTimestampMillis(
497                             rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS)
498                     .set80211mcMeasurement(rttResult.type == RttType.TWO_SIDED)
499                     .build());
500         }
501         return rangingResults;
502     }
503 
504     private @WifiRttController.FrameworkRttStatus
convertHalStatusToFrameworkStatus(int halStatus)505             int convertHalStatusToFrameworkStatus(int halStatus) {
506         switch (halStatus) {
507             case RttStatus.SUCCESS:
508                 return WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS;
509             case RttStatus.FAILURE:
510                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAILURE;
511             case RttStatus.FAIL_NO_RSP:
512                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP;
513             case RttStatus.FAIL_REJECTED:
514                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_REJECTED;
515             case RttStatus.FAIL_NOT_SCHEDULED_YET:
516                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET;
517             case RttStatus.FAIL_TM_TIMEOUT:
518                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT;
519             case RttStatus.FAIL_AP_ON_DIFF_CHANNEL:
520                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL;
521             case RttStatus.FAIL_NO_CAPABILITY:
522                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY;
523             case RttStatus.ABORTED:
524                 return WifiRttController.FRAMEWORK_RTT_STATUS_ABORTED;
525             case RttStatus.FAIL_INVALID_TS:
526                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS;
527             case RttStatus.FAIL_PROTOCOL:
528                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL;
529             case RttStatus.FAIL_SCHEDULE:
530                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE;
531             case RttStatus.FAIL_BUSY_TRY_LATER:
532                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER;
533             case RttStatus.INVALID_REQ:
534                 return WifiRttController.FRAMEWORK_RTT_STATUS_INVALID_REQ;
535             case RttStatus.NO_WIFI:
536                 return WifiRttController.FRAMEWORK_RTT_STATUS_NO_WIFI;
537             case RttStatus.FAIL_FTM_PARAM_OVERRIDE:
538                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE;
539             default:
540                 Log.e(TAG, "Unrecognized RttStatus: " + halStatus);
541                 return WifiRttController.FRAMEWORK_RTT_STATUS_UNKNOWN;
542         }
543     }
544 
updateRttCapabilities()545     private void updateRttCapabilities() {
546         if (mRttCapabilities != null) return;
547         if (mVerboseLoggingEnabled) Log.v(TAG, "updateRttCapabilities");
548 
549         try {
550             if (mWifiRttController16 != null) {
551                 mWifiRttController16.getCapabilities_1_6(
552                         (status, capabilities16) -> {
553                             if (status.code != WifiStatusCode.SUCCESS) {
554                                 Log.e(TAG, "updateRttCapabilities:"
555                                         + " error requesting capabilities "
556                                         + "-- code=" + status.code);
557                                 return;
558                             }
559                             if (mVerboseLoggingEnabled) {
560                                 Log.v(TAG, "updateRttCapabilities: RTT capabilities="
561                                         + capabilities16);
562                             }
563                             mRttCapabilities = new WifiRttController.Capabilities(capabilities16);
564                         });
565             } else if (mWifiRttController14 != null) {
566                 mWifiRttController14.getCapabilities_1_4(
567                         (status, capabilities14) -> {
568                             if (status.code != WifiStatusCode.SUCCESS) {
569                                 Log.e(TAG, "updateRttCapabilities:"
570                                         + " error requesting capabilities "
571                                         + "-- code=" + status.code);
572                                 return;
573                             }
574                             if (mVerboseLoggingEnabled) {
575                                 Log.v(TAG, "updateRttCapabilities: RTT capabilities="
576                                         + capabilities14);
577                             }
578                             mRttCapabilities = new WifiRttController.Capabilities(capabilities14);
579                         });
580             } else {
581                 mWifiRttController.getCapabilities(
582                         (status, capabilities) -> {
583                             if (status.code != WifiStatusCode.SUCCESS) {
584                                 Log.e(TAG, "updateRttCapabilities:"
585                                         + " error requesting capabilities "
586                                         + "-- code=" + status.code);
587                                 return;
588                             }
589                             if (mVerboseLoggingEnabled) {
590                                 Log.v(TAG, "updateRttCapabilities: RTT capabilities="
591                                         + capabilities);
592                             }
593                             mRttCapabilities = new WifiRttController.Capabilities(capabilities);
594                         });
595 
596             }
597         } catch (RemoteException e) {
598             handleRemoteException(e, "updateRttCapabilities");
599         }
600 
601         if (mRttCapabilities != null && !mRttCapabilities.rttFtmSupported) {
602             Log.wtf(TAG, "Firmware indicates RTT is not supported - but device supports RTT - "
603                     + "ignored!?");
604         }
605     }
606 
convertRangingRequestToRttConfigs( RangingRequest request, WifiRttController.Capabilities cap)607     private static ArrayList<RttConfig> convertRangingRequestToRttConfigs(
608             RangingRequest request, WifiRttController.Capabilities cap) {
609         ArrayList<RttConfig> rttConfigs = new ArrayList<>(request.mRttPeers.size());
610 
611         // Skip any configurations which have an error (just print out a message).
612         // The caller will only get results for valid configurations.
613         for (ResponderConfig responder: request.mRttPeers) {
614             RttConfig config = new RttConfig();
615 
616             System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0,
617                     config.addr.length);
618 
619             try {
620                 config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED;
621                 if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) {
622                     Log.w(TAG, "Device does not support one-sided RTT");
623                     continue;
624                 }
625 
626                 config.peer = halRttPeerTypeFromResponderType(responder.responderType);
627                 config.channel.width = halChannelWidthFromResponderChannelWidth(
628                         responder.channelWidth);
629                 config.channel.centerFreq = responder.frequency;
630                 config.channel.centerFreq0 = responder.centerFreq0;
631                 config.channel.centerFreq1 = responder.centerFreq1;
632                 config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth);
633                 config.preamble = halRttPreambleFromResponderPreamble(responder.preamble);
634                 validateBwAndPreambleCombination(config.bw, config.preamble);
635 
636                 if (config.peer == RttPeerType.NAN) {
637                     config.mustRequestLci = false;
638                     config.mustRequestLcr = false;
639                     config.burstPeriod = 0;
640                     config.numBurst = 0;
641                     config.numFramesPerBurst = request.mRttBurstSize;
642                     config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT
643                     config.numRetriesPerFtmr = 3;
644                     config.burstDuration = 9;
645                 } else { // AP + all non-NAN requests
646                     config.mustRequestLci = true;
647                     config.mustRequestLcr = true;
648                     config.burstPeriod = 0;
649                     config.numBurst = 0;
650                     config.numFramesPerBurst = request.mRttBurstSize;
651                     config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3);
652                     config.numRetriesPerFtmr = 3;
653                     config.burstDuration = 9;
654 
655                     if (cap != null) { // constrain parameters per device capabilities
656                         config.mustRequestLci = config.mustRequestLci && cap.lciSupported;
657                         config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported;
658                         config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap);
659                         config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap);
660                     }
661                 }
662             } catch (IllegalArgumentException e) {
663                 Log.e(TAG, "Invalid configuration: " + e.getMessage());
664                 continue;
665             }
666 
667             rttConfigs.add(config);
668         }
669 
670         return rttConfigs;
671     }
672 
validateBwAndPreambleCombination(int bw, int preamble)673     private static void validateBwAndPreambleCombination(int bw, int preamble) {
674         if (bw <= RttBw.BW_20MHZ) {
675             return;
676         }
677         if (bw == RttBw.BW_40MHZ && preamble >= RttPreamble.HT) {
678             return;
679         }
680         if (bw == RttBw.BW_320MHZ && preamble == RttPreamble.EHT) {
681             return;
682         }
683         if (bw >= RttBw.BW_80MHZ && bw < RttBw.BW_320MHZ && preamble >= RttPreamble.VHT) {
684             return;
685         }
686         throw new IllegalArgumentException(
687                 "bw and preamble combination is invalid, bw: " + bw + " preamble: " + preamble);
688     }
689 
690     private static ArrayList<android.hardware.wifi.V1_4.RttConfig>
convertRangingRequestToRttConfigs14(RangingRequest request, WifiRttController.Capabilities cap)691             convertRangingRequestToRttConfigs14(RangingRequest request,
692             WifiRttController.Capabilities cap) {
693         ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfigs =
694                 new ArrayList<>(request.mRttPeers.size());
695 
696         // Skip any configurations which have an error (just print out a message).
697         // The caller will only get results for valid configurations.
698         for (ResponderConfig responder: request.mRttPeers) {
699             android.hardware.wifi.V1_4.RttConfig config =
700                     new android.hardware.wifi.V1_4.RttConfig();
701             System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0,
702                     config.addr.length);
703 
704             try {
705                 config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED;
706                 if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) {
707                     Log.w(TAG, "Device does not support one-sided RTT");
708                     continue;
709                 }
710 
711                 config.peer = halRttPeerTypeFromResponderType(responder.responderType);
712                 config.channel.width = halChannelWidthFromResponderChannelWidth(
713                         responder.channelWidth);
714                 config.channel.centerFreq = responder.frequency;
715                 config.channel.centerFreq0 = responder.centerFreq0;
716                 config.channel.centerFreq1 = responder.centerFreq1;
717                 config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth);
718                 config.preamble = halRttPreamble14FromResponderPreamble(responder.preamble);
719 
720                 if (config.peer == RttPeerType.NAN) {
721                     config.mustRequestLci = false;
722                     config.mustRequestLcr = false;
723                     config.burstPeriod = 0;
724                     config.numBurst = 0;
725                     config.numFramesPerBurst = request.mRttBurstSize;
726                     config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT
727                     config.numRetriesPerFtmr = 3;
728                     config.burstDuration = 9;
729                 } else { // AP + all non-NAN requests
730                     config.mustRequestLci = true;
731                     config.mustRequestLcr = true;
732                     config.burstPeriod = 0;
733                     config.numBurst = 0;
734                     config.numFramesPerBurst = request.mRttBurstSize;
735                     config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3);
736                     config.numRetriesPerFtmr = 3;
737                     config.burstDuration = 9;
738 
739                     if (cap != null) { // constrain parameters per device capabilities
740                         config.mustRequestLci = config.mustRequestLci && cap.lciSupported;
741                         config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported;
742                         config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap);
743                         config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap);
744                     }
745                 }
746             } catch (IllegalArgumentException e) {
747                 Log.e(TAG, "Invalid configuration: " + e.getMessage());
748                 continue;
749             }
750 
751             rttConfigs.add(config);
752         }
753 
754         return rttConfigs;
755     }
756 
757     private static ArrayList<android.hardware.wifi.V1_6.RttConfig>
convertRangingRequestToRttConfigs16(RangingRequest request, WifiRttController.Capabilities cap)758             convertRangingRequestToRttConfigs16(RangingRequest request,
759             WifiRttController.Capabilities cap) {
760         ArrayList<android.hardware.wifi.V1_6.RttConfig> rttConfigs =
761                 new ArrayList<>(request.mRttPeers.size());
762 
763         // Skip any configurations which have an error (just print out a message).
764         // The caller will only get results for valid configurations.
765         for (ResponderConfig responder: request.mRttPeers) {
766             android.hardware.wifi.V1_6.RttConfig config =
767                     new android.hardware.wifi.V1_6.RttConfig();
768             System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0,
769                     config.addr.length);
770 
771             try {
772                 config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED;
773                 if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) {
774                     Log.w(TAG, "Device does not support one-sided RTT");
775                     continue;
776                 }
777 
778                 config.peer = halRttPeerTypeFromResponderType(responder.responderType);
779                 config.channel.width = halChannelWidthFromResponderChannelWidth(
780                         responder.channelWidth);
781                 config.channel.centerFreq = responder.frequency;
782                 config.channel.centerFreq0 = responder.centerFreq0;
783                 config.channel.centerFreq1 = responder.centerFreq1;
784                 config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth);
785                 config.preamble = halRttPreamble14FromResponderPreamble(responder.preamble);
786 
787                 if (config.peer == RttPeerType.NAN) {
788                     config.mustRequestLci = false;
789                     config.mustRequestLcr = false;
790                     config.burstPeriod = 0;
791                     config.numBurst = 0;
792                     config.numFramesPerBurst = request.mRttBurstSize;
793                     config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT
794                     config.numRetriesPerFtmr = 3;
795                     config.burstDuration = 9;
796                 } else { // AP + all non-NAN requests
797                     config.mustRequestLci = true;
798                     config.mustRequestLcr = true;
799                     config.burstPeriod = 0;
800                     config.numBurst = 0;
801                     config.numFramesPerBurst = request.mRttBurstSize;
802                     config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3);
803                     config.numRetriesPerFtmr = 3;
804                     config.burstDuration = 9;
805 
806                     if (cap != null) { // constrain parameters per device capabilities
807                         config.mustRequestLci = config.mustRequestLci && cap.lciSupported;
808                         config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported;
809                         config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap);
810                         config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap);
811                     }
812                 }
813             } catch (IllegalArgumentException e) {
814                 Log.e(TAG, "Invalid configuration: " + e.getMessage());
815                 continue;
816             }
817 
818             rttConfigs.add(config);
819         }
820 
821         return rttConfigs;
822     }
823 
halRttPeerTypeFromResponderType(int responderType)824     private static int halRttPeerTypeFromResponderType(int responderType) {
825         switch (responderType) {
826             case ResponderConfig.RESPONDER_AP:
827                 return RttPeerType.AP;
828             case ResponderConfig.RESPONDER_STA:
829                 return RttPeerType.STA;
830             case ResponderConfig.RESPONDER_P2P_GO:
831                 return RttPeerType.P2P_GO;
832             case ResponderConfig.RESPONDER_P2P_CLIENT:
833                 return RttPeerType.P2P_CLIENT;
834             case ResponderConfig.RESPONDER_AWARE:
835                 return RttPeerType.NAN;
836             default:
837                 throw new IllegalArgumentException(
838                         "halRttPeerTypeFromResponderType: bad " + responderType);
839         }
840     }
841 
halChannelWidthFromResponderChannelWidth(int responderChannelWidth)842     private static int halChannelWidthFromResponderChannelWidth(int responderChannelWidth) {
843         switch (responderChannelWidth) {
844             case ResponderConfig.CHANNEL_WIDTH_20MHZ:
845                 return WifiChannelWidthInMhz.WIDTH_20;
846             case ResponderConfig.CHANNEL_WIDTH_40MHZ:
847                 return WifiChannelWidthInMhz.WIDTH_40;
848             case ResponderConfig.CHANNEL_WIDTH_80MHZ:
849                 return WifiChannelWidthInMhz.WIDTH_80;
850             case ResponderConfig.CHANNEL_WIDTH_160MHZ:
851                 return WifiChannelWidthInMhz.WIDTH_160;
852             case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
853                 return WifiChannelWidthInMhz.WIDTH_80P80;
854             case ResponderConfig.CHANNEL_WIDTH_320MHZ:
855                 return WifiChannelWidthInMhz.WIDTH_320;
856             default:
857                 throw new IllegalArgumentException(
858                         "halChannelWidthFromResponderChannelWidth: bad " + responderChannelWidth);
859         }
860     }
861 
halRttChannelBandwidthFromResponderChannelWidth(int responderChannelWidth)862     private static int halRttChannelBandwidthFromResponderChannelWidth(int responderChannelWidth) {
863         switch (responderChannelWidth) {
864             case ResponderConfig.CHANNEL_WIDTH_20MHZ:
865                 return RttBw.BW_20MHZ;
866             case ResponderConfig.CHANNEL_WIDTH_40MHZ:
867                 return RttBw.BW_40MHZ;
868             case ResponderConfig.CHANNEL_WIDTH_80MHZ:
869                 return RttBw.BW_80MHZ;
870             case ResponderConfig.CHANNEL_WIDTH_160MHZ:
871             case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
872                 return RttBw.BW_160MHZ;
873             case ResponderConfig.CHANNEL_WIDTH_320MHZ:
874                 return RttBw.BW_320MHZ;
875             default:
876                 throw new IllegalArgumentException(
877                         "halRttChannelBandwidthFromHalBandwidth: bad " + responderChannelWidth);
878         }
879     }
880 
halRttPreambleFromResponderPreamble(int responderPreamble)881     private static int halRttPreambleFromResponderPreamble(int responderPreamble) {
882         switch (responderPreamble) {
883             case ResponderConfig.PREAMBLE_LEGACY:
884                 return RttPreamble.LEGACY;
885             case ResponderConfig.PREAMBLE_HT:
886                 return RttPreamble.HT;
887             case ResponderConfig.PREAMBLE_VHT:
888                 return RttPreamble.VHT;
889             case ResponderConfig.PREAMBLE_HE:
890                 return RttPreamble.HE;
891             case ResponderConfig.PREAMBLE_EHT:
892                 return RttPreamble.EHT;
893             default:
894                 throw new IllegalArgumentException(
895                         "halRttPreambleFromResponderPreamble: bad " + responderPreamble);
896         }
897     }
898 
halRttPreamble14FromResponderPreamble(int responderPreamble)899     private static int halRttPreamble14FromResponderPreamble(int responderPreamble) {
900         switch (responderPreamble) {
901             case ResponderConfig.PREAMBLE_LEGACY:
902                 return RttPreamble.LEGACY;
903             case ResponderConfig.PREAMBLE_HT:
904                 return RttPreamble.HT;
905             case ResponderConfig.PREAMBLE_VHT:
906                 return RttPreamble.VHT;
907             case ResponderConfig.PREAMBLE_HE:
908                 return RttPreamble.HE;
909             default:
910                 throw new IllegalArgumentException(
911                         "halRttPreamble14FromResponderPreamble: bad " + responderPreamble);
912         }
913     }
914 
915     /**
916      * Check whether the selected RTT channel bandwidth is supported by the device.
917      * If supported, return the requested bandwidth.
918      * If not supported, return the next lower bandwidth which is supported.
919      * If none, throw an IllegalArgumentException.
920      *
921      * Note: the halRttChannelBandwidth is a single bit flag from the HAL RttBw type.
922      */
halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, WifiRttController.Capabilities cap)923     private static int halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth,
924             WifiRttController.Capabilities cap) {
925         int requestedBandwidth = halRttChannelBandwidth;
926         while ((halRttChannelBandwidth != 0) && ((halRttChannelBandwidth & cap.bwSupported) == 0)) {
927             halRttChannelBandwidth >>= 1;
928         }
929 
930         if (halRttChannelBandwidth != 0) {
931             return halRttChannelBandwidth;
932         }
933 
934         throw new IllegalArgumentException(
935                 "RTT BW=" + requestedBandwidth + ", not supported by device capabilities=" + cap
936                         + " - and no supported alternative");
937     }
938 
939     /**
940      * Check whether the selected RTT preamble is supported by the device.
941      * If supported, return the requested preamble.
942      * If not supported, return the next "lower" preamble which is supported.
943      * If none, throw an IllegalArgumentException.
944      *
945      * Note: the halRttPreamble is a single bit flag from the HAL RttPreamble type.
946      */
halRttPreambleCapabilityLimiter(int halRttPreamble, WifiRttController.Capabilities cap)947     private static int halRttPreambleCapabilityLimiter(int halRttPreamble,
948             WifiRttController.Capabilities cap) {
949         int requestedPreamble = halRttPreamble;
950         while ((halRttPreamble != 0) && ((halRttPreamble & cap.preambleSupported) == 0)) {
951             halRttPreamble >>= 1;
952         }
953 
954         if (halRttPreamble != 0) {
955             return halRttPreamble;
956         }
957 
958         throw new IllegalArgumentException(
959                 "RTT Preamble=" + requestedPreamble + ", not supported by device capabilities="
960                         + cap + " - and no supported alternative");
961     }
962 
dispatchOnRangingResults(int cmdId, List<RangingResult> rangingResults)963     private void dispatchOnRangingResults(int cmdId, List<RangingResult> rangingResults) {
964         for (WifiRttController.RttControllerRangingResultsCallback
965                 callback : mRangingResultsCallbacks) {
966             callback.onRangingResults(cmdId, rangingResults);
967         }
968     }
969 
isOk(WifiStatus status, String methodStr)970     private boolean isOk(WifiStatus status, String methodStr) {
971         if (status.code == WifiStatusCode.SUCCESS) return true;
972         Log.e(TAG, methodStr + " failed with status: " + status);
973         return false;
974     }
975 
handleRemoteException(RemoteException e, String methodStr)976     private void handleRemoteException(RemoteException e, String methodStr) {
977         Log.e(TAG, methodStr + " failed with remote exception: " + e);
978         mWifiRttController = null;
979     }
980 
validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier)981     private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) {
982         if (mWifiRttController == null) {
983             Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiRttController is null");
984             return defaultVal;
985         }
986         return supplier.get();
987     }
988 }
989