summaryrefslogtreecommitdiff
path: root/wifi/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'wifi/java/android')
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl15
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java154
-rw-r--r--wifi/java/android/net/wifi/WifiLinkLayerStats.java211
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java157
-rw-r--r--wifi/java/android/net/wifi/WifiScanner.java31
-rw-r--r--wifi/java/android/net/wifi/aware/DiscoverySession.java32
-rw-r--r--wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java26
-rw-r--r--wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl2
-rw-r--r--wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl5
-rw-r--r--wifi/java/android/net/wifi/aware/IWifiAwareMacAddressProvider.aidl27
-rw-r--r--wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl6
-rw-r--r--wifi/java/android/net/wifi/aware/PublishConfig.java56
-rw-r--r--wifi/java/android/net/wifi/aware/SubscribeConfig.java156
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareManager.java161
-rw-r--r--wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl36
-rw-r--r--wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java59
-rw-r--r--wifi/java/android/net/wifi/rtt/IRttCallback.aidl37
-rw-r--r--wifi/java/android/net/wifi/rtt/IWifiRttManager.aidl33
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingRequest.aidl19
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingRequest.java248
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingResult.aidl19
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingResult.java281
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingResultCallback.java72
-rw-r--r--wifi/java/android/net/wifi/rtt/ResponderConfig.aidl19
-rw-r--r--wifi/java/android/net/wifi/rtt/ResponderConfig.java436
-rw-r--r--wifi/java/android/net/wifi/rtt/WifiRttManager.java182
-rw-r--r--wifi/java/android/net/wifi/rtt/package.html39
27 files changed, 1858 insertions, 661 deletions
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index a3a1054f869e..0dd964c0ef46 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -21,6 +21,7 @@ import android.content.pm.ParceledListSlice;
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.IProvisioningCallback;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
@@ -62,6 +63,8 @@ interface IWifiManager
WifiConfiguration getMatchingWifiConfig(in ScanResult scanResult);
+ List<WifiConfiguration> getAllMatchingWifiConfigs(in ScanResult scanResult);
+
List<OsuProvider> getMatchingOsuProviders(in ScanResult scanResult);
int addOrUpdateNetwork(in WifiConfiguration config);
@@ -100,7 +103,7 @@ interface IWifiManager
int getWifiEnabledState();
- void setCountryCode(String country, boolean persist);
+ void setCountryCode(String country);
String getCountryCode();
@@ -126,8 +129,6 @@ interface IWifiManager
void releaseMulticastLock();
- void setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
-
void updateInterfaceIpState(String ifaceName, int mode);
boolean startSoftAp(in WifiConfiguration wifiConfig);
@@ -163,12 +164,6 @@ interface IWifiManager
void enableAggressiveHandover(int enabled);
int getAggressiveHandover();
- void setAllowScansWithTraffic(int enabled);
- int getAllowScansWithTraffic();
-
- boolean setEnableAutoJoinWhenAssociated(boolean enabled);
- boolean getEnableAutoJoinWhenAssociated();
-
void enableWifiConnectivityManager(boolean enabled);
WifiConnectionStatistics getConnectionStatistics();
@@ -184,5 +179,7 @@ interface IWifiManager
void restoreBackupData(in byte[] data);
void restoreSupplicantBackupData(in byte[] supplicantData, in byte[] ipConfigData);
+
+ void startSubscriptionProvisioning(in OsuProvider provider, in IProvisioningCallback callback);
}
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index a367b2310721..3eb13ce6f8b1 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -22,7 +22,6 @@ import android.net.NetworkInfo.DetailedState;
import android.net.NetworkUtils;
import android.text.TextUtils;
-import java.lang.Math;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.UnknownHostException;
@@ -126,143 +125,35 @@ public class WifiInfo implements Parcelable {
public long rxSuccess;
/**
- * Average rate of lost transmitted packets, in units of packets per 5 seconds.
+ * Average rate of lost transmitted packets, in units of packets per second.
* @hide
*/
public double txBadRate;
/**
- * Average rate of transmitted retry packets, in units of packets per 5 seconds.
+ * Average rate of transmitted retry packets, in units of packets per second.
* @hide
*/
public double txRetriesRate;
/**
- * Average rate of successfully transmitted unicast packets, in units of packets per 5 seconds.
+ * Average rate of successfully transmitted unicast packets, in units of packets per second.
* @hide
*/
public double txSuccessRate;
/**
- * Average rate of received unicast data packets, in units of packets per 5 seconds.
+ * Average rate of received unicast data packets, in units of packets per second.
* @hide
*/
public double rxSuccessRate;
- private static final long RESET_TIME_STAMP = Long.MIN_VALUE;
- private static final long FILTER_TIME_CONSTANT = 3000;
- /**
- * This factor is used to adjust the rate output under the new algorithm
- * such that the result is comparable to the previous algorithm.
- * This actually converts from unit 'packets per second' to 'packets per 5 seconds'.
- */
- private static final long OUTPUT_SCALE_FACTOR = 5;
- private long mLastPacketCountUpdateTimeStamp;
-
- /**
- * @hide
- */
- public int badRssiCount;
-
- /**
- * @hide
- */
- public int linkStuckCount;
-
- /**
- * @hide
- */
- public int lowRssiCount;
-
/**
* @hide
*/
public int score;
/**
- * @hide
+ * Flag indicating that AP has hinted that upstream connection is metered,
+ * and sensitive to heavy data transfers.
*/
- public void updatePacketRates(WifiLinkLayerStats stats, long timeStamp) {
- if (stats != null) {
- long txgood = stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo;
- long txretries = stats.retries_be + stats.retries_bk
- + stats.retries_vi + stats.retries_vo;
- long rxgood = stats.rxmpdu_be + stats.rxmpdu_bk + stats.rxmpdu_vi + stats.rxmpdu_vo;
- long txbad = stats.lostmpdu_be + stats.lostmpdu_bk
- + stats.lostmpdu_vi + stats.lostmpdu_vo;
-
- if (mLastPacketCountUpdateTimeStamp != RESET_TIME_STAMP
- && mLastPacketCountUpdateTimeStamp < timeStamp
- && txBad <= txbad
- && txSuccess <= txgood
- && rxSuccess <= rxgood
- && txRetries <= txretries) {
- long timeDelta = timeStamp - mLastPacketCountUpdateTimeStamp;
- double lastSampleWeight = Math.exp(-1.0 * timeDelta / FILTER_TIME_CONSTANT);
- double currentSampleWeight = 1.0 - lastSampleWeight;
-
- txBadRate = txBadRate * lastSampleWeight
- + (txbad - txBad) * OUTPUT_SCALE_FACTOR * 1000 / timeDelta
- * currentSampleWeight;
- txSuccessRate = txSuccessRate * lastSampleWeight
- + (txgood - txSuccess) * OUTPUT_SCALE_FACTOR * 1000 / timeDelta
- * currentSampleWeight;
- rxSuccessRate = rxSuccessRate * lastSampleWeight
- + (rxgood - rxSuccess) * OUTPUT_SCALE_FACTOR * 1000 / timeDelta
- * currentSampleWeight;
- txRetriesRate = txRetriesRate * lastSampleWeight
- + (txretries - txRetries) * OUTPUT_SCALE_FACTOR * 1000/ timeDelta
- * currentSampleWeight;
- } else {
- txBadRate = 0;
- txSuccessRate = 0;
- rxSuccessRate = 0;
- txRetriesRate = 0;
- }
- txBad = txbad;
- txSuccess = txgood;
- rxSuccess = rxgood;
- txRetries = txretries;
- mLastPacketCountUpdateTimeStamp = timeStamp;
- } else {
- txBad = 0;
- txSuccess = 0;
- rxSuccess = 0;
- txRetries = 0;
- txBadRate = 0;
- txSuccessRate = 0;
- rxSuccessRate = 0;
- txRetriesRate = 0;
- mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP;
- }
- }
-
-
- /**
- * This function is less powerful and used if the WifiLinkLayerStats API is not implemented
- * at the Wifi HAL
- * @hide
- */
- public void updatePacketRates(long txPackets, long rxPackets) {
- //paranoia
- txBad = 0;
- txRetries = 0;
- txBadRate = 0;
- txRetriesRate = 0;
- if (txSuccess <= txPackets && rxSuccess <= rxPackets) {
- txSuccessRate = (txSuccessRate * 0.5)
- + ((double) (txPackets - txSuccess) * 0.5);
- rxSuccessRate = (rxSuccessRate * 0.5)
- + ((double) (rxPackets - rxSuccess) * 0.5);
- } else {
- txBadRate = 0;
- txRetriesRate = 0;
- }
- txSuccess = txPackets;
- rxSuccess = rxPackets;
- }
-
- /**
- * Flag indicating that AP has hinted that upstream connection is metered,
- * and sensitive to heavy data transfers.
- */
private boolean mMeteredHint;
/** @hide */
@@ -274,7 +165,6 @@ public class WifiInfo implements Parcelable {
mRssi = INVALID_RSSI;
mLinkSpeed = -1;
mFrequency = -1;
- mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP;
}
/** @hide */
@@ -296,11 +186,7 @@ public class WifiInfo implements Parcelable {
txSuccessRate = 0;
rxSuccessRate = 0;
txRetriesRate = 0;
- lowRssiCount = 0;
- badRssiCount = 0;
- linkStuckCount = 0;
score = 0;
- mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP;
}
/**
@@ -328,12 +214,7 @@ public class WifiInfo implements Parcelable {
txRetriesRate = source.txRetriesRate;
txSuccessRate = source.txSuccessRate;
rxSuccessRate = source.rxSuccessRate;
- mLastPacketCountUpdateTimeStamp =
- source.mLastPacketCountUpdateTimeStamp;
score = source.score;
- badRssiCount = source.badRssiCount;
- lowRssiCount = source.lowRssiCount;
- linkStuckCount = source.linkStuckCount;
}
}
@@ -348,6 +229,9 @@ public class WifiInfo implements Parcelable {
* quotation marks. Otherwise, it is returned as a string of hex digits. The
* SSID may be &lt;unknown ssid&gt; if there is no network currently connected,
* or if the caller has insufficient permissions to access the SSID.
+ *
+ * Prior to {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method
+ * always returned the SSID with no quotes around it.
* @return the SSID
*/
public String getSSID() {
@@ -449,22 +333,6 @@ public class WifiInfo implements Parcelable {
}
/**
- * @hide
- * This returns txSuccessRate in packets per second.
- */
- public double getTxSuccessRatePps() {
- return txSuccessRate / OUTPUT_SCALE_FACTOR;
- }
-
- /**
- * @hide
- * This returns rxSuccessRate in packets per second.
- */
- public double getRxSuccessRatePps() {
- return rxSuccessRate / OUTPUT_SCALE_FACTOR;
- }
-
- /**
* Record the MAC address of the WLAN interface
* @param macAddress the MAC address in {@code XX:XX:XX:XX:XX:XX} form
* @hide
@@ -655,8 +523,6 @@ public class WifiInfo implements Parcelable {
dest.writeDouble(txRetriesRate);
dest.writeDouble(txBadRate);
dest.writeDouble(rxSuccessRate);
- dest.writeInt(badRssiCount);
- dest.writeInt(lowRssiCount);
mSupplicantState.writeToParcel(dest, flags);
}
@@ -686,8 +552,6 @@ public class WifiInfo implements Parcelable {
info.txRetriesRate = in.readDouble();
info.txBadRate = in.readDouble();
info.rxSuccessRate = in.readDouble();
- info.badRssiCount = in.readInt();
- info.lowRssiCount = in.readInt();
info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
return info;
}
diff --git a/wifi/java/android/net/wifi/WifiLinkLayerStats.java b/wifi/java/android/net/wifi/WifiLinkLayerStats.java
deleted file mode 100644
index edd400b56238..000000000000
--- a/wifi/java/android/net/wifi/WifiLinkLayerStats.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import java.util.Arrays;
-
-/**
- * A class representing link layer statistics collected over a Wifi Interface.
- */
-/** {@hide} */
-public class WifiLinkLayerStats implements Parcelable {
- private static final String TAG = "WifiLinkLayerStats";
-
- /**
- * The current status of this network configuration entry.
- * @see Status
- */
- /** {@hide} */
- public int status;
-
- /**
- * The network's SSID. Can either be an ASCII string,
- * which must be enclosed in double quotation marks
- * (e.g., {@code "MyNetwork"}, or a string of
- * hex digits,which are not enclosed in quotes
- * (e.g., {@code 01a243f405}).
- */
- /** {@hide} */
- public String SSID;
- /**
- * When set. this is the BSSID the radio is currently associated with.
- * The value is a string in the format of an Ethernet MAC address, e.g.,
- * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit.
- */
- /** {@hide} */
- public String BSSID;
-
- /* number beacons received from our own AP */
- /** {@hide} */
- public int beacon_rx;
-
- /* RSSI taken on management frames */
- /** {@hide} */
- public int rssi_mgmt;
-
- /* packets counters */
- /** {@hide} */
- /* WME Best Effort Access Category (receive mpdu, transmit mpdu, lost mpdu, number of retries)*/
- public long rxmpdu_be;
- /** {@hide} */
- public long txmpdu_be;
- /** {@hide} */
- public long lostmpdu_be;
- /** {@hide} */
- public long retries_be;
- /** {@hide} */
- /* WME Background Access Category (receive mpdu, transmit mpdu, lost mpdu, number of retries) */
- public long rxmpdu_bk;
- /** {@hide} */
- public long txmpdu_bk;
- /** {@hide} */
- public long lostmpdu_bk;
- /** {@hide} */
- public long retries_bk;
- /** {@hide} */
- /* WME Video Access Category (receive mpdu, transmit mpdu, lost mpdu, number of retries) */
- public long rxmpdu_vi;
- /** {@hide} */
- public long txmpdu_vi;
- /** {@hide} */
- public long lostmpdu_vi;
- /** {@hide} */
- public long retries_vi;
- /** {@hide} */
- /* WME Voice Access Category (receive mpdu, transmit mpdu, lost mpdu, number of retries) */
- public long rxmpdu_vo;
- /** {@hide} */
- public long txmpdu_vo;
- /** {@hide} */
- public long lostmpdu_vo;
- /** {@hide} */
- public long retries_vo;
-
- /** {@hide} */
- public int on_time;
- /** {@hide} */
- public int tx_time;
- /** {@hide} */
- public int[] tx_time_per_level;
- /** {@hide} */
- public int rx_time;
- /** {@hide} */
- public int on_time_scan;
-
- /** {@hide} */
- public WifiLinkLayerStats() {
- }
-
- @Override
- /** {@hide} */
- public String toString() {
- StringBuilder sbuf = new StringBuilder();
- sbuf.append(" WifiLinkLayerStats: ").append('\n');
-
- if (this.SSID != null) {
- sbuf.append(" SSID: ").append(this.SSID).append('\n');
- }
- if (this.BSSID != null) {
- sbuf.append(" BSSID: ").append(this.BSSID).append('\n');
- }
-
- sbuf.append(" my bss beacon rx: ").append(Integer.toString(this.beacon_rx)).append('\n');
- sbuf.append(" RSSI mgmt: ").append(Integer.toString(this.rssi_mgmt)).append('\n');
- sbuf.append(" BE : ").append(" rx=").append(Long.toString(this.rxmpdu_be))
- .append(" tx=").append(Long.toString(this.txmpdu_be))
- .append(" lost=").append(Long.toString(this.lostmpdu_be))
- .append(" retries=").append(Long.toString(this.retries_be)).append('\n');
- sbuf.append(" BK : ").append(" rx=").append(Long.toString(this.rxmpdu_bk))
- .append(" tx=").append(Long.toString(this.txmpdu_bk))
- .append(" lost=").append(Long.toString(this.lostmpdu_bk))
- .append(" retries=").append(Long.toString(this.retries_bk)).append('\n');
- sbuf.append(" VI : ").append(" rx=").append(Long.toString(this.rxmpdu_vi))
- .append(" tx=").append(Long.toString(this.txmpdu_vi))
- .append(" lost=").append(Long.toString(this.lostmpdu_vi))
- .append(" retries=").append(Long.toString(this.retries_vi)).append('\n');
- sbuf.append(" VO : ").append(" rx=").append(Long.toString(this.rxmpdu_vo))
- .append(" tx=").append(Long.toString(this.txmpdu_vo))
- .append(" lost=").append(Long.toString(this.lostmpdu_vo))
- .append(" retries=").append(Long.toString(this.retries_vo)).append('\n');
- sbuf.append(" on_time : ").append(Integer.toString(this.on_time))
- .append(" rx_time=").append(Integer.toString(this.rx_time))
- .append(" scan_time=").append(Integer.toString(this.on_time_scan)).append('\n')
- .append(" tx_time=").append(Integer.toString(this.tx_time))
- .append(" tx_time_per_level=" + Arrays.toString(tx_time_per_level));
- return sbuf.toString();
- }
-
- /** Implement the Parcelable interface {@hide} */
- public int describeContents() {
- return 0;
- }
-
- /** {@hide} */
- public String getPrintableSsid() {
- if (SSID == null) return "";
- final int length = SSID.length();
- if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') {
- return SSID.substring(1, length - 1);
- }
-
- /** The ascii-encoded string format is P"<ascii-encoded-string>"
- * The decoding is implemented in the supplicant for a newly configured
- * network.
- */
- if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') &&
- (SSID.charAt(length-1) == '"')) {
- WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(
- SSID.substring(2, length - 1));
- return wifiSsid.toString();
- }
- return SSID;
- }
-
- /** Implement the Parcelable interface {@hide} */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(SSID);
- dest.writeString(BSSID);
- dest.writeInt(on_time);
- dest.writeInt(tx_time);
- dest.writeIntArray(tx_time_per_level);
- dest.writeInt(rx_time);
- dest.writeInt(on_time_scan);
- }
-
- /** Implement the Parcelable interface {@hide} */
- public static final Creator<WifiLinkLayerStats> CREATOR =
- new Creator<WifiLinkLayerStats>() {
- public WifiLinkLayerStats createFromParcel(Parcel in) {
- WifiLinkLayerStats stats = new WifiLinkLayerStats();
- stats.SSID = in.readString();
- stats.BSSID = in.readString();
- stats.on_time = in.readInt();
- stats.tx_time = in.readInt();
- stats.tx_time_per_level = in.createIntArray();
- stats.rx_time = in.readInt();
- stats.on_time_scan = in.readInt();
- return stats;
- };
- public WifiLinkLayerStats[] newArray(int size) {
- return new WifiLinkLayerStats[size];
- }
-
- };
-}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index e9e20caa7dfe..a158d94b646e 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -16,6 +16,7 @@
package android.net.wifi;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
@@ -32,6 +33,8 @@ import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.IProvisioningCallback;
+import android.net.wifi.hotspot2.ProvisioningCallback;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
@@ -970,8 +973,7 @@ public class WifiManager {
* <li>allowedGroupCiphers</li>
* </ul>
* @return a list of network configurations in the form of a list
- * of {@link WifiConfiguration} objects. Upon failure to fetch or
- * when Wi-Fi is turned off, it can be null.
+ * of {@link WifiConfiguration} objects.
*/
public List<WifiConfiguration> getConfiguredNetworks() {
try {
@@ -1033,6 +1035,26 @@ public class WifiManager {
}
/**
+ * Return all matching WifiConfigurations for this ScanResult.
+ *
+ * An empty list will be returned when no configurations are installed or if no configurations
+ * match the ScanResult.
+ *
+ * @param scanResult scanResult that represents the BSSID
+ * @return A list of {@link WifiConfiguration}
+ * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
+ * @hide
+ */
+ public List<WifiConfiguration> getAllMatchingWifiConfigs(ScanResult scanResult) {
+ try {
+ return mService.getAllMatchingWifiConfigs(scanResult);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+
+ /**
* Returns a list of Hotspot 2.0 OSU (Online Sign-Up) providers associated with the given AP.
*
* An empty list will be returned if no match is found.
@@ -1729,13 +1751,12 @@ public class WifiManager {
/**
* Set the country code.
* @param countryCode country code in ISO 3166 format.
- * @param persist {@code true} if this needs to be remembered
*
* @hide
*/
- public void setCountryCode(String country, boolean persist) {
+ public void setCountryCode(@NonNull String country) {
try {
- mService.setCountryCode(country, persist);
+ mService.setCountryCode(country);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1784,18 +1805,14 @@ public class WifiManager {
/**
* Enable or disable Wi-Fi.
- *
- * Note: This method will return false if wifi cannot be enabled (e.g., an incompatible mode
- * where the user has enabled tethering or Airplane Mode).
- *
- * Applications need to have the {@link android.Manifest.permission#CHANGE_WIFI_STATE}
- * permission to toggle wifi. Callers without the permissions will trigger a
- * {@link java.lang.SecurityException}.
+ * <p>
+ * Applications must have the {@link android.Manifest.permission#CHANGE_WIFI_STATE}
+ * permission to toggle wifi.
*
* @param enabled {@code true} to enable, {@code false} to disable.
- * @return {@code true} if the operation succeeds (or if the existing state
- * is the same as the requested state). False if wifi cannot be toggled on/off when the
- * request is made.
+ * @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is
+ * either already in the requested state, or in progress toward the requested state.
+ * @throws {@link java.lang.SecurityException} if the caller is missing required permissions.
*/
public boolean setWifiEnabled(boolean enabled) {
try {
@@ -1875,32 +1892,6 @@ public class WifiManager {
}
/**
- * This call is deprecated and removed. It is no longer used to
- * start WiFi Tethering. Please use {@link ConnectivityManager#startTethering(int, boolean,
- * ConnectivityManager#OnStartTetheringCallback)} if
- * the caller has proper permissions. Callers can also use the LocalOnlyHotspot feature for a
- * hotspot capable of communicating with co-located devices {@link
- * WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback)}.
- *
- * @param wifiConfig SSID, security and channel details as
- * part of WifiConfiguration
- * @return {@code false}
- *
- * @hide
- * @deprecated This API is nolonger supported.
- * @removed
- */
- @SystemApi
- @Deprecated
- @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
- public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
- String packageName = mContext.getOpPackageName();
-
- Log.w(TAG, packageName + " attempted call to setWifiApEnabled: enabled = " + enabled);
- return false;
- }
-
- /**
* Call allowing ConnectivityService to update WifiService with interface mode changes.
*
* The possible modes include: {@link IFACE_IP_MODE_TETHERED},
@@ -3448,6 +3439,7 @@ public class WifiManager {
* Set wifi verbose log. Called from developer settings.
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public void enableVerboseLogging (int verbose) {
try {
mService.enableVerboseLogging(verbose);
@@ -3496,27 +3488,23 @@ public class WifiManager {
}
/**
- * Set setting for allowing Scans when traffic is ongoing.
+ * Deprecated
+ * Does nothing
* @hide
+ * @deprecated
*/
public void setAllowScansWithTraffic(int enabled) {
- try {
- mService.setAllowScansWithTraffic(enabled);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return;
}
/**
- * Get setting for allowing Scans when traffic is ongoing.
+ * Deprecated
+ * returns value for 'disabled'
* @hide
+ * @deprecated
*/
public int getAllowScansWithTraffic() {
- try {
- return mService.getAllowScansWithTraffic();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return 0;
}
/**
@@ -3546,29 +3534,23 @@ public class WifiManager {
}
/**
- * Framework layer autojoin enable/disable when device is associated
- * this will enable/disable autojoin scan and switch network when connected
- * @return true -- if set successful false -- if set failed
+ * Deprecated
+ * returns false
* @hide
+ * @deprecated
*/
public boolean setEnableAutoJoinWhenAssociated(boolean enabled) {
- try {
- return mService.setEnableAutoJoinWhenAssociated(enabled);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return false;
}
/**
- * Get setting for Framework layer autojoin enable status
+ * Deprecated
+ * returns false
* @hide
+ * @deprecated
*/
public boolean getEnableAutoJoinWhenAssociated() {
- try {
- return mService.getEnableAutoJoinWhenAssociated();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return false;
}
/**
@@ -3620,4 +3602,45 @@ public class WifiManager {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Start subscription provisioning flow
+ * @param provider {@link OsuProvider} to provision with
+ * @param callback {@link ProvisioningCallback} for updates regarding provisioning flow
+ * @hide
+ */
+ public void startSubscriptionProvisioning(OsuProvider provider, ProvisioningCallback callback,
+ @Nullable Handler handler) {
+ Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
+ try {
+ mService.startSubscriptionProvisioning(provider,
+ new ProvisioningCallbackProxy(looper, callback));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private static class ProvisioningCallbackProxy extends IProvisioningCallback.Stub {
+ private final Handler mHandler;
+ private final ProvisioningCallback mCallback;
+
+ ProvisioningCallbackProxy(Looper looper, ProvisioningCallback callback) {
+ mHandler = new Handler(looper);
+ mCallback = callback;
+ }
+
+ @Override
+ public void onProvisioningStatus(int status) {
+ mHandler.post(() -> {
+ mCallback.onProvisioningStatus(status);
+ });
+ }
+
+ @Override
+ public void onProvisioningFailure(int status) {
+ mHandler.post(() -> {
+ mCallback.onProvisioningFailure(status);
+ });
+ }
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index f47d5caf182b..e3752ac77a5e 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -1105,8 +1105,6 @@ public class WifiScanner {
private static final int BASE = Protocol.BASE_WIFI_SCANNER;
/** @hide */
- public static final int CMD_SCAN = BASE + 0;
- /** @hide */
public static final int CMD_START_BACKGROUND_SCAN = BASE + 2;
/** @hide */
public static final int CMD_STOP_BACKGROUND_SCAN = BASE + 3;
@@ -1115,20 +1113,10 @@ public class WifiScanner {
/** @hide */
public static final int CMD_SCAN_RESULT = BASE + 5;
/** @hide */
- public static final int CMD_AP_FOUND = BASE + 9;
- /** @hide */
- public static final int CMD_AP_LOST = BASE + 10;
- /** @hide */
- public static final int CMD_WIFI_CHANGE_DETECTED = BASE + 15;
- /** @hide */
- public static final int CMD_WIFI_CHANGES_STABILIZED = BASE + 16;
- /** @hide */
public static final int CMD_OP_SUCCEEDED = BASE + 17;
/** @hide */
public static final int CMD_OP_FAILED = BASE + 18;
/** @hide */
- public static final int CMD_PERIOD_CHANGED = BASE + 19;
- /** @hide */
public static final int CMD_FULL_SCAN_RESULT = BASE + 20;
/** @hide */
public static final int CMD_START_SINGLE_SCAN = BASE + 21;
@@ -1359,25 +1347,6 @@ public class WifiScanner {
ScanResult result = (ScanResult) msg.obj;
((ScanListener) listener).onFullResult(result);
return;
- case CMD_PERIOD_CHANGED:
- ((ScanListener) listener).onPeriodChanged(msg.arg1);
- return;
- case CMD_AP_FOUND:
- ((BssidListener) listener).onFound(
- ((ParcelableScanResults) msg.obj).getResults());
- return;
- case CMD_AP_LOST:
- ((BssidListener) listener).onLost(
- ((ParcelableScanResults) msg.obj).getResults());
- return;
- case CMD_WIFI_CHANGE_DETECTED:
- ((WifiChangeListener) listener).onChanging(
- ((ParcelableScanResults) msg.obj).getResults());
- return;
- case CMD_WIFI_CHANGES_STABILIZED:
- ((WifiChangeListener) listener).onQuiescence(
- ((ParcelableScanResults) msg.obj).getResults());
- return;
case CMD_SINGLE_SCAN_COMPLETED:
if (DBG) Log.d(TAG, "removing listener for single scan");
removeListener(msg.arg2);
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index 357f76e37d28..9f7362234ad8 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.net.NetworkSpecifier;
-import android.net.wifi.RttManager;
import android.util.Log;
import dalvik.system.CloseGuard;
@@ -224,37 +223,6 @@ public class DiscoverySession implements AutoCloseable {
}
/**
- * Start a ranging operation with the specified peers. The peer IDs are obtained from an
- * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
- * byte[], java.util.List)} or
- * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
- * byte[])} operation - can
- * only range devices which are part of an ongoing discovery session.
- *
- * @param params RTT parameters - each corresponding to a specific peer ID (the array sizes
- * must be identical). The
- * {@link android.net.wifi.RttManager.RttParams#bssid} member must be set to
- * a peer ID - not to a MAC address.
- * @param listener The listener to receive the results of the ranging session.
- * @hide
- * [TODO: b/28847998 - track RTT API & visilibity]
- */
- public void startRanging(RttManager.RttParams[] params, RttManager.RttListener listener) {
- if (mTerminated) {
- Log.w(TAG, "startRanging: called on terminated session");
- return;
- }
-
- WifiAwareManager mgr = mMgr.get();
- if (mgr == null) {
- Log.w(TAG, "startRanging: called post GC on WifiAwareManager");
- return;
- }
-
- mgr.startRanging(mClientId, mSessionId, params, listener);
- }
-
- /**
* Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
* an unencrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
index 115b86d156e5..aa2c268cab88 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -113,6 +113,32 @@ public class DiscoverySessionCallback {
}
/**
+ * Called when a discovery (publish or subscribe) operation results in a
+ * service discovery. Called when a Subscribe service was configured with a range requirement
+ * {@link SubscribeConfig.Builder#setMinDistanceMm(int)} and/or
+ * {@link SubscribeConfig.Builder#setMaxDistanceMm(int)}. A discovery will only be declared
+ * (i.e. this callback called) if the range of the publisher is within the specified distance
+ * constraints.
+ *
+ * @param peerHandle An opaque handle to the peer matching our discovery operation.
+ * @param serviceSpecificInfo The service specific information (arbitrary
+ * byte array) provided by the peer as part of its discovery
+ * configuration.
+ * @param matchFilter The filter which resulted in this service discovery. For
+ * {@link PublishConfig#PUBLISH_TYPE_UNSOLICITED},
+ * {@link SubscribeConfig#SUBSCRIBE_TYPE_PASSIVE} discovery sessions this is the publisher's
+ * match filter. For {@link PublishConfig#PUBLISH_TYPE_SOLICITED},
+ * {@link SubscribeConfig#SUBSCRIBE_TYPE_ACTIVE} discovery sessions this
+ * is the subscriber's match filter.
+ * @param distanceMm The measured distance to the Publisher in mm.
+ * @hide
+ */
+ public void onServiceDiscoveredWithinRange(PeerHandle peerHandle,
+ byte[] serviceSpecificInfo, List<byte[]> matchFilter, int distanceMm) {
+ /* empty */
+ }
+
+ /**
* Called in response to
* {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])}
* when a message is transmitted successfully - i.e. when it was received successfully by the
diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
index 8ff38425d5e0..421a8af2073e 100644
--- a/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl
@@ -29,6 +29,8 @@ oneway interface IWifiAwareDiscoverySessionCallback
void onSessionTerminated(int reason);
void onMatch(int peerId, in byte[] serviceSpecificInfo, in byte[] matchFilter);
+ void onMatchWithDistance(int peerId, in byte[] serviceSpecificInfo, in byte[] matchFilter,
+ int distanceMm);
void onMessageSendSuccess(int messageId);
void onMessageSendFail(int messageId, int reason);
diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl
index 30dd64dd28f4..b646567512ac 100644
--- a/wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl
@@ -17,7 +17,6 @@
package android.net.wifi.aware;
import android.net.wifi.aware.ConfigRequest;
-import android.net.wifi.RttManager;
/**
* Callback interface that WifiAwareManager implements
@@ -29,8 +28,4 @@ oneway interface IWifiAwareEventCallback
void onConnectSuccess(int clientId);
void onConnectFail(int reason);
void onIdentityChanged(in byte[] mac);
-
- void onRangingSuccess(int rangingId, in RttManager.ParcelableRttResults results);
- void onRangingFailure(int rangingId, int reason, in String description);
- void onRangingAborted(int rangingId);
}
diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareMacAddressProvider.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareMacAddressProvider.aidl
new file mode 100644
index 000000000000..0e7289cd9c46
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareMacAddressProvider.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.aware;
+
+/**
+ * Callback for IWifiAwareManager.getMacAddressFromPeerHandle
+ *
+ * @hide
+ */
+oneway interface IWifiAwareMacAddressProvider
+{
+ void macAddress(in Map peerIdToMacMap);
+}
diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
index 0f4910f0c29f..bad5ce226efc 100644
--- a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
@@ -21,10 +21,10 @@ import android.app.PendingIntent;
import android.net.wifi.aware.ConfigRequest;
import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback;
import android.net.wifi.aware.IWifiAwareEventCallback;
+import android.net.wifi.aware.IWifiAwareMacAddressProvider;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.SubscribeConfig;
import android.net.wifi.aware.Characteristics;
-import android.net.wifi.RttManager;
/**
* Interface that WifiAwareService implements
@@ -53,5 +53,7 @@ interface IWifiAwareManager
void sendMessage(int clientId, int discoverySessionId, int peerId, in byte[] message,
int messageId, int retryCount);
void terminateSession(int clientId, int discoverySessionId);
- int startRanging(int clientId, int discoverySessionId, in RttManager.ParcelableRttParams parms);
+
+ // internal APIs: intended to be used between System Services (restricted permissions)
+ void requestMacAddresses(int uid, in List peerIds, in IWifiAwareMacAddressProvider callback);
}
diff --git a/wifi/java/android/net/wifi/aware/PublishConfig.java b/wifi/java/android/net/wifi/aware/PublishConfig.java
index d018620719e2..e60f52f88f9e 100644
--- a/wifi/java/android/net/wifi/aware/PublishConfig.java
+++ b/wifi/java/android/net/wifi/aware/PublishConfig.java
@@ -29,6 +29,7 @@ import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* Defines the configuration of a Aware publish session. Built using
@@ -81,14 +82,19 @@ public final class PublishConfig implements Parcelable {
public final boolean mEnableTerminateNotification;
/** @hide */
+ public final boolean mEnableRanging;
+
+ /** @hide */
public PublishConfig(byte[] serviceName, byte[] serviceSpecificInfo, byte[] matchFilter,
- int publishType, int ttlSec, boolean enableTerminateNotification) {
+ int publishType, int ttlSec, boolean enableTerminateNotification,
+ boolean enableRanging) {
mServiceName = serviceName;
mServiceSpecificInfo = serviceSpecificInfo;
mMatchFilter = matchFilter;
mPublishType = publishType;
mTtlSec = ttlSec;
mEnableTerminateNotification = enableTerminateNotification;
+ mEnableRanging = enableRanging;
}
@Override
@@ -103,7 +109,8 @@ public final class PublishConfig implements Parcelable {
+ (new TlvBufferUtils.TlvIterable(0, 1, mMatchFilter)).toString()
+ ", mMatchFilter.length=" + (mMatchFilter == null ? 0 : mMatchFilter.length)
+ ", mPublishType=" + mPublishType + ", mTtlSec=" + mTtlSec
- + ", mEnableTerminateNotification=" + mEnableTerminateNotification + "]";
+ + ", mEnableTerminateNotification=" + mEnableTerminateNotification
+ + ", mEnableRanging=" + mEnableRanging + "]";
}
@Override
@@ -119,6 +126,7 @@ public final class PublishConfig implements Parcelable {
dest.writeInt(mPublishType);
dest.writeInt(mTtlSec);
dest.writeInt(mEnableTerminateNotification ? 1 : 0);
+ dest.writeInt(mEnableRanging ? 1 : 0);
}
public static final Creator<PublishConfig> CREATOR = new Creator<PublishConfig>() {
@@ -135,9 +143,10 @@ public final class PublishConfig implements Parcelable {
int publishType = in.readInt();
int ttlSec = in.readInt();
boolean enableTerminateNotification = in.readInt() != 0;
+ boolean enableRanging = in.readInt() != 0;
return new PublishConfig(serviceName, ssi, matchFilter, publishType,
- ttlSec, enableTerminateNotification);
+ ttlSec, enableTerminateNotification, enableRanging);
}
};
@@ -157,21 +166,14 @@ public final class PublishConfig implements Parcelable {
lhs.mServiceSpecificInfo) && Arrays.equals(mMatchFilter, lhs.mMatchFilter)
&& mPublishType == lhs.mPublishType
&& mTtlSec == lhs.mTtlSec
- && mEnableTerminateNotification == lhs.mEnableTerminateNotification;
+ && mEnableTerminateNotification == lhs.mEnableTerminateNotification
+ && mEnableRanging == lhs.mEnableRanging;
}
@Override
public int hashCode() {
- int result = 17;
-
- result = 31 * result + Arrays.hashCode(mServiceName);
- result = 31 * result + Arrays.hashCode(mServiceSpecificInfo);
- result = 31 * result + Arrays.hashCode(mMatchFilter);
- result = 31 * result + mPublishType;
- result = 31 * result + mTtlSec;
- result = 31 * result + (mEnableTerminateNotification ? 1 : 0);
-
- return result;
+ return Objects.hash(mServiceName, mServiceSpecificInfo, mMatchFilter, mPublishType, mTtlSec,
+ mEnableTerminateNotification, mEnableRanging);
}
/**
@@ -226,6 +228,7 @@ public final class PublishConfig implements Parcelable {
private int mPublishType = PUBLISH_TYPE_UNSOLICITED;
private int mTtlSec = 0;
private boolean mEnableTerminateNotification = true;
+ private boolean mEnableRanging = false;
/**
* Specify the service name of the publish session. The actual on-air
@@ -352,12 +355,35 @@ public final class PublishConfig implements Parcelable {
}
/**
+ * Configure whether the publish discovery session supports ranging and allows peers to
+ * measure distance to it. This API is used in conjunction with
+ * {@link SubscribeConfig.Builder#setMinDistanceMm(int)} and
+ * {@link SubscribeConfig.Builder#setMaxDistanceMm(int)} to specify a minimum and/or
+ * maximum distance at which discovery will be triggered.
+ * <p>
+ * Optional. Disabled by default - i.e. any peer which attempts to measure distance to this
+ * device will be refused. If the peer has ranging enabled (using the
+ * {@link SubscribeConfig} APIs listed above, it will never discover this device.
+ *
+ * @param enable If true, ranging is supported on request of the peer.
+ *
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ *
+ * @hide
+ */
+ public Builder setRangingEnabled(boolean enable) {
+ mEnableRanging = enable;
+ return this;
+ }
+
+ /**
* Build {@link PublishConfig} given the current requests made on the
* builder.
*/
public PublishConfig build() {
return new PublishConfig(mServiceName, mServiceSpecificInfo, mMatchFilter, mPublishType,
- mTtlSec, mEnableTerminateNotification);
+ mTtlSec, mEnableTerminateNotification, mEnableRanging);
}
}
}
diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
index 4bf2fb6aa6fe..f6552a767f4f 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -29,6 +29,7 @@ import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* Defines the configuration of a Aware subscribe session. Built using
@@ -79,15 +80,32 @@ public final class SubscribeConfig implements Parcelable {
public final boolean mEnableTerminateNotification;
/** @hide */
+ public final boolean mMinDistanceMmSet;
+
+ /** @hide */
+ public final int mMinDistanceMm;
+
+ /** @hide */
+ public final boolean mMaxDistanceMmSet;
+
+ /** @hide */
+ public final int mMaxDistanceMm;
+
+ /** @hide */
public SubscribeConfig(byte[] serviceName, byte[] serviceSpecificInfo, byte[] matchFilter,
- int subscribeType, int ttlSec,
- boolean enableTerminateNotification) {
+ int subscribeType, int ttlSec, boolean enableTerminateNotification,
+ boolean minDistanceMmSet, int minDistanceMm, boolean maxDistanceMmSet,
+ int maxDistanceMm) {
mServiceName = serviceName;
mServiceSpecificInfo = serviceSpecificInfo;
mMatchFilter = matchFilter;
mSubscribeType = subscribeType;
mTtlSec = ttlSec;
mEnableTerminateNotification = enableTerminateNotification;
+ mMinDistanceMm = minDistanceMm;
+ mMinDistanceMmSet = minDistanceMmSet;
+ mMaxDistanceMm = maxDistanceMm;
+ mMaxDistanceMmSet = maxDistanceMmSet;
}
@Override
@@ -102,7 +120,11 @@ public final class SubscribeConfig implements Parcelable {
+ (new TlvBufferUtils.TlvIterable(0, 1, mMatchFilter)).toString()
+ ", mMatchFilter.length=" + (mMatchFilter == null ? 0 : mMatchFilter.length)
+ ", mSubscribeType=" + mSubscribeType + ", mTtlSec=" + mTtlSec
- + ", mEnableTerminateNotification=" + mEnableTerminateNotification + "]";
+ + ", mEnableTerminateNotification=" + mEnableTerminateNotification
+ + ", mMinDistanceMm=" + mMinDistanceMm
+ + ", mMinDistanceMmSet=" + mMinDistanceMmSet
+ + ", mMaxDistanceMm=" + mMaxDistanceMm
+ + ", mMaxDistanceMmSet=" + mMaxDistanceMmSet + "]";
}
@Override
@@ -118,6 +140,10 @@ public final class SubscribeConfig implements Parcelable {
dest.writeInt(mSubscribeType);
dest.writeInt(mTtlSec);
dest.writeInt(mEnableTerminateNotification ? 1 : 0);
+ dest.writeInt(mMinDistanceMm);
+ dest.writeInt(mMinDistanceMmSet ? 1 : 0);
+ dest.writeInt(mMaxDistanceMm);
+ dest.writeInt(mMaxDistanceMmSet ? 1 : 0);
}
public static final Creator<SubscribeConfig> CREATOR = new Creator<SubscribeConfig>() {
@@ -134,9 +160,14 @@ public final class SubscribeConfig implements Parcelable {
int subscribeType = in.readInt();
int ttlSec = in.readInt();
boolean enableTerminateNotification = in.readInt() != 0;
-
- return new SubscribeConfig(serviceName, ssi, matchFilter, subscribeType,
- ttlSec, enableTerminateNotification);
+ int minDistanceMm = in.readInt();
+ boolean minDistanceMmSet = in.readInt() != 0;
+ int maxDistanceMm = in.readInt();
+ boolean maxDistanceMmSet = in.readInt() != 0;
+
+ return new SubscribeConfig(serviceName, ssi, matchFilter, subscribeType, ttlSec,
+ enableTerminateNotification, minDistanceMmSet, minDistanceMm, maxDistanceMmSet,
+ maxDistanceMm);
}
};
@@ -152,23 +183,37 @@ public final class SubscribeConfig implements Parcelable {
SubscribeConfig lhs = (SubscribeConfig) o;
- return Arrays.equals(mServiceName, lhs.mServiceName) && Arrays.equals(mServiceSpecificInfo,
- lhs.mServiceSpecificInfo) && Arrays.equals(mMatchFilter, lhs.mMatchFilter)
- && mSubscribeType == lhs.mSubscribeType
- && mTtlSec == lhs.mTtlSec
- && mEnableTerminateNotification == lhs.mEnableTerminateNotification;
+ if (!(Arrays.equals(mServiceName, lhs.mServiceName) && Arrays.equals(
+ mServiceSpecificInfo, lhs.mServiceSpecificInfo) && Arrays.equals(mMatchFilter,
+ lhs.mMatchFilter) && mSubscribeType == lhs.mSubscribeType && mTtlSec == lhs.mTtlSec
+ && mEnableTerminateNotification == lhs.mEnableTerminateNotification
+ && mMinDistanceMmSet == lhs.mMinDistanceMmSet
+ && mMaxDistanceMmSet == lhs.mMaxDistanceMmSet)) {
+ return false;
+ }
+
+ if (mMinDistanceMmSet && mMinDistanceMm != lhs.mMinDistanceMm) {
+ return false;
+ }
+
+ if (mMaxDistanceMmSet && mMaxDistanceMm != lhs.mMaxDistanceMm) {
+ return false;
+ }
+
+ return true;
}
@Override
public int hashCode() {
- int result = 17;
+ int result = Objects.hash(mServiceName, mServiceSpecificInfo, mMatchFilter, mSubscribeType,
+ mTtlSec, mEnableTerminateNotification, mMinDistanceMmSet, mMaxDistanceMmSet);
- result = 31 * result + Arrays.hashCode(mServiceName);
- result = 31 * result + Arrays.hashCode(mServiceSpecificInfo);
- result = 31 * result + Arrays.hashCode(mMatchFilter);
- result = 31 * result + mSubscribeType;
- result = 31 * result + mTtlSec;
- result = 31 * result + (mEnableTerminateNotification ? 1 : 0);
+ if (mMinDistanceMmSet) {
+ result = Objects.hash(result, mMinDistanceMm);
+ }
+ if (mMaxDistanceMmSet) {
+ result = Objects.hash(result, mMaxDistanceMm);
+ }
return result;
}
@@ -213,6 +258,17 @@ public final class SubscribeConfig implements Parcelable {
"Match filter longer than supported by device characteristics");
}
}
+
+ if (mMinDistanceMmSet && mMinDistanceMm < 0) {
+ throw new IllegalArgumentException("Minimum distance must be non-negative");
+ }
+ if (mMaxDistanceMmSet && mMaxDistanceMm < 0) {
+ throw new IllegalArgumentException("Maximum distance must be non-negative");
+ }
+ if (mMinDistanceMmSet && mMaxDistanceMmSet && mMaxDistanceMm <= mMinDistanceMm) {
+ throw new IllegalArgumentException(
+ "Maximum distance must be greater than minimum distance");
+ }
}
/**
@@ -225,6 +281,10 @@ public final class SubscribeConfig implements Parcelable {
private int mSubscribeType = SUBSCRIBE_TYPE_PASSIVE;
private int mTtlSec = 0;
private boolean mEnableTerminateNotification = true;
+ private boolean mMinDistanceMmSet = false;
+ private int mMinDistanceMm;
+ private boolean mMaxDistanceMmSet = false;
+ private int mMaxDistanceMm;
/**
* Specify the service name of the subscribe session. The actual on-air
@@ -350,13 +410,69 @@ public final class SubscribeConfig implements Parcelable {
}
/**
+ * Configure the minimum distance to a discovered publisher at which to trigger a discovery
+ * notification. I.e. discovery will only be triggered if we've found a matching publisher
+ * (based on the other criteria in this configuration) <b>and</b> the distance to the
+ * publisher is > the value specified in this API.
+ * <p>
+ * Can be used in conjunction with {@link #setMaxDistanceMm(int)} to specify a geo-fence,
+ * i.e. discovery with min < distance < max.
+ * <p>
+ * If this API is called, the subscriber requires ranging. In such a case, the publisher
+ * peer must enable ranging using
+ * {@link PublishConfig.Builder#setRangingEnabled(boolean)}. Otherwise discovery will
+ * never be triggered.
+ *
+ * @param minDistanceMm Minimum distance, in mm, to the publisher above which to trigger
+ * discovery.
+ *
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ *
+ * @hide
+ */
+ public Builder setMinDistanceMm(int minDistanceMm) {
+ mMinDistanceMm = minDistanceMm;
+ mMinDistanceMmSet = true;
+ return this;
+ }
+
+ /**
+ * Configure the maximum distance to a discovered publisher at which to trigger a discovery
+ * notification. I.e. discovery will only be triggered if we've found a matching publisher
+ * (based on the other criteria in this configuration) <b>and</b> the distance to the
+ * publisher is < the value specified in this API.
+ * <p>
+ * Can be used in conjunction with {@link #setMinDistanceMm(int)} to specify a geo-fence,
+ * i.e. discovery with min < distance < max.
+ * <p>
+ * If this API is called, the subscriber requires ranging. In such a case, the publisher
+ * peer must enable ranging using
+ * {@link PublishConfig.Builder#setRangingEnabled(boolean)}. Otherwise discovery will
+ * never be triggered.
+ *
+ * @param maxDistanceMm Maximum distance, in mm, to the publisher below which to trigger
+ * discovery.
+ *
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ *
+ * @hide
+ */
+ public Builder setMaxDistanceMm(int maxDistanceMm) {
+ mMaxDistanceMm = maxDistanceMm;
+ mMaxDistanceMmSet = true;
+ return this;
+ }
+
+ /**
* Build {@link SubscribeConfig} given the current requests made on the
* builder.
*/
public SubscribeConfig build() {
return new SubscribeConfig(mServiceName, mServiceSpecificInfo, mMatchFilter,
- mSubscribeType, mTtlSec,
- mEnableTerminateNotification);
+ mSubscribeType, mTtlSec, mEnableTerminateNotification,
+ mMinDistanceMmSet, mMinDistanceMm, mMaxDistanceMmSet, mMaxDistanceMm);
}
}
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index df0d9d23fe14..166da48ed90a 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -20,13 +20,12 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
-import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemService;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
-import android.net.wifi.RttManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -35,9 +34,6 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.GuardedBy;
import libcore.util.HexEncoding;
@@ -45,7 +41,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.nio.BufferOverflowException;
-import java.util.Arrays;
import java.util.List;
/**
@@ -172,9 +167,6 @@ public class WifiAwareManager {
private final Object mLock = new Object(); // lock access to the following vars
- @GuardedBy("mLock")
- private SparseArray<RttManager.RttListener> mRangingListeners = new SparseArray<>();
-
/** @hide */
public WifiAwareManager(Context context, IWifiAwareManager service) {
mContext = context;
@@ -401,27 +393,6 @@ public class WifiAwareManager {
}
/** @hide */
- public void startRanging(int clientId, int sessionId, RttManager.RttParams[] params,
- RttManager.RttListener listener) {
- if (VDBG) {
- Log.v(TAG, "startRanging: clientId=" + clientId + ", sessionId=" + sessionId + ", "
- + "params=" + Arrays.toString(params) + ", listener=" + listener);
- }
-
- int rangingKey = 0;
- try {
- rangingKey = mService.startRanging(clientId, sessionId,
- new RttManager.ParcelableRttParams(params));
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
-
- synchronized (mLock) {
- mRangingListeners.put(rangingKey, listener);
- }
- }
-
- /** @hide */
public NetworkSpecifier createNetworkSpecifier(int clientId, int role, int sessionId,
PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
if (VDBG) {
@@ -500,29 +471,12 @@ public class WifiAwareManager {
private static final int CALLBACK_CONNECT_SUCCESS = 0;
private static final int CALLBACK_CONNECT_FAIL = 1;
private static final int CALLBACK_IDENTITY_CHANGED = 2;
- private static final int CALLBACK_RANGING_SUCCESS = 3;
- private static final int CALLBACK_RANGING_FAILURE = 4;
- private static final int CALLBACK_RANGING_ABORTED = 5;
private final Handler mHandler;
private final WeakReference<WifiAwareManager> mAwareManager;
private final Binder mBinder;
private final Looper mLooper;
- RttManager.RttListener getAndRemoveRangingListener(int rangingId) {
- WifiAwareManager mgr = mAwareManager.get();
- if (mgr == null) {
- Log.w(TAG, "getAndRemoveRangingListener: called post GC");
- return null;
- }
-
- synchronized (mgr.mLock) {
- RttManager.RttListener listener = mgr.mRangingListeners.get(rangingId);
- mgr.mRangingListeners.delete(rangingId);
- return listener;
- }
- }
-
/**
* Constructs a {@link AttachCallback} using the specified looper.
* All callbacks will delivered on the thread of the specified looper.
@@ -567,37 +521,6 @@ public class WifiAwareManager {
identityChangedListener.onIdentityChanged((byte[]) msg.obj);
}
break;
- case CALLBACK_RANGING_SUCCESS: {
- RttManager.RttListener listener = getAndRemoveRangingListener(msg.arg1);
- if (listener == null) {
- Log.e(TAG, "CALLBACK_RANGING_SUCCESS rangingId=" + msg.arg1
- + ": no listener registered (anymore)");
- } else {
- listener.onSuccess(
- ((RttManager.ParcelableRttResults) msg.obj).mResults);
- }
- break;
- }
- case CALLBACK_RANGING_FAILURE: {
- RttManager.RttListener listener = getAndRemoveRangingListener(msg.arg1);
- if (listener == null) {
- Log.e(TAG, "CALLBACK_RANGING_SUCCESS rangingId=" + msg.arg1
- + ": no listener registered (anymore)");
- } else {
- listener.onFailure(msg.arg2, (String) msg.obj);
- }
- break;
- }
- case CALLBACK_RANGING_ABORTED: {
- RttManager.RttListener listener = getAndRemoveRangingListener(msg.arg1);
- if (listener == null) {
- Log.e(TAG, "CALLBACK_RANGING_SUCCESS rangingId=" + msg.arg1
- + ": no listener registered (anymore)");
- } else {
- listener.onAborted();
- }
- break;
- }
}
}
};
@@ -629,43 +552,6 @@ public class WifiAwareManager {
msg.obj = mac;
mHandler.sendMessage(msg);
}
-
- @Override
- public void onRangingSuccess(int rangingId, RttManager.ParcelableRttResults results) {
- if (VDBG) {
- Log.v(TAG, "onRangingSuccess: rangingId=" + rangingId + ", results=" + results);
- }
-
- Message msg = mHandler.obtainMessage(CALLBACK_RANGING_SUCCESS);
- msg.arg1 = rangingId;
- msg.obj = results;
- mHandler.sendMessage(msg);
- }
-
- @Override
- public void onRangingFailure(int rangingId, int reason, String description) {
- if (VDBG) {
- Log.v(TAG, "onRangingSuccess: rangingId=" + rangingId + ", reason=" + reason
- + ", description=" + description);
- }
-
- Message msg = mHandler.obtainMessage(CALLBACK_RANGING_FAILURE);
- msg.arg1 = rangingId;
- msg.arg2 = reason;
- msg.obj = description;
- mHandler.sendMessage(msg);
-
- }
-
- @Override
- public void onRangingAborted(int rangingId) {
- if (VDBG) Log.v(TAG, "onRangingAborted: rangingId=" + rangingId);
-
- Message msg = mHandler.obtainMessage(CALLBACK_RANGING_ABORTED);
- msg.arg1 = rangingId;
- mHandler.sendMessage(msg);
-
- }
}
private static class WifiAwareDiscoverySessionCallbackProxy extends
@@ -678,6 +564,7 @@ public class WifiAwareManager {
private static final int CALLBACK_MESSAGE_SEND_SUCCESS = 5;
private static final int CALLBACK_MESSAGE_SEND_FAIL = 6;
private static final int CALLBACK_MESSAGE_RECEIVED = 7;
+ private static final int CALLBACK_MATCH_WITH_DISTANCE = 8;
private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message";
private static final String MESSAGE_BUNDLE_KEY_MESSAGE2 = "message2";
@@ -732,7 +619,9 @@ public class WifiAwareManager {
case CALLBACK_SESSION_TERMINATED:
onProxySessionTerminated(msg.arg1);
break;
- case CALLBACK_MATCH: {
+ case CALLBACK_MATCH:
+ case CALLBACK_MATCH_WITH_DISTANCE:
+ {
List<byte[]> matchFilter = null;
byte[] arg = msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2);
try {
@@ -743,9 +632,16 @@ public class WifiAwareManager {
+ new String(HexEncoding.encode(arg))
+ "' - cannot be parsed: e=" + e);
}
- mOriginalCallback.onServiceDiscovered(new PeerHandle(msg.arg1),
- msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
- matchFilter);
+ if (msg.what == CALLBACK_MATCH) {
+ mOriginalCallback.onServiceDiscovered(new PeerHandle(msg.arg1),
+ msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
+ matchFilter);
+ } else {
+ mOriginalCallback.onServiceDiscoveredWithinRange(
+ new PeerHandle(msg.arg1),
+ msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
+ matchFilter, msg.arg2);
+ }
break;
}
case CALLBACK_MESSAGE_SEND_SUCCESS:
@@ -798,21 +694,38 @@ public class WifiAwareManager {
mHandler.sendMessage(msg);
}
- @Override
- public void onMatch(int peerId, byte[] serviceSpecificInfo, byte[] matchFilter) {
- if (VDBG) Log.v(TAG, "onMatch: peerId=" + peerId);
-
+ private void onMatchCommon(int messageType, int peerId, byte[] serviceSpecificInfo,
+ byte[] matchFilter, int distanceMm) {
Bundle data = new Bundle();
data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, serviceSpecificInfo);
data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2, matchFilter);
- Message msg = mHandler.obtainMessage(CALLBACK_MATCH);
+ Message msg = mHandler.obtainMessage(messageType);
msg.arg1 = peerId;
+ msg.arg2 = distanceMm;
msg.setData(data);
mHandler.sendMessage(msg);
}
@Override
+ public void onMatch(int peerId, byte[] serviceSpecificInfo, byte[] matchFilter) {
+ if (VDBG) Log.v(TAG, "onMatch: peerId=" + peerId);
+
+ onMatchCommon(CALLBACK_MATCH, peerId, serviceSpecificInfo, matchFilter, 0);
+ }
+
+ @Override
+ public void onMatchWithDistance(int peerId, byte[] serviceSpecificInfo, byte[] matchFilter,
+ int distanceMm) {
+ if (VDBG) {
+ Log.v(TAG, "onMatchWithDistance: peerId=" + peerId + ", distanceMm=" + distanceMm);
+ }
+
+ onMatchCommon(CALLBACK_MATCH_WITH_DISTANCE, peerId, serviceSpecificInfo, matchFilter,
+ distanceMm);
+ }
+
+ @Override
public void onMessageSendSuccess(int messageId) {
if (VDBG) Log.v(TAG, "onMessageSendSuccess");
diff --git a/wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl b/wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl
new file mode 100644
index 000000000000..c2cb16ab847c
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.hotspot2;
+
+/**
+ * Interface for Provisioning callback.
+ *
+ * @hide
+ */
+oneway interface IProvisioningCallback
+{
+ /**
+ * Service to manager callback providing failure notification
+ */
+ void onProvisioningFailure(int status);
+
+ /**
+ * Service to manager callback providing Provisioning status
+ */
+ void onProvisioningStatus(int status);
+}
+
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
new file mode 100644
index 000000000000..8b86cdde4a9e
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.hotspot2;
+
+import android.os.Handler;
+
+/**
+ * Base class for provisioning callbacks. Should be extended by applications and set when calling
+ * {@link WifiManager#startSubscriptionProvisiong(OsuProvider, ProvisioningCallback, Handler)}.
+ *
+ * @hide
+ */
+public abstract class ProvisioningCallback {
+
+ /**
+ * The reason code for Provisioning Failure due to connection failure to OSU AP.
+ * @hide
+ */
+ public static final int OSU_FAILURE_AP_CONNECTION = 1;
+
+ /**
+ * The status code for Provisioning flow to indicate connecting to OSU AP
+ * @hide
+ */
+ public static final int OSU_STATUS_AP_CONNECTING = 1;
+
+ /**
+ * The status code for Provisioning flow to indicate connected to OSU AP
+ * @hide
+ */
+ public static final int OSU_STATUS_AP_CONNECTED = 2;
+
+ /**
+ * Provisioning status for OSU failure
+ * @param status indicates error condition
+ */
+ public abstract void onProvisioningFailure(int status);
+
+ /**
+ * Provisioning status when OSU is in progress
+ * @param status indicates status of OSU flow
+ */
+ public abstract void onProvisioningStatus(int status);
+}
+
diff --git a/wifi/java/android/net/wifi/rtt/IRttCallback.aidl b/wifi/java/android/net/wifi/rtt/IRttCallback.aidl
new file mode 100644
index 000000000000..578dd1e94997
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/IRttCallback.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.rtt;
+
+import android.net.wifi.rtt.RangingResult;
+
+/**
+ * Interface for RTT result callback.
+ *
+ * @hide
+ */
+oneway interface IRttCallback
+{
+ /**
+ * Service to manager callback indicating failure.
+ */
+ void onRangingFailure(int status);
+
+ /**
+ * Service to manager callback indicating success and providing results.
+ */
+ void onRangingResults(in List<RangingResult> results);
+}
diff --git a/wifi/java/android/net/wifi/rtt/IWifiRttManager.aidl b/wifi/java/android/net/wifi/rtt/IWifiRttManager.aidl
new file mode 100644
index 000000000000..3e37af06ab27
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/IWifiRttManager.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.rtt;
+
+import android.os.WorkSource;
+
+import android.net.wifi.rtt.IRttCallback;
+import android.net.wifi.rtt.RangingRequest;
+
+/**
+ * @hide
+ */
+interface IWifiRttManager
+{
+ boolean isAvailable();
+ void startRanging(in IBinder binder, in String callingPackage, in WorkSource workSource,
+ in RangingRequest request, in IRttCallback callback);
+ void cancelRanging(in WorkSource workSource);
+}
diff --git a/wifi/java/android/net/wifi/rtt/RangingRequest.aidl b/wifi/java/android/net/wifi/rtt/RangingRequest.aidl
new file mode 100644
index 000000000000..8053c9416aeb
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/RangingRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.rtt;
+
+parcelable RangingRequest;
diff --git a/wifi/java/android/net/wifi/rtt/RangingRequest.java b/wifi/java/android/net/wifi/rtt/RangingRequest.java
new file mode 100644
index 000000000000..b4e3097a56a7
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/RangingRequest.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.rtt;
+
+import android.annotation.NonNull;
+import android.net.MacAddress;
+import android.net.wifi.ScanResult;
+import android.net.wifi.aware.AttachCallback;
+import android.net.wifi.aware.DiscoverySessionCallback;
+import android.net.wifi.aware.IdentityChangedListener;
+import android.net.wifi.aware.PeerHandle;
+import android.net.wifi.aware.WifiAwareManager;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringJoiner;
+
+/**
+ * Defines the ranging request to other devices. The ranging request is built using
+ * {@link RangingRequest.Builder}.
+ * A ranging request is executed using
+ * {@link WifiRttManager#startRanging(RangingRequest, RangingResultCallback, Handler)}.
+ * <p>
+ * The ranging request is a batch request - specifying a set of devices (specified using
+ * {@link RangingRequest.Builder#addAccessPoint(ScanResult)} and
+ * {@link RangingRequest.Builder#addAccessPoints(List)}).
+ *
+ * @hide RTT_API
+ */
+public final class RangingRequest implements Parcelable {
+ private static final int MAX_PEERS = 10;
+
+ /**
+ * Returns the maximum number of peers to range which can be specified in a single {@code
+ * RangingRequest}. The limit applies no matter how the peers are added to the request, e.g.
+ * through {@link RangingRequest.Builder#addAccessPoint(ScanResult)} or
+ * {@link RangingRequest.Builder#addAccessPoints(List)}.
+ *
+ * @return Maximum number of peers.
+ */
+ public static int getMaxPeers() {
+ return MAX_PEERS;
+ }
+
+ /** @hide */
+ public final List<ResponderConfig> mRttPeers;
+
+ /** @hide */
+ private RangingRequest(List<ResponderConfig> rttPeers) {
+ mRttPeers = rttPeers;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeList(mRttPeers);
+ }
+
+ public static final Creator<RangingRequest> CREATOR = new Creator<RangingRequest>() {
+ @Override
+ public RangingRequest[] newArray(int size) {
+ return new RangingRequest[size];
+ }
+
+ @Override
+ public RangingRequest createFromParcel(Parcel in) {
+ return new RangingRequest(in.readArrayList(null));
+ }
+ };
+
+ /** @hide */
+ @Override
+ public String toString() {
+ StringJoiner sj = new StringJoiner(", ", "RangingRequest: mRttPeers=[", "]");
+ for (ResponderConfig rc : mRttPeers) {
+ sj.add(rc.toString());
+ }
+ return sj.toString();
+ }
+
+ /** @hide */
+ public void enforceValidity(boolean awareSupported) {
+ if (mRttPeers.size() > MAX_PEERS) {
+ throw new IllegalArgumentException(
+ "Ranging to too many peers requested. Use getMaxPeers() API to get limit.");
+ }
+
+ for (ResponderConfig peer: mRttPeers) {
+ if (!peer.isValid(awareSupported)) {
+ throw new IllegalArgumentException("Invalid Responder specification");
+ }
+ }
+ }
+
+ /**
+ * Builder class used to construct {@link RangingRequest} objects.
+ */
+ public static final class Builder {
+ private List<ResponderConfig> mRttPeers = new ArrayList<>();
+
+ /**
+ * Add the device specified by the {@link ScanResult} to the list of devices with
+ * which to measure range. The total number of peers added to a request cannot exceed the
+ * limit specified by {@link #getMaxPeers()}.
+ *
+ * @param apInfo Information of an Access Point (AP) obtained in a Scan Result.
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ */
+ public Builder addAccessPoint(@NonNull ScanResult apInfo) {
+ if (apInfo == null) {
+ throw new IllegalArgumentException("Null ScanResult!");
+ }
+ return addResponder(ResponderConfig.fromScanResult(apInfo));
+ }
+
+ /**
+ * Add the devices specified by the {@link ScanResult}s to the list of devices with
+ * which to measure range. The total number of peers added to a request cannot exceed the
+ * limit specified by {@link #getMaxPeers()}.
+ *
+ * @param apInfos Information of an Access Points (APs) obtained in a Scan Result.
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ */
+ public Builder addAccessPoints(@NonNull List<ScanResult> apInfos) {
+ if (apInfos == null) {
+ throw new IllegalArgumentException("Null list of ScanResults!");
+ }
+ for (ScanResult scanResult : apInfos) {
+ addAccessPoint(scanResult);
+ }
+ return this;
+ }
+
+ /**
+ * Add the device specified by the {@code peerMacAddress} to the list of devices with
+ * which to measure range.
+ *
+ * The MAC address may be obtained out-of-band from a peer Wi-Fi Aware device. A Wi-Fi
+ * Aware device may obtain its MAC address using the {@link IdentityChangedListener}
+ * provided to
+ * {@link WifiAwareManager#attach(AttachCallback, IdentityChangedListener, Handler)}.
+ *
+ * * Note: in order to use this API the device must support Wi-Fi Aware
+ * {@link android.net.wifi.aware}.
+ *
+ * @param peerMacAddress The MAC address of the Wi-Fi Aware peer.
+ * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ public Builder addWifiAwarePeer(@NonNull MacAddress peerMacAddress) {
+ if (peerMacAddress == null) {
+ throw new IllegalArgumentException("Null peer MAC address");
+ }
+ return addResponder(
+ ResponderConfig.fromWifiAwarePeerMacAddressWithDefaults(peerMacAddress));
+ }
+
+ /**
+ * Add a device specified by a {@link PeerHandle} to the list of devices with which to
+ * measure range.
+ *
+ * The {@link PeerHandle} may be obtained as part of the Wi-Fi Aware discovery process. E.g.
+ * using {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], List)}.
+ *
+ * Note: in order to use this API the device must support Wi-Fi Aware
+ * {@link android.net.wifi.aware}.
+ *
+ * @param peerHandle The peer handler of the peer Wi-Fi Aware device.
+ * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ public Builder addWifiAwarePeer(@NonNull PeerHandle peerHandle) {
+ if (peerHandle == null) {
+ throw new IllegalArgumentException("Null peer handler (identifier)");
+ }
+
+ return addResponder(ResponderConfig.fromWifiAwarePeerHandleWithDefaults(peerHandle));
+ }
+
+ /*
+ * Add the Responder device specified by the {@link ResponderConfig} to the list of devices
+ * with which to measure range. The total number of peers added to the request cannot exceed
+ * the limit specified by {@link #getMaxPeers()}.
+ *
+ * @param responder Information on the RTT Responder.
+ * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ *
+ * @hide (SystemApi)
+ */
+ public Builder addResponder(@NonNull ResponderConfig responder) {
+ if (responder == null) {
+ throw new IllegalArgumentException("Null Responder!");
+ }
+
+ mRttPeers.add(responder);
+ return this;
+ }
+
+ /**
+ * Build {@link RangingRequest} given the current configurations made on the
+ * builder.
+ */
+ public RangingRequest build() {
+ return new RangingRequest(mRttPeers);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof RangingRequest)) {
+ return false;
+ }
+
+ RangingRequest lhs = (RangingRequest) o;
+
+ return mRttPeers.size() == lhs.mRttPeers.size() && mRttPeers.containsAll(lhs.mRttPeers);
+ }
+
+ @Override
+ public int hashCode() {
+ return mRttPeers.hashCode();
+ }
+}
diff --git a/wifi/java/android/net/wifi/rtt/RangingResult.aidl b/wifi/java/android/net/wifi/rtt/RangingResult.aidl
new file mode 100644
index 000000000000..ae295a610afa
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/RangingResult.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.rtt;
+
+parcelable RangingResult;
diff --git a/wifi/java/android/net/wifi/rtt/RangingResult.java b/wifi/java/android/net/wifi/rtt/RangingResult.java
new file mode 100644
index 000000000000..a380fae7141a
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/RangingResult.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.rtt;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.net.MacAddress;
+import android.net.wifi.aware.PeerHandle;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Ranging result for a request started by
+ * {@link WifiRttManager#startRanging(RangingRequest, RangingResultCallback, Handler)}. Results are
+ * returned in {@link RangingResultCallback#onRangingResults(List)}.
+ * <p>
+ * A ranging result is the distance measurement result for a single device specified in the
+ * {@link RangingRequest}.
+ *
+ * @hide RTT_API
+ */
+public final class RangingResult implements Parcelable {
+ private static final String TAG = "RangingResult";
+
+ /** @hide */
+ @IntDef({STATUS_SUCCESS, STATUS_FAIL})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RangeResultStatus {
+ }
+
+ /**
+ * Individual range request status, {@link #getStatus()}. Indicates ranging operation was
+ * successful and distance value is valid.
+ */
+ public static final int STATUS_SUCCESS = 0;
+
+ /**
+ * Individual range request status, {@link #getStatus()}. Indicates ranging operation failed
+ * and the distance value is invalid.
+ */
+ public static final int STATUS_FAIL = 1;
+
+ private final int mStatus;
+ private final MacAddress mMac;
+ private final PeerHandle mPeerHandle;
+ private final int mDistanceMm;
+ private final int mDistanceStdDevMm;
+ private final int mRssi;
+ private final long mTimestamp;
+
+ /** @hide */
+ public RangingResult(@RangeResultStatus int status, @NonNull MacAddress mac, int distanceMm,
+ int distanceStdDevMm, int rssi, long timestamp) {
+ mStatus = status;
+ mMac = mac;
+ mPeerHandle = null;
+ mDistanceMm = distanceMm;
+ mDistanceStdDevMm = distanceStdDevMm;
+ mRssi = rssi;
+ mTimestamp = timestamp;
+ }
+
+ /** @hide */
+ public RangingResult(@RangeResultStatus int status, PeerHandle peerHandle, int distanceMm,
+ int distanceStdDevMm, int rssi, long timestamp) {
+ mStatus = status;
+ mMac = null;
+ mPeerHandle = peerHandle;
+ mDistanceMm = distanceMm;
+ mDistanceStdDevMm = distanceStdDevMm;
+ mRssi = rssi;
+ mTimestamp = timestamp;
+ }
+
+ /**
+ * @return The status of ranging measurement: {@link #STATUS_SUCCESS} in case of success, and
+ * {@link #STATUS_FAIL} in case of failure.
+ */
+ @RangeResultStatus
+ public int getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * @return The MAC address of the device whose range measurement was requested. Will correspond
+ * to the MAC address of the device in the {@link RangingRequest}.
+ * <p>
+ * Will return a {@code null} for results corresponding to requests issued using a {@code
+ * PeerHandle}, i.e. using the {@link RangingRequest.Builder#addWifiAwarePeer(PeerHandle)} API.
+ */
+ public MacAddress getMacAddress() {
+ return mMac;
+ }
+
+ /**
+ * @return The PeerHandle of the device whose reange measurement was requested. Will correspond
+ * to the PeerHandle of the devices requested using
+ * {@link RangingRequest.Builder#addWifiAwarePeer(PeerHandle)}.
+ * <p>
+ * Will return a {@code null} for results corresponding to requests issued using a MAC address.
+ */
+ public PeerHandle getPeerHandle() {
+ return mPeerHandle;
+ }
+
+ /**
+ * @return The distance (in mm) to the device specified by {@link #getMacAddress()} or
+ * {@link #getPeerHandle()}.
+ * <p>
+ * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
+ * exception.
+ */
+ public int getDistanceMm() {
+ if (mStatus != STATUS_SUCCESS) {
+ throw new IllegalStateException(
+ "getDistanceMm(): invoked on an invalid result: getStatus()=" + mStatus);
+ }
+ return mDistanceMm;
+ }
+
+ /**
+ * @return The standard deviation of the measured distance (in mm) to the device specified by
+ * {@link #getMacAddress()} or {@link #getPeerHandle()}. The standard deviation is calculated
+ * over the measurements executed in a single RTT burst.
+ * <p>
+ * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
+ * exception.
+ */
+ public int getDistanceStdDevMm() {
+ if (mStatus != STATUS_SUCCESS) {
+ throw new IllegalStateException(
+ "getDistanceStdDevMm(): invoked on an invalid result: getStatus()=" + mStatus);
+ }
+ return mDistanceStdDevMm;
+ }
+
+ /**
+ * @return The average RSSI (in units of -0.5dB) observed during the RTT measurement.
+ * <p>
+ * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
+ * exception.
+ */
+ public int getRssi() {
+ if (mStatus != STATUS_SUCCESS) {
+ throw new IllegalStateException(
+ "getRssi(): invoked on an invalid result: getStatus()=" + mStatus);
+ }
+ return mRssi;
+ }
+
+ /**
+ * @return The timestamp, in us since boot, at which the ranging operation was performed.
+ * <p>
+ * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
+ * exception.
+ */
+ public long getRangingTimestampUs() {
+ if (mStatus != STATUS_SUCCESS) {
+ throw new IllegalStateException(
+ "getRangingTimestamp(): invoked on an invalid result: getStatus()=" + mStatus);
+ }
+ return mTimestamp;
+ }
+
+ /** @hide */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mStatus);
+ if (mMac == null) {
+ dest.writeBoolean(false);
+ } else {
+ dest.writeBoolean(true);
+ mMac.writeToParcel(dest, flags);
+ }
+ if (mPeerHandle == null) {
+ dest.writeBoolean(false);
+ } else {
+ dest.writeBoolean(true);
+ dest.writeInt(mPeerHandle.peerId);
+ }
+ dest.writeInt(mDistanceMm);
+ dest.writeInt(mDistanceStdDevMm);
+ dest.writeInt(mRssi);
+ dest.writeLong(mTimestamp);
+ }
+
+ /** @hide */
+ public static final Creator<RangingResult> CREATOR = new Creator<RangingResult>() {
+ @Override
+ public RangingResult[] newArray(int size) {
+ return new RangingResult[size];
+ }
+
+ @Override
+ public RangingResult createFromParcel(Parcel in) {
+ int status = in.readInt();
+ boolean macAddressPresent = in.readBoolean();
+ MacAddress mac = null;
+ if (macAddressPresent) {
+ mac = MacAddress.CREATOR.createFromParcel(in);
+ }
+ boolean peerHandlePresent = in.readBoolean();
+ PeerHandle peerHandle = null;
+ if (peerHandlePresent) {
+ peerHandle = new PeerHandle(in.readInt());
+ }
+ int distanceMm = in.readInt();
+ int distanceStdDevMm = in.readInt();
+ int rssi = in.readInt();
+ long timestamp = in.readLong();
+ if (peerHandlePresent) {
+ return new RangingResult(status, peerHandle, distanceMm, distanceStdDevMm, rssi,
+ timestamp);
+ } else {
+ return new RangingResult(status, mac, distanceMm, distanceStdDevMm, rssi,
+ timestamp);
+ }
+ }
+ };
+
+ /** @hide */
+ @Override
+ public String toString() {
+ return new StringBuilder("RangingResult: [status=").append(mStatus).append(", mac=").append(
+ mMac).append(", peerHandle=").append(
+ mPeerHandle == null ? "<null>" : mPeerHandle.peerId).append(", distanceMm=").append(
+ mDistanceMm).append(", distanceStdDevMm=").append(mDistanceStdDevMm).append(
+ ", rssi=").append(mRssi).append(", timestamp=").append(mTimestamp).append(
+ "]").toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof RangingResult)) {
+ return false;
+ }
+
+ RangingResult lhs = (RangingResult) o;
+
+ return mStatus == lhs.mStatus && Objects.equals(mMac, lhs.mMac) && Objects.equals(
+ mPeerHandle, lhs.mPeerHandle) && mDistanceMm == lhs.mDistanceMm
+ && mDistanceStdDevMm == lhs.mDistanceStdDevMm && mRssi == lhs.mRssi
+ && mTimestamp == lhs.mTimestamp;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mStatus, mMac, mPeerHandle, mDistanceMm, mDistanceStdDevMm, mRssi,
+ mTimestamp);
+ }
+}
diff --git a/wifi/java/android/net/wifi/rtt/RangingResultCallback.java b/wifi/java/android/net/wifi/rtt/RangingResultCallback.java
new file mode 100644
index 000000000000..c8aea3c4aa62
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/RangingResultCallback.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.rtt;
+
+import android.annotation.IntDef;
+import android.os.Handler;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
+/**
+ * Base class for ranging result callbacks. Should be extended by applications and set when calling
+ * {@link WifiRttManager#startRanging(RangingRequest, RangingResultCallback, Handler)}. If the
+ * ranging operation fails in whole (not attempted) then {@link #onRangingFailure(int)} will be
+ * called with a failure code. If the ranging operation is performed for each of the requested
+ * peers then the {@link #onRangingResults(List)} will be called with the set of results (@link
+ * {@link RangingResult}, each of which has its own success/failure code
+ * {@link RangingResult#getStatus()}.
+ *
+ * @hide RTT_API
+ */
+public abstract class RangingResultCallback {
+ /** @hide */
+ @IntDef({STATUS_CODE_FAIL, STATUS_CODE_FAIL_RTT_NOT_AVAILABLE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RangingOperationStatus {
+ }
+
+ /**
+ * A failure code for the whole ranging request operation. Indicates a failure.
+ */
+ public static final int STATUS_CODE_FAIL = 1;
+
+ /**
+ * A failure code for the whole ranging request operation. Indicates that the request failed due
+ * to RTT not being available - e.g. Wi-Fi was disabled. Use the
+ * {@link WifiRttManager#isAvailable()} and {@link WifiRttManager#ACTION_WIFI_RTT_STATE_CHANGED}
+ * to track RTT availability.
+ */
+ public static final int STATUS_CODE_FAIL_RTT_NOT_AVAILABLE = 2;
+
+ /**
+ * Called when a ranging operation failed in whole - i.e. no ranging operation to any of the
+ * devices specified in the request was attempted.
+ *
+ * @param code A status code indicating the type of failure.
+ */
+ public abstract void onRangingFailure(@RangingOperationStatus int code);
+
+ /**
+ * Called when a ranging operation was executed. The list of results corresponds to devices
+ * specified in the ranging request.
+ *
+ * @param results List of range measurements, one per requested device.
+ */
+ public abstract void onRangingResults(List<RangingResult> results);
+}
diff --git a/wifi/java/android/net/wifi/rtt/ResponderConfig.aidl b/wifi/java/android/net/wifi/rtt/ResponderConfig.aidl
new file mode 100644
index 000000000000..fd3988aca06c
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/ResponderConfig.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.rtt;
+
+parcelable ResponderConfig;
diff --git a/wifi/java/android/net/wifi/rtt/ResponderConfig.java b/wifi/java/android/net/wifi/rtt/ResponderConfig.java
new file mode 100644
index 000000000000..8be7782d5664
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/ResponderConfig.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.rtt;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.net.MacAddress;
+import android.net.wifi.ScanResult;
+import android.net.wifi.aware.PeerHandle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Defines the configuration of an IEEE 802.11mc Responder. The Responder may be an Access Point
+ * (AP), a Wi-Fi Aware device, or a manually configured Responder.
+ * <p>
+ * A Responder configuration may be constructed from a {@link ScanResult} or manually (with the
+ * data obtained out-of-band from a peer).
+ *
+ * @hide (@SystemApi)
+ */
+public class ResponderConfig implements Parcelable {
+ private static final int AWARE_BAND_2_DISCOVERY_CHANNEL = 2437;
+
+ /** @hide */
+ @IntDef({RESPONDER_AP, RESPONDER_STA, RESPONDER_P2P_GO, RESPONDER_P2P_CLIENT, RESPONDER_AWARE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ResponderType {
+ }
+
+ /**
+ * Responder is an AP.
+ */
+ public static final int RESPONDER_AP = 0;
+ /**
+ * Responder is a STA.
+ */
+ public static final int RESPONDER_STA = 1;
+ /**
+ * Responder is a Wi-Fi Direct Group Owner (GO).
+ */
+ public static final int RESPONDER_P2P_GO = 2;
+ /**
+ * Responder is a Wi-Fi Direct Group Client.
+ */
+ public static final int RESPONDER_P2P_CLIENT = 3;
+ /**
+ * Responder is a Wi-Fi Aware device.
+ */
+ public static final int RESPONDER_AWARE = 4;
+
+
+ /** @hide */
+ @IntDef({
+ CHANNEL_WIDTH_20MHZ, CHANNEL_WIDTH_40MHZ, CHANNEL_WIDTH_80MHZ, CHANNEL_WIDTH_160MHZ,
+ CHANNEL_WIDTH_80MHZ_PLUS_MHZ})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ChannelWidth {
+ }
+
+ /**
+ * Channel bandwidth is 20 MHZ
+ */
+ public static final int CHANNEL_WIDTH_20MHZ = 0;
+ /**
+ * Channel bandwidth is 40 MHZ
+ */
+ public static final int CHANNEL_WIDTH_40MHZ = 1;
+ /**
+ * Channel bandwidth is 80 MHZ
+ */
+ public static final int CHANNEL_WIDTH_80MHZ = 2;
+ /**
+ * Channel bandwidth is 160 MHZ
+ */
+ public static final int CHANNEL_WIDTH_160MHZ = 3;
+ /**
+ * Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ
+ */
+ public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4;
+
+ /** @hide */
+ @IntDef({PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PreambleType {
+ }
+
+ /**
+ * Preamble type: Legacy.
+ */
+ public static final int PREAMBLE_LEGACY = 0;
+
+ /**
+ * Preamble type: HT.
+ */
+ public static final int PREAMBLE_HT = 1;
+
+ /**
+ * Preamble type: VHT.
+ */
+ public static final int PREAMBLE_VHT = 2;
+
+
+ /**
+ * The MAC address of the Responder. Will be null if a Wi-Fi Aware peer identifier (the
+ * peerHandle field) ise used to identify the Responder.
+ * TODO: convert to MacAddress
+ */
+ public MacAddress macAddress;
+
+ /**
+ * The peer identifier of a Wi-Fi Aware Responder. Will be null if a MAC Address (the macAddress
+ * field) is used to identify the Responder.
+ */
+ public PeerHandle peerHandle;
+
+ /**
+ * The device type of the Responder.
+ */
+ public final int responderType;
+
+ /**
+ * Indicates whether the Responder device supports IEEE 802.11mc.
+ */
+ public final boolean supports80211mc;
+
+ /**
+ * Responder channel bandwidth, specified using {@link ChannelWidth}.
+ */
+ public final int channelWidth;
+
+ /**
+ * The primary 20 MHz frequency (in MHz) of the channel of the Responder.
+ */
+ public final int frequency;
+
+ /**
+ * Not used if the {@link #channelWidth} is 20 MHz. If the Responder uses 40, 80 or 160 MHz,
+ * this is the center frequency (in MHz), if the Responder uses 80 + 80 MHz, this is the
+ * center frequency of the first segment (in MHz).
+ */
+ public final int centerFreq0;
+
+ /**
+ * Only used if the {@link #channelWidth} is 80 + 80 MHz. If the Responder uses 80 + 80 MHz,
+ * this is the center frequency of the second segment (in MHz).
+ */
+ public final int centerFreq1;
+
+ /**
+ * The preamble used by the Responder, specified using {@link PreambleType}.
+ */
+ public final int preamble;
+
+ /**
+ * Constructs Responder configuration.
+ *
+ * @param macAddress The MAC address of the Responder.
+ * @param responderType The type of the responder device, specified using
+ * {@link ResponderType}.
+ * @param supports80211mc Indicates whether the responder supports IEEE 802.11mc.
+ * @param channelWidth Responder channel bandwidth, specified using {@link ChannelWidth}.
+ * @param frequency The primary 20 MHz frequency (in MHz) of the channel of the Responder.
+ * @param centerFreq0 Not used if the {@code channelWidth} is 20 MHz. If the Responder uses
+ * 40, 80 or 160 MHz, this is the center frequency (in MHz), if the
+ * Responder uses 80 + 80 MHz, this is the center frequency of the first
+ * segment (in MHz).
+ * @param centerFreq1 Only used if the {@code channelWidth} is 80 + 80 MHz. If the
+ * Responder
+ * uses 80 + 80 MHz, this is the center frequency of the second segment
+ * (in
+ * MHz).
+ * @param preamble The preamble used by the Responder, specified using
+ * {@link PreambleType}.
+ */
+ public ResponderConfig(@NonNull MacAddress macAddress, @ResponderType int responderType,
+ boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0,
+ int centerFreq1, @PreambleType int preamble) {
+ if (macAddress == null) {
+ throw new IllegalArgumentException(
+ "Invalid ResponderConfig - must specify a MAC address");
+ }
+ this.macAddress = macAddress;
+ this.peerHandle = null;
+ this.responderType = responderType;
+ this.supports80211mc = supports80211mc;
+ this.channelWidth = channelWidth;
+ this.frequency = frequency;
+ this.centerFreq0 = centerFreq0;
+ this.centerFreq1 = centerFreq1;
+ this.preamble = preamble;
+ }
+
+ /**
+ * Constructs Responder configuration.
+ *
+ * @param peerHandle The Wi-Fi Aware peer identifier of the Responder.
+ * @param responderType The type of the responder device, specified using
+ * {@link ResponderType}.
+ * @param supports80211mc Indicates whether the responder supports IEEE 802.11mc.
+ * @param channelWidth Responder channel bandwidth, specified using {@link ChannelWidth}.
+ * @param frequency The primary 20 MHz frequency (in MHz) of the channel of the Responder.
+ * @param centerFreq0 Not used if the {@code channelWidth} is 20 MHz. If the Responder uses
+ * 40, 80 or 160 MHz, this is the center frequency (in MHz), if the
+ * Responder uses 80 + 80 MHz, this is the center frequency of the first
+ * segment (in MHz).
+ * @param centerFreq1 Only used if the {@code channelWidth} is 80 + 80 MHz. If the
+ * Responder
+ * uses 80 + 80 MHz, this is the center frequency of the second segment
+ * (in
+ * MHz).
+ * @param preamble The preamble used by the Responder, specified using
+ * {@link PreambleType}.
+ */
+ public ResponderConfig(@NonNull PeerHandle peerHandle, @ResponderType int responderType,
+ boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0,
+ int centerFreq1, @PreambleType int preamble) {
+ this.macAddress = null;
+ this.peerHandle = peerHandle;
+ this.responderType = responderType;
+ this.supports80211mc = supports80211mc;
+ this.channelWidth = channelWidth;
+ this.frequency = frequency;
+ this.centerFreq0 = centerFreq0;
+ this.centerFreq1 = centerFreq1;
+ this.preamble = preamble;
+ }
+
+ /**
+ * Creates a Responder configuration from a {@link ScanResult} corresponding to an Access
+ * Point (AP), which can be obtained from {@link android.net.wifi.WifiManager#getScanResults()}.
+ */
+ public static ResponderConfig fromScanResult(ScanResult scanResult) {
+ MacAddress macAddress = MacAddress.fromString(scanResult.BSSID);
+ int responderType = RESPONDER_AP;
+ boolean supports80211mc = scanResult.is80211mcResponder();
+ int channelWidth = translcateScanResultChannelWidth(scanResult.channelWidth);
+ int frequency = scanResult.frequency;
+ int centerFreq0 = scanResult.centerFreq0;
+ int centerFreq1 = scanResult.centerFreq1;
+
+ // TODO: b/68936111 - extract preamble info from IE
+ int preamble;
+ if (channelWidth == CHANNEL_WIDTH_80MHZ || channelWidth == CHANNEL_WIDTH_160MHZ) {
+ preamble = PREAMBLE_VHT;
+ } else {
+ preamble = PREAMBLE_HT;
+ }
+
+ return new ResponderConfig(macAddress, responderType, supports80211mc, channelWidth,
+ frequency, centerFreq0, centerFreq1, preamble);
+ }
+
+ /**
+ * Creates a Responder configuration from a MAC address corresponding to a Wi-Fi Aware
+ * Responder. The Responder parameters are set to defaults.
+ */
+ public static ResponderConfig fromWifiAwarePeerMacAddressWithDefaults(MacAddress macAddress) {
+ /* Note: the parameters are those of the Aware discovery channel (channel 6). A Responder
+ * is expected to be brought up and available to negotiate a maximum accuracy channel
+ * (i.e. Band 5 @ 80MHz). A Responder is brought up on the peer by starting an Aware
+ * Unsolicited Publisher with Ranging enabled.
+ */
+ return new ResponderConfig(macAddress, RESPONDER_AWARE, true, CHANNEL_WIDTH_20MHZ,
+ AWARE_BAND_2_DISCOVERY_CHANNEL, 0, 0, PREAMBLE_HT);
+ }
+
+ /**
+ * Creates a Responder configuration from a {@link PeerHandle} corresponding to a Wi-Fi Aware
+ * Responder. The Responder parameters are set to defaults.
+ */
+ public static ResponderConfig fromWifiAwarePeerHandleWithDefaults(PeerHandle peerHandle) {
+ /* Note: the parameters are those of the Aware discovery channel (channel 6). A Responder
+ * is expected to be brought up and available to negotiate a maximum accuracy channel
+ * (i.e. Band 5 @ 80MHz). A Responder is brought up on the peer by starting an Aware
+ * Unsolicited Publisher with Ranging enabled.
+ */
+ return new ResponderConfig(peerHandle, RESPONDER_AWARE, true, CHANNEL_WIDTH_20MHZ,
+ AWARE_BAND_2_DISCOVERY_CHANNEL, 0, 0, PREAMBLE_HT);
+ }
+
+ /**
+ * Check whether the Responder configuration is valid.
+ *
+ * @return true if valid, false otherwise.
+ * @hide
+ */
+ public boolean isValid(boolean awareSupported) {
+ if (macAddress == null && peerHandle == null || macAddress != null && peerHandle != null) {
+ return false;
+ }
+ if (!awareSupported && responderType == RESPONDER_AWARE) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (macAddress == null) {
+ dest.writeBoolean(false);
+ } else {
+ dest.writeBoolean(true);
+ macAddress.writeToParcel(dest, flags);
+ }
+ if (peerHandle == null) {
+ dest.writeBoolean(false);
+ } else {
+ dest.writeBoolean(true);
+ dest.writeInt(peerHandle.peerId);
+ }
+ dest.writeInt(responderType);
+ dest.writeInt(supports80211mc ? 1 : 0);
+ dest.writeInt(channelWidth);
+ dest.writeInt(frequency);
+ dest.writeInt(centerFreq0);
+ dest.writeInt(centerFreq1);
+ dest.writeInt(preamble);
+ }
+
+ public static final Creator<ResponderConfig> CREATOR = new Creator<ResponderConfig>() {
+ @Override
+ public ResponderConfig[] newArray(int size) {
+ return new ResponderConfig[size];
+ }
+
+ @Override
+ public ResponderConfig createFromParcel(Parcel in) {
+ boolean macAddressPresent = in.readBoolean();
+ MacAddress macAddress = null;
+ if (macAddressPresent) {
+ macAddress = MacAddress.CREATOR.createFromParcel(in);
+ }
+ boolean peerHandlePresent = in.readBoolean();
+ PeerHandle peerHandle = null;
+ if (peerHandlePresent) {
+ peerHandle = new PeerHandle(in.readInt());
+ }
+ int responderType = in.readInt();
+ boolean supports80211mc = in.readInt() == 1;
+ int channelWidth = in.readInt();
+ int frequency = in.readInt();
+ int centerFreq0 = in.readInt();
+ int centerFreq1 = in.readInt();
+ int preamble = in.readInt();
+
+ if (peerHandle == null) {
+ return new ResponderConfig(macAddress, responderType, supports80211mc, channelWidth,
+ frequency, centerFreq0, centerFreq1, preamble);
+ } else {
+ return new ResponderConfig(peerHandle, responderType, supports80211mc, channelWidth,
+ frequency, centerFreq0, centerFreq1, preamble);
+ }
+ }
+ };
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof ResponderConfig)) {
+ return false;
+ }
+
+ ResponderConfig lhs = (ResponderConfig) o;
+
+ return Objects.equals(macAddress, lhs.macAddress) && Objects.equals(peerHandle,
+ lhs.peerHandle) && responderType == lhs.responderType
+ && supports80211mc == lhs.supports80211mc && channelWidth == lhs.channelWidth
+ && frequency == lhs.frequency && centerFreq0 == lhs.centerFreq0
+ && centerFreq1 == lhs.centerFreq1 && preamble == lhs.preamble;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(macAddress, peerHandle, responderType, supports80211mc, channelWidth,
+ frequency, centerFreq0, centerFreq1, preamble);
+ }
+
+ /** @hide */
+ @Override
+ public String toString() {
+ return new StringBuffer("ResponderConfig: macAddress=").append(macAddress).append(
+ ", peerHandle=").append(peerHandle == null ? "<null>" : peerHandle.peerId).append(
+ ", responderType=").append(responderType).append(", supports80211mc=").append(
+ supports80211mc).append(", channelWidth=").append(channelWidth).append(
+ ", frequency=").append(frequency).append(", centerFreq0=").append(
+ centerFreq0).append(", centerFreq1=").append(centerFreq1).append(
+ ", preamble=").append(preamble).toString();
+ }
+
+ /** @hide */
+ static int translcateScanResultChannelWidth(int scanResultChannelWidth) {
+ switch (scanResultChannelWidth) {
+ case ScanResult.CHANNEL_WIDTH_20MHZ:
+ return CHANNEL_WIDTH_20MHZ;
+ case ScanResult.CHANNEL_WIDTH_40MHZ:
+ return CHANNEL_WIDTH_40MHZ;
+ case ScanResult.CHANNEL_WIDTH_80MHZ:
+ return CHANNEL_WIDTH_80MHZ;
+ case ScanResult.CHANNEL_WIDTH_160MHZ:
+ return CHANNEL_WIDTH_160MHZ;
+ case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
+ return CHANNEL_WIDTH_80MHZ_PLUS_MHZ;
+ default:
+ throw new IllegalArgumentException(
+ "translcateScanResultChannelWidth: bad " + scanResultChannelWidth);
+ }
+ }
+}
diff --git a/wifi/java/android/net/wifi/rtt/WifiRttManager.java b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
new file mode 100644
index 000000000000..b4c690f4840d
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -0,0 +1,182 @@
+package android.net.wifi.rtt;
+
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_WIFI_STATE;
+import static android.Manifest.permission.CHANGE_WIFI_STATE;
+import static android.Manifest.permission.LOCATION_HARDWARE;
+
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.WorkSource;
+import android.util.Log;
+
+import java.util.List;
+
+/**
+ * This class provides the primary API for measuring distance (range) to other devices using the
+ * IEEE 802.11mc Wi-Fi Round Trip Time (RTT) technology.
+ * <p>
+ * The devices which can be ranged include:
+ * <li>Access Points (APs)
+ * <li>Wi-Fi Aware peers
+ * <p>
+ * Ranging requests are triggered using
+ * {@link #startRanging(RangingRequest, RangingResultCallback, Handler)}. Results (in case of
+ * successful operation) are returned in the {@link RangingResultCallback#onRangingResults(List)}
+ * callback.
+ * <p>
+ * Wi-Fi RTT may not be usable at some points, e.g. when Wi-Fi is disabled. To validate that
+ * the functionality is available use the {@link #isAvailable()} function. To track
+ * changes in RTT usability register for the {@link #ACTION_WIFI_RTT_STATE_CHANGED}
+ * broadcast. Note that this broadcast is not sticky - you should register for it and then
+ * check the above API to avoid a race condition.
+ *
+ * @hide RTT_API
+ */
+@SystemService(Context.WIFI_RTT_RANGING_SERVICE)
+public class WifiRttManager {
+ private static final String TAG = "WifiRttManager";
+ private static final boolean VDBG = false;
+
+ private final Context mContext;
+ private final IWifiRttManager mService;
+
+ /**
+ * Broadcast intent action to indicate that the state of Wi-Fi RTT availability has changed.
+ * Use the {@link #isAvailable()} to query the current status.
+ * This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering
+ * the broadcast to check the current state of Wi-Fi RTT.
+ * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+ * components will be launched.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_WIFI_RTT_STATE_CHANGED =
+ "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED";
+
+ /** @hide */
+ public WifiRttManager(Context context, IWifiRttManager service) {
+ mContext = context;
+ mService = service;
+ }
+
+ /**
+ * Returns the current status of RTT API: whether or not RTT is available. To track
+ * changes in the state of RTT API register for the
+ * {@link #ACTION_WIFI_RTT_STATE_CHANGED} broadcast.
+ *
+ * @return A boolean indicating whether the app can use the RTT API at this time (true) or
+ * not (false).
+ */
+ public boolean isAvailable() {
+ try {
+ return mService.isAvailable();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Initiate a request to range to a set of devices specified in the {@link RangingRequest}.
+ * Results will be returned in the {@link RangingResultCallback} set of callbacks.
+ *
+ * @param request A request specifying a set of devices whose distance measurements are
+ * requested.
+ * @param callback A callback for the result of the ranging request.
+ * @param handler The Handler on whose thread to execute the callbacks of the {@code
+ * callback} object. If a null is provided then the application's main thread
+ * will be used.
+ */
+ @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE, ACCESS_WIFI_STATE})
+ public void startRanging(RangingRequest request, RangingResultCallback callback,
+ @Nullable Handler handler) {
+ startRanging(null, request, callback, handler);
+ }
+
+ /**
+ * Initiate a request to range to a set of devices specified in the {@link RangingRequest}.
+ * Results will be returned in the {@link RangingResultCallback} set of callbacks.
+ *
+ * @param workSource A mechanism to specify an alternative work-source for the request.
+ * @param request A request specifying a set of devices whose distance measurements are
+ * requested.
+ * @param callback A callback for the result of the ranging request.
+ * @param handler The Handler on whose thread to execute the callbacks of the {@code
+ * callback} object. If a null is provided then the application's main thread
+ * will be used.
+ *
+ * @hide (@SystemApi)
+ */
+ @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_COARSE_LOCATION, CHANGE_WIFI_STATE,
+ ACCESS_WIFI_STATE})
+ public void startRanging(@Nullable WorkSource workSource, RangingRequest request,
+ RangingResultCallback callback, @Nullable Handler handler) {
+ if (VDBG) {
+ Log.v(TAG, "startRanging: workSource=" + workSource + ", request=" + request
+ + ", callback=" + callback + ", handler=" + handler);
+ }
+
+ Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
+ Binder binder = new Binder();
+ try {
+ mService.startRanging(binder, mContext.getOpPackageName(), workSource, request,
+ new RttCallbackProxy(looper, callback));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Cancel all ranging requests for the specified work sources. The requests have been requested
+ * using {@link #startRanging(WorkSource, RangingRequest, RangingResultCallback, Handler)}.
+ *
+ * @param workSource The work-sources of the requesters.
+ *
+ * @hide (@SystemApi)
+ */
+ @RequiresPermission(allOf = {LOCATION_HARDWARE})
+ public void cancelRanging(WorkSource workSource) {
+ if (VDBG) {
+ Log.v(TAG, "cancelRanging: workSource=" + workSource);
+ }
+
+ try {
+ mService.cancelRanging(workSource);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private static class RttCallbackProxy extends IRttCallback.Stub {
+ private final Handler mHandler;
+ private final RangingResultCallback mCallback;
+
+ RttCallbackProxy(Looper looper, RangingResultCallback callback) {
+ mHandler = new Handler(looper);
+ mCallback = callback;
+ }
+
+ @Override
+ public void onRangingFailure(int status) throws RemoteException {
+ if (VDBG) Log.v(TAG, "RttCallbackProxy: onRangingFailure: status=" + status);
+ mHandler.post(() -> {
+ mCallback.onRangingFailure(status);
+ });
+ }
+
+ @Override
+ public void onRangingResults(List<RangingResult> results) throws RemoteException {
+ if (VDBG) Log.v(TAG, "RttCallbackProxy: onRanginResults: results=" + results);
+ mHandler.post(() -> {
+ mCallback.onRangingResults(results);
+ });
+ }
+ }
+}
diff --git a/wifi/java/android/net/wifi/rtt/package.html b/wifi/java/android/net/wifi/rtt/package.html
new file mode 100644
index 000000000000..a0d407a927a2
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/package.html
@@ -0,0 +1,39 @@
+<HTML>
+<BODY>
+<p>Provides classes which allow applications to use Wi-Fi RTT (IEEE 802.11mc) to measure distance
+ to supporting Access Points and peer devices.</p>
+<p>The primary entry point to Wi-Fi RTT capabilities is the
+ {@link android.net.wifi.rtt.WifiRttManager} class, which is acquired by calling
+ {@link android.content.Context#getSystemService(String)
+ Context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE)}</p>
+
+<p>Some APIs may require the following user permissions:</p>
+<ul>
+ <li>{@link android.Manifest.permission#ACCESS_WIFI_STATE}</li>
+ <li>{@link android.Manifest.permission#CHANGE_WIFI_STATE}</li>
+ <li>{@link android.Manifest.permission#ACCESS_COARSE_LOCATION}</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> Not all Android-powered devices support Wi-Fi RTT
+ functionality.
+ If your application only works with Wi-Fi RTT (i.e. it should only be installed on devices which
+ support Wi-Fi RTT), declare so with a <a
+ href="{@docRoot}guide/topics/manifest/uses-feature-element.html">
+ {@code <uses-feature>}</a>
+ element in the manifest file:</p>
+<pre>
+&lt;manifest ...>
+ &lt;uses-feature android:name="android.hardware.wifi.rtt" />
+ ...
+&lt;/manifest>
+</pre>
+<p>Alternatively, if your application does not require Wi-Fi RTT but can take advantage of it if
+ available, you can perform
+ the check at run-time in your code using {@link
+ android.content.pm.PackageManager#hasSystemFeature(String)} with {@link
+ android.content.pm.PackageManager#FEATURE_WIFI_RTT}:</p>
+<pre>
+ getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)
+</pre>
+</BODY>
+</HTML>