• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.rtt;
18 
19 import android.annotation.IntDef;
20 import android.annotation.Nullable;
21 import android.hardware.wifi.V1_0.IWifiRttController;
22 import android.hardware.wifi.V1_0.IWifiRttControllerEventCallback;
23 import android.hardware.wifi.V1_0.RttBw;
24 import android.hardware.wifi.V1_0.RttCapabilities;
25 import android.hardware.wifi.V1_0.RttConfig;
26 import android.hardware.wifi.V1_0.RttPeerType;
27 import android.hardware.wifi.V1_0.RttPreamble;
28 import android.hardware.wifi.V1_0.RttResult;
29 import android.hardware.wifi.V1_0.RttStatus;
30 import android.hardware.wifi.V1_0.RttType;
31 import android.hardware.wifi.V1_0.WifiChannelWidthInMhz;
32 import android.hardware.wifi.V1_0.WifiStatus;
33 import android.hardware.wifi.V1_0.WifiStatusCode;
34 import android.net.MacAddress;
35 import android.net.wifi.rtt.RangingRequest;
36 import android.net.wifi.rtt.RangingResult;
37 import android.net.wifi.rtt.ResponderConfig;
38 import android.net.wifi.rtt.ResponderLocation;
39 import android.os.Handler;
40 import android.os.RemoteException;
41 import android.util.Log;
42 
43 import com.android.server.wifi.HalDeviceManager;
44 import com.android.server.wifi.util.NativeUtil;
45 
46 import java.io.FileDescriptor;
47 import java.io.PrintWriter;
48 import java.lang.annotation.Retention;
49 import java.lang.annotation.RetentionPolicy;
50 import java.util.ArrayList;
51 import java.util.Objects;
52 
53 /**
54  * TBD
55  */
56 public class RttNative {
57     private static final String TAG = "RttNative";
58     private static final boolean VDBG = false; // STOPSHIP if true
59     /* package */ boolean mDbg = false;
60 
61     /** Unknown status */
62     public static final int FRAMEWORK_RTT_STATUS_UNKNOWN = -1;
63     /** Success */
64     public static final int FRAMEWORK_RTT_STATUS_SUCCESS = 0;
65     /** General failure status */
66     public static final int FRAMEWORK_RTT_STATUS_FAILURE = 1;
67     /** Target STA does not respond to request */
68     public static final int FRAMEWORK_RTT_STATUS_FAIL_NO_RSP = 2;
69     /** Request rejected. Applies to 2-sided RTT only */
70     public static final int FRAMEWORK_RTT_STATUS_FAIL_REJECTED = 3;
71     public static final int FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4;
72     /** Timing measurement times out */
73     public static final int FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT = 5;
74     /** Target on different channel, cannot range */
75     public static final int FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6;
76     /** Ranging not supported */
77     public static final int FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY = 7;
78     /** Request aborted for unknown reason */
79     public static final int FRAMEWORK_RTT_STATUS_ABORTED = 8;
80     /** Invalid T1-T4 timestamp */
81     public static final int FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS = 9;
82     /** 11mc protocol failed */
83     public static final int FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL = 10;
84     /** Request could not be scheduled */
85     public static final int FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE = 11;
86     /** Responder cannot collaborate at time of request */
87     public static final int FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER = 12;
88     /** Bad request args */
89     public static final int FRAMEWORK_RTT_STATUS_INVALID_REQ = 13;
90     /** WiFi not enabled. */
91     public static final int FRAMEWORK_RTT_STATUS_NO_WIFI = 14;
92     /** Responder overrides param info, cannot range with new params */
93     public static final int FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15;
94 
95     /** @hide */
96     @IntDef(prefix = "FRAMEWORK_RTT_STATUS_", value = {FRAMEWORK_RTT_STATUS_UNKNOWN,
97             FRAMEWORK_RTT_STATUS_SUCCESS, FRAMEWORK_RTT_STATUS_FAILURE,
98             FRAMEWORK_RTT_STATUS_FAIL_NO_RSP, FRAMEWORK_RTT_STATUS_FAIL_REJECTED,
99             FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET, FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT,
100             FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY,
101             FRAMEWORK_RTT_STATUS_ABORTED, FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS,
102             FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL, FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE,
103             FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER, FRAMEWORK_RTT_STATUS_INVALID_REQ,
104             FRAMEWORK_RTT_STATUS_NO_WIFI, FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE})
105     @Retention(RetentionPolicy.SOURCE)
106     public @interface FrameworkRttStatus {}
107 
108 
109     private final RttServiceImpl mRttService;
110     private final HalDeviceManager mHalDeviceManager;
111 
112     private Object mLock = new Object();
113 
114     private volatile IWifiRttController mIWifiRttController;
115     private volatile Capabilities mRttCapabilities;
116     private final WifiRttControllerEventCallback mWifiRttControllerEventCallback;
117     private volatile android.hardware.wifi.V1_4.IWifiRttController mIWifiRttController14;
118     private final WifiRttControllerEventCallback14 mWifiRttControllerEventCallback14;
119     private static final int CONVERSION_US_TO_MS = 1_000;
120 
121     private final HalDeviceManager.InterfaceRttControllerLifecycleCallback mRttLifecycleCb =
122             new HalDeviceManager.InterfaceRttControllerLifecycleCallback() {
123                 @Override
124                 public void onNewRttController(IWifiRttController controller) {
125                     if (mDbg) Log.d(TAG, "onNewRttController: controller=" + controller);
126                     synchronized (mLock) {
127                         mIWifiRttController = controller;
128                         mIWifiRttController14 = getWifiRttControllerV1_4();
129 
130                         try {
131                             if (mIWifiRttController14 != null) {
132                                 mIWifiRttController14.registerEventCallback_1_4(
133                                         mWifiRttControllerEventCallback14);
134                             } else {
135                                 mIWifiRttController.registerEventCallback(
136                                         mWifiRttControllerEventCallback);
137                             }
138                         } catch (RemoteException e) {
139                             Log.e(TAG, "onNewRttController: exception registering callback: " + e);
140                             if (mIWifiRttController != null) {
141                                 mIWifiRttController = null;
142                                 mIWifiRttController14 = null;
143                                 mRttService.disable();
144                             }
145                             return;
146                         }
147                         mRttService.enableIfPossible();
148                         updateRttCapabilities();
149                     }
150                 }
151 
152                 @Override
153                 public void onRttControllerDestroyed() {
154                     if (mDbg) Log.d(TAG, "onRttControllerDestroyed");
155                     synchronized (mLock) {
156                         mIWifiRttController = null;
157                         mIWifiRttController14 = null;
158                         mRttCapabilities = null;
159                         mRttService.disable();
160                     }
161                 }
162             };
163 
RttNative(RttServiceImpl rttService, HalDeviceManager halDeviceManager)164     public RttNative(RttServiceImpl rttService, HalDeviceManager halDeviceManager) {
165         mRttService = rttService;
166         mHalDeviceManager = halDeviceManager;
167         mWifiRttControllerEventCallback = new WifiRttControllerEventCallback();
168         mWifiRttControllerEventCallback14 = new WifiRttControllerEventCallback14();
169     }
170 
171     /**
172      * Initialize the object - registering with the HAL device manager.
173      */
start(Handler handler)174     public void start(Handler handler) {
175         synchronized (mLock) {
176             mHalDeviceManager.initialize();
177             mHalDeviceManager.registerStatusListener(() -> {
178                 if (VDBG) Log.d(TAG, "hdm.onStatusChanged");
179                 if (mHalDeviceManager.isStarted()) {
180                     mHalDeviceManager.registerRttControllerLifecycleCallback(mRttLifecycleCb,
181                             handler);
182                 }
183             }, handler);
184             if (mHalDeviceManager.isStarted()) {
185                 mHalDeviceManager.registerRttControllerLifecycleCallback(mRttLifecycleCb, handler);
186             }
187         }
188     }
189 
190     /**
191      * Returns true if Wi-Fi is ready for RTT requests, false otherwise.
192      */
isReady()193     public boolean isReady() {
194         return mIWifiRttController != null;
195     }
196 
197     /**
198      * Returns the RTT capabilities. Will only be null when disabled (e.g. no STA interface
199      * available - not necessarily up).
200      */
getRttCapabilities()201     public @Nullable Capabilities getRttCapabilities() {
202         return mRttCapabilities;
203     }
204 
205     /**
206      * Updates the RTT capabilities.
207      */
updateRttCapabilities()208     void updateRttCapabilities() {
209         if (mIWifiRttController == null) {
210             Log.e(TAG, "updateRttCapabilities: but a RTT controller is NULL!?");
211             return;
212         }
213         if (mRttCapabilities != null) {
214             return;
215         }
216         if (mDbg) Log.v(TAG, "updateRttCapabilities");
217 
218         synchronized (mLock) {
219             try {
220                 if (mIWifiRttController14 != null) {
221                     mIWifiRttController14.getCapabilities_1_4(
222                             (status, capabilities14) -> {
223                                 if (status.code != WifiStatusCode.SUCCESS) {
224                                     Log.e(TAG, "updateRttCapabilities:"
225                                             + " error requesting capabilities "
226                                             + "-- code=" + status.code);
227                                     return;
228                                 }
229                                 if (mDbg) {
230                                     Log.v(TAG, "updateRttCapabilities: RTT capabilities="
231                                             + capabilities14);
232                                 }
233                                 mRttCapabilities = new Capabilities(capabilities14);
234                             });
235                 } else {
236                     mIWifiRttController.getCapabilities(
237                             (status, capabilities) -> {
238                                 if (status.code != WifiStatusCode.SUCCESS) {
239                                     Log.e(TAG, "updateRttCapabilities:"
240                                             + " error requesting capabilities "
241                                             + "-- code=" + status.code);
242                                     return;
243                                 }
244                                 if (mDbg) {
245                                     Log.v(TAG, "updateRttCapabilities: RTT capabilities="
246                                             + capabilities);
247                                 }
248                                 mRttCapabilities = new Capabilities(capabilities);
249                             });
250                 }
251             } catch (RemoteException e) {
252                 Log.e(TAG, "updateRttCapabilities: exception requesting capabilities: " + e);
253             }
254 
255             if (mRttCapabilities != null && !mRttCapabilities.rttFtmSupported) {
256                 Log.wtf(TAG, "Firmware indicates RTT is not supported - but device supports RTT - "
257                         + "ignored!?");
258             }
259         }
260     }
261 
262     /**
263      * Issue a range request to the HAL.
264      *
265      * @param cmdId Command ID for the request. Will be used in the corresponding
266      * {@link WifiRttControllerEventCallback#onResults(int, ArrayList)}.
267      * @param request Range request.
268      * @param isCalledFromPrivilegedContext Indicates whether privileged APIs are permitted,
269      *                                      initially: support for one-sided RTT.
270      *
271      * @return Success status: true for success, false for failure.
272      */
rangeRequest(int cmdId, RangingRequest request, boolean isCalledFromPrivilegedContext)273     public boolean rangeRequest(int cmdId, RangingRequest request,
274             boolean isCalledFromPrivilegedContext) {
275         if (mDbg) {
276             Log.v(TAG,
277                     "rangeRequest: cmdId=" + cmdId + ", # of requests=" + request.mRttPeers.size());
278         }
279         if (VDBG) Log.v(TAG, "rangeRequest: request=" + request);
280         synchronized (mLock) {
281             if (!isReady()) {
282                 Log.e(TAG, "rangeRequest: RttController is null");
283                 return false;
284             }
285             updateRttCapabilities();
286 
287             if (mIWifiRttController14 != null) {
288                 return sendRangeRequest14(cmdId, request, isCalledFromPrivilegedContext);
289             } else {
290                 return sendRangeRequest(cmdId, request, isCalledFromPrivilegedContext);
291             }
292         }
293     }
294 
sendRangeRequest(int cmdId, RangingRequest request, boolean isCalledFromPrivilegedContext)295     private boolean sendRangeRequest(int cmdId, RangingRequest request,
296             boolean isCalledFromPrivilegedContext) {
297         ArrayList<RttConfig> rttConfig = convertRangingRequestToRttConfigs(request,
298                 isCalledFromPrivilegedContext, mRttCapabilities);
299         if (rttConfig == null) {
300             Log.e(TAG, "sendRangeRequest: invalid request parameters");
301             return false;
302         }
303         if (rttConfig.size() == 0) {
304             Log.e(TAG, "sendRangeRequest: all requests invalidated");
305             mRttService.onRangingResults(cmdId, new ArrayList<>());
306             return true;
307         }
308 
309         try {
310             WifiStatus status = mIWifiRttController.rangeRequest(cmdId, rttConfig);
311             if (status.code != WifiStatusCode.SUCCESS) {
312                 Log.e(TAG, "sendRangeRequest: cannot issue range request -- code=" + status.code);
313                 return false;
314             }
315         } catch (RemoteException e) {
316             Log.e(TAG, "sendRangeRequest: exception issuing range request: " + e);
317             return false;
318         }
319 
320         return true;
321     }
322 
sendRangeRequest14(int cmdId, RangingRequest request, boolean isCalledFromPrivilegedContext)323     private boolean sendRangeRequest14(int cmdId, RangingRequest request,
324             boolean isCalledFromPrivilegedContext) {
325         ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfig =
326                 convertRangingRequestToRttConfigs14(request,
327                 isCalledFromPrivilegedContext, mRttCapabilities);
328         if (rttConfig == null) {
329             Log.e(TAG, "sendRangeRequest14: invalid request parameters");
330             return false;
331         }
332         if (rttConfig.size() == 0) {
333             Log.e(TAG, "sendRangeRequest14: all requests invalidated");
334             mRttService.onRangingResults(cmdId, new ArrayList<>());
335             return true;
336         }
337 
338         try {
339             WifiStatus status = mIWifiRttController14.rangeRequest_1_4(cmdId, rttConfig);
340             if (status.code != WifiStatusCode.SUCCESS) {
341                 Log.e(TAG, "sendRangeRequest14: cannot issue range request -- code="
342                         + status.code);
343                 return false;
344             }
345         } catch (RemoteException e) {
346             Log.e(TAG, "sendRangeRequest14: exception issuing range request: " + e);
347             return false;
348         }
349 
350         return true;
351     }
352 
353     /**
354      * Cancel an outstanding ranging request: no guarantees of execution - we will ignore any
355      * results which are returned for the canceled request.
356      *
357      * @param cmdId The cmdId issued with the original rangeRequest command.
358      * @param macAddresses A list of MAC addresses for which to cancel the operation.
359      * @return Success status: true for success, false for failure.
360      */
rangeCancel(int cmdId, ArrayList<byte[]> macAddresses)361     public boolean rangeCancel(int cmdId, ArrayList<byte[]> macAddresses) {
362         if (mDbg) Log.v(TAG, "rangeCancel: cmdId=" + cmdId);
363         synchronized (mLock) {
364             if (!isReady()) {
365                 Log.e(TAG, "rangeCancel: RttController is null");
366                 return false;
367             }
368 
369             try {
370                 WifiStatus status = mIWifiRttController.rangeCancel(cmdId, macAddresses);
371                 if (status.code != WifiStatusCode.SUCCESS) {
372                     Log.e(TAG, "rangeCancel: cannot issue range cancel -- code=" + status.code);
373                     return false;
374                 }
375             } catch (RemoteException e) {
376                 Log.e(TAG, "rangeCancel: exception issuing range cancel: " + e);
377                 return false;
378             }
379 
380             return true;
381         }
382     }
383 
convertRangingRequestToRttConfigs(RangingRequest request, boolean isCalledFromPrivilegedContext, Capabilities cap)384     private static ArrayList<RttConfig> convertRangingRequestToRttConfigs(RangingRequest request,
385             boolean isCalledFromPrivilegedContext, Capabilities cap) {
386         ArrayList<RttConfig> rttConfigs = new ArrayList<>(request.mRttPeers.size());
387 
388         // Skipping any configurations which have an error (printing out a message).
389         // The caller will only get results for valid configurations.
390         for (ResponderConfig responder: request.mRttPeers) {
391             RttConfig config = new RttConfig();
392 
393             System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0,
394                     config.addr.length);
395 
396             try {
397                 config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED;
398                 if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) {
399                     Log.w(TAG, "Device does not support one-sided RTT");
400                     continue;
401                 }
402 
403                 config.peer = halRttPeerTypeFromResponderType(responder.responderType);
404                 config.channel.width = halChannelWidthFromResponderChannelWidth(
405                         responder.channelWidth);
406                 config.channel.centerFreq = responder.frequency;
407                 config.channel.centerFreq0 = responder.centerFreq0;
408                 config.channel.centerFreq1 = responder.centerFreq1;
409                 config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth);
410                 config.preamble = halRttPreambleFromResponderPreamble(responder.preamble);
411                 validateBwAndPreambleCombination(config.bw, config.preamble);
412 
413                 if (config.peer == RttPeerType.NAN) {
414                     config.mustRequestLci = false;
415                     config.mustRequestLcr = false;
416                     config.burstPeriod = 0;
417                     config.numBurst = 0;
418                     config.numFramesPerBurst = request.mRttBurstSize;
419                     config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT
420                     config.numRetriesPerFtmr = 3;
421                     config.burstDuration = 9;
422                 } else { // AP + all non-NAN requests
423                     config.mustRequestLci = true;
424                     config.mustRequestLcr = true;
425                     config.burstPeriod = 0;
426                     config.numBurst = 0;
427                     config.numFramesPerBurst = request.mRttBurstSize;
428                     config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3);
429                     config.numRetriesPerFtmr = 3;
430                     config.burstDuration = 9;
431 
432                     if (cap != null) { // constrain parameters per device capabilities
433                         config.mustRequestLci = config.mustRequestLci && cap.lciSupported;
434                         config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported;
435                         config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap);
436                         config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap);
437                     }
438                 }
439             } catch (IllegalArgumentException e) {
440                 Log.e(TAG, "Invalid configuration: " + e.getMessage());
441                 continue;
442             }
443 
444             rttConfigs.add(config);
445         }
446 
447         return rttConfigs;
448     }
449 
validateBwAndPreambleCombination(int bw, int preamble)450     private static void validateBwAndPreambleCombination(int bw, int preamble) {
451         if (bw <= RttBw.BW_20MHZ) {
452             return;
453         }
454         if (bw == RttBw.BW_40MHZ && preamble >= RttPreamble.HT) {
455             return;
456         }
457         if (bw >= RttBw.BW_80MHZ && preamble >= RttPreamble.VHT) {
458             return;
459         }
460         throw new IllegalArgumentException(
461                 "bw and preamble combination is invalid, bw: " + bw + " preamble: " + preamble);
462     }
463 
464     private static ArrayList<android.hardware.wifi.V1_4.RttConfig>
convertRangingRequestToRttConfigs14( RangingRequest request, boolean isCalledFromPrivilegedContext, Capabilities cap)465             convertRangingRequestToRttConfigs14(
466             RangingRequest request, boolean isCalledFromPrivilegedContext, Capabilities cap) {
467         ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfigs =
468                 new ArrayList<>(request.mRttPeers.size());
469 
470         // Skipping any configurations which have an error (printing out a message).
471         // The caller will only get results for valid configurations.
472         for (ResponderConfig responder: request.mRttPeers) {
473 
474             android.hardware.wifi.V1_4.RttConfig config =
475                     new android.hardware.wifi.V1_4.RttConfig();
476 
477             System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0,
478                     config.addr.length);
479 
480             try {
481                 config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED;
482                 if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) {
483                     Log.w(TAG, "Device does not support one-sided RTT");
484                     continue;
485                 }
486 
487                 config.peer = halRttPeerTypeFromResponderType(responder.responderType);
488                 config.channel.width = halChannelWidthFromResponderChannelWidth(
489                         responder.channelWidth);
490                 config.channel.centerFreq = responder.frequency;
491                 config.channel.centerFreq0 = responder.centerFreq0;
492                 config.channel.centerFreq1 = responder.centerFreq1;
493                 config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth);
494                 config.preamble = halRttPreamble14FromResponderPreamble(responder.preamble);
495 
496                 if (config.peer == RttPeerType.NAN) {
497                     config.mustRequestLci = false;
498                     config.mustRequestLcr = false;
499                     config.burstPeriod = 0;
500                     config.numBurst = 0;
501                     config.numFramesPerBurst = request.mRttBurstSize;
502                     config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT
503                     config.numRetriesPerFtmr = 3;
504                     config.burstDuration = 9;
505                 } else { // AP + all non-NAN requests
506                     config.mustRequestLci = true;
507                     config.mustRequestLcr = true;
508                     config.burstPeriod = 0;
509                     config.numBurst = 0;
510                     config.numFramesPerBurst = request.mRttBurstSize;
511                     config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3);
512                     config.numRetriesPerFtmr = 3;
513                     config.burstDuration = 9;
514 
515                     if (cap != null) { // constrain parameters per device capabilities
516                         config.mustRequestLci = config.mustRequestLci && cap.lciSupported;
517                         config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported;
518                         config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap);
519                         config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap);
520                     }
521                 }
522             } catch (IllegalArgumentException e) {
523                 Log.e(TAG, "Invalid configuration: " + e.getMessage());
524                 continue;
525             }
526 
527             rttConfigs.add(config);
528         }
529 
530         return rttConfigs;
531     }
532 
halRttPeerTypeFromResponderType(int responderType)533     private static int halRttPeerTypeFromResponderType(int responderType) {
534         switch (responderType) {
535             case ResponderConfig.RESPONDER_AP:
536                 return RttPeerType.AP;
537             case ResponderConfig.RESPONDER_STA:
538                 return RttPeerType.STA;
539             case ResponderConfig.RESPONDER_P2P_GO:
540                 return RttPeerType.P2P_GO;
541             case ResponderConfig.RESPONDER_P2P_CLIENT:
542                 return RttPeerType.P2P_CLIENT;
543             case ResponderConfig.RESPONDER_AWARE:
544                 return RttPeerType.NAN;
545             default:
546                 throw new IllegalArgumentException(
547                         "halRttPeerTypeFromResponderType: bad " + responderType);
548         }
549     }
550 
halChannelWidthFromResponderChannelWidth(int responderChannelWidth)551     private static int halChannelWidthFromResponderChannelWidth(int responderChannelWidth) {
552         switch (responderChannelWidth) {
553             case ResponderConfig.CHANNEL_WIDTH_20MHZ:
554                 return WifiChannelWidthInMhz.WIDTH_20;
555             case ResponderConfig.CHANNEL_WIDTH_40MHZ:
556                 return WifiChannelWidthInMhz.WIDTH_40;
557             case ResponderConfig.CHANNEL_WIDTH_80MHZ:
558                 return WifiChannelWidthInMhz.WIDTH_80;
559             case ResponderConfig.CHANNEL_WIDTH_160MHZ:
560                 return WifiChannelWidthInMhz.WIDTH_160;
561             case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
562                 return WifiChannelWidthInMhz.WIDTH_80P80;
563             default:
564                 throw new IllegalArgumentException(
565                         "halChannelWidthFromResponderChannelWidth: bad " + responderChannelWidth);
566         }
567     }
568 
halRttChannelBandwidthFromResponderChannelWidth(int responderChannelWidth)569     private static int halRttChannelBandwidthFromResponderChannelWidth(int responderChannelWidth) {
570         switch (responderChannelWidth) {
571             case ResponderConfig.CHANNEL_WIDTH_20MHZ:
572                 return RttBw.BW_20MHZ;
573             case ResponderConfig.CHANNEL_WIDTH_40MHZ:
574                 return RttBw.BW_40MHZ;
575             case ResponderConfig.CHANNEL_WIDTH_80MHZ:
576                 return RttBw.BW_80MHZ;
577             case ResponderConfig.CHANNEL_WIDTH_160MHZ:
578             case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
579                 return RttBw.BW_160MHZ;
580             default:
581                 throw new IllegalArgumentException(
582                         "halRttChannelBandwidthFromHalBandwidth: bad " + responderChannelWidth);
583         }
584     }
585 
halRttPreambleFromResponderPreamble(int responderPreamble)586     private static int halRttPreambleFromResponderPreamble(int responderPreamble) {
587         switch (responderPreamble) {
588             case ResponderConfig.PREAMBLE_LEGACY:
589                 return RttPreamble.LEGACY;
590             case ResponderConfig.PREAMBLE_HT:
591                 return RttPreamble.HT;
592             case ResponderConfig.PREAMBLE_VHT:
593                 return RttPreamble.VHT;
594             default:
595                 throw new IllegalArgumentException(
596                         "halRttPreambleFromResponderPreamble: bad " + responderPreamble);
597         }
598     }
599 
halRttPreamble14FromResponderPreamble(int responderPreamble)600     private static int halRttPreamble14FromResponderPreamble(int responderPreamble) {
601         switch (responderPreamble) {
602             case ResponderConfig.PREAMBLE_LEGACY:
603                 return RttPreamble.LEGACY;
604             case ResponderConfig.PREAMBLE_HT:
605                 return RttPreamble.HT;
606             case ResponderConfig.PREAMBLE_VHT:
607                 return RttPreamble.VHT;
608             case ResponderConfig.PREAMBLE_HE:
609                 return android.hardware.wifi.V1_4.RttPreamble.HE;
610             default:
611                 throw new IllegalArgumentException(
612                         "halRttPreamble14FromResponderPreamble: bad " + responderPreamble);
613         }
614     }
615 
616     /**
617      * Check to see whether the selected RTT channel bandwidth is supported by the device.
618      * If not supported: return the next lower bandwidth which is supported
619      * If none: throw an IllegalArgumentException.
620      *
621      * Note: the halRttChannelBandwidth is a single bit flag of the ones used in cap.bwSupport (HAL
622      * specifications).
623      */
halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, Capabilities cap)624     private static int halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth,
625             Capabilities cap) {
626         while ((halRttChannelBandwidth != 0) && ((halRttChannelBandwidth & cap.bwSupported) == 0)) {
627             halRttChannelBandwidth >>= 1;
628         }
629 
630         if (halRttChannelBandwidth != 0) {
631             return halRttChannelBandwidth;
632         }
633 
634         throw new IllegalArgumentException(
635                 "RTT BW=" + halRttChannelBandwidth + ", not supported by device capabilities=" + cap
636                         + " - and no supported alternative");
637     }
638 
639     /**
640      * Check to see whether the selected RTT preamble is supported by the device.
641      * If not supported: return the next "lower" preamble which is supported
642      * If none: throw an IllegalArgumentException.
643      *
644      * Note: the halRttPreamble is a single bit flag of the ones used in cap.preambleSupport (HAL
645      * specifications).
646      */
halRttPreambleCapabilityLimiter(int halRttPreamble, Capabilities cap)647     private static int halRttPreambleCapabilityLimiter(int halRttPreamble, Capabilities cap) {
648         while ((halRttPreamble != 0) && ((halRttPreamble & cap.preambleSupported) == 0)) {
649             halRttPreamble >>= 1;
650         }
651 
652         if (halRttPreamble != 0) {
653             return halRttPreamble;
654         }
655 
656         throw new IllegalArgumentException(
657                 "RTT Preamble=" + halRttPreamble + ", not supported by device capabilities=" + cap
658                         + " - and no supported alternative");
659     }
660 
661     /**
662      * Check if HAL Interface 1.4 is running
663      *
664      * @return 1.4 IWifiRttController object if the device is running the 1.4 hal service, null
665      * otherwise
666      */
getWifiRttControllerV1_4()667     private android.hardware.wifi.V1_4.IWifiRttController getWifiRttControllerV1_4() {
668         if (mIWifiRttController == null) {
669             return null;
670         }
671         return android.hardware.wifi.V1_4.IWifiRttController.castFrom(mIWifiRttController);
672     }
673 
674     /**
675      * Dump the internal state of the class.
676      */
dump(FileDescriptor fd, PrintWriter pw, String[] args)677     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
678         pw.println("RttNative:");
679         pw.println("  mHalDeviceManager: " + mHalDeviceManager);
680         pw.println("  mIWifiRttController: " + mIWifiRttController);
681         pw.println("  mRttCapabilities: " + mRttCapabilities);
682     }
683 
684     /**
685      *  Callback for events on 1.0 WifiRttController
686      */
687     private class WifiRttControllerEventCallback extends IWifiRttControllerEventCallback.Stub {
688         /**
689          * Callback from HAL with range results.
690          *
691          * @param cmdId Command ID specified in the original request
692          * {@link #rangeRequest(int, RangingRequest, boolean)}.
693          * @param halResults A list of range results.
694          */
695         @Override
onResults(int cmdId, ArrayList<RttResult> halResults)696         public void onResults(int cmdId, ArrayList<RttResult> halResults) {
697             // sanitize HAL results
698             if (halResults == null) {
699                 halResults = new ArrayList<>();
700             }
701             halResults.removeIf(Objects::isNull);
702             if (mDbg) {
703                 Log.v(TAG, "onResults: cmdId=" + cmdId + ", # of results=" + halResults.size());
704             }
705             ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults(halResults);
706             mRttService.onRangingResults(cmdId, rangingResults);
707         }
708     }
709 
710     /**
711      *  Callback for events on 1.4 WifiRttController
712      */
713     private class WifiRttControllerEventCallback14 extends
714             android.hardware.wifi.V1_4.IWifiRttControllerEventCallback.Stub {
715         @Override
onResults(int cmdId, ArrayList<RttResult> halResults)716         public void onResults(int cmdId, ArrayList<RttResult> halResults) {
717             // This callback is not supported on this version of the interface
718             return;
719         }
720 
721         @Override
onResults_1_4(int cmdId, ArrayList<android.hardware.wifi.V1_4.RttResult> halResults)722         public void onResults_1_4(int cmdId,
723                 ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) {
724             if (mDbg) {
725                 Log.v(TAG,
726                         "onResults_1_4: cmdId=" + cmdId + ", # of results=" + halResults.size());
727             }
728             // sanitize HAL results
729             if (halResults == null) {
730                 halResults = new ArrayList<>();
731             }
732             halResults.removeIf(Objects::isNull);
733             ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults14(halResults);
734             mRttService.onRangingResults(cmdId, rangingResults);
735         }
736     }
737 
convertHalResultsRangingResults( ArrayList<RttResult> halResults)738     private ArrayList<RangingResult> convertHalResultsRangingResults(
739             ArrayList<RttResult> halResults) {
740         ArrayList<RangingResult> rangingResults = new ArrayList<>();
741         for (RttResult rttResult : halResults) {
742             byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data);
743             byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data);
744             ResponderLocation responderLocation;
745             try {
746                 responderLocation = new ResponderLocation(lci, lcr);
747                 if (!responderLocation.isValid()) {
748                     responderLocation = null;
749                 }
750             } catch (Exception e) {
751                 responderLocation = null;
752                 Log.e(TAG,
753                         "ResponderLocation: lci/lcr parser failed exception -- " + e);
754             }
755             if (rttResult.successNumber <= 1
756                     && rttResult.distanceSdInMm != 0) {
757                 if (mDbg) {
758                     Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num "
759                             + "samples!? result=" + rttResult);
760                 }
761                 rttResult.distanceSdInMm = 0;
762             }
763             rangingResults.add(new RangingResult(
764                     convertHalStatusToFrameworkStatus(rttResult.status),
765                     MacAddress.fromBytes(rttResult.addr),
766                     rttResult.distanceInMm, rttResult.distanceSdInMm,
767                     rttResult.rssi / -2, rttResult.numberPerBurstPeer,
768                     rttResult.successNumber, lci, lcr, responderLocation,
769                     rttResult.timeStampInUs / CONVERSION_US_TO_MS,
770                     rttResult.type == RttType.TWO_SIDED));
771         }
772         return rangingResults;
773     }
774 
convertHalResultsRangingResults14( ArrayList<android.hardware.wifi.V1_4.RttResult> halResults)775     private ArrayList<RangingResult> convertHalResultsRangingResults14(
776             ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) {
777         ArrayList<RangingResult> rangingResults = new ArrayList<>();
778         for (android.hardware.wifi.V1_4.RttResult rttResult : halResults) {
779             byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data);
780             byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data);
781             ResponderLocation responderLocation;
782             try {
783                 responderLocation = new ResponderLocation(lci, lcr);
784                 if (!responderLocation.isValid()) {
785                     responderLocation = null;
786                 }
787             } catch (Exception e) {
788                 responderLocation = null;
789                 Log.e(TAG,
790                         "ResponderLocation: lci/lcr parser failed exception -- " + e);
791             }
792             if (rttResult.successNumber <= 1
793                     && rttResult.distanceSdInMm != 0) {
794                 if (mDbg) {
795                     Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num "
796                             + "samples!? result=" + rttResult);
797                 }
798                 rttResult.distanceSdInMm = 0;
799             }
800             rangingResults.add(new RangingResult(
801                     convertHalStatusToFrameworkStatus(rttResult.status),
802                     MacAddress.fromBytes(rttResult.addr),
803                     rttResult.distanceInMm, rttResult.distanceSdInMm,
804                     rttResult.rssi / -2, rttResult.numberPerBurstPeer,
805                     rttResult.successNumber, lci, lcr, responderLocation,
806                     rttResult.timeStampInUs / CONVERSION_US_TO_MS,
807                     rttResult.type == RttType.TWO_SIDED));
808         }
809         return rangingResults;
810     }
811 
convertHalStatusToFrameworkStatus(int halStatus)812     private @FrameworkRttStatus int convertHalStatusToFrameworkStatus(int halStatus) {
813         switch (halStatus) {
814             case RttStatus.SUCCESS:
815                 return FRAMEWORK_RTT_STATUS_SUCCESS;
816             case RttStatus.FAILURE:
817                 return FRAMEWORK_RTT_STATUS_FAILURE;
818             case RttStatus.FAIL_NO_RSP:
819                 return FRAMEWORK_RTT_STATUS_FAIL_NO_RSP;
820             case RttStatus.FAIL_REJECTED:
821                 return FRAMEWORK_RTT_STATUS_FAIL_REJECTED;
822             case RttStatus.FAIL_NOT_SCHEDULED_YET:
823                 return FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET;
824             case RttStatus.FAIL_TM_TIMEOUT:
825                 return FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT;
826             case RttStatus.FAIL_AP_ON_DIFF_CHANNEL:
827                 return FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL;
828             case RttStatus.FAIL_NO_CAPABILITY:
829                 return FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY;
830             case RttStatus.ABORTED:
831                 return FRAMEWORK_RTT_STATUS_ABORTED;
832             case RttStatus.FAIL_INVALID_TS:
833                 return FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS;
834             case RttStatus.FAIL_PROTOCOL:
835                 return FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL;
836             case RttStatus.FAIL_SCHEDULE:
837                 return FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE;
838             case RttStatus.FAIL_BUSY_TRY_LATER:
839                 return FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER;
840             case RttStatus.INVALID_REQ:
841                 return FRAMEWORK_RTT_STATUS_INVALID_REQ;
842             case RttStatus.NO_WIFI:
843                 return FRAMEWORK_RTT_STATUS_NO_WIFI;
844             case RttStatus.FAIL_FTM_PARAM_OVERRIDE:
845                 return FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE;
846             default:
847                 Log.e(TAG, "Unrecognized RttStatus: " + halStatus);
848                 return FRAMEWORK_RTT_STATUS_UNKNOWN;
849         }
850     }
851 
852     /**
853      * Rtt capabilities inside framework
854      */
855     public class Capabilities {
856         //1-sided rtt measurement is supported
857         public boolean oneSidedRttSupported;
858         //location configuration information supported
859         public boolean lciSupported;
860         //location civic records supported
861         public boolean lcrSupported;
862         //preamble supported, see bit mask definition above
863         public int preambleSupported;
864         //RTT bandwidth supported
865         public int bwSupported;
866         // Whether STA responder role is supported.
867         public boolean responderSupported;
868         //Draft 11mc version supported, including major and minor version. e.g, draft 4.3 is 43.
869         public byte mcVersion;
870         //if ftm rtt data collection is supported.
871         public boolean rttFtmSupported;
872 
Capabilities(RttCapabilities rttHalCapabilities)873         public Capabilities(RttCapabilities rttHalCapabilities) {
874             oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported;
875             lciSupported = rttHalCapabilities.lciSupported;
876             lcrSupported = rttHalCapabilities.lcrSupported;
877             responderSupported = rttHalCapabilities.responderSupported;
878             preambleSupported = rttHalCapabilities.preambleSupport;
879             mcVersion = rttHalCapabilities.mcVersion;
880             bwSupported = rttHalCapabilities.bwSupport;
881             rttFtmSupported = rttHalCapabilities.rttFtmSupported;
882         }
883 
Capabilities(android.hardware.wifi.V1_4.RttCapabilities rttHalCapabilities)884         public Capabilities(android.hardware.wifi.V1_4.RttCapabilities rttHalCapabilities) {
885             oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported;
886             lciSupported = rttHalCapabilities.lciSupported;
887             lcrSupported = rttHalCapabilities.lcrSupported;
888             responderSupported = rttHalCapabilities.responderSupported;
889             preambleSupported = rttHalCapabilities.preambleSupport;
890             mcVersion = rttHalCapabilities.mcVersion;
891             bwSupported = rttHalCapabilities.bwSupport;
892             rttFtmSupported = rttHalCapabilities.rttFtmSupported;
893         }
894     }
895 }
896