• 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.IWifiRttControllerEventCallback;
22 import android.hardware.wifi.RttBw;
23 import android.hardware.wifi.RttCapabilities;
24 import android.hardware.wifi.RttConfig;
25 import android.hardware.wifi.RttPeerType;
26 import android.hardware.wifi.RttPreamble;
27 import android.hardware.wifi.RttResult;
28 import android.hardware.wifi.RttStatus;
29 import android.hardware.wifi.RttType;
30 import android.hardware.wifi.WifiChannelInfo;
31 import android.hardware.wifi.WifiChannelWidthInMhz;
32 import android.hardware.wifi.common.OuiKeyedData;
33 import android.net.MacAddress;
34 import android.net.wifi.ScanResult;
35 import android.net.wifi.WifiAnnotations;
36 import android.net.wifi.rtt.RangingRequest;
37 import android.net.wifi.rtt.RangingResult;
38 import android.net.wifi.rtt.ResponderConfig;
39 import android.net.wifi.rtt.ResponderLocation;
40 import android.os.RemoteException;
41 import android.os.ServiceSpecificException;
42 import android.util.Log;
43 
44 import com.android.modules.utils.build.SdkLevel;
45 import com.android.server.wifi.util.HalAidlUtil;
46 
47 import java.io.PrintWriter;
48 import java.util.ArrayList;
49 import java.util.HashSet;
50 import java.util.List;
51 import java.util.Set;
52 
53 /**
54  * AIDL implementation of the IWifiRttController interface.
55  */
56 public class WifiRttControllerAidlImpl implements IWifiRttController {
57     private static final String TAG = "WifiRttControllerAidl";
58     private boolean mVerboseLoggingEnabled = false;
59 
60     private android.hardware.wifi.IWifiRttController mWifiRttController;
61     private WifiRttController.Capabilities mRttCapabilities;
62     private WifiRttControllerEventCallback mHalCallback;
63     private Set<WifiRttController.RttControllerRangingResultsCallback> mRangingResultsCallbacks =
64             new HashSet<>();
65     private final Object mLock = new Object();
66 
WifiRttControllerAidlImpl( @onNull android.hardware.wifi.IWifiRttController rttController)67     public WifiRttControllerAidlImpl(
68             @NonNull android.hardware.wifi.IWifiRttController rttController) {
69         mWifiRttController = rttController;
70         mHalCallback = new WifiRttControllerEventCallback();
71     }
72 
73     /**
74      * See comments for {@link IWifiRttController#setup()}
75      */
76     @Override
setup()77     public boolean setup() {
78         final String methodStr = "setup";
79         synchronized (mLock) {
80             if (!checkIfaceAndLogFailure(methodStr)) return false;
81             try {
82                 mWifiRttController.registerEventCallback(mHalCallback);
83             } catch (RemoteException e) {
84                 handleRemoteException(e, methodStr);
85                 return false;
86             } catch (ServiceSpecificException e) {
87                 handleServiceSpecificException(e, methodStr);
88             }
89             updateRttCapabilities();
90             return true;
91         }
92     }
93 
94     /**
95      * See comments for {@link IWifiRttController#enableVerboseLogging(boolean)}
96      */
97     @Override
enableVerboseLogging(boolean verbose)98     public void enableVerboseLogging(boolean verbose) {
99         synchronized (mLock) {
100             mVerboseLoggingEnabled = verbose;
101         }
102     }
103 
104     /**
105      * See comments for {@link IWifiRttController#registerRangingResultsCallback(
106      *                         WifiRttController.RttControllerRangingResultsCallback)}
107      */
108     @Override
registerRangingResultsCallback( WifiRttController.RttControllerRangingResultsCallback callback)109     public void registerRangingResultsCallback(
110             WifiRttController.RttControllerRangingResultsCallback callback) {
111         synchronized (mLock) {
112             if (!mRangingResultsCallbacks.add(callback)) {
113                 Log.e(TAG, "Ranging results callback was already registered");
114             }
115         }
116     }
117 
118     /**
119      * See comments for {@link IWifiRttController#validate()}
120      */
121     @Override
validate()122     public boolean validate() {
123         final String methodStr = "validate";
124         synchronized (mLock) {
125             if (!checkIfaceAndLogFailure(methodStr)) return false;
126             try {
127                 // Just check that we can call this method successfully.
128                 mWifiRttController.getBoundIface();
129                 return true;
130             } catch (RemoteException e) {
131                 handleRemoteException(e, methodStr);
132             } catch (ServiceSpecificException e) {
133                 handleServiceSpecificException(e, methodStr);
134             }
135             return false;
136         }
137     }
138 
139     /**
140      * See comments for {@link IWifiRttController#getRttCapabilities()}
141      */
142     @Override
143     @Nullable
getRttCapabilities()144     public WifiRttController.Capabilities getRttCapabilities() {
145         synchronized (mLock) {
146             return mRttCapabilities;
147         }
148     }
149 
150     /**
151      * See comments for {@link IWifiRttController#rangeRequest(int, RangingRequest)}
152      */
153     @Override
rangeRequest(int cmdId, RangingRequest request)154     public boolean rangeRequest(int cmdId, RangingRequest request) {
155         final String methodStr = "rangeRequest";
156         synchronized (mLock) {
157             if (!checkIfaceAndLogFailure(methodStr)) return false;
158             if (mVerboseLoggingEnabled) {
159                 Log.v(TAG, "rangeRequest: cmdId=" + cmdId + ", # of requests="
160                         + request.mRttPeers.size() + ", request=" + request);
161             }
162 
163             updateRttCapabilities();
164             try {
165                 RttConfig[] rttConfigs =
166                         convertRangingRequestToRttConfigs(request, mRttCapabilities);
167                 if (rttConfigs == null) {
168                     Log.e(TAG, methodStr + " received invalid request parameters");
169                     return false;
170                 } else if (rttConfigs.length == 0) {
171                     Log.e(TAG, methodStr + " invalidated all requests");
172                     dispatchOnRangingResults(cmdId, new ArrayList<>());
173                     return true;
174                 }
175                 mWifiRttController.rangeRequest(cmdId, rttConfigs);
176                 return true;
177             } catch (RemoteException e) {
178                 handleRemoteException(e, methodStr);
179             } catch (ServiceSpecificException e) {
180                 handleServiceSpecificException(e, methodStr);
181             }
182             return false;
183         }
184     }
185 
186     /**
187      * See comments for {@link IWifiRttController#rangeCancel(int, List)}
188      */
189     @Override
rangeCancel(int cmdId, List<MacAddress> macAddresses)190     public boolean rangeCancel(int cmdId, List<MacAddress> macAddresses) {
191         final String methodStr = "rangeCancel";
192         synchronized (mLock) {
193             if (!checkIfaceAndLogFailure(methodStr)) return false;
194             try {
195                 android.hardware.wifi.MacAddress[] halAddresses =
196                         new android.hardware.wifi.MacAddress[macAddresses.size()];
197                 for (int i = 0; i < macAddresses.size(); i++) {
198                     android.hardware.wifi.MacAddress halAddress =
199                             new android.hardware.wifi.MacAddress();
200                     halAddress.data = macAddresses.get(i).toByteArray();
201                     halAddresses[i] = halAddress;
202                 }
203                 mWifiRttController.rangeCancel(cmdId, halAddresses);
204                 return true;
205             } catch (RemoteException e) {
206                 handleRemoteException(e, methodStr);
207             } catch (ServiceSpecificException e) {
208                 handleServiceSpecificException(e, methodStr);
209             }
210             return false;
211         }
212     }
213 
214     /**
215      * See comments for {@link IWifiRttController#dump(PrintWriter)}
216      */
217     @Override
dump(PrintWriter pw)218     public void dump(PrintWriter pw) {
219         pw.println("WifiRttController:");
220         pw.println("  mIWifiRttController: " + mWifiRttController);
221         pw.println("  mRttCapabilities: " + mRttCapabilities);
222     }
223 
224     /**
225      *  Callback for HAL events on the WifiRttController
226      */
227     private class WifiRttControllerEventCallback extends IWifiRttControllerEventCallback.Stub {
228         @Override
onResults(int cmdId, RttResult[] halResults)229         public void onResults(int cmdId, RttResult[] halResults) {
230             if (mVerboseLoggingEnabled) {
231                 int numResults = halResults != null ? halResults.length : -1;
232                 Log.v(TAG, "onResults: cmdId=" + cmdId + ", # of results=" + numResults);
233             }
234             if (halResults == null) {
235                 halResults = new RttResult[0];
236             }
237             ArrayList<RangingResult> rangingResults = halToFrameworkRangingResults(halResults);
238             dispatchOnRangingResults(cmdId, rangingResults);
239         }
240 
241         @Override
getInterfaceHash()242         public String getInterfaceHash() {
243             return IWifiRttControllerEventCallback.HASH;
244         }
245 
246         @Override
getInterfaceVersion()247         public int getInterfaceVersion() {
248             return IWifiRttControllerEventCallback.VERSION;
249         }
250     }
251 
252 
253     // Utilities
254 
halToFrameworkRangingResults(RttResult[] halResults)255     private ArrayList<RangingResult> halToFrameworkRangingResults(RttResult[] halResults) {
256         ArrayList<RangingResult> rangingResults = new ArrayList();
257         for (RttResult rttResult : halResults) {
258             if (rttResult == null) continue;
259             byte[] lci = rttResult.lci.data;
260             byte[] lcr = rttResult.lcr.data;
261             ResponderLocation responderLocation;
262             try {
263                 responderLocation = new ResponderLocation(lci, lcr);
264                 if (!responderLocation.isValid()) {
265                     responderLocation = null;
266                 }
267             } catch (Exception e) {
268                 responderLocation = null;
269                 Log.e(TAG, "ResponderLocation: lci/lcr parser failed exception -- " + e);
270             }
271             if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) {
272                 if (mVerboseLoggingEnabled) {
273                     Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num "
274                             + "samples!? result=" + rttResult);
275                 }
276                 rttResult.distanceSdInMm = 0;
277             }
278             RangingResult.Builder resultBuilder = new RangingResult.Builder()
279                     .setStatus(halToFrameworkRttStatus(rttResult.status))
280                     .setMacAddress(MacAddress.fromBytes(rttResult.addr))
281                     .setDistanceMm(rttResult.distanceInMm)
282                     .setDistanceStdDevMm(rttResult.distanceSdInMm)
283                     .setRssi(rttResult.rssi / -2)
284                     .setNumAttemptedMeasurements(rttResult.numberPerBurstPeer)
285                     .setNumSuccessfulMeasurements(rttResult.successNumber)
286                     .setLci(lci)
287                     .setLcr(lcr)
288                     .setUnverifiedResponderLocation(responderLocation)
289                     .setRangingTimestampMillis(
290                             rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS)
291                     .set80211mcMeasurement(rttResult.type == RttType.TWO_SIDED_11MC)
292                     .setMeasurementChannelFrequencyMHz(rttResult.channelFreqMHz)
293                     .setMeasurementBandwidth(halToFrameworkChannelBandwidth(rttResult.packetBw))
294                     .set80211azNtbMeasurement(rttResult.type == RttType.TWO_SIDED_11AZ_NTB)
295                     .setMinTimeBetweenNtbMeasurementsMicros(rttResult.ntbMinMeasurementTime)
296                     .setMaxTimeBetweenNtbMeasurementsMicros(rttResult.ntbMaxMeasurementTime)
297                     .set80211azInitiatorTxLtfRepetitionsCount(rttResult.i2rTxLtfRepetitionCount)
298                     .set80211azResponderTxLtfRepetitionsCount(rttResult.r2iTxLtfRepetitionCount)
299                     .set80211azNumberOfTxSpatialStreams(rttResult.numTxSpatialStreams)
300                     .set80211azNumberOfRxSpatialStreams(rttResult.numRxSpatialStreams);
301             if (SdkLevel.isAtLeastV() && WifiHalAidlImpl.isServiceVersionAtLeast(2)
302                     && rttResult.vendorData != null) {
303                 resultBuilder.setVendorData(
304                         HalAidlUtil.halToFrameworkOuiKeyedDataList(rttResult.vendorData));
305             }
306             rangingResults.add(resultBuilder.build());
307         }
308         return rangingResults;
309     }
310 
halToFrameworkChannelBandwidth( @ttBw int packetBw)311     private static @WifiAnnotations.ChannelWidth int halToFrameworkChannelBandwidth(
312             @RttBw int packetBw) {
313         switch (packetBw) {
314             case RttBw.BW_20MHZ:
315                 return ScanResult.CHANNEL_WIDTH_20MHZ;
316             case RttBw.BW_40MHZ:
317                 return ScanResult.CHANNEL_WIDTH_40MHZ;
318             case RttBw.BW_80MHZ:
319                 return ScanResult.CHANNEL_WIDTH_80MHZ;
320             case RttBw.BW_160MHZ:
321                 return ScanResult.CHANNEL_WIDTH_160MHZ;
322             case RttBw.BW_320MHZ:
323                 return ScanResult.CHANNEL_WIDTH_320MHZ;
324             default:
325                 return RangingResult.UNSPECIFIED;
326         }
327     }
328 
halToFrameworkRttStatus( int halStatus)329     private static @WifiRttController.FrameworkRttStatus int halToFrameworkRttStatus(
330             int halStatus) {
331         switch (halStatus) {
332             case RttStatus.SUCCESS:
333                 return WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS;
334             case RttStatus.FAILURE:
335                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAILURE;
336             case RttStatus.FAIL_NO_RSP:
337                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP;
338             case RttStatus.FAIL_REJECTED:
339                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_REJECTED;
340             case RttStatus.FAIL_NOT_SCHEDULED_YET:
341                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET;
342             case RttStatus.FAIL_TM_TIMEOUT:
343                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT;
344             case RttStatus.FAIL_AP_ON_DIFF_CHANNEL:
345                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL;
346             case RttStatus.FAIL_NO_CAPABILITY:
347                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY;
348             case RttStatus.ABORTED:
349                 return WifiRttController.FRAMEWORK_RTT_STATUS_ABORTED;
350             case RttStatus.FAIL_INVALID_TS:
351                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS;
352             case RttStatus.FAIL_PROTOCOL:
353                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL;
354             case RttStatus.FAIL_SCHEDULE:
355                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE;
356             case RttStatus.FAIL_BUSY_TRY_LATER:
357                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER;
358             case RttStatus.INVALID_REQ:
359                 return WifiRttController.FRAMEWORK_RTT_STATUS_INVALID_REQ;
360             case RttStatus.NO_WIFI:
361                 return WifiRttController.FRAMEWORK_RTT_STATUS_NO_WIFI;
362             case RttStatus.FAIL_FTM_PARAM_OVERRIDE:
363                 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE;
364             default:
365                 Log.e(TAG, "Unrecognized RttStatus: " + halStatus);
366                 return WifiRttController.FRAMEWORK_RTT_STATUS_UNKNOWN;
367         }
368     }
369 
updateRttCapabilities()370     private void updateRttCapabilities() {
371         final String methodStr = "updateRttCapabilities";
372         if (mRttCapabilities != null) return;
373         if (mVerboseLoggingEnabled) Log.v(TAG, "updateRttCapabilities");
374 
375         try {
376             RttCapabilities halCapabilities = mWifiRttController.getCapabilities();
377             mRttCapabilities = new WifiRttController.Capabilities(halCapabilities);
378         } catch (RemoteException e) {
379             handleRemoteException(e, methodStr);
380         } catch (ServiceSpecificException e) {
381             handleServiceSpecificException(e, methodStr);
382         }
383 
384         if (mRttCapabilities != null && !mRttCapabilities.rttFtmSupported) {
385             Log.wtf(TAG, "Firmware indicates RTT is not supported - but device supports RTT - "
386                     + "ignored!?");
387         }
388     }
389 
390     /**
391      * Get optimum burst duration corresponding to a burst size.
392      *
393      * IEEE 802.11 spec, Section 11.21.6.3 Fine timing measurement procedure negotiation, burst
394      * duration is defined as
395      *
396      * Burst duration = (N_FTMPB  * (K + 1)) – 1) * T_MDFTM + T_FTM + aSIFSTime + T_Ack, where
397      *  - N_FTMPB is the value of the FTMs Per Burst subfield
398      *  - K is the maximum number of Fine Timing Measurement frame retransmissions the
399      *    responding STA might attempt
400      *  - T_MDFTM is the duration indicated by the Min Delta FTM subfield of the Fine Timing
401      *    Measurement Parameters field of the initial Fine Timing Measurement frame (FTM_1)
402      *  - T_FTM is the duration of the initial Fine Timing Measurement frame if the FTMs Per Burst
403      *    subfield of the Fine Timing Measurement Parameters field of FTM_1 is set to 1,
404      *    and the duration of the non-initial Fine Timing Measurement frame otherwise
405      *    T_Ack is the duration of the Ack frame expected as a response
406      *
407      * Since many of the parameters are dependent on the chip and the vendor software, framework is
408      * doing a simple conversion with experimented values. Vendor Software may override the burst
409      * duration with more optimal values.
410      *
411      * Section '9.4.2.167 Fine Timing Measurement Parameters element' defines Burst Duration
412      * subfield encoding as,
413      * +--------------------+
414      * |Value|   Represents |
415      * +--------------------+
416      * | 0-1 |  Reserved    |
417      * |  2  |    250 us    |
418      * |  3  |    500 us    |
419      * |  4  |      1 ms    |
420      * |  5  |      2 ms    |
421      * |  6  |      4 ms    |
422      * |  7  |      8 ms    |
423      * |  8  |     16 ms    |
424      * |  9  |     32 ms    |
425      * | 10  |     64 ms    |
426      * | 11  |    128 ms    |
427      * |12-14|  Reserved    |
428      * | 15  | No Preference|
429      * +-----+--------------+
430      */
getOptimumBurstDuration(int burstSize)431     private static int getOptimumBurstDuration(int burstSize) {
432         if (burstSize <= 8) return 9; // 32 ms
433         if (burstSize <= 24) return 10; // 64 ms
434         return 11; // 128 ms
435     }
436 
convertRangingRequestToRttConfigs(RangingRequest request, WifiRttController.Capabilities cap)437     private static RttConfig[] convertRangingRequestToRttConfigs(RangingRequest request,
438             WifiRttController.Capabilities cap) {
439         ArrayList<RttConfig> rttConfigs = new ArrayList<>();
440 
441         // Skip any configurations which have an error (just print out a message).
442         // The caller will only get results for valid configurations.
443         for (ResponderConfig responder: request.mRttPeers) {
444             RttConfig config = new RttConfig();
445             config.addr = responder.macAddress.toByteArray();
446 
447             OuiKeyedData[] vendorData = null;
448             if (SdkLevel.isAtLeastV() && request.getVendorData() != null
449                     && !request.getVendorData().isEmpty()) {
450                 vendorData = HalAidlUtil.frameworkToHalOuiKeyedDataList(request.getVendorData());
451             }
452 
453             try {
454                 if (cap != null) {
455                     if (responder.supports80211azNtb && cap.ntbInitiatorSupported) {
456                         config.type = RttType.TWO_SIDED_11AZ_NTB;
457                     } else if (responder.supports80211mc) {
458                         // IEEE 802.11mc is supported by the device
459                         config.type = RttType.TWO_SIDED_11MC;
460                     } else if (cap.oneSidedRttSupported) {
461                         config.type = RttType.ONE_SIDED;
462                     } else {
463                         Log.w(TAG, "Device does not support one-sided RTT");
464                         continue;
465                     }
466                 } else {
467                     if (responder.supports80211mc) {
468                         // IEEE 802.11mc is supported by the device
469                         config.type = RttType.TWO_SIDED_11MC;
470                     } else {
471                         config.type = RttType.ONE_SIDED;
472                     }
473                 }
474 
475                 config.peer = frameworkToHalRttPeerType(responder.responderType);
476                 config.channel = new WifiChannelInfo();
477                 config.channel.width = frameworkToHalChannelWidth(
478                         responder.channelWidth);
479                 config.channel.centerFreq = responder.frequency;
480                 config.channel.centerFreq0 = responder.centerFreq0;
481                 config.channel.centerFreq1 = responder.centerFreq1;
482                 config.bw = frameworkToHalChannelBandwidth(responder.channelWidth);
483                 config.preamble = frameworkToHalResponderPreamble(responder.preamble);
484                 if (WifiHalAidlImpl.isServiceVersionAtLeast(2) && vendorData != null) {
485                     config.vendorData = vendorData;
486                 }
487                 validateBwAndPreambleCombination(config.bw, config.preamble);
488                 // ResponderConfig#ntbMaxMeasurementTime is in units of 10 milliseconds
489                 config.ntbMaxMeasurementTime =
490                         responder.getNtbMaxTimeBetweenMeasurementsMicros() / 10000;
491                 // ResponderConfig#ntbMinMeasurementTime is in units of 100 microseconds
492                 config.ntbMinMeasurementTime =
493                         responder.getNtbMinTimeBetweenMeasurementsMicros() / 100;
494 
495                 if (config.peer == RttPeerType.NAN_TYPE) {
496                     config.mustRequestLci = false;
497                     config.mustRequestLcr = false;
498                     config.burstPeriod = 0;
499                     config.numBurst = 0;
500                     config.numFramesPerBurst = request.mRttBurstSize;
501                     config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT
502                     config.numRetriesPerFtmr = 3;
503                     config.burstDuration = getOptimumBurstDuration(request.mRttBurstSize);
504                 } else { // AP + all non-NAN requests
505                     config.mustRequestLci = true;
506                     config.mustRequestLcr = true;
507                     config.burstPeriod = 0;
508                     config.numBurst = 0;
509                     config.numFramesPerBurst = request.mRttBurstSize;
510                     config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3);
511                     config.numRetriesPerFtmr = 3;
512                     config.burstDuration = getOptimumBurstDuration(request.mRttBurstSize);
513 
514                     if (cap != null) { // constrain parameters per device capabilities
515                         config.mustRequestLci = config.mustRequestLci && cap.lciSupported;
516                         config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported;
517                         config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap,
518                                 config.type);
519                         config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap,
520                                 config.type);
521                     }
522                 }
523             } catch (IllegalArgumentException e) {
524                 Log.e(TAG, "Invalid configuration: " + e.getMessage());
525                 continue;
526             }
527 
528             rttConfigs.add(config);
529         }
530 
531         RttConfig[] configArray = new RttConfig[rttConfigs.size()];
532         for (int i = 0; i < rttConfigs.size(); i++) {
533             configArray[i] = rttConfigs.get(i);
534         }
535         return configArray;
536     }
537 
validateBwAndPreambleCombination(int bw, int preamble)538     private static void validateBwAndPreambleCombination(int bw, int preamble) {
539         if (bw <= RttBw.BW_20MHZ) {
540             return;
541         }
542         if (bw == RttBw.BW_40MHZ && preamble >= RttPreamble.HT) {
543             return;
544         }
545         if (bw == RttBw.BW_320MHZ && preamble == RttPreamble.EHT) {
546             return;
547         }
548         if (bw >= RttBw.BW_80MHZ && bw < RttBw.BW_320MHZ && preamble >= RttPreamble.VHT) {
549             return;
550         }
551         throw new IllegalArgumentException(
552                 "bw and preamble combination is invalid, bw: " + bw + " preamble: " + preamble);
553     }
554 
frameworkToHalRttPeerType(int responderType)555     private static int frameworkToHalRttPeerType(int responderType)
556             throws IllegalArgumentException {
557         switch (responderType) {
558             case ResponderConfig.RESPONDER_AP:
559                 return RttPeerType.AP;
560             case ResponderConfig.RESPONDER_STA:
561                 return RttPeerType.STA;
562             case ResponderConfig.RESPONDER_P2P_GO:
563                 return RttPeerType.P2P_GO;
564             case ResponderConfig.RESPONDER_P2P_CLIENT:
565                 return RttPeerType.P2P_CLIENT;
566             case ResponderConfig.RESPONDER_AWARE:
567                 return RttPeerType.NAN_TYPE;
568             default:
569                 throw new IllegalArgumentException(
570                         "frameworkToHalRttPeerType: bad " + responderType);
571         }
572     }
573 
frameworkToHalChannelWidth(int responderChannelWidth)574     private static int frameworkToHalChannelWidth(int responderChannelWidth)
575             throws IllegalArgumentException {
576         switch (responderChannelWidth) {
577             case ResponderConfig.CHANNEL_WIDTH_20MHZ:
578                 return WifiChannelWidthInMhz.WIDTH_20;
579             case ResponderConfig.CHANNEL_WIDTH_40MHZ:
580                 return WifiChannelWidthInMhz.WIDTH_40;
581             case ResponderConfig.CHANNEL_WIDTH_80MHZ:
582                 return WifiChannelWidthInMhz.WIDTH_80;
583             case ResponderConfig.CHANNEL_WIDTH_160MHZ:
584                 return WifiChannelWidthInMhz.WIDTH_160;
585             case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
586                 return WifiChannelWidthInMhz.WIDTH_80P80;
587             case ResponderConfig.CHANNEL_WIDTH_320MHZ:
588                 return WifiChannelWidthInMhz.WIDTH_320;
589             default:
590                 throw new IllegalArgumentException(
591                         "frameworkToHalChannelWidth: bad " + responderChannelWidth);
592         }
593     }
594 
frameworkToHalChannelBandwidth(int responderChannelWidth)595     private static int frameworkToHalChannelBandwidth(int responderChannelWidth)
596             throws IllegalArgumentException {
597         switch (responderChannelWidth) {
598             case ResponderConfig.CHANNEL_WIDTH_20MHZ:
599                 return RttBw.BW_20MHZ;
600             case ResponderConfig.CHANNEL_WIDTH_40MHZ:
601                 return RttBw.BW_40MHZ;
602             case ResponderConfig.CHANNEL_WIDTH_80MHZ:
603                 return RttBw.BW_80MHZ;
604             case ResponderConfig.CHANNEL_WIDTH_160MHZ:
605             case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
606                 return RttBw.BW_160MHZ;
607             case ResponderConfig.CHANNEL_WIDTH_320MHZ:
608                 return RttBw.BW_320MHZ;
609             default:
610                 throw new IllegalArgumentException(
611                         "halRttChannelBandwidthFromHalBandwidth: bad " + responderChannelWidth);
612         }
613     }
614 
frameworkToHalResponderPreamble(int responderPreamble)615     private static int frameworkToHalResponderPreamble(int responderPreamble)
616             throws IllegalArgumentException {
617         switch (responderPreamble) {
618             case ResponderConfig.PREAMBLE_LEGACY:
619                 return RttPreamble.LEGACY;
620             case ResponderConfig.PREAMBLE_HT:
621                 return RttPreamble.HT;
622             case ResponderConfig.PREAMBLE_VHT:
623                 return RttPreamble.VHT;
624             case ResponderConfig.PREAMBLE_HE:
625                 return RttPreamble.HE;
626             default:
627                 throw new IllegalArgumentException(
628                         "frameworkToHalResponderPreamble: bad " + responderPreamble);
629         }
630     }
631 
632     /**
633      * Check whether the selected RTT channel bandwidth is supported by the device.
634      * If supported, return the requested bandwidth.
635      * If not supported, return the next lower bandwidth which is supported.
636      * If none, throw an IllegalArgumentException.
637      *
638      * Note: the halRttChannelBandwidth is a single bit flag from the HAL RttBw type.
639      */
halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, WifiRttController.Capabilities cap, @RttType int rttType)640     private static int halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth,
641             WifiRttController.Capabilities cap, @RttType int rttType)
642             throws IllegalArgumentException {
643         int requestedBandwidth = halRttChannelBandwidth;
644         int bwSupported =
645                 (rttType == RttType.TWO_SIDED_11AZ_NTB) ? cap.azBwSupported : cap.bwSupported;
646         while ((halRttChannelBandwidth != 0) && ((halRttChannelBandwidth & bwSupported) == 0)) {
647             halRttChannelBandwidth >>= 1;
648         }
649 
650         if (halRttChannelBandwidth != 0) {
651             return halRttChannelBandwidth;
652         }
653 
654         throw new IllegalArgumentException(
655                 "RTT BW=" + requestedBandwidth + ", not supported by device capabilities=" + cap
656                         + " - and no supported alternative");
657     }
658 
659     /**
660      * Check whether the selected RTT preamble is supported by the device.
661      * If supported, return the requested preamble.
662      * If not supported, return the next "lower" preamble which is supported.
663      * If none, throw an IllegalArgumentException.
664      *
665      * Note: the halRttPreamble is a single bit flag from the HAL RttPreamble type.
666      */
halRttPreambleCapabilityLimiter(int halRttPreamble, WifiRttController.Capabilities cap, @RttType int rttType)667     private static int halRttPreambleCapabilityLimiter(int halRttPreamble,
668             WifiRttController.Capabilities cap, @RttType int rttType)
669             throws IllegalArgumentException {
670         int requestedPreamble = halRttPreamble;
671         int preambleSupported = (rttType == RttType.TWO_SIDED_11AZ_NTB) ? cap.azPreambleSupported
672                 : cap.preambleSupported;
673         while ((halRttPreamble != 0) && ((halRttPreamble & preambleSupported) == 0)) {
674             halRttPreamble >>= 1;
675         }
676 
677         if (halRttPreamble != 0) {
678             return halRttPreamble;
679         }
680 
681         throw new IllegalArgumentException(
682                 "RTT Preamble=" + requestedPreamble + ", not supported by device capabilities="
683                         + cap + " - and no supported alternative");
684     }
685 
dispatchOnRangingResults(int cmdId, List<RangingResult> rangingResults)686     private void dispatchOnRangingResults(int cmdId, List<RangingResult> rangingResults) {
687         for (WifiRttController.RttControllerRangingResultsCallback
688                 callback : mRangingResultsCallbacks) {
689             callback.onRangingResults(cmdId, rangingResults);
690         }
691     }
692 
checkIfaceAndLogFailure(String methodStr)693     private boolean checkIfaceAndLogFailure(String methodStr) {
694         if (mWifiRttController == null) {
695             Log.e(TAG, "Unable to call " + methodStr + " because iface is null.");
696             return false;
697         }
698         return true;
699     }
700 
handleRemoteException(RemoteException e, String methodStr)701     private void handleRemoteException(RemoteException e, String methodStr) {
702         mWifiRttController = null;
703         Log.e(TAG, methodStr + " failed with remote exception: " + e);
704     }
705 
handleServiceSpecificException(ServiceSpecificException e, String methodStr)706     private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) {
707         Log.e(TAG, methodStr + " failed with service-specific exception: " + e);
708     }
709 }
710