package android.net.wifi; import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.content.pm.PackageManager; import android.net.wifi.rtt.RangingRequest; import android.net.wifi.rtt.RangingResult; import android.net.wifi.rtt.RangingResultCallback; import android.net.wifi.rtt.WifiRttManager; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Protocol; import java.util.List; /** @hide */ @SystemApi @Deprecated @SystemService(Context.WIFI_RTT_SERVICE) public class RttManager { private static final boolean DBG = false; private static final String TAG = "RttManager"; /** @deprecated It is Not supported anymore. */ @Deprecated public static final int RTT_TYPE_UNSPECIFIED = 0; public static final int RTT_TYPE_ONE_SIDED = 1; public static final int RTT_TYPE_TWO_SIDED = 2; /** @deprecated It is not supported anymore. */ @Deprecated public static final int RTT_TYPE_11_V = 2; /** @deprecated It is not supported anymore. */ @Deprecated public static final int RTT_TYPE_11_MC = 4; /** @deprecated It is not supported anymore. */ @Deprecated public static final int RTT_PEER_TYPE_UNSPECIFIED = 0; public static final int RTT_PEER_TYPE_AP = 1; public static final int RTT_PEER_TYPE_STA = 2; /* requires NAN */ public static final int RTT_PEER_P2P_GO = 3; public static final int RTT_PEER_P2P_CLIENT = 4; public static final int RTT_PEER_NAN = 5; /** * @deprecated It is not supported anymore. * Use {@link android.net.wifi.RttManager#RTT_BW_20_SUPPORT} API. */ @Deprecated public static final int RTT_CHANNEL_WIDTH_20 = 0; /** * @deprecated It is not supported anymore. * Use {@link android.net.wifi.RttManager#RTT_BW_40_SUPPORT} API. */ @Deprecated public static final int RTT_CHANNEL_WIDTH_40 = 1; /** * @deprecated It is not supported anymore. * Use {@link android.net.wifi.RttManager#RTT_BW_80_SUPPORT} API. */ @Deprecated public static final int RTT_CHANNEL_WIDTH_80 = 2; /**@deprecated It is not supported anymore. * Use {@link android.net.wifi.RttManager#RTT_BW_160_SUPPORT} API. */ @Deprecated public static final int RTT_CHANNEL_WIDTH_160 = 3; /**@deprecated not supported anymore*/ @Deprecated public static final int RTT_CHANNEL_WIDTH_80P80 = 4; /**@deprecated It is not supported anymore. * Use {@link android.net.wifi.RttManager#RTT_BW_5_SUPPORT} API. */ @Deprecated public static final int RTT_CHANNEL_WIDTH_5 = 5; /**@deprecated It is not supported anymore. * Use {@link android.net.wifi.RttManager#RTT_BW_10_SUPPORT} API. */ @Deprecated public static final int RTT_CHANNEL_WIDTH_10 = 6; /** @deprecated channel info must be specified. */ @Deprecated public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; public static final int RTT_STATUS_SUCCESS = 0; /** General failure*/ public static final int RTT_STATUS_FAILURE = 1; /** Destination does not respond to RTT request*/ public static final int RTT_STATUS_FAIL_NO_RSP = 2; /** RTT request is rejected by the destination. Double side RTT only*/ public static final int RTT_STATUS_FAIL_REJECTED = 3; /** */ public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; /** Timing measurement timeout*/ public static final int RTT_STATUS_FAIL_TM_TIMEOUT = 5; /** Destination is on a different channel from the RTT Request*/ public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; /** This type of Ranging is not support by Hardware*/ public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7; /** Request abort fro uncertain reason*/ public static final int RTT_STATUS_ABORTED = 8; /** The T1-T4 or TOD/TOA Timestamp is illegal*/ public static final int RTT_STATUS_FAIL_INVALID_TS = 9; /** 11mc protocol level failed, eg, unrecognized FTMR/FTM frame*/ public static final int RTT_STATUS_FAIL_PROTOCOL = 10; /** Request can not be scheduled by hardware*/ public static final int RTT_STATUS_FAIL_SCHEDULE = 11; /** destination is busy now, you can try after a specified time from destination*/ public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; /** Bad Request argument*/ public static final int RTT_STATUS_INVALID_REQ = 13; /** Wifi is not enabled*/ public static final int RTT_STATUS_NO_WIFI = 14; /** Responder overrides param info, cannot range with new params 2-side RTT only*/ public static final int RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15; public static final int REASON_UNSPECIFIED = -1; public static final int REASON_NOT_AVAILABLE = -2; public static final int REASON_INVALID_LISTENER = -3; public static final int REASON_INVALID_REQUEST = -4; /** Do not have required permission */ public static final int REASON_PERMISSION_DENIED = -5; /** Ranging failed because responder role is enabled in STA mode.*/ public static final int REASON_INITIATOR_NOT_ALLOWED_WHEN_RESPONDER_ON = -6; public static final String DESCRIPTION_KEY = "android.net.wifi.RttManager.Description"; /** * RTT BW supported bit mask, used as RTT param bandWidth too */ public static final int RTT_BW_5_SUPPORT = 0x01; public static final int RTT_BW_10_SUPPORT = 0x02; public static final int RTT_BW_20_SUPPORT = 0x04; public static final int RTT_BW_40_SUPPORT = 0x08; public static final int RTT_BW_80_SUPPORT = 0x10; public static final int RTT_BW_160_SUPPORT = 0x20; /** * RTT Preamble Support bit mask */ public static final int PREAMBLE_LEGACY = 0x01; public static final int PREAMBLE_HT = 0x02; public static final int PREAMBLE_VHT = 0x04; /** @deprecated Use the new {@link android.net.wifi.RttManager.RttCapabilities} API */ @Deprecated public class Capabilities { public int supportedType; public int supportedPeerType; } /** @deprecated Use the new {@link android.net.wifi.RttManager#getRttCapabilities()} API.*/ @Deprecated @SuppressLint("RequiresPermission") public Capabilities getCapabilities() { throw new UnsupportedOperationException( "getCapabilities is not supported in the adaptation layer"); } /** * This class describe the RTT capability of the Hardware */ @Deprecated public static class RttCapabilities implements Parcelable { /** @deprecated It is not supported*/ @Deprecated public boolean supportedType; /** @deprecated It is not supported*/ @Deprecated public boolean supportedPeerType; //1-sided rtt measurement is supported public boolean oneSidedRttSupported; //11mc 2-sided rtt measurement is supported public boolean twoSided11McRttSupported; //location configuration information supported public boolean lciSupported; //location civic records supported public boolean lcrSupported; //preamble supported, see bit mask definition above public int preambleSupported; //RTT bandwidth supported public int bwSupported; // Whether STA responder role is supported. public boolean responderSupported; /** Whether the secure RTT protocol is supported. */ public boolean secureRttSupported; /** Draft 11mc version supported, including major and minor version. e.g, draft 4.3 is 43 */ public int mcVersion; @NonNull @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("oneSidedRtt "). append(oneSidedRttSupported ? "is Supported. " : "is not supported. "). append("twoSided11McRtt "). append(twoSided11McRttSupported ? "is Supported. " : "is not supported. "). append("lci "). append(lciSupported ? "is Supported. " : "is not supported. "). append("lcr "). append(lcrSupported ? "is Supported. " : "is not supported. "); if ((preambleSupported & PREAMBLE_LEGACY) != 0) { sb.append("Legacy "); } if ((preambleSupported & PREAMBLE_HT) != 0) { sb.append("HT "); } if ((preambleSupported & PREAMBLE_VHT) != 0) { sb.append("VHT "); } sb.append("is supported. "); if ((bwSupported & RTT_BW_5_SUPPORT) != 0) { sb.append("5 MHz "); } if ((bwSupported & RTT_BW_10_SUPPORT) != 0) { sb.append("10 MHz "); } if ((bwSupported & RTT_BW_20_SUPPORT) != 0) { sb.append("20 MHz "); } if ((bwSupported & RTT_BW_40_SUPPORT) != 0) { sb.append("40 MHz "); } if ((bwSupported & RTT_BW_80_SUPPORT) != 0) { sb.append("80 MHz "); } if ((bwSupported & RTT_BW_160_SUPPORT) != 0) { sb.append("160 MHz "); } sb.append("is supported."); sb.append(" STA responder role is ") .append(responderSupported ? "supported" : "not supported"); sb.append(" Secure RTT protocol is ") .append(secureRttSupported ? "supported" : "not supported"); sb.append(" 11mc version is " + mcVersion); return sb.toString(); } /** Implement the Parcelable interface {@hide} */ @Override public int describeContents() { return 0; } /** Implement the Parcelable interface {@hide} */ @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(oneSidedRttSupported ? 1 : 0); dest.writeInt(twoSided11McRttSupported ? 1 : 0); dest.writeInt(lciSupported ? 1 : 0); dest.writeInt(lcrSupported ? 1 : 0); dest.writeInt(preambleSupported); dest.writeInt(bwSupported); dest.writeInt(responderSupported ? 1 : 0); dest.writeInt(secureRttSupported ? 1 : 0); dest.writeInt(mcVersion); } /** Implement the Parcelable interface {@hide} */ public static final @android.annotation.NonNull Creator CREATOR = new Creator() { @Override public RttCapabilities createFromParcel(Parcel in) { RttCapabilities capabilities = new RttCapabilities(); capabilities.oneSidedRttSupported = (in.readInt() == 1); capabilities.twoSided11McRttSupported = (in.readInt() == 1); capabilities.lciSupported = (in.readInt() == 1); capabilities.lcrSupported = (in.readInt() == 1); capabilities.preambleSupported = in.readInt(); capabilities.bwSupported = in.readInt(); capabilities.responderSupported = (in.readInt() == 1); capabilities.secureRttSupported = (in.readInt() == 1); capabilities.mcVersion = in.readInt(); return capabilities; } /** Implement the Parcelable interface {@hide} */ @Override public RttCapabilities[] newArray(int size) { return new RttCapabilities[size]; } }; } /** * This method is deprecated. Please use the {@link WifiRttManager} API. */ @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) public RttCapabilities getRttCapabilities() { return mRttCapabilities; } /** specifies parameters for RTT request */ @Deprecated public static class RttParams { /** * type of destination device being ranged * currently only support RTT_PEER_TYPE_AP * Range:RTT_PEER_TYPE_xxxx Default value:RTT_PEER_TYPE_AP */ public int deviceType; /** * type of RTT measurement method. Need check scan result and RttCapabilities first * Range: RTT_TYPE_ONE_SIDED or RTT_TYPE_TWO_SIDED * Default value: RTT_TYPE_ONE_SIDED */ public int requestType; /** * Whether the secure RTT protocol needs to be used for ranging this peer device. */ public boolean secure; /** * mac address of the device being ranged * Default value: null */ public String bssid; /** * The primary control channel over which the client is * communicating with the AP.Same as ScanResult.frequency * Default value: 0 */ public int frequency; /** * channel width of the destination AP. Same as ScanResult.channelWidth * Default value: 0 */ public int channelWidth; /** * Not used if the AP bandwidth is 20 MHz * If the AP use 40, 80 or 160 MHz, this is the center frequency * if the AP use 80 + 80 MHz, this is the center frequency of the first segment * same as ScanResult.centerFreq0 * Default value: 0 */ public int centerFreq0; /** * Only used if the AP bandwidth is 80 + 80 MHz * if the AP use 80 + 80 MHz, this is the center frequency of the second segment * same as ScanResult.centerFreq1 * Default value: 0 */ public int centerFreq1; /** * number of samples to be taken * @deprecated Use the new {@link android.net.wifi.RttManager.RttParams#numSamplesPerBurst} */ @Deprecated public int num_samples; /** * number of retries if a sample fails * @deprecated * Use {@link android.net.wifi.RttManager.RttParams#numRetriesPerMeasurementFrame} API. */ @Deprecated public int num_retries; /** Number of burst in exp , 2^x. 0 means single shot measurement, range 0-15 * Currently only single shot is supported * Default value: 0 */ public int numberBurst; /** * valid only if numberBurst > 1, interval between burst(100ms). * Range : 0-31, 0--means no specific * Default value: 0 */ public int interval; /** * number of samples to be taken in one burst * Range: 1-31 * Default value: 8 */ public int numSamplesPerBurst; /** number of retries for each measurement frame if a sample fails * Only used by single side RTT, * Range 0 - 3 Default value: 0 */ public int numRetriesPerMeasurementFrame; /** * number of retries for FTMR frame (control frame) if it fails. * Only used by 80211MC double side RTT * Range: 0-3 Default Value : 0 */ public int numRetriesPerFTMR; /** * Request LCI information, only available when choose double side RTT measurement * need check RttCapabilties first. * Default value: false * */ public boolean LCIRequest; /** * Request LCR information, only available when choose double side RTT measurement * need check RttCapabilties first. * Default value: false * */ public boolean LCRRequest; /** * Timeout for each burst, (250 * 2^x) us, * Range 1-11 and 15. 15 means no control Default value: 15 * */ public int burstTimeout; /** preamble used for RTT measurement * Range: PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT * Default value: PREAMBLE_HT */ public int preamble; /** bandWidth used for RTT measurement.User need verify the highest BW the destination * support (from scan result etc) before set this value. Wider channels result usually give * better accuracy. However, the frame loss can increase too. * should be one of RTT_BW_5_SUPPORT to RTT_BW_160_SUPPORT. However, need check * RttCapabilities firstto verify HW support this bandwidth. * Default value:RTT_BW_20_SUPPORT */ public int bandwidth; public RttParams() { //provide initial value for RttParams deviceType = RTT_PEER_TYPE_AP; requestType = RTT_TYPE_ONE_SIDED; numberBurst = 0; numSamplesPerBurst = 8; numRetriesPerMeasurementFrame = 0; numRetriesPerFTMR = 0; burstTimeout = 15; preamble = PREAMBLE_HT; bandwidth = RTT_BW_20_SUPPORT; } /** * {@hide} */ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("deviceType=" + deviceType); sb.append(", requestType=" + requestType); sb.append(", secure=" + secure); sb.append(", bssid=" + bssid); sb.append(", frequency=" + frequency); sb.append(", channelWidth=" + channelWidth); sb.append(", centerFreq0=" + centerFreq0); sb.append(", centerFreq1=" + centerFreq1); sb.append(", num_samples=" + num_samples); sb.append(", num_retries=" + num_retries); sb.append(", numberBurst=" + numberBurst); sb.append(", interval=" + interval); sb.append(", numSamplesPerBurst=" + numSamplesPerBurst); sb.append(", numRetriesPerMeasurementFrame=" + numRetriesPerMeasurementFrame); sb.append(", numRetriesPerFTMR=" + numRetriesPerFTMR); sb.append(", LCIRequest=" + LCIRequest); sb.append(", LCRRequest=" + LCRRequest); sb.append(", burstTimeout=" + burstTimeout); sb.append(", preamble=" + preamble); sb.append(", bandwidth=" + bandwidth); return sb.toString(); } } /** pseudo-private class used to parcel arguments */ @Deprecated public static class ParcelableRttParams implements Parcelable { @NonNull public RttParams mParams[]; /** * @hide */ @VisibleForTesting public ParcelableRttParams(RttParams[] params) { mParams = (params == null ? new RttParams[0] : params); } /** Implement the Parcelable interface {@hide} */ @Override public int describeContents() { return 0; } /** Implement the Parcelable interface {@hide} */ @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mParams.length); for (RttParams params : mParams) { dest.writeInt(params.deviceType); dest.writeInt(params.requestType); dest.writeByte(params.secure ? (byte) 1 : 0); dest.writeString(params.bssid); dest.writeInt(params.channelWidth); dest.writeInt(params.frequency); dest.writeInt(params.centerFreq0); dest.writeInt(params.centerFreq1); dest.writeInt(params.numberBurst); dest.writeInt(params.interval); dest.writeInt(params.numSamplesPerBurst); dest.writeInt(params.numRetriesPerMeasurementFrame); dest.writeInt(params.numRetriesPerFTMR); dest.writeInt(params.LCIRequest ? 1 : 0); dest.writeInt(params.LCRRequest ? 1 : 0); dest.writeInt(params.burstTimeout); dest.writeInt(params.preamble); dest.writeInt(params.bandwidth); } } /** Implement the Parcelable interface {@hide} */ public static final @android.annotation.NonNull Creator CREATOR = new Creator() { @Override public ParcelableRttParams createFromParcel(Parcel in) { int num = in.readInt(); RttParams params[] = new RttParams[num]; for (int i = 0; i < num; i++) { params[i] = new RttParams(); params[i].deviceType = in.readInt(); params[i].requestType = in.readInt(); params[i].secure = (in.readByte() != 0); params[i].bssid = in.readString(); params[i].channelWidth = in.readInt(); params[i].frequency = in.readInt(); params[i].centerFreq0 = in.readInt(); params[i].centerFreq1 = in.readInt(); params[i].numberBurst = in.readInt(); params[i].interval = in.readInt(); params[i].numSamplesPerBurst = in.readInt(); params[i].numRetriesPerMeasurementFrame = in.readInt(); params[i].numRetriesPerFTMR = in.readInt(); params[i].LCIRequest = (in.readInt() == 1); params[i].LCRRequest = (in.readInt() == 1); params[i].burstTimeout = in.readInt(); params[i].preamble = in.readInt(); params[i].bandwidth = in.readInt(); } ParcelableRttParams parcelableParams = new ParcelableRttParams(params); return parcelableParams; } @Override public ParcelableRttParams[] newArray(int size) { return new ParcelableRttParams[size]; } }; } @Deprecated public static class WifiInformationElement { /** Information Element ID 0xFF means element is invalid. */ public byte id; public byte[] data; } /** specifies RTT results */ @Deprecated public static class RttResult { /** mac address of the device being ranged. */ public String bssid; /** # of burst for this measurement. */ public int burstNumber; /** total number of measurement frames attempted in this measurement. */ public int measurementFrameNumber; /** total successful number of measurement frames in this measurement. */ public int successMeasurementFrameNumber; /** * Maximum number of frames per burst supported by peer. Two side RTT only * Valid only if less than request */ public int frameNumberPerBurstPeer; /** status of the request */ public int status; /** * type of the request used * @deprecated Use {@link android.net.wifi.RttManager.RttResult#measurementType} */ @Deprecated public int requestType; /** RTT measurement method type used, should be one of RTT_TYPE_ONE_SIDED or * RTT_TYPE_TWO_SIDED. */ public int measurementType; /** * only valid when status == RTT_STATUS_FAIL_BUSY_TRY_LATER * please retry RTT measurement after this duration since peer indicate busy at ths moment * Unit S Range:1-31 */ public int retryAfterDuration; /** timestamp of completion, in microsecond since boot. */ public long ts; /** average RSSI observed, unit of 0.5 dB. */ public int rssi; /** * RSSI spread (i.e. max - min) * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rssiSpread} API. */ @Deprecated public int rssi_spread; /**RSSI spread (i.e. max - min), unit of 0.5 dB. */ public int rssiSpread; /** * average transmit rate * @deprecated Use {@link android.net.wifi.RttManager.RttResult#txRate} API. */ @Deprecated public int tx_rate; /** average transmit rate. Unit (kbps). */ public int txRate; /** average receiving rate Unit (kbps). */ public int rxRate; /** * average round trip time in nano second * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rtt} API. */ @Deprecated public long rtt_ns; /** average round trip time in picoseconds. */ public long rtt; /** * standard deviation observed in round trip time * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rttStandardDeviation} API. */ @Deprecated public long rtt_sd_ns; /** standard deviation of RTT in picoseconds. */ public long rttStandardDeviation; /** * spread (i.e. max - min) round trip time * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rttSpread} API. */ @Deprecated public long rtt_spread_ns; /** spread (i.e. max - min) RTT in picoseconds. */ public long rttSpread; /** * average distance in centimeter, computed based on rtt_ns * @deprecated use {@link android.net.wifi.RttManager.RttResult#distance} API. */ @Deprecated public int distance_cm; /** average distance in cm, computed based on rtt. */ public int distance; /** * standard deviation observed in distance * @deprecated * Use {@link .android.net.wifi.RttManager.RttResult#distanceStandardDeviation} API. */ @Deprecated public int distance_sd_cm; /** standard deviation observed in distance in cm. */ public int distanceStandardDeviation; /** * spread (i.e. max - min) distance * @deprecated Use {@link android.net.wifi.RttManager.RttResult#distanceSpread} API. */ @Deprecated public int distance_spread_cm; /** spread (i.e. max - min) distance in cm. */ public int distanceSpread; /** the duration of this measurement burst, unit ms. */ public int burstDuration; /** Burst number supported by peer after negotiation, 2side RTT only*/ public int negotiatedBurstNum; /** LCI information Element, only available for double side RTT. */ public WifiInformationElement LCI; /** LCR information Element, only available to double side RTT. */ public WifiInformationElement LCR; /** * Whether the secure RTT protocol was used for ranging. */ public boolean secure; } /** pseudo-private class used to parcel results. */ @Deprecated public static class ParcelableRttResults implements Parcelable { public RttResult mResults[]; public ParcelableRttResults(RttResult[] results) { mResults = results; } /** * {@hide} */ public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < mResults.length; ++i) { sb.append("[" + i + "]: "); sb.append("bssid=" + mResults[i].bssid); sb.append(", burstNumber=" + mResults[i].burstNumber); sb.append(", measurementFrameNumber=" + mResults[i].measurementFrameNumber); sb.append(", successMeasurementFrameNumber=" + mResults[i].successMeasurementFrameNumber); sb.append(", frameNumberPerBurstPeer=" + mResults[i].frameNumberPerBurstPeer); sb.append(", status=" + mResults[i].status); sb.append(", requestType=" + mResults[i].requestType); sb.append(", measurementType=" + mResults[i].measurementType); sb.append(", retryAfterDuration=" + mResults[i].retryAfterDuration); sb.append(", ts=" + mResults[i].ts); sb.append(", rssi=" + mResults[i].rssi); sb.append(", rssi_spread=" + mResults[i].rssi_spread); sb.append(", rssiSpread=" + mResults[i].rssiSpread); sb.append(", tx_rate=" + mResults[i].tx_rate); sb.append(", txRate=" + mResults[i].txRate); sb.append(", rxRate=" + mResults[i].rxRate); sb.append(", rtt_ns=" + mResults[i].rtt_ns); sb.append(", rtt=" + mResults[i].rtt); sb.append(", rtt_sd_ns=" + mResults[i].rtt_sd_ns); sb.append(", rttStandardDeviation=" + mResults[i].rttStandardDeviation); sb.append(", rtt_spread_ns=" + mResults[i].rtt_spread_ns); sb.append(", rttSpread=" + mResults[i].rttSpread); sb.append(", distance_cm=" + mResults[i].distance_cm); sb.append(", distance=" + mResults[i].distance); sb.append(", distance_sd_cm=" + mResults[i].distance_sd_cm); sb.append(", distanceStandardDeviation=" + mResults[i].distanceStandardDeviation); sb.append(", distance_spread_cm=" + mResults[i].distance_spread_cm); sb.append(", distanceSpread=" + mResults[i].distanceSpread); sb.append(", burstDuration=" + mResults[i].burstDuration); sb.append(", negotiatedBurstNum=" + mResults[i].negotiatedBurstNum); sb.append(", LCI=" + mResults[i].LCI); sb.append(", LCR=" + mResults[i].LCR); sb.append(", secure=" + mResults[i].secure); } return sb.toString(); } /** Implement the Parcelable interface {@hide} */ @Override public int describeContents() { return 0; } /** Implement the Parcelable interface {@hide} */ @Override public void writeToParcel(Parcel dest, int flags) { if (mResults != null) { dest.writeInt(mResults.length); for (RttResult result : mResults) { dest.writeString(result.bssid); dest.writeInt(result.burstNumber); dest.writeInt(result.measurementFrameNumber); dest.writeInt(result.successMeasurementFrameNumber); dest.writeInt(result.frameNumberPerBurstPeer); dest.writeInt(result.status); dest.writeInt(result.measurementType); dest.writeInt(result.retryAfterDuration); dest.writeLong(result.ts); dest.writeInt(result.rssi); dest.writeInt(result.rssiSpread); dest.writeInt(result.txRate); dest.writeLong(result.rtt); dest.writeLong(result.rttStandardDeviation); dest.writeLong(result.rttSpread); dest.writeInt(result.distance); dest.writeInt(result.distanceStandardDeviation); dest.writeInt(result.distanceSpread); dest.writeInt(result.burstDuration); dest.writeInt(result.negotiatedBurstNum); dest.writeByte(result.LCI.id); if (result.LCI.id != (byte) 0xFF) { dest.writeByte((byte)result.LCI.data.length); dest.writeByteArray(result.LCI.data); } dest.writeByte(result.LCR.id); if (result.LCR.id != (byte) 0xFF) { dest.writeByte((byte) result.LCR.data.length); dest.writeByteArray(result.LCR.data); } dest.writeByte(result.secure ? (byte) 1 : 0); } } else { dest.writeInt(0); } } /** Implement the Parcelable interface {@hide} */ public static final @android.annotation.NonNull Creator CREATOR = new Creator() { @Override public ParcelableRttResults createFromParcel(Parcel in) { int num = in.readInt(); if (num == 0) { return new ParcelableRttResults(null); } RttResult results[] = new RttResult[num]; for (int i = 0; i < num; i++) { results[i] = new RttResult(); results[i].bssid = in.readString(); results[i].burstNumber = in.readInt(); results[i].measurementFrameNumber = in.readInt(); results[i].successMeasurementFrameNumber = in.readInt(); results[i].frameNumberPerBurstPeer = in.readInt(); results[i].status = in.readInt(); results[i].measurementType = in.readInt(); results[i].retryAfterDuration = in.readInt(); results[i].ts = in.readLong(); results[i].rssi = in.readInt(); results[i].rssiSpread = in.readInt(); results[i].txRate = in.readInt(); results[i].rtt = in.readLong(); results[i].rttStandardDeviation = in.readLong(); results[i].rttSpread = in.readLong(); results[i].distance = in.readInt(); results[i].distanceStandardDeviation = in.readInt(); results[i].distanceSpread = in.readInt(); results[i].burstDuration = in.readInt(); results[i].negotiatedBurstNum = in.readInt(); results[i].LCI = new WifiInformationElement(); results[i].LCI.id = in.readByte(); if (results[i].LCI.id != (byte) 0xFF) { byte length = in.readByte(); results[i].LCI.data = new byte[length]; in.readByteArray(results[i].LCI.data); } results[i].LCR = new WifiInformationElement(); results[i].LCR.id = in.readByte(); if (results[i].LCR.id != (byte) 0xFF) { byte length = in.readByte(); results[i].LCR.data = new byte[length]; in.readByteArray(results[i].LCR.data); } results[i].secure = (in.readByte() != 0); } ParcelableRttResults parcelableResults = new ParcelableRttResults(results); return parcelableResults; } @Override public ParcelableRttResults[] newArray(int size) { return new ParcelableRttResults[size]; } }; } @Deprecated public static interface RttListener { public void onSuccess(RttResult[] results); public void onFailure(int reason, String description); public void onAborted(); } /** * Request to start an RTT ranging *

* This method is deprecated. Please use the * {@link WifiRttManager#startRanging(RangingRequest, java.util.concurrent.Executor, RangingResultCallback)} * API. * * @param params -- RTT request Parameters * @param listener -- Call back to inform RTT result * @exception throw IllegalArgumentException when params are illegal * throw IllegalStateException when RttCapabilities do not exist */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startRanging(RttParams[] params, RttListener listener) { Log.i(TAG, "Send RTT request to RTT Service"); if (!mNewService.isAvailable()) { listener.onFailure(REASON_NOT_AVAILABLE, ""); return; } RangingRequest.Builder builder = new RangingRequest.Builder(); for (RttParams rttParams : params) { if (rttParams.deviceType != RTT_PEER_TYPE_AP) { listener.onFailure(REASON_INVALID_REQUEST, "Only AP peers are supported"); return; } ScanResult reconstructed = new ScanResult(); reconstructed.BSSID = rttParams.bssid; if (rttParams.requestType == RTT_TYPE_TWO_SIDED) { reconstructed.setFlag(ScanResult.FLAG_80211mc_RESPONDER); } reconstructed.channelWidth = rttParams.channelWidth; reconstructed.frequency = rttParams.frequency; reconstructed.centerFreq0 = rttParams.centerFreq0; reconstructed.centerFreq1 = rttParams.centerFreq1; builder.addResponder( android.net.wifi.rtt.ResponderConfig.fromScanResult(reconstructed)); } try { mNewService.startRanging(builder.build(), mContext.getMainExecutor(), new RangingResultCallback() { @Override public void onRangingFailure(int code) { int localCode = REASON_UNSPECIFIED; if (code == STATUS_CODE_FAIL_RTT_NOT_AVAILABLE) { localCode = REASON_NOT_AVAILABLE; } listener.onFailure(localCode, ""); } @Override public void onRangingResults(List results) { RttResult[] legacyResults = new RttResult[results.size()]; int i = 0; for (RangingResult result : results) { legacyResults[i] = new RttResult(); legacyResults[i].status = result.getStatus(); legacyResults[i].bssid = result.getMacAddress().toString(); if (result.getStatus() == RangingResult.STATUS_SUCCESS) { legacyResults[i].distance = result.getDistanceMm() / 10; legacyResults[i].distanceStandardDeviation = result.getDistanceStdDevMm() / 10; legacyResults[i].rssi = result.getRssi() * -2; legacyResults[i].ts = result.getRangingTimestampMillis() * 1000; legacyResults[i].measurementFrameNumber = result.getNumAttemptedMeasurements(); legacyResults[i].successMeasurementFrameNumber = result.getNumSuccessfulMeasurements(); } else { // just in case legacy API needed some relatively real timestamp legacyResults[i].ts = SystemClock.elapsedRealtime() * 1000; } i++; } listener.onSuccess(legacyResults); } }); } catch (IllegalArgumentException e) { Log.e(TAG, "startRanging: invalid arguments - " + e); listener.onFailure(REASON_INVALID_REQUEST, e.getMessage()); } catch (SecurityException e) { Log.e(TAG, "startRanging: security exception - " + e); listener.onFailure(REASON_PERMISSION_DENIED, e.getMessage()); } } /** * This method is deprecated and performs no function. Please use the {@link WifiRttManager} * API. */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void stopRanging(RttListener listener) { Log.e(TAG, "stopRanging: unsupported operation - nop"); } /** * Callbacks for responder operations. *

* A {@link ResponderCallback} is the handle to the calling client. {@link RttManager} will keep * a reference to the callback for the entire period when responder is enabled. The same * callback as used in enabling responder needs to be passed for disabling responder. * The client can freely destroy or reuse the callback after {@link RttManager#disableResponder} * is called. */ @Deprecated public abstract static class ResponderCallback { /** Callback when responder is enabled. */ public abstract void onResponderEnabled(ResponderConfig config); /** Callback when enabling responder failed. */ public abstract void onResponderEnableFailure(int reason); // TODO: consider adding onResponderAborted once it's supported. } /** * Enable Wi-Fi RTT responder mode on the device. The enabling result will be delivered via * {@code callback}. *

* Note calling this method with the same callback when the responder is already enabled won't * change the responder state, a cached {@link ResponderConfig} from the last enabling will be * returned through the callback. *

* This method is deprecated and will throw an {@link UnsupportedOperationException} * exception. Please use the {@link WifiRttManager} API to perform a Wi-Fi Aware peer-to-peer * ranging. * * @param callback Callback for responder enabling/disabling result. * @throws IllegalArgumentException If {@code callback} is null. */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void enableResponder(ResponderCallback callback) { throw new UnsupportedOperationException( "enableResponder is not supported in the adaptation layer"); } /** * Disable Wi-Fi RTT responder mode on the device. The {@code callback} needs to be the * same one used in {@link #enableResponder(ResponderCallback)}. *

* Calling this method when responder isn't enabled won't have any effect. The callback can be * reused for enabling responder after this method is called. *

* This method is deprecated and will throw an {@link UnsupportedOperationException} * exception. Please use the {@link WifiRttManager} API to perform a Wi-Fi Aware peer-to-peer * ranging. * * @param callback The same callback used for enabling responder. * @throws IllegalArgumentException If {@code callback} is null. */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void disableResponder(ResponderCallback callback) { throw new UnsupportedOperationException( "disableResponder is not supported in the adaptation layer"); } /** * Configuration used for RTT responder mode. The configuration information can be used by a * peer device to range the responder. * * @see ScanResult */ @Deprecated public static class ResponderConfig implements Parcelable { // TODO: make all fields final once we can get mac address from responder HAL APIs. /** * Wi-Fi mac address used for responder mode. */ public String macAddress = ""; /** * The primary 20 MHz frequency (in MHz) of the channel where responder is enabled. * @see ScanResult#frequency */ public int frequency; /** * Center frequency of the channel where responder is enabled on. Only in use when channel * width is at least 40MHz. * @see ScanResult#centerFreq0 */ public int centerFreq0; /** * Center frequency of the second segment when channel width is 80 + 80 MHz. * @see ScanResult#centerFreq1 */ public int centerFreq1; /** * Width of the channel where responder is enabled on. * @see ScanResult#channelWidth */ public int channelWidth; /** * Preamble supported by responder. */ public int preamble; @NonNull @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("macAddress = ").append(macAddress) .append(" frequency = ").append(frequency) .append(" centerFreq0 = ").append(centerFreq0) .append(" centerFreq1 = ").append(centerFreq1) .append(" channelWidth = ").append(channelWidth) .append(" preamble = ").append(preamble); return builder.toString(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(macAddress); dest.writeInt(frequency); dest.writeInt(centerFreq0); dest.writeInt(centerFreq1); dest.writeInt(channelWidth); dest.writeInt(preamble); } /** Implement {@link Parcelable} interface */ public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public ResponderConfig createFromParcel(Parcel in) { ResponderConfig config = new ResponderConfig(); config.macAddress = in.readString(); config.frequency = in.readInt(); config.centerFreq0 = in.readInt(); config.centerFreq1 = in.readInt(); config.channelWidth = in.readInt(); config.preamble = in.readInt(); return config; } @Override public ResponderConfig[] newArray(int size) { return new ResponderConfig[size]; } }; } /* private methods */ public static final int BASE = Protocol.BASE_WIFI_RTT_MANAGER; public static final int CMD_OP_START_RANGING = BASE + 0; public static final int CMD_OP_STOP_RANGING = BASE + 1; public static final int CMD_OP_FAILED = BASE + 2; public static final int CMD_OP_SUCCEEDED = BASE + 3; public static final int CMD_OP_ABORTED = BASE + 4; public static final int CMD_OP_ENABLE_RESPONDER = BASE + 5; public static final int CMD_OP_DISABLE_RESPONDER = BASE + 6; public static final int CMD_OP_ENALBE_RESPONDER_SUCCEEDED = BASE + 7; public static final int CMD_OP_ENALBE_RESPONDER_FAILED = BASE + 8; /** @hide */ public static final int CMD_OP_REG_BINDER = BASE + 9; private final WifiRttManager mNewService; private final Context mContext; private RttCapabilities mRttCapabilities; /** * Create a new WifiScanner instance. * Applications will almost always want to use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve * the standard {@link android.content.Context#WIFI_RTT_SERVICE Context.WIFI_RTT_SERVICE}. * @param service the new WifiRttManager service * * @hide */ public RttManager(@NonNull Context context, @NonNull WifiRttManager service) { mNewService = service; mContext = context; boolean rttSupported = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WIFI_RTT); mRttCapabilities = new RttCapabilities(); mRttCapabilities.oneSidedRttSupported = rttSupported; mRttCapabilities.twoSided11McRttSupported = rttSupported; mRttCapabilities.lciSupported = false; mRttCapabilities.lcrSupported = false; mRttCapabilities.preambleSupported = PREAMBLE_HT | PREAMBLE_VHT; mRttCapabilities.bwSupported = RTT_BW_40_SUPPORT | RTT_BW_80_SUPPORT; mRttCapabilities.responderSupported = false; mRttCapabilities.secureRttSupported = false; } }