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/ISoftApCallback.aidl44
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl71
-rw-r--r--wifi/java/android/net/wifi/RttManager.java450
-rw-r--r--wifi/java/android/net/wifi/ScanResult.java99
-rw-r--r--wifi/java/android/net/wifi/WifiActivityEnergyInfo.java25
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java113
-rw-r--r--wifi/java/android/net/wifi/WifiConnectionStatistics.java158
-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.java585
-rw-r--r--wifi/java/android/net/wifi/WifiScanner.java61
-rw-r--r--wifi/java/android/net/wifi/aware/DiscoverySession.java77
-rw-r--r--wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java25
-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.aidl (renamed from wifi/java/android/net/wifi/IRttManager.aidl)15
-rw-r--r--wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl10
-rw-r--r--wifi/java/android/net/wifi/aware/PublishConfig.java63
-rw-r--r--wifi/java/android/net/wifi/aware/SubscribeConfig.java164
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareManager.java198
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareSession.java31
-rw-r--r--wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl36
-rw-r--r--wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java113
-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/LocationCivic.java118
-rw-r--r--wifi/java/android/net/wifi/rtt/LocationConfigurationInformation.java272
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingRequest.aidl (renamed from wifi/java/android/net/wifi/WifiConnectionStatistics.aidl)24
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingRequest.java256
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingResult.aidl19
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingResult.java354
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingResultCallback.java71
-rw-r--r--wifi/java/android/net/wifi/rtt/ResponderConfig.aidl19
-rw-r--r--wifi/java/android/net/wifi/rtt/ResponderConfig.java476
-rw-r--r--wifi/java/android/net/wifi/rtt/WifiRttManager.java205
-rw-r--r--wifi/java/android/net/wifi/rtt/package.html41
36 files changed, 3138 insertions, 1497 deletions
diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl
new file mode 100644
index 000000000000..b8d2971e74bb
--- /dev/null
+++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 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;
+
+/**
+ * Interface for Soft AP callback.
+ *
+ * @hide
+ */
+oneway interface ISoftApCallback
+{
+ /**
+ * Service to manager callback providing current soft AP state. The possible
+ * parameter values listed are defined in WifiManager.java
+ *
+ * @param state new AP state. One of WIFI_AP_STATE_DISABLED,
+ * WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED,
+ * WIFI_AP_STATE_ENABLING, WIFI_AP_STATE_FAILED
+ * @param failureReason reason when in failed state. One of
+ * SAP_START_FAILURE_GENERAL, SAP_START_FAILURE_NO_CHANNEL
+ */
+ void onStateChanged(int state, int failureReason);
+
+ /**
+ * Service to manager callback providing number of connected clients.
+ *
+ * @param numClients number of connected clients
+ */
+ void onNumClientsChanged(int numClients);
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index a3a1054f869e..309bc80b8864 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -21,17 +21,17 @@ 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;
-import android.net.wifi.ScanSettings;
-import android.net.wifi.ScanResult;
+import android.net.DhcpInfo;
+import android.net.Network;
+import android.net.wifi.ISoftApCallback;
import android.net.wifi.PasspointManagementObjectDefinition;
-import android.net.wifi.WifiConnectionStatistics;
+import android.net.wifi.ScanResult;
+import android.net.wifi.ScanSettings;
import android.net.wifi.WifiActivityEnergyInfo;
-import android.net.Network;
-
-import android.net.DhcpInfo;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
import android.os.Messenger;
import android.os.ResultReceiver;
@@ -62,13 +62,15 @@ interface IWifiManager
WifiConfiguration getMatchingWifiConfig(in ScanResult scanResult);
+ List<WifiConfiguration> getAllMatchingWifiConfigs(in ScanResult scanResult);
+
List<OsuProvider> getMatchingOsuProviders(in ScanResult scanResult);
- int addOrUpdateNetwork(in WifiConfiguration config);
+ int addOrUpdateNetwork(in WifiConfiguration config, String packageName);
- boolean addOrUpdatePasspointConfiguration(in PasspointConfiguration config);
+ boolean addOrUpdatePasspointConfiguration(in PasspointConfiguration config, String packageName);
- boolean removePasspointConfiguration(in String fqdn);
+ boolean removePasspointConfiguration(in String fqdn, String packageName);
List<PasspointConfiguration> getPasspointConfigurations();
@@ -78,21 +80,21 @@ interface IWifiManager
void deauthenticateNetwork(long holdoff, boolean ess);
- boolean removeNetwork(int netId);
+ boolean removeNetwork(int netId, String packageName);
- boolean enableNetwork(int netId, boolean disableOthers);
+ boolean enableNetwork(int netId, boolean disableOthers, String packageName);
- boolean disableNetwork(int netId);
+ boolean disableNetwork(int netId, String packageName);
- void startScan(in ScanSettings requested, in WorkSource ws, in String packageName);
+ void startScan(in ScanSettings requested, in WorkSource ws, String packageName);
List<ScanResult> getScanResults(String callingPackage);
- void disconnect();
+ void disconnect(String packageName);
- void reconnect();
+ void reconnect(String packageName);
- void reassociate();
+ void reassociate(String packageName);
WifiInfo getConnectionInfo(String callingPackage);
@@ -100,14 +102,12 @@ interface IWifiManager
int getWifiEnabledState();
- void setCountryCode(String country, boolean persist);
+ void setCountryCode(String country);
String getCountryCode();
boolean isDualBandSupported();
- boolean saveConfiguration();
-
DhcpInfo getDhcpInfo();
boolean isScanAlwaysAvailable();
@@ -126,15 +126,13 @@ interface IWifiManager
void releaseMulticastLock();
- void setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
-
void updateInterfaceIpState(String ifaceName, int mode);
boolean startSoftAp(in WifiConfiguration wifiConfig);
boolean stopSoftAp();
- int startLocalOnlyHotspot(in Messenger messenger, in IBinder binder, in String packageName);
+ int startLocalOnlyHotspot(in Messenger messenger, in IBinder binder, String packageName);
void stopLocalOnlyHotspot();
@@ -146,9 +144,9 @@ interface IWifiManager
WifiConfiguration getWifiApConfiguration();
- void setWifiApConfiguration(in WifiConfiguration wifiConfig);
+ void setWifiApConfiguration(in WifiConfiguration wifiConfig, String packageName);
- Messenger getWifiServiceMessenger();
+ Messenger getWifiServiceMessenger(String packageName);
void enableTdls(String remoteIPAddress, boolean enable);
@@ -160,22 +158,11 @@ interface IWifiManager
int getVerboseLoggingLevel();
- void enableAggressiveHandover(int enabled);
- int getAggressiveHandover();
-
- void setAllowScansWithTraffic(int enabled);
- int getAllowScansWithTraffic();
-
- boolean setEnableAutoJoinWhenAssociated(boolean enabled);
- boolean getEnableAutoJoinWhenAssociated();
-
void enableWifiConnectivityManager(boolean enabled);
- WifiConnectionStatistics getConnectionStatistics();
-
- void disableEphemeralNetwork(String SSID);
+ void disableEphemeralNetwork(String SSID, String packageName);
- void factoryReset();
+ void factoryReset(String packageName);
Network getCurrentNetwork();
@@ -184,5 +171,11 @@ interface IWifiManager
void restoreBackupData(in byte[] data);
void restoreSupplicantBackupData(in byte[] supplicantData, in byte[] ipConfigData);
+
+ void startSubscriptionProvisioning(in OsuProvider provider, in IProvisioningCallback callback);
+
+ void registerSoftApCallback(in IBinder binder, in ISoftApCallback callback, int callbackIdentifier);
+
+ void unregisterSoftApCallback(int callbackIdentifier);
}
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index 12a8ddf9fcdc..bdbc149a0a42 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -7,24 +7,24 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
-import android.os.Binder;
-import android.os.Bundle;
+import android.content.pm.PackageManager;
+import android.net.wifi.rtt.RangingRequest;
+import android.net.wifi.rtt.RangingResult;
+import android.net.wifi.rtt.RangingResultCallback;
+import android.net.wifi.rtt.WifiRttManager;
import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.RemoteException;
import android.util.Log;
-import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
+import java.util.List;
+
/** @hide */
@SystemApi
+@Deprecated
@SystemService(Context.WIFI_RTT_SERVICE)
public class RttManager {
@@ -175,12 +175,14 @@ public class RttManager {
@Deprecated
@SuppressLint("Doclava125")
public Capabilities getCapabilities() {
- return new Capabilities();
+ throw new UnsupportedOperationException(
+ "getCapabilities is not supported in the adaptation layer");
}
/**
* This class describe the RTT capability of the Hardware
*/
+ @Deprecated
public static class RttCapabilities implements Parcelable {
/** @deprecated It is not supported*/
@Deprecated
@@ -314,21 +316,16 @@ public class RttManager {
};
}
+ /**
+ * This method is deprecated. Please use the {@link WifiRttManager} API.
+ */
@RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
public RttCapabilities getRttCapabilities() {
- synchronized (mCapabilitiesLock) {
- if (mRttCapabilities == null) {
- try {
- mRttCapabilities = mService.getRttCapabilities();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- return mRttCapabilities;
- }
+ return mRttCapabilities;
}
/** specifies parameters for RTT request */
+ @Deprecated
public static class RttParams {
/**
* type of destination device being ranged
@@ -511,6 +508,7 @@ public class RttManager {
}
/** pseudo-private class used to parcel arguments */
+ @Deprecated
public static class ParcelableRttParams implements Parcelable {
@NonNull
@@ -598,12 +596,14 @@ public class RttManager {
};
}
+ @Deprecated
public static class WifiInformationElement {
/** Information Element ID 0xFF means element is invalid. */
public byte id;
public byte[] data;
}
/** specifies RTT results */
+ @Deprecated
public static class RttResult {
/** mac address of the device being ranged. */
public String bssid;
@@ -755,6 +755,7 @@ public class RttManager {
/** pseudo-private class used to parcel results. */
+ @Deprecated
public static class ParcelableRttResults implements Parcelable {
public RttResult mResults[];
@@ -920,7 +921,7 @@ public class RttManager {
};
}
-
+ @Deprecated
public static interface RttListener {
public void onSuccess(RttResult[] results);
public void onFailure(int reason, String description);
@@ -928,141 +929,88 @@ public class RttManager {
}
/**
- * A parcelable that contains rtt client information.
+ * Request to start an RTT ranging
+ * <p>
+ * This method is deprecated. Please use the
+ * {@link WifiRttManager#startRanging(RangingRequest, RangingResultCallback, Handler)} API.
*
- * @hide
+ * @param params -- RTT request Parameters
+ * @param listener -- Call back to inform RTT result
+ * @exception throw IllegalArgumentException when params are illegal
+ * throw IllegalStateException when RttCapabilities do not exist
*/
- public static class RttClient implements Parcelable {
- // Package name of RttClient.
- private final String mPackageName;
-
- public RttClient(String packageName) {
- mPackageName = packageName;
- }
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+ public void startRanging(RttParams[] params, RttListener listener) {
+ Log.i(TAG, "Send RTT request to RTT Service");
- protected RttClient(Parcel in) {
- mPackageName = in.readString();
+ if (!mNewService.isAvailable()) {
+ listener.onFailure(REASON_NOT_AVAILABLE, "");
+ return;
}
- public static final Creator<RttManager.RttClient> CREATOR =
- new Creator<RttManager.RttClient>() {
- @Override
- public RttManager.RttClient createFromParcel(Parcel in) {
- return new RttManager.RttClient(in);
- }
-
- @Override
- public RttManager.RttClient[] newArray(int size) {
- return new RttManager.RttClient[size];
+ RangingRequest.Builder builder = new RangingRequest.Builder();
+ for (RttParams rttParams : params) {
+ if (rttParams.deviceType != RTT_PEER_TYPE_AP) {
+ listener.onFailure(REASON_INVALID_REQUEST, "Only AP peers are supported");
+ return;
}
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
- @Override
- public void writeToParcel(Parcel parcel, int i) {
- parcel.writeString(mPackageName);
- }
-
- public String getPackageName() {
- return mPackageName;
- }
- }
-
- private boolean rttParamSanity(RttParams params, int index) {
- if (mRttCapabilities == null) {
- if(getRttCapabilities() == null) {
- Log.e(TAG, "Can not get RTT capabilities");
- throw new IllegalStateException("RTT chip is not working");
+ ScanResult reconstructed = new ScanResult();
+ reconstructed.BSSID = rttParams.bssid;
+ if (rttParams.requestType == RTT_TYPE_TWO_SIDED) {
+ reconstructed.setFlag(ScanResult.FLAG_80211mc_RESPONDER);
}
+ reconstructed.channelWidth = rttParams.channelWidth;
+ reconstructed.frequency = rttParams.frequency;
+ reconstructed.centerFreq0 = rttParams.centerFreq0;
+ reconstructed.centerFreq1 = rttParams.centerFreq1;
+ builder.addResponder(
+ android.net.wifi.rtt.ResponderConfig.fromScanResult(reconstructed));
}
+ try {
+ mNewService.startRanging(builder.build(), new RangingResultCallback() {
+ @Override
+ public void onRangingFailure(int code) {
+ int localCode = REASON_UNSPECIFIED;
+ if (code == STATUS_CODE_FAIL_RTT_NOT_AVAILABLE) {
+ localCode = REASON_NOT_AVAILABLE;
+ }
+ listener.onFailure(localCode, "");
+ }
- if (params.deviceType != RTT_PEER_TYPE_AP) {
- return false;
- } else if (params.requestType != RTT_TYPE_ONE_SIDED && params.requestType !=
- RTT_TYPE_TWO_SIDED) {
- Log.e(TAG, "Request " + index + ": Illegal Request Type: " + params.requestType);
- return false;
- } else if (params.requestType == RTT_TYPE_ONE_SIDED &&
- !mRttCapabilities.oneSidedRttSupported) {
- Log.e(TAG, "Request " + index + ": One side RTT is not supported");
- return false;
- } else if (params.requestType == RTT_TYPE_TWO_SIDED &&
- !mRttCapabilities.twoSided11McRttSupported) {
- Log.e(TAG, "Request " + index + ": two side RTT is not supported");
- return false;
- } else if(params.bssid == null || params.bssid.isEmpty()) {
- Log.e(TAG,"No BSSID in params");
- return false;
- } else if ( params.numberBurst != 0 ) {
- Log.e(TAG, "Request " + index + ": Illegal number of burst: " + params.numberBurst);
- return false;
- } else if (params.numSamplesPerBurst <= 0 || params.numSamplesPerBurst > 31) {
- Log.e(TAG, "Request " + index + ": Illegal sample number per burst: " +
- params.numSamplesPerBurst);
- return false;
- } else if (params.numRetriesPerMeasurementFrame < 0 ||
- params.numRetriesPerMeasurementFrame > 3) {
- Log.e(TAG, "Request " + index + ": Illegal measurement frame retry number:" +
- params.numRetriesPerMeasurementFrame);
- return false;
- } else if(params.numRetriesPerFTMR < 0 ||
- params.numRetriesPerFTMR > 3) {
- Log.e(TAG, "Request " + index + ": Illegal FTMR frame retry number:" +
- params.numRetriesPerFTMR);
- return false;
- } else if (params.LCIRequest && !mRttCapabilities.lciSupported) {
- Log.e(TAG, "Request " + index + ": LCI is not supported");
- return false;
- } else if (params.LCRRequest && !mRttCapabilities.lcrSupported) {
- Log.e(TAG, "Request " + index + ": LCR is not supported");
- return false;
- } else if (params.burstTimeout < 1 ||
- (params.burstTimeout > 11 && params.burstTimeout != 15)){
- Log.e(TAG, "Request " + index + ": Illegal burst timeout: " + params.burstTimeout);
- return false;
- } else if ((params.preamble & mRttCapabilities.preambleSupported) == 0) {
- Log.e(TAG, "Request " + index + ": Do not support this preamble: " + params.preamble);
- return false;
- } else if ((params.bandwidth & mRttCapabilities.bwSupported) == 0) {
- Log.e(TAG, "Request " + index + ": Do not support this bandwidth: " + params.bandwidth);
- return false;
+ @Override
+ public void onRangingResults(List<RangingResult> results) {
+ RttResult[] legacyResults = new RttResult[results.size()];
+ int i = 0;
+ for (RangingResult result : results) {
+ legacyResults[i] = new RttResult();
+ legacyResults[i].status = result.getStatus();
+ legacyResults[i].bssid = result.getMacAddress().toString();
+ legacyResults[i].distance = result.getDistanceMm() / 10;
+ legacyResults[i].distanceStandardDeviation =
+ result.getDistanceStdDevMm() / 10;
+ legacyResults[i].rssi = result.getRssi();
+ legacyResults[i].ts = result.getRangingTimestampUs();
+ }
+ listener.onSuccess(legacyResults);
+ }
+ }, null);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "startRanging: invalid arguments - " + e);
+ listener.onFailure(REASON_INVALID_REQUEST, e.getMessage());
+ } catch (SecurityException e) {
+ Log.e(TAG, "startRanging: security exception - " + e);
+ listener.onFailure(REASON_PERMISSION_DENIED, e.getMessage());
}
-
- return true;
}
/**
- * Request to start an RTT ranging
- *
- * @param params -- RTT request Parameters
- * @param listener -- Call back to inform RTT result
- * @exception throw IllegalArgumentException when params are illegal
- * throw IllegalStateException when RttCapabilities do not exist
+ * This method is deprecated and performs no function. Please use the {@link WifiRttManager}
+ * API.
*/
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
- public void startRanging(RttParams[] params, RttListener listener) {
- int index = 0;
- for(RttParams rttParam : params) {
- if (!rttParamSanity(rttParam, index)) {
- throw new IllegalArgumentException("RTT Request Parameter Illegal");
- }
- index++;
- }
- validateChannel();
- ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
- Log.i(TAG, "Send RTT request to RTT Service");
- mAsyncChannel.sendMessage(CMD_OP_START_RANGING,
- 0, putListener(listener), parcelableParams);
- }
-
- @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void stopRanging(RttListener listener) {
- validateChannel();
- mAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
+ Log.e(TAG, "stopRanging: unsupported operation - nop");
}
/**
@@ -1074,6 +1022,7 @@ public class RttManager {
* The client can freely destroy or reuse the callback after {@link RttManager#disableResponder}
* is called.
*/
+ @Deprecated
public abstract static class ResponderCallback {
/** Callback when responder is enabled. */
public abstract void onResponderEnabled(ResponderConfig config);
@@ -1089,18 +1038,18 @@ public class RttManager {
* Note calling this method with the same callback when the responder is already enabled won't
* change the responder state, a cached {@link ResponderConfig} from the last enabling will be
* returned through the callback.
+ * <p>
+ * This method is deprecated and will throw an {@link UnsupportedOperationException}
+ * exception. Please use the {@link WifiRttManager} API to perform a Wi-Fi Aware peer-to-peer
+ * ranging.
*
* @param callback Callback for responder enabling/disabling result.
* @throws IllegalArgumentException If {@code callback} is null.
*/
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void enableResponder(ResponderCallback callback) {
- if (callback == null) {
- throw new IllegalArgumentException("callback cannot be null");
- }
- validateChannel();
- int key = putListenerIfAbsent(callback);
- mAsyncChannel.sendMessage(CMD_OP_ENABLE_RESPONDER, 0, key);
+ throw new UnsupportedOperationException(
+ "enableResponder is not supported in the adaptation layer");
}
/**
@@ -1109,22 +1058,18 @@ public class RttManager {
* <p>
* Calling this method when responder isn't enabled won't have any effect. The callback can be
* reused for enabling responder after this method is called.
+ * <p>
+ * This method is deprecated and will throw an {@link UnsupportedOperationException}
+ * exception. Please use the {@link WifiRttManager} API to perform a Wi-Fi Aware peer-to-peer
+ * ranging.
*
* @param callback The same callback used for enabling responder.
* @throws IllegalArgumentException If {@code callback} is null.
*/
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void disableResponder(ResponderCallback callback) {
- if (callback == null) {
- throw new IllegalArgumentException("callback cannot be null");
- }
- validateChannel();
- int key = removeListener(callback);
- if (key == INVALID_KEY) {
- Log.e(TAG, "responder not enabled yet");
- return;
- }
- mAsyncChannel.sendMessage(CMD_OP_DISABLE_RESPONDER, 0, key);
+ throw new UnsupportedOperationException(
+ "disableResponder is not supported in the adaptation layer");
}
/**
@@ -1133,6 +1078,7 @@ public class RttManager {
*
* @see ScanResult
*/
+ @Deprecated
public static class ResponderConfig implements Parcelable {
// TODO: make all fields final once we can get mac address from responder HAL APIs.
@@ -1238,195 +1184,33 @@ public class RttManager {
/** @hide */
public static final int CMD_OP_REG_BINDER = BASE + 9;
- private static final int INVALID_KEY = 0;
-
- private final Context mContext;
- private final IRttManager mService;
- private final SparseArray mListenerMap = new SparseArray();
- private final Object mListenerMapLock = new Object();
- private final Object mCapabilitiesLock = new Object();
-
+ private final WifiRttManager mNewService;
private RttCapabilities mRttCapabilities;
- private int mListenerKey = 1;
- private AsyncChannel mAsyncChannel;
/**
* Create a new WifiScanner instance.
* Applications will almost always want to use
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
* the standard {@link android.content.Context#WIFI_RTT_SERVICE Context.WIFI_RTT_SERVICE}.
- * @param context the application context
- * @param service the Binder interface
- * @param looper Looper for running the callbacks.
+ * @param service the new WifiRttManager service
*
* @hide
*/
- public RttManager(Context context, IRttManager service, Looper looper) {
- mContext = context;
- mService = service;
- Messenger messenger = null;
- int[] key = new int[1];
- try {
- Log.d(TAG, "Get the messenger from " + mService);
- messenger = mService.getMessenger(new Binder(), key);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
-
- if (messenger == null) {
- throw new IllegalStateException("getMessenger() returned null! This is invalid.");
- }
-
- mAsyncChannel = new AsyncChannel();
-
- Handler handler = new ServiceHandler(looper);
- mAsyncChannel.connectSync(mContext, handler, messenger);
- // We cannot use fullyConnectSync because it sends the FULL_CONNECTION message
- // synchronously, which causes RttService to receive the wrong replyTo value.
- mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION,
- new RttClient(context.getPackageName()));
- mAsyncChannel.sendMessage(CMD_OP_REG_BINDER, key[0]);
+ public RttManager(Context context, WifiRttManager service) {
+ mNewService = service;
+
+ boolean rttSupported = context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_WIFI_RTT);
+
+ mRttCapabilities = new RttCapabilities();
+ mRttCapabilities.oneSidedRttSupported = rttSupported;
+ mRttCapabilities.twoSided11McRttSupported = rttSupported;
+ mRttCapabilities.lciSupported = false;
+ mRttCapabilities.lcrSupported = false;
+ mRttCapabilities.preambleSupported = PREAMBLE_HT | PREAMBLE_VHT;
+ mRttCapabilities.bwSupported = RTT_BW_40_SUPPORT | RTT_BW_80_SUPPORT;
+ mRttCapabilities.responderSupported = false;
+ mRttCapabilities.secureRttSupported = false;
}
-
- private void validateChannel() {
- if (mAsyncChannel == null) throw new IllegalStateException(
- "No permission to access and change wifi or a bad initialization");
- }
-
- private int putListener(Object listener) {
- if (listener == null) return INVALID_KEY;
- int key;
- synchronized (mListenerMapLock) {
- do {
- key = mListenerKey++;
- } while (key == INVALID_KEY);
- mListenerMap.put(key, listener);
- }
- return key;
- }
-
- // Insert a listener if it doesn't exist in mListenerMap. Returns the key of the listener.
- private int putListenerIfAbsent(Object listener) {
- if (listener == null) return INVALID_KEY;
- synchronized (mListenerMapLock) {
- int key = getListenerKey(listener);
- if (key != INVALID_KEY) {
- return key;
- }
- do {
- key = mListenerKey++;
- } while (key == INVALID_KEY);
- mListenerMap.put(key, listener);
- return key;
- }
-
- }
-
- private Object getListener(int key) {
- if (key == INVALID_KEY) return null;
- synchronized (mListenerMapLock) {
- Object listener = mListenerMap.get(key);
- return listener;
- }
- }
-
- private int getListenerKey(Object listener) {
- if (listener == null) return INVALID_KEY;
- synchronized (mListenerMapLock) {
- int index = mListenerMap.indexOfValue(listener);
- if (index == -1) {
- return INVALID_KEY;
- } else {
- return mListenerMap.keyAt(index);
- }
- }
- }
-
- private Object removeListener(int key) {
- if (key == INVALID_KEY) return null;
- synchronized (mListenerMapLock) {
- Object listener = mListenerMap.get(key);
- mListenerMap.remove(key);
- return listener;
- }
- }
-
- private int removeListener(Object listener) {
- int key = getListenerKey(listener);
- if (key == INVALID_KEY) return key;
- synchronized (mListenerMapLock) {
- mListenerMap.remove(key);
- return key;
- }
- }
-
- private class ServiceHandler extends Handler {
- ServiceHandler(Looper looper) {
- super(looper);
- }
- @Override
- public void handleMessage(Message msg) {
- Log.i(TAG, "RTT manager get message: " + msg.what);
- switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
- return;
- case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
- Log.e(TAG, "Channel connection lost");
- // This will cause all further async API calls on the WifiManager
- // to fail and throw an exception
- mAsyncChannel = null;
- getLooper().quit();
- return;
- }
-
- Object listener = getListener(msg.arg2);
- if (listener == null) {
- Log.e(TAG, "invalid listener key = " + msg.arg2 );
- return;
- } else {
- Log.i(TAG, "listener key = " + msg.arg2);
- }
-
- switch (msg.what) {
- /* ActionListeners grouped together */
- case CMD_OP_SUCCEEDED :
- reportSuccess(listener, msg);
- removeListener(msg.arg2);
- break;
- case CMD_OP_FAILED :
- reportFailure(listener, msg);
- removeListener(msg.arg2);
- break;
- case CMD_OP_ABORTED :
- ((RttListener) listener).onAborted();
- removeListener(msg.arg2);
- break;
- case CMD_OP_ENALBE_RESPONDER_SUCCEEDED:
- ResponderConfig config = (ResponderConfig) msg.obj;
- ((ResponderCallback) (listener)).onResponderEnabled(config);
- break;
- case CMD_OP_ENALBE_RESPONDER_FAILED:
- ((ResponderCallback) (listener)).onResponderEnableFailure(msg.arg1);
- removeListener(msg.arg2);
- break;
- default:
- if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
- return;
- }
- }
-
- void reportSuccess(Object listener, Message msg) {
- RttListener rttListener = (RttListener) listener;
- ParcelableRttResults parcelableResults = (ParcelableRttResults) msg.obj;
- ((RttListener) listener).onSuccess(parcelableResults.mResults);
- }
-
- void reportFailure(Object listener, Message msg) {
- RttListener rttListener = (RttListener) listener;
- Bundle bundle = (Bundle) msg.obj;
- ((RttListener) listener).onFailure(msg.arg1, bundle.getString(DESCRIPTION_KEY));
- }
- }
-
}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index b6ad92614bfe..8024bf08b1d4 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -21,7 +21,9 @@ import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* Describes information about a detected access point. In addition
@@ -227,37 +229,48 @@ public class ScanResult implements Parcelable {
public long seen;
/**
- * @hide
- * Update RSSI of the scan result
- * @param previousRssi
- * @param previousSeen
- * @param maxAge
+ * On devices with multiple hardware radio chains, this class provides metadata about
+ * each radio chain that was used to receive this scan result (probe response or beacon).
+ * {@hide}
*/
- public void averageRssi(int previousRssi, long previousSeen, int maxAge) {
+ public static class RadioChainInfo {
+ /** Vendor defined id for a radio chain. */
+ public int id;
+ /** Detected signal level in dBm (also known as the RSSI) on this radio chain. */
+ public int level;
- if (seen == 0) {
- seen = System.currentTimeMillis();
+ @Override
+ public String toString() {
+ return "RadioChainInfo: id=" + id + ", level=" + level;
}
- long age = seen - previousSeen;
- if (previousSeen > 0 && age > 0 && age < maxAge/2) {
- // Average the RSSI with previously seen instances of this scan result
- double alpha = 0.5 - (double) age / (double) maxAge;
- level = (int) ((double) level * (1 - alpha) + (double) previousRssi * alpha);
+ @Override
+ public boolean equals(Object otherObj) {
+ if (this == otherObj) {
+ return true;
+ }
+ if (!(otherObj instanceof RadioChainInfo)) {
+ return false;
+ }
+ RadioChainInfo other = (RadioChainInfo) otherObj;
+ return id == other.id && level == other.level;
}
- }
- /**
- * num IP configuration failures
- * @hide
- */
- public int numIpConfigFailures;
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, level);
+ }
+ };
/**
- * @hide
- * Last time we blacklisted the ScanResult
+ * Information about the list of the radio chains used to receive this scan result
+ * (probe response or beacon).
+ *
+ * For Example: On devices with 2 hardware radio chains, this list could hold 1 or 2
+ * entries based on whether this scan result was received using one or both the chains.
+ * {@hide}
*/
- public long blackListTimestamp;
+ public RadioChainInfo[] radioChainInfos;
/**
* Status indicating the scan result does not correspond to a user's saved configuration
@@ -268,12 +281,6 @@ public class ScanResult implements Parcelable {
public boolean untrusted;
/**
- * Number of time we connected to it
- * @hide
- */
- public int numConnection;
-
- /**
* Number of time autojoin used it
* @hide
*/
@@ -386,12 +393,6 @@ public class ScanResult implements Parcelable {
*/
public List<String> anqpLines;
- /**
- * @hide
- * storing the raw bytes of full result IEs
- **/
- public byte[] bytes;
-
/** information elements from beacon
* @hide
*/
@@ -481,6 +482,7 @@ public class ScanResult implements Parcelable {
this.isCarrierAp = false;
this.carrierApEapType = UNSPECIFIED;
this.carrierName = null;
+ this.radioChainInfos = null;
}
/** {@hide} */
@@ -502,6 +504,7 @@ public class ScanResult implements Parcelable {
this.isCarrierAp = false;
this.carrierApEapType = UNSPECIFIED;
this.carrierName = null;
+ this.radioChainInfos = null;
}
/** {@hide} */
@@ -530,6 +533,7 @@ public class ScanResult implements Parcelable {
this.isCarrierAp = false;
this.carrierApEapType = UNSPECIFIED;
this.carrierName = null;
+ this.radioChainInfos = null;
}
/** {@hide} */
@@ -563,15 +567,14 @@ public class ScanResult implements Parcelable {
distanceSdCm = source.distanceSdCm;
seen = source.seen;
untrusted = source.untrusted;
- numConnection = source.numConnection;
numUsage = source.numUsage;
- numIpConfigFailures = source.numIpConfigFailures;
venueName = source.venueName;
operatorFriendlyName = source.operatorFriendlyName;
flags = source.flags;
isCarrierAp = source.isCarrierAp;
carrierApEapType = source.carrierApEapType;
carrierName = source.carrierName;
+ radioChainInfos = source.radioChainInfos;
}
}
@@ -615,6 +618,7 @@ public class ScanResult implements Parcelable {
sb.append(", Carrier AP: ").append(isCarrierAp ? "yes" : "no");
sb.append(", Carrier AP EAP Type: ").append(carrierApEapType);
sb.append(", Carrier name: ").append(carrierName);
+ sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos));
return sb.toString();
}
@@ -646,9 +650,7 @@ public class ScanResult implements Parcelable {
dest.writeInt(centerFreq1);
dest.writeLong(seen);
dest.writeInt(untrusted ? 1 : 0);
- dest.writeInt(numConnection);
dest.writeInt(numUsage);
- dest.writeInt(numIpConfigFailures);
dest.writeString((venueName != null) ? venueName.toString() : "");
dest.writeString((operatorFriendlyName != null) ? operatorFriendlyName.toString() : "");
dest.writeLong(this.flags);
@@ -687,6 +689,16 @@ public class ScanResult implements Parcelable {
dest.writeInt(isCarrierAp ? 1 : 0);
dest.writeInt(carrierApEapType);
dest.writeString(carrierName);
+
+ if (radioChainInfos != null) {
+ dest.writeInt(radioChainInfos.length);
+ for (int i = 0; i < radioChainInfos.length; i++) {
+ dest.writeInt(radioChainInfos[i].id);
+ dest.writeInt(radioChainInfos[i].level);
+ }
+ } else {
+ dest.writeInt(0);
+ }
}
/** Implement the Parcelable interface {@hide} */
@@ -718,9 +730,7 @@ public class ScanResult implements Parcelable {
sr.seen = in.readLong();
sr.untrusted = in.readInt() != 0;
- sr.numConnection = in.readInt();
sr.numUsage = in.readInt();
- sr.numIpConfigFailures = in.readInt();
sr.venueName = in.readString();
sr.operatorFriendlyName = in.readString();
sr.flags = in.readLong();
@@ -759,6 +769,15 @@ public class ScanResult implements Parcelable {
sr.isCarrierAp = in.readInt() != 0;
sr.carrierApEapType = in.readInt();
sr.carrierName = in.readString();
+ n = in.readInt();
+ if (n != 0) {
+ sr.radioChainInfos = new RadioChainInfo[n];
+ for (int i = 0; i < n; i++) {
+ sr.radioChainInfos[i] = new RadioChainInfo();
+ sr.radioChainInfos[i].id = in.readInt();
+ sr.radioChainInfos[i].level = in.readInt();
+ }
+ }
return sr;
}
diff --git a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
index 29bf02cac8fe..03c9fbeec918 100644
--- a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
+++ b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
@@ -56,6 +56,11 @@ public final class WifiActivityEnergyInfo implements Parcelable {
/**
* @hide
*/
+ public long mControllerScanTimeMs;
+
+ /**
+ * @hide
+ */
public long mControllerIdleTimeMs;
/**
@@ -69,13 +74,14 @@ public final class WifiActivityEnergyInfo implements Parcelable {
public static final int STACK_STATE_STATE_IDLE = 3;
public WifiActivityEnergyInfo(long timestamp, int stackState,
- long txTime, long[] txTimePerLevel, long rxTime, long idleTime,
- long energyUsed) {
+ long txTime, long[] txTimePerLevel, long rxTime, long scanTime,
+ long idleTime, long energyUsed) {
mTimestamp = timestamp;
mStackState = stackState;
mControllerTxTimeMs = txTime;
mControllerTxTimePerLevelMs = txTimePerLevel;
mControllerRxTimeMs = rxTime;
+ mControllerScanTimeMs = scanTime;
mControllerIdleTimeMs = idleTime;
mControllerEnergyUsed = energyUsed;
}
@@ -88,6 +94,7 @@ public final class WifiActivityEnergyInfo implements Parcelable {
+ " mControllerTxTimeMs=" + mControllerTxTimeMs
+ " mControllerTxTimePerLevelMs=" + Arrays.toString(mControllerTxTimePerLevelMs)
+ " mControllerRxTimeMs=" + mControllerRxTimeMs
+ + " mControllerScanTimeMs=" + mControllerScanTimeMs
+ " mControllerIdleTimeMs=" + mControllerIdleTimeMs
+ " mControllerEnergyUsed=" + mControllerEnergyUsed
+ " }";
@@ -101,10 +108,11 @@ public final class WifiActivityEnergyInfo implements Parcelable {
long txTime = in.readLong();
long[] txTimePerLevel = in.createLongArray();
long rxTime = in.readLong();
+ long scanTime = in.readLong();
long idleTime = in.readLong();
long energyUsed = in.readLong();
return new WifiActivityEnergyInfo(timestamp, stackState,
- txTime, txTimePerLevel, rxTime, idleTime, energyUsed);
+ txTime, txTimePerLevel, rxTime, scanTime, idleTime, energyUsed);
}
public WifiActivityEnergyInfo[] newArray(int size) {
return new WifiActivityEnergyInfo[size];
@@ -117,6 +125,7 @@ public final class WifiActivityEnergyInfo implements Parcelable {
out.writeLong(mControllerTxTimeMs);
out.writeLongArray(mControllerTxTimePerLevelMs);
out.writeLong(mControllerRxTimeMs);
+ out.writeLong(mControllerScanTimeMs);
out.writeLong(mControllerIdleTimeMs);
out.writeLong(mControllerEnergyUsed);
}
@@ -157,6 +166,13 @@ public final class WifiActivityEnergyInfo implements Parcelable {
}
/**
+ * @return scan time in ms
+ */
+ public long getControllerScanTimeMillis() {
+ return mControllerScanTimeMs;
+ }
+
+ /**
* @return idle time in ms
*/
public long getControllerIdleTimeMillis() {
@@ -183,6 +199,7 @@ public final class WifiActivityEnergyInfo implements Parcelable {
public boolean isValid() {
return ((mControllerTxTimeMs >=0) &&
(mControllerRxTimeMs >=0) &&
+ (mControllerScanTimeMs >=0) &&
(mControllerIdleTimeMs >=0));
}
-}
+} \ No newline at end of file
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 6438631cb8ed..ddcf327b9dd1 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -16,10 +16,12 @@
package android.net.wifi;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.pm.PackageManager;
import android.net.IpConfiguration;
import android.net.IpConfiguration.ProxySettings;
+import android.net.MacAddress;
import android.net.ProxyInfo;
import android.net.StaticIpConfiguration;
import android.net.Uri;
@@ -54,8 +56,10 @@ public class WifiConfiguration implements Parcelable {
/** {@hide} */
public static final String pskVarName = "psk";
/** {@hide} */
+ @Deprecated
public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" };
/** {@hide} */
+ @Deprecated
public static final String wepTxKeyIdxVarName = "wep_tx_keyidx";
/** {@hide} */
public static final String priorityVarName = "priority";
@@ -82,6 +86,9 @@ public class WifiConfiguration implements Parcelable {
/** WPA is not used; plaintext or static WEP could be used. */
public static final int NONE = 0;
/** WPA pre-shared key (requires {@code preSharedKey} to be specified). */
+ /** @deprecated Due to security and performance limitations, use of WPA-1 networks
+ * is discouraged. WPA-2 (RSN) should be used instead. */
+ @Deprecated
public static final int WPA_PSK = 1;
/** WPA using EAP authentication. Generally used with an external authentication server. */
public static final int WPA_EAP = 2;
@@ -115,8 +122,8 @@ public class WifiConfiguration implements Parcelable {
public static final String varName = "key_mgmt";
- public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X",
- "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" };
+ public static final String[] strings = { "NONE", /* deprecated */ "WPA_PSK", "WPA_EAP",
+ "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" };
}
/**
@@ -125,7 +132,10 @@ public class WifiConfiguration implements Parcelable {
public static class Protocol {
private Protocol() { }
- /** WPA/IEEE 802.11i/D3.0 */
+ /** WPA/IEEE 802.11i/D3.0
+ * @deprecated Due to security and performance limitations, use of WPA-1 networks
+ * is discouraged. WPA-2 (RSN) should be used instead. */
+ @Deprecated
public static final int WPA = 0;
/** WPA2/IEEE 802.11i */
public static final int RSN = 1;
@@ -147,7 +157,10 @@ public class WifiConfiguration implements Parcelable {
/** Open System authentication (required for WPA/WPA2) */
public static final int OPEN = 0;
- /** Shared Key authentication (requires static WEP keys) */
+ /** Shared Key authentication (requires static WEP keys)
+ * @deprecated Due to security and performance limitations, use of WEP networks
+ * is discouraged. */
+ @Deprecated
public static final int SHARED = 1;
/** LEAP/Network EAP (only used with LEAP) */
public static final int LEAP = 2;
@@ -165,7 +178,10 @@ public class WifiConfiguration implements Parcelable {
/** Use only Group keys (deprecated) */
public static final int NONE = 0;
- /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
+ /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
+ * @deprecated Due to security and performance limitations, use of WPA-1 networks
+ * is discouraged. WPA-2 (RSN) should be used instead. */
+ @Deprecated
public static final int TKIP = 1;
/** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
public static final int CCMP = 2;
@@ -187,9 +203,15 @@ public class WifiConfiguration implements Parcelable {
public static class GroupCipher {
private GroupCipher() { }
- /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) */
+ /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
+ * @deprecated Due to security and performance limitations, use of WEP networks
+ * is discouraged. */
+ @Deprecated
public static final int WEP40 = 0;
- /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key */
+ /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
+ * @deprecated Due to security and performance limitations, use of WEP networks
+ * is discouraged. */
+ @Deprecated
public static final int WEP104 = 1;
/** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
public static final int TKIP = 2;
@@ -203,7 +225,8 @@ public class WifiConfiguration implements Parcelable {
public static final String varName = "group";
public static final String[] strings =
- { "WEP40", "WEP104", "TKIP", "CCMP", "GTK_NOT_USED" };
+ { /* deprecated */ "WEP40", /* deprecated */ "WEP104",
+ "TKIP", "CCMP", "GTK_NOT_USED" };
}
/** Possible status of a network configuration. */
@@ -267,8 +290,15 @@ public class WifiConfiguration implements Parcelable {
public static final int AP_BAND_5GHZ = 1;
/**
+ * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability,
+ * operating country code and current radio conditions.
+ * @hide
+ */
+ public static final int AP_BAND_ANY = -1;
+
+ /**
* The band which AP resides on
- * 0-2G 1-5G
+ * -1:Any 0:2G 1:5G
* By default, 2G is chosen
* @hide
*/
@@ -302,10 +332,16 @@ public class WifiConfiguration implements Parcelable {
* When the value of one of these keys is read, the actual key is
* not returned, just a "*" if the key has a value, or the null
* string otherwise.
+ * @deprecated Due to security and performance limitations, use of WEP networks
+ * is discouraged.
*/
+ @Deprecated
public String[] wepKeys;
- /** Default WEP key index, ranging from 0 to 3. */
+ /** Default WEP key index, ranging from 0 to 3.
+ * @deprecated Due to security and performance limitations, use of WEP networks
+ * is discouraged. */
+ @Deprecated
public int wepTxKeyIndex;
/**
@@ -404,6 +440,7 @@ public class WifiConfiguration implements Parcelable {
/**
* @hide
*/
+ @NonNull
private IpConfiguration mIpConfiguration;
/**
@@ -845,6 +882,55 @@ public class WifiConfiguration implements Parcelable {
@SystemApi
public int numAssociation;
+ /**
+ * @hide
+ * Randomized MAC address to use with this particular network
+ */
+ private MacAddress mRandomizedMacAddress;
+
+ /**
+ * @hide
+ * Checks if the given MAC address can be used for Connected Mac Randomization
+ * by verifying that it is non-null, unicast, and locally assigned.
+ * @param mac MacAddress to check
+ * @return true if mac is good to use
+ */
+ private boolean isValidMacAddressForRandomization(MacAddress mac) {
+ return mac != null && !mac.isMulticastAddress() && mac.isLocallyAssigned();
+ }
+
+ /**
+ * @hide
+ * Returns Randomized MAC address to use with the network.
+ * If it is not set/valid, create a new randomized address.
+ */
+ public MacAddress getOrCreateRandomizedMacAddress() {
+ if (!isValidMacAddressForRandomization(mRandomizedMacAddress)) {
+ mRandomizedMacAddress = MacAddress.createRandomUnicastAddress();
+ }
+ return mRandomizedMacAddress;
+ }
+
+ /**
+ * @hide
+ * Returns MAC address set to be the local randomized MAC address.
+ * Does not guarantee that the returned address is valid for use.
+ */
+ public MacAddress getRandomizedMacAddress() {
+ if (mRandomizedMacAddress == null) {
+ mRandomizedMacAddress = MacAddress.ALL_ZEROS_ADDRESS;
+ }
+ return mRandomizedMacAddress;
+ }
+
+ /**
+ * @hide
+ * @param mac MacAddress to change into
+ */
+ public void setRandomizedMacAddress(MacAddress mac) {
+ mRandomizedMacAddress = mac;
+ }
+
/** @hide
* Boost given to RSSI on a home network for the purpose of calculating the score
* This adds stickiness to home networks, as defined by:
@@ -1534,6 +1620,7 @@ public class WifiConfiguration implements Parcelable {
creatorUid = -1;
shared = true;
dtimInterval = 0;
+ mRandomizedMacAddress = MacAddress.ALL_ZEROS_ADDRESS;
}
/**
@@ -1942,6 +2029,7 @@ public class WifiConfiguration implements Parcelable {
/** @hide */
public void setIpConfiguration(IpConfiguration ipConfiguration) {
+ if (ipConfiguration == null) ipConfiguration = new IpConfiguration();
mIpConfiguration = ipConfiguration;
}
@@ -2117,6 +2205,7 @@ public class WifiConfiguration implements Parcelable {
updateTime = source.updateTime;
shared = source.shared;
recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus());
+ mRandomizedMacAddress = source.mRandomizedMacAddress;
}
}
@@ -2184,6 +2273,7 @@ public class WifiConfiguration implements Parcelable {
dest.writeInt(shared ? 1 : 0);
dest.writeString(mPasspointManagementObjectTree);
dest.writeInt(recentFailure.getAssociationStatus());
+ dest.writeParcelable(mRandomizedMacAddress, flags);
}
/** Implement the Parcelable interface {@hide} */
@@ -2223,7 +2313,7 @@ public class WifiConfiguration implements Parcelable {
config.allowedGroupCiphers = readBitSet(in);
config.enterpriseConfig = in.readParcelable(null);
- config.mIpConfiguration = in.readParcelable(null);
+ config.setIpConfiguration(in.readParcelable(null));
config.dhcpServer = in.readString();
config.defaultGwMacAddress = in.readString();
config.selfAdded = in.readInt() != 0;
@@ -2252,6 +2342,7 @@ public class WifiConfiguration implements Parcelable {
config.shared = in.readInt() != 0;
config.mPasspointManagementObjectTree = in.readString();
config.recentFailure.setAssociationStatus(in.readInt());
+ config.mRandomizedMacAddress = in.readParcelable(null);
return config;
}
diff --git a/wifi/java/android/net/wifi/WifiConnectionStatistics.java b/wifi/java/android/net/wifi/WifiConnectionStatistics.java
deleted file mode 100644
index 1120c66ea418..000000000000
--- a/wifi/java/android/net/wifi/WifiConnectionStatistics.java
+++ /dev/null
@@ -1,158 +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.annotation.SystemApi;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-import java.util.HashMap;
-
-/**
- * Wifi Connection Statistics: gather various stats regarding WiFi connections,
- * connection requests, auto-join
- * and WiFi usage.
- * @hide
- * @removed
- */
-@SystemApi
-public class WifiConnectionStatistics implements Parcelable {
- private static final String TAG = "WifiConnnectionStatistics";
-
- /**
- * history of past connection to untrusted SSID
- * Key = SSID
- * Value = num connection
- */
- public HashMap<String, WifiNetworkConnectionStatistics> untrustedNetworkHistory;
-
- // Number of time we polled the chip and were on 5GHz
- public int num5GhzConnected;
-
- // Number of time we polled the chip and were on 2.4GHz
- public int num24GhzConnected;
-
- // Number autojoin attempts
- public int numAutoJoinAttempt;
-
- // Number auto-roam attempts
- public int numAutoRoamAttempt;
-
- // Number wifimanager join attempts
- public int numWifiManagerJoinAttempt;
-
- public WifiConnectionStatistics() {
- untrustedNetworkHistory = new HashMap<String, WifiNetworkConnectionStatistics>();
- }
-
- public void incrementOrAddUntrusted(String SSID, int connection, int usage) {
- WifiNetworkConnectionStatistics stats;
- if (TextUtils.isEmpty(SSID))
- return;
- if (untrustedNetworkHistory.containsKey(SSID)) {
- stats = untrustedNetworkHistory.get(SSID);
- if (stats != null){
- stats.numConnection = connection + stats.numConnection;
- stats.numUsage = usage + stats.numUsage;
- }
- } else {
- stats = new WifiNetworkConnectionStatistics(connection, usage);
- }
- if (stats != null) {
- untrustedNetworkHistory.put(SSID, stats);
- }
- }
-
- @Override
- public String toString() {
- StringBuilder sbuf = new StringBuilder();
- sbuf.append("Connected on: 2.4Ghz=").append(num24GhzConnected);
- sbuf.append(" 5Ghz=").append(num5GhzConnected).append("\n");
- sbuf.append(" join=").append(numWifiManagerJoinAttempt);
- sbuf.append("\\").append(numAutoJoinAttempt).append("\n");
- sbuf.append(" roam=").append(numAutoRoamAttempt).append("\n");
-
- for (String Key : untrustedNetworkHistory.keySet()) {
- WifiNetworkConnectionStatistics stats = untrustedNetworkHistory.get(Key);
- if (stats != null) {
- sbuf.append(Key).append(" ").append(stats.toString()).append("\n");
- }
- }
- return sbuf.toString();
- }
-
- /** copy constructor*/
- public WifiConnectionStatistics(WifiConnectionStatistics source) {
- untrustedNetworkHistory = new HashMap<String, WifiNetworkConnectionStatistics>();
- if (source != null) {
- untrustedNetworkHistory.putAll(source.untrustedNetworkHistory);
- }
- }
-
- /** Implement the Parcelable interface */
- public int describeContents() {
- return 0;
- }
-
- /** Implement the Parcelable interface */
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(num24GhzConnected);
- dest.writeInt(num5GhzConnected);
- dest.writeInt(numAutoJoinAttempt);
- dest.writeInt(numAutoRoamAttempt);
- dest.writeInt(numWifiManagerJoinAttempt);
-
- dest.writeInt(untrustedNetworkHistory.size());
- for (String Key : untrustedNetworkHistory.keySet()) {
- WifiNetworkConnectionStatistics num = untrustedNetworkHistory.get(Key);
- dest.writeString(Key);
- dest.writeInt(num.numConnection);
- dest.writeInt(num.numUsage);
-
- }
- }
-
- /** Implement the Parcelable interface */
- public static final Creator<WifiConnectionStatistics> CREATOR =
- new Creator<WifiConnectionStatistics>() {
- public WifiConnectionStatistics createFromParcel(Parcel in) {
- WifiConnectionStatistics stats = new WifiConnectionStatistics();
- stats.num24GhzConnected = in.readInt();
- stats.num5GhzConnected = in.readInt();
- stats.numAutoJoinAttempt = in.readInt();
- stats.numAutoRoamAttempt = in.readInt();
- stats.numWifiManagerJoinAttempt = in.readInt();
- int n = in.readInt();
- while (n-- > 0) {
- String Key = in.readString();
- int numConnection = in.readInt();
- int numUsage = in.readInt();
- WifiNetworkConnectionStatistics st =
- new WifiNetworkConnectionStatistics(numConnection, numUsage);
- stats.untrustedNetworkHistory.put(Key, st);
- }
- return stats;
- }
-
- public WifiConnectionStatistics[] newArray(int size) {
- return new WifiConnectionStatistics[size];
- }
- };
-}
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..897b1eaa2a64 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -16,6 +16,8 @@
package android.net.wifi;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
@@ -32,6 +34,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;
@@ -52,6 +56,8 @@ import com.android.server.net.NetworkPinner;
import dalvik.system.CloseGuard;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.net.InetAddress;
import java.util.Collections;
@@ -429,6 +435,17 @@ public class WifiManager {
*/
public static final String EXTRA_WIFI_AP_MODE = "wifi_ap_mode";
+ /** @hide */
+ @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = {
+ WIFI_AP_STATE_DISABLING,
+ WIFI_AP_STATE_DISABLED,
+ WIFI_AP_STATE_ENABLING,
+ WIFI_AP_STATE_ENABLED,
+ WIFI_AP_STATE_FAILED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface WifiApState {}
+
/**
* Wi-Fi AP is currently being disabled. The state will change to
* {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully.
@@ -483,6 +500,14 @@ public class WifiManager {
@SystemApi
public static final int WIFI_AP_STATE_FAILED = 14;
+ /** @hide */
+ @IntDef(flag = false, prefix = { "SAP_START_FAILURE_" }, value = {
+ SAP_START_FAILURE_GENERAL,
+ SAP_START_FAILURE_NO_CHANNEL,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SapStartFailure {}
+
/**
* If WIFI AP start failed, this reason code means there is no legal channel exists on
* user selected band by regulatory
@@ -554,14 +579,9 @@ public class WifiManager {
public static final String EXTRA_SUPPLICANT_CONNECTED = "connected";
/**
* Broadcast intent action indicating that the state of Wi-Fi connectivity
- * has changed. One extra provides the new state
- * in the form of a {@link android.net.NetworkInfo} object. If the new
- * state is CONNECTED, additional extras may provide the BSSID and WifiInfo of
- * the access point.
- * as a {@code String}.
+ * has changed. An extra provides the new state
+ * in the form of a {@link android.net.NetworkInfo} object.
* @see #EXTRA_NETWORK_INFO
- * @see #EXTRA_BSSID
- * @see #EXTRA_WIFI_INFO
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
@@ -573,17 +593,16 @@ public class WifiManager {
public static final String EXTRA_NETWORK_INFO = "networkInfo";
/**
* The lookup key for a String giving the BSSID of the access point to which
- * we are connected. Only present when the new state is CONNECTED.
- * Retrieve with
- * {@link android.content.Intent#getStringExtra(String)}.
+ * we are connected. No longer used.
*/
+ @Deprecated
public static final String EXTRA_BSSID = "bssid";
/**
* The lookup key for a {@link android.net.wifi.WifiInfo} object giving the
- * information about the access point to which we are connected. Only present
- * when the new state is CONNECTED. Retrieve with
- * {@link android.content.Intent#getParcelableExtra(String)}.
+ * information about the access point to which we are connected.
+ * No longer used.
*/
+ @Deprecated
public static final String EXTRA_WIFI_INFO = "wifiInfo";
/**
* Broadcast intent action indicating that the state of establishing a connection to
@@ -692,11 +711,11 @@ public class WifiManager {
* representing if the scan was successful or not.
* Scans may fail for multiple reasons, these may include:
* <ol>
- * <li>A non-privileged app requested too many scans in a certain period of time.
- * This may lead to additional scan request rejections via "scan throttling".
- * See
- * <a href="https://developer.android.com/preview/features/background-location-limits.html">
- * here</a> for details.
+ * <li>An app requested too many scans in a certain period of time.
+ * This may lead to additional scan request rejections via "scan throttling" for both
+ * foreground and background apps.
+ * Note: Apps holding android.Manifest.permission.NETWORK_SETTINGS permission are
+ * exempted from scan throttling.
* </li>
* <li>The device is idle and scanning is disabled.</li>
* <li>Wifi hardware reported a scan failure.</li>
@@ -970,8 +989,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 {
@@ -1003,35 +1021,41 @@ public class WifiManager {
}
/**
+ * Returns a WifiConfiguration matching this ScanResult
+ *
+ * @param scanResult scanResult that represents the BSSID
+ * @return {@link WifiConfiguration} that matches this BSSID or null
+ * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
* @hide
- * @removed
*/
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL)
- public WifiConnectionStatistics getConnectionStatistics() {
+ public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) {
try {
- return mService.getConnectionStatistics();
+ return mService.getMatchingWifiConfig(scanResult);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Returns a WifiConfiguration matching this ScanResult
+ * 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 {@link WifiConfiguration} that matches this BSSID or null
+ * @return A list of {@link WifiConfiguration}
* @throws UnsupportedOperationException if Passpoint is not enabled on the device.
* @hide
*/
- public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) {
+ public List<WifiConfiguration> getAllMatchingWifiConfigs(ScanResult scanResult) {
try {
- return mService.getMatchingWifiConfig(scanResult);
+ 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.
*
@@ -1108,7 +1132,7 @@ public class WifiManager {
*/
private int addOrUpdateNetwork(WifiConfiguration config) {
try {
- return mService.addOrUpdateNetwork(config);
+ return mService.addOrUpdateNetwork(config, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1129,7 +1153,7 @@ public class WifiManager {
*/
public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
try {
- if (!mService.addOrUpdatePasspointConfiguration(config)) {
+ if (!mService.addOrUpdatePasspointConfiguration(config, mContext.getOpPackageName())) {
throw new IllegalArgumentException();
}
} catch (RemoteException e) {
@@ -1146,7 +1170,7 @@ public class WifiManager {
*/
public void removePasspointConfiguration(String fqdn) {
try {
- if (!mService.removePasspointConfiguration(fqdn)) {
+ if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) {
throw new IllegalArgumentException();
}
} catch (RemoteException e) {
@@ -1232,7 +1256,7 @@ public class WifiManager {
*/
public boolean removeNetwork(int netId) {
try {
- return mService.removeNetwork(netId);
+ return mService.removeNetwork(netId, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1278,7 +1302,7 @@ public class WifiManager {
boolean success;
try {
- success = mService.enableNetwork(netId, attemptConnect);
+ success = mService.enableNetwork(netId, attemptConnect, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1304,7 +1328,7 @@ public class WifiManager {
*/
public boolean disableNetwork(int netId) {
try {
- return mService.disableNetwork(netId);
+ return mService.disableNetwork(netId, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1317,7 +1341,7 @@ public class WifiManager {
*/
public boolean disconnect() {
try {
- mService.disconnect();
+ mService.disconnect(mContext.getOpPackageName());
return true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1332,7 +1356,7 @@ public class WifiManager {
*/
public boolean reconnect() {
try {
- mService.reconnect();
+ mService.reconnect(mContext.getOpPackageName());
return true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1347,7 +1371,7 @@ public class WifiManager {
*/
public boolean reassociate() {
try {
- mService.reassociate();
+ mService.reassociate(mContext.getOpPackageName());
return true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1574,7 +1598,10 @@ public class WifiManager {
* {@code ((WifiManager) getSystemService(WIFI_SERVICE)).getScanResults()}</li>
* </ol>
* @return {@code true} if the operation succeeded, i.e., the scan was initiated.
+ * @deprecated The ability for apps to trigger scan requests will be removed in a future
+ * release.
*/
+ @Deprecated
public boolean startScan() {
return startScan(null);
}
@@ -1593,65 +1620,14 @@ public class WifiManager {
}
/**
- * startLocationRestrictedScan()
- * Trigger a scan which will not make use of DFS channels and is thus not suitable for
- * establishing wifi connection.
- * @deprecated This API is nolonger supported.
- * Use {@link android.net.wifi.WifiScanner} API
- * @hide
- * @removed
- */
- @Deprecated
- @SystemApi
- @SuppressLint("Doclava125")
- public boolean startLocationRestrictedScan(WorkSource workSource) {
- return false;
- }
-
- /**
- * Check if the Batched Scan feature is supported.
- *
- * @return false if not supported.
- * @deprecated This API is nolonger supported.
- * Use {@link android.net.wifi.WifiScanner} API
- * @hide
- * @removed
- */
- @Deprecated
- @SystemApi
- @SuppressLint("Doclava125")
- public boolean isBatchedScanSupported() {
- return false;
- }
-
- /**
- * Retrieve the latest batched scan result. This should be called immediately after
- * {@link BATCHED_SCAN_RESULTS_AVAILABLE_ACTION} is received.
- * @deprecated This API is nolonger supported.
- * Use {@link android.net.wifi.WifiScanner} API
- * @hide
- * @removed
- */
- @Deprecated
- @SystemApi
- @SuppressLint("Doclava125")
- public List<BatchedScanResult> getBatchedScanResults() {
- return null;
- }
-
- /**
- * Creates a configuration token describing the current network of MIME type
- * application/vnd.wfa.wsc. Can be used to configure WiFi networks via NFC.
+ * WPS has been deprecated from Client mode operation.
*
- * @return hex-string encoded configuration token or null if there is no current network
+ * @return null
* @hide
+ * @deprecated This API is deprecated
*/
public String getCurrentNetworkWpsNfcConfigurationToken() {
- try {
- return mService.getCurrentNetworkWpsNfcConfigurationToken();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return null;
}
/**
@@ -1712,30 +1688,25 @@ public class WifiManager {
* existing networks. You should assume the network IDs can be different
* after calling this method.
*
- * @return {@code true} if the operation succeeded
+ * @return {@code false} Will always return true.
* @deprecated There is no need to call this method -
* {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)}
* and {@link #removeNetwork(int)} already persist the configurations automatically.
*/
@Deprecated
public boolean saveConfiguration() {
- try {
- return mService.saveConfiguration();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return true;
}
/**
* 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 +1755,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 +1842,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},
@@ -2186,7 +2127,7 @@ public class WifiManager {
@RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
try {
- mService.setWifiApConfiguration(wifiConfig);
+ mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName());
return true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -2261,20 +2202,34 @@ public class WifiManager {
/** @hide */
public static final int SAVE_NETWORK_SUCCEEDED = BASE + 9;
- /** @hide */
+ /** @hide
+ * @deprecated This is deprecated
+ */
public static final int START_WPS = BASE + 10;
- /** @hide */
+ /** @hide
+ * @deprecated This is deprecated
+ */
public static final int START_WPS_SUCCEEDED = BASE + 11;
- /** @hide */
+ /** @hide
+ * @deprecated This is deprecated
+ */
public static final int WPS_FAILED = BASE + 12;
- /** @hide */
+ /** @hide
+ * @deprecated This is deprecated
+ */
public static final int WPS_COMPLETED = BASE + 13;
- /** @hide */
+ /** @hide
+ * @deprecated This is deprecated
+ */
public static final int CANCEL_WPS = BASE + 14;
- /** @hide */
+ /** @hide
+ * @deprecated This is deprecated
+ */
public static final int CANCEL_WPS_FAILED = BASE + 15;
- /** @hide */
+ /** @hide
+ * @deprecated This is deprecated
+ */
public static final int CANCEL_WPS_SUCCEDED = BASE + 16;
/** @hide */
@@ -2314,15 +2269,25 @@ public class WifiManager {
public static final int BUSY = 2;
/* WPS specific errors */
- /** WPS overlap detected */
+ /** WPS overlap detected
+ * @deprecated This is deprecated
+ */
public static final int WPS_OVERLAP_ERROR = 3;
- /** WEP on WPS is prohibited */
+ /** WEP on WPS is prohibited
+ * @deprecated This is deprecated
+ */
public static final int WPS_WEP_PROHIBITED = 4;
- /** TKIP only prohibited */
+ /** TKIP only prohibited
+ * @deprecated This is deprecated
+ */
public static final int WPS_TKIP_ONLY_PROHIBITED = 5;
- /** Authentication failure on WPS */
+ /** Authentication failure on WPS
+ * @deprecated This is deprecated
+ */
public static final int WPS_AUTH_FAILURE = 6;
- /** WPS timed out */
+ /** WPS timed out
+ * @deprecated This is deprecated
+ */
public static final int WPS_TIMED_OUT = 7;
/**
@@ -2363,12 +2328,19 @@ public class WifiManager {
public void onFailure(int reason);
}
- /** Interface for callback invocation on a start WPS action */
+ /** Interface for callback invocation on a start WPS action
+ * @deprecated This is deprecated
+ */
public static abstract class WpsCallback {
- /** WPS start succeeded */
+
+ /** WPS start succeeded
+ * @deprecated This API is deprecated
+ */
public abstract void onStarted(String pin);
- /** WPS operation completed successfully */
+ /** WPS operation completed successfully
+ * @deprecated This API is deprecated
+ */
public abstract void onSucceeded();
/**
@@ -2377,6 +2349,7 @@ public class WifiManager {
* {@link #WPS_TKIP_ONLY_PROHIBITED}, {@link #WPS_OVERLAP_ERROR},
* {@link #WPS_WEP_PROHIBITED}, {@link #WPS_TIMED_OUT} or {@link #WPS_AUTH_FAILURE}
* and some generic errors.
+ * @deprecated This API is deprecated
*/
public abstract void onFailed(int reason);
}
@@ -2397,6 +2370,119 @@ public class WifiManager {
}
/**
+ * Base class for soft AP callback. Should be extended by applications and set when calling
+ * {@link WifiManager#registerSoftApCallback(SoftApCallback, Handler)}.
+ *
+ * @hide
+ */
+ public interface SoftApCallback {
+ /**
+ * Called when soft AP state changes.
+ *
+ * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED},
+ * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
+ * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
+ * @param failureReason reason when in failed state. One of
+ * {@link #SAP_START_FAILURE_GENERAL}, {@link #SAP_START_FAILURE_NO_CHANNEL}
+ */
+ public abstract void onStateChanged(@WifiApState int state,
+ @SapStartFailure int failureReason);
+
+ /**
+ * Called when number of connected clients to soft AP changes.
+ *
+ * @param numClients number of connected clients
+ */
+ public abstract void onNumClientsChanged(int numClients);
+ }
+
+ /**
+ * Callback proxy for SoftApCallback objects.
+ *
+ * @hide
+ */
+ private static class SoftApCallbackProxy extends ISoftApCallback.Stub {
+ private final Handler mHandler;
+ private final SoftApCallback mCallback;
+
+ SoftApCallbackProxy(Looper looper, SoftApCallback callback) {
+ mHandler = new Handler(looper);
+ mCallback = callback;
+ }
+
+ @Override
+ public void onStateChanged(int state, int failureReason) throws RemoteException {
+ Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state + ", failureReason=" +
+ failureReason);
+ mHandler.post(() -> {
+ mCallback.onStateChanged(state, failureReason);
+ });
+ }
+
+ @Override
+ public void onNumClientsChanged(int numClients) throws RemoteException {
+ Log.v(TAG, "SoftApCallbackProxy: onNumClientsChanged: numClients=" + numClients);
+ mHandler.post(() -> {
+ mCallback.onNumClientsChanged(numClients);
+ });
+ }
+ }
+
+ /**
+ * Registers a callback for Soft AP. See {@link SoftApCallback}. Caller will receive the current
+ * soft AP state and number of connected devices immediately after a successful call to this API
+ * via callback. Note that receiving an immediate WIFI_AP_STATE_FAILED value for soft AP state
+ * indicates that the latest attempt to start soft AP has failed. Caller can unregister a
+ * previously registered callback using {@link unregisterSoftApCallback}
+ * <p>
+ * Applications should have the
+ * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers
+ * without the permission will trigger a {@link java.lang.SecurityException}.
+ * <p>
+ *
+ * @param callback Callback for soft AP events
+ * @param handler The Handler on whose thread to execute the callbacks of the {@code callback}
+ * object. If null, then the application's main thread will be used.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ public void registerSoftApCallback(@NonNull SoftApCallback callback,
+ @Nullable Handler handler) {
+ if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+ Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", handler=" + handler);
+
+ Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
+ Binder binder = new Binder();
+ try {
+ mService.registerSoftApCallback(binder, new SoftApCallbackProxy(looper, callback),
+ callback.hashCode());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Allow callers to unregister a previously registered callback. After calling this method,
+ * applications will no longer receive soft AP events.
+ *
+ * @param callback Callback to unregister for soft AP events
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ public void unregisterSoftApCallback(@NonNull SoftApCallback callback) {
+ if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+ Log.v(TAG, "unregisterSoftApCallback: callback=" + callback);
+
+ try {
+ mService.unregisterSoftApCallback(callback.hashCode());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* LocalOnlyHotspotReservation that contains the {@link WifiConfiguration} for the active
* LocalOnlyHotspot request.
* <p>
@@ -2756,36 +2842,6 @@ public class WifiManager {
((ActionListener) listener).onSuccess();
}
break;
- case WifiManager.START_WPS_SUCCEEDED:
- if (listener != null) {
- WpsResult result = (WpsResult) message.obj;
- ((WpsCallback) listener).onStarted(result.pin);
- //Listener needs to stay until completion or failure
- synchronized (mListenerMapLock) {
- mListenerMap.put(message.arg2, listener);
- }
- }
- break;
- case WifiManager.WPS_COMPLETED:
- if (listener != null) {
- ((WpsCallback) listener).onSucceeded();
- }
- break;
- case WifiManager.WPS_FAILED:
- if (listener != null) {
- ((WpsCallback) listener).onFailed(message.arg1);
- }
- break;
- case WifiManager.CANCEL_WPS_SUCCEDED:
- if (listener != null) {
- ((WpsCallback) listener).onSucceeded();
- }
- break;
- case WifiManager.CANCEL_WPS_FAILED:
- if (listener != null) {
- ((WpsCallback) listener).onFailed(message.arg1);
- }
- break;
case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
if (listener != null) {
RssiPacketCountInfo info = (RssiPacketCountInfo) message.obj;
@@ -2855,8 +2911,7 @@ public class WifiManager {
* gets added to the list of configured networks for the foreground user.
*
* For a new network, this function is used instead of a
- * sequence of addNetwork(), enableNetwork(), saveConfiguration() and
- * reconnect()
+ * sequence of addNetwork(), enableNetwork(), and reconnect()
*
* @param config the set of variables that describe the configuration,
* contained in a {@link WifiConfiguration} object.
@@ -2878,8 +2933,7 @@ public class WifiManager {
/**
* Connect to a network with the given networkId.
*
- * This function is used instead of a enableNetwork(), saveConfiguration() and
- * reconnect()
+ * This function is used instead of a enableNetwork() and reconnect()
*
* @param networkId the ID of the network as returned by {@link #addNetwork} or {@link
* getConfiguredNetworks}.
@@ -2899,10 +2953,12 @@ public class WifiManager {
* is updated. Any new network is enabled by default.
*
* For a new network, this function is used instead of a
- * sequence of addNetwork(), enableNetwork() and saveConfiguration().
+ * sequence of addNetwork() and enableNetwork().
*
* For an existing network, it accomplishes the task of updateNetwork()
- * and saveConfiguration()
+ *
+ * This API will cause reconnect if the crecdentials of the current active
+ * connection has been changed.
*
* @param config the set of variables that describe the configuration,
* contained in a {@link WifiConfiguration} object.
@@ -2921,7 +2977,6 @@ public class WifiManager {
* foreground user.
*
* This function is used instead of a sequence of removeNetwork()
- * and saveConfiguration().
*
* @param config the set of variables that describe the configuration,
* contained in a {@link WifiConfiguration} object.
@@ -2958,34 +3013,39 @@ public class WifiManager {
public void disableEphemeralNetwork(String SSID) {
if (SSID == null) throw new IllegalArgumentException("SSID cannot be null");
try {
- mService.disableEphemeralNetwork(SSID);
+ mService.disableEphemeralNetwork(SSID, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Start Wi-fi Protected Setup
+ * WPS suport has been deprecated from Client mode and this method will immediately trigger
+ * {@link WpsCallback#onFailed(int)} with a generic error.
*
* @param config WPS configuration (does not support {@link WpsInfo#LABEL})
* @param listener for callbacks on success or failure. Can be null.
- * @throws IllegalStateException if the WifiManager instance needs to be
- * initialized again
+ * @throws IllegalStateException if the WifiManager instance needs to be initialized again
+ * @deprecated This API is deprecated
*/
public void startWps(WpsInfo config, WpsCallback listener) {
- if (config == null) throw new IllegalArgumentException("config cannot be null");
- getChannel().sendMessage(START_WPS, 0, putListener(listener), config);
+ if (listener != null ) {
+ listener.onFailed(ERROR);
+ }
}
/**
- * Cancel any ongoing Wi-fi Protected Setup
+ * WPS support has been deprecated from Client mode and this method will immediately trigger
+ * {@link WpsCallback#onFailed(int)} with a generic error.
*
* @param listener for callbacks on success or failure. Can be null.
- * @throws IllegalStateException if the WifiManager instance needs to be
- * initialized again
+ * @throws IllegalStateException if the WifiManager instance needs to be initialized again
+ * @deprecated This API is deprecated
*/
public void cancelWps(WpsCallback listener) {
- getChannel().sendMessage(CANCEL_WPS, 0, putListener(listener));
+ if (listener != null) {
+ listener.onFailed(ERROR);
+ }
}
/**
@@ -2997,7 +3057,7 @@ public class WifiManager {
*/
public Messenger getWifiServiceMessenger() {
try {
- return mService.getWifiServiceMessenger();
+ return mService.getWifiServiceMessenger(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3133,7 +3193,7 @@ public class WifiManager {
public void setWorkSource(WorkSource ws) {
synchronized (mBinder) {
- if (ws != null && ws.size() == 0) {
+ if (ws != null && ws.isEmpty()) {
ws = null;
}
boolean changed = true;
@@ -3145,7 +3205,7 @@ public class WifiManager {
changed = mWorkSource != null;
mWorkSource = new WorkSource(ws);
} else {
- changed = mWorkSource.diff(ws);
+ changed = !mWorkSource.equals(ws);
if (changed) {
mWorkSource.set(ws);
}
@@ -3448,6 +3508,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);
@@ -3471,62 +3532,13 @@ public class WifiManager {
}
/**
- * Set wifi Aggressive Handover. Called from developer settings.
- * @hide
- */
- public void enableAggressiveHandover(int enabled) {
- try {
- mService.enableAggressiveHandover(enabled);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get the WiFi Handover aggressiveness.This is used by settings
- * to decide what to show within the picker.
- * @hide
- */
- public int getAggressiveHandover() {
- try {
- return mService.getAggressiveHandover();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Set setting for allowing Scans when traffic is ongoing.
- * @hide
- */
- public void setAllowScansWithTraffic(int enabled) {
- try {
- mService.setAllowScansWithTraffic(enabled);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get setting for allowing Scans when traffic is ongoing.
- * @hide
- */
- public int getAllowScansWithTraffic() {
- try {
- return mService.getAllowScansWithTraffic();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Resets all wifi manager settings back to factory defaults.
+ * Removes all saved wifi networks.
*
* @hide
*/
public void factoryReset() {
try {
- mService.factoryReset();
+ mService.factoryReset(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3546,29 +3558,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 +3626,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..928a1da8b51c 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -160,6 +160,24 @@ public class WifiScanner {
*/
public static final int REPORT_EVENT_NO_BATCH = (1 << 2);
+ /**
+ * This is used to indicate the purpose of the scan to the wifi chip in
+ * {@link ScanSettings#type}.
+ * On devices with multiple hardware radio chains (and hence different modes of scan),
+ * this type serves as an indication to the hardware on what mode of scan to perform.
+ * Only apps holding android.Manifest.permission.NETWORK_STACK permission can set this value.
+ *
+ * Note: This serves as an intent and not as a stipulation, the wifi chip
+ * might honor or ignore the indication based on the current radio conditions. Always
+ * use the {@link ScanResult#radioChainInfos} to figure out the radio chain configuration used
+ * to receive the corresponding scan result.
+ */
+ /** {@hide} */
+ public static final int TYPE_LOW_LATENCY = 0;
+ /** {@hide} */
+ public static final int TYPE_LOW_POWER = 1;
+ /** {@hide} */
+ public static final int TYPE_HIGH_ACCURACY = 2;
/** {@hide} */
public static final String SCAN_PARAMS_SCAN_SETTINGS_KEY = "ScanSettings";
@@ -193,7 +211,8 @@ public class WifiScanner {
* list of hidden networks to scan for. Explicit probe requests are sent out for such
* networks during scan. Only valid for single scan requests.
* {@hide}
- * */
+ */
+ @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
public HiddenNetwork[] hiddenNetworks;
/** period of background scan; in millisecond, 0 => single shot scan */
public int periodInMs;
@@ -223,6 +242,13 @@ public class WifiScanner {
* {@hide}
*/
public boolean isPnoScan;
+ /**
+ * Indicate the type of scan to be performed by the wifi chip.
+ * Default value: {@link #TYPE_LOW_LATENCY}.
+ * {@hide}
+ */
+ @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
+ public int type = TYPE_LOW_LATENCY;
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
@@ -239,6 +265,7 @@ public class WifiScanner {
dest.writeInt(maxPeriodInMs);
dest.writeInt(stepCount);
dest.writeInt(isPnoScan ? 1 : 0);
+ dest.writeInt(type);
if (channels != null) {
dest.writeInt(channels.length);
for (int i = 0; i < channels.length; i++) {
@@ -272,6 +299,7 @@ public class WifiScanner {
settings.maxPeriodInMs = in.readInt();
settings.stepCount = in.readInt();
settings.isPnoScan = in.readInt() == 1;
+ settings.type = in.readInt();
int num_channels = in.readInt();
settings.channels = new ChannelSpec[num_channels];
for (int i = 0; i < num_channels; i++) {
@@ -1105,8 +1133,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 +1141,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 +1375,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..699f54cf13fb 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -20,9 +20,10 @@ 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 com.android.internal.annotations.VisibleForTesting;
+
import dalvik.system.CloseGuard;
import java.lang.ref.WeakReference;
@@ -143,6 +144,34 @@ public class DiscoverySession implements AutoCloseable {
}
/**
+ * Access the client ID of the Aware session.
+ *
+ * Note: internal visibility for testing.
+ *
+ * @return The internal client ID.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public int getClientId() {
+ return mClientId;
+ }
+
+ /**
+ * Access the discovery session ID of the Aware session.
+ *
+ * Note: internal visibility for testing.
+ *
+ * @return The internal discovery session ID.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public int getSessionId() {
+ return mSessionId;
+ }
+
+ /**
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
* {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
@@ -224,37 +253,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
@@ -278,8 +276,7 @@ public class DiscoverySession implements AutoCloseable {
* or
* {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}.
* On a RESPONDER this value is used to gate the acceptance of a connection
- * request from only that peer. A RESPONDER may specify a {@code null} -
- * indicating that it will accept connection requests from any device.
+ * request from only that peer.
*
* @return A {@link NetworkSpecifier} to be used to construct
* {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
@@ -287,7 +284,7 @@ public class DiscoverySession implements AutoCloseable {
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public NetworkSpecifier createNetworkSpecifierOpen(@Nullable PeerHandle peerHandle) {
+ public NetworkSpecifier createNetworkSpecifierOpen(@NonNull PeerHandle peerHandle) {
if (mTerminated) {
Log.w(TAG, "createNetworkSpecifierOpen: called on terminated session");
return null;
@@ -327,8 +324,7 @@ public class DiscoverySession implements AutoCloseable {
* byte[], java.util.List)} or
* {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
- * from only that peer. A RESPONDER may specify a {@code null} - indicating
- * that it will accept connection requests from any device.
+ * from only that peer.
* @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from
* the passphrase. Use the
* {@link #createNetworkSpecifierOpen(PeerHandle)} API to
@@ -341,7 +337,7 @@ public class DiscoverySession implements AutoCloseable {
* [or other varieties of that API].
*/
public NetworkSpecifier createNetworkSpecifierPassphrase(
- @Nullable PeerHandle peerHandle, @NonNull String passphrase) {
+ @NonNull PeerHandle peerHandle, @NonNull String passphrase) {
if (!WifiAwareUtils.validatePassphrase(passphrase)) {
throw new IllegalArgumentException("Passphrase must meet length requirements");
}
@@ -386,8 +382,7 @@ public class DiscoverySession implements AutoCloseable {
* byte[], java.util.List)} or
* {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
- * from only that peer. A RESPONDER may specify a null - indicating that
- * it will accept connection requests from any device.
+ * from only that peer.
* @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
* encrypting the data-path. Use the
* {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} to specify a
@@ -403,7 +398,7 @@ public class DiscoverySession implements AutoCloseable {
* @hide
*/
@SystemApi
- public NetworkSpecifier createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle,
+ public NetworkSpecifier createNetworkSpecifierPmk(@NonNull PeerHandle peerHandle,
@NonNull byte[] pmk) {
if (!WifiAwareUtils.validatePmk(pmk)) {
throw new IllegalArgumentException("PMK must 32 bytes");
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
index 115b86d156e5..2052f155abee 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -113,6 +113,31 @@ 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.
+ */
+ 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/IRttManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareMacAddressProvider.aidl
index 383180995b21..0e7289cd9c46 100644
--- a/wifi/java/android/net/wifi/IRttManager.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareMacAddressProvider.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * 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.
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-package android.net.wifi;
-import android.os.Messenger;
-import android.net.wifi.RttManager;
+package android.net.wifi.aware;
/**
- * {@hide}
+ * Callback for IWifiAwareManager.getMacAddressFromPeerHandle
+ *
+ * @hide
*/
-interface IRttManager
+oneway interface IWifiAwareMacAddressProvider
{
- Messenger getMessenger(in IBinder binder, out int[] key);
- RttManager.RttCapabilities getRttCapabilities();
+ 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..c4b24cfa2394 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
@@ -42,9 +42,9 @@ interface IWifiAwareManager
in ConfigRequest configRequest, boolean notifyOnIdentityChanged);
void disconnect(int clientId, in IBinder binder);
- void publish(int clientId, in PublishConfig publishConfig,
+ void publish(in String callingPackage, int clientId, in PublishConfig publishConfig,
in IWifiAwareDiscoverySessionCallback callback);
- void subscribe(int clientId, in SubscribeConfig subscribeConfig,
+ void subscribe(in String callingPackage, int clientId, in SubscribeConfig subscribeConfig,
in IWifiAwareDiscoverySessionCallback callback);
// session API
@@ -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..7a0250bf0700 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);
}
/**
@@ -180,7 +182,7 @@ public final class PublishConfig implements Parcelable {
*
* @hide
*/
- public void assertValid(Characteristics characteristics)
+ public void assertValid(Characteristics characteristics, boolean rttSupported)
throws IllegalArgumentException {
WifiAwareUtils.validateServiceName(mServiceName);
@@ -214,6 +216,10 @@ public final class PublishConfig implements Parcelable {
"Match filter longer than supported by device characteristics");
}
}
+
+ if (!rttSupported && mEnableRanging) {
+ throw new IllegalArgumentException("Ranging is not supported");
+ }
}
/**
@@ -226,6 +232,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 +359,36 @@ 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.
+ * <p>
+ * The device must support Wi-Fi RTT for this feature to be used. Feature support is checked
+ * as described in {@link android.net.wifi.rtt}.
+ *
+ * @param enable If true, ranging is supported on request of the peer.
+ *
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ */
+ 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..2eab76a10cb4 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;
}
@@ -179,7 +224,7 @@ public final class SubscribeConfig implements Parcelable {
*
* @hide
*/
- public void assertValid(Characteristics characteristics)
+ public void assertValid(Characteristics characteristics, boolean rttSupported)
throws IllegalArgumentException {
WifiAwareUtils.validateServiceName(mServiceName);
@@ -213,6 +258,21 @@ 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");
+ }
+
+ if (!rttSupported && (mMinDistanceMmSet || mMaxDistanceMmSet)) {
+ throw new IllegalArgumentException("Ranging is not supported");
+ }
}
/**
@@ -225,6 +285,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 +414,71 @@ 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.
+ * <p>
+ * The device must support Wi-Fi RTT for this feature to be used. Feature support is checked
+ * as described in {@link android.net.wifi.rtt}.
+ *
+ * @param minDistanceMm Minimum distance, in mm, to the publisher above which to trigger
+ * discovery.
+ *
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ */
+ 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.
+ * <p>
+ * The device must support Wi-Fi RTT for this feature to be used. Feature support is checked
+ * as described in {@link android.net.wifi.rtt}.
+ *
+ * @param maxDistanceMm Maximum distance, in mm, to the publisher below which to trigger
+ * discovery.
+ *
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ */
+ 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..06a5c2e2710b 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;
@@ -277,6 +269,10 @@ public class WifiAwareManager {
+ identityChangedListener);
}
+ if (attachCallback == null) {
+ throw new IllegalArgumentException("Null callback provided");
+ }
+
synchronized (mLock) {
Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
@@ -308,8 +304,12 @@ public class WifiAwareManager {
DiscoverySessionCallback callback) {
if (VDBG) Log.v(TAG, "publish(): clientId=" + clientId + ", config=" + publishConfig);
+ if (callback == null) {
+ throw new IllegalArgumentException("Null callback provided");
+ }
+
try {
- mService.publish(clientId, publishConfig,
+ mService.publish(mContext.getOpPackageName(), clientId, publishConfig,
new WifiAwareDiscoverySessionCallbackProxy(this, looper, true, callback,
clientId));
} catch (RemoteException e) {
@@ -341,8 +341,12 @@ public class WifiAwareManager {
}
}
+ if (callback == null) {
+ throw new IllegalArgumentException("Null callback provided");
+ }
+
try {
- mService.subscribe(clientId, subscribeConfig,
+ mService.subscribe(mContext.getOpPackageName(), clientId, subscribeConfig,
new WifiAwareDiscoverySessionCallbackProxy(this, looper, false, callback,
clientId));
} catch (RemoteException e) {
@@ -401,29 +405,8 @@ 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) {
+ @NonNull PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
if (VDBG) {
Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
+ ", peerHandle=" + ((peerHandle == null) ? peerHandle : peerHandle.peerId)
@@ -437,12 +420,9 @@ public class WifiAwareManager {
"createNetworkSpecifier: Invalid 'role' argument when creating a network "
+ "specifier");
}
- if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
- if (peerHandle == null) {
- throw new IllegalArgumentException(
- "createNetworkSpecifier: Invalid peer handle (value of null) - not "
- + "permitted on INITIATOR");
- }
+ if (peerHandle == null) {
+ throw new IllegalArgumentException(
+ "createNetworkSpecifier: Invalid peer handle - cannot be null");
}
return new WifiAwareNetworkSpecifier(
@@ -460,7 +440,7 @@ public class WifiAwareManager {
/** @hide */
public NetworkSpecifier createNetworkSpecifier(int clientId, @DataPathRole int role,
- @Nullable byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) {
+ @NonNull byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) {
if (VDBG) {
Log.v(TAG, "createNetworkSpecifier: role=" + role
+ ", pmk=" + ((pmk == null) ? "null" : "non-null")
@@ -473,11 +453,9 @@ public class WifiAwareManager {
"createNetworkSpecifier: Invalid 'role' argument when creating a network "
+ "specifier");
}
- if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
- if (peer == null) {
- throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC "
- + "address - null not permitted on INITIATOR");
- }
+ if (peer == null) {
+ throw new IllegalArgumentException(
+ "createNetworkSpecifier: Invalid peer MAC - cannot be null");
}
if (peer != null && peer.length != 6) {
throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC address");
@@ -500,29 +478,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 +528,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 +559,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 +571,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 +626,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 +639,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 +701,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/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index f26b9f5aacfc..321965330e0b 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -25,6 +25,8 @@ import android.os.Handler;
import android.os.Looper;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import dalvik.system.CloseGuard;
import java.lang.ref.WeakReference;
@@ -97,6 +99,20 @@ public class WifiAwareSession implements AutoCloseable {
}
/**
+ * Access the client ID of the Aware session.
+ *
+ * Note: internal visibility for testing.
+ *
+ * @return The internal client ID.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public int getClientId() {
+ return mClientId;
+ }
+
+ /**
* Issue a request to the Aware service to create a new Aware publish discovery session, using
* the specified {@code publishConfig} configuration. The results of the publish operation
* are routed to the callbacks of {@link DiscoverySessionCallback}:
@@ -207,8 +223,7 @@ public class WifiAwareSession implements AutoCloseable {
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
* @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this
* value is used to gate the acceptance of a connection request from only that
- * peer. A RESPONDER may specify a {@code null} - indicating that it will accept
- * connection requests from any device.
+ * peer.
*
* @return A {@link NetworkSpecifier} to be used to construct
* {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
@@ -217,7 +232,7 @@ public class WifiAwareSession implements AutoCloseable {
* [or other varieties of that API].
*/
public NetworkSpecifier createNetworkSpecifierOpen(
- @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer) {
+ @WifiAwareManager.DataPathRole int role, @NonNull byte[] peer) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager");
@@ -246,8 +261,7 @@ public class WifiAwareSession implements AutoCloseable {
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
* @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this
* value is used to gate the acceptance of a connection request from only that
- * peer. A RESPONDER may specify a {@code null} - indicating that it will accept
- * connection requests from any device.
+ * peer.
* @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from
* the passphrase. Use {@link #createNetworkSpecifierOpen(int, byte[])} to
* specify an open (unencrypted) link.
@@ -259,7 +273,7 @@ public class WifiAwareSession implements AutoCloseable {
* [or other varieties of that API].
*/
public NetworkSpecifier createNetworkSpecifierPassphrase(
- @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer,
+ @WifiAwareManager.DataPathRole int role, @NonNull byte[] peer,
@NonNull String passphrase) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
@@ -293,8 +307,7 @@ public class WifiAwareSession implements AutoCloseable {
* {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
* @param peer The MAC address of the peer's Aware discovery interface. On a RESPONDER this
* value is used to gate the acceptance of a connection request from only that
- * peer. A RESPONDER may specify a null - indicating that it will accept
- * connection requests from any device.
+ * peer.
* @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
* encrypting the data-path. Use the
* {@link #createNetworkSpecifierPassphrase(int, byte[], String)} to specify a
@@ -311,7 +324,7 @@ public class WifiAwareSession implements AutoCloseable {
*/
@SystemApi
public NetworkSpecifier createNetworkSpecifierPmk(
- @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer, @NonNull byte[] pmk) {
+ @WifiAwareManager.DataPathRole int role, @NonNull byte[] peer, @NonNull byte[] pmk) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager");
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..2ea6e797ec93
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -0,0 +1,113 @@
+/*
+ * 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 reason code for Provisioning Failure due to connection failure to OSU AP.
+ * @hide
+ */
+ public static final int OSU_FAILURE_SERVER_URL_INVALID = 2;
+
+ /**
+ * The reason code for Provisioning Failure due to connection failure to OSU AP.
+ * @hide
+ */
+ public static final int OSU_FAILURE_SERVER_CONNECTION = 3;
+
+ /**
+ * The reason code for Provisioning Failure due to connection failure to OSU AP.
+ * @hide
+ */
+ public static final int OSU_FAILURE_SERVER_VALIDATION = 4;
+
+ /**
+ * The reason code for Provisioning Failure due to connection failure to OSU AP.
+ * @hide
+ */
+ public static final int OSU_FAILURE_PROVIDER_VERIFICATION = 5;
+
+ /**
+ * The reason code for Provisioning Failure when a provisioning flow is aborted.
+ * @hide
+ */
+ public static final int OSU_FAILURE_PROVISIONING_ABORTED = 6;
+
+ /**
+ * The reason code for Provisioning Failure when a provisioning flow is aborted.
+ * @hide
+ */
+ public static final int OSU_FAILURE_PROVISIONING_NOT_AVAILABLE = 7;
+
+ /**
+ * 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;
+
+ /**
+ * The status code for Provisioning flow to indicate connecting to OSU AP
+ * @hide
+ */
+ public static final int OSU_STATUS_SERVER_CONNECTED = 3;
+
+ /**
+ * The status code for Provisioning flow to indicate connecting to OSU AP
+ * @hide
+ */
+ public static final int OSU_STATUS_SERVER_VALIDATED = 4;
+
+ /**
+ * The status code for Provisioning flow to indicate connecting to OSU AP
+ * @hide
+ */
+ public static final int OSU_STATUS_PROVIDER_VERIFIED = 5;
+
+ /**
+ * 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/LocationCivic.java b/wifi/java/android/net/wifi/rtt/LocationCivic.java
new file mode 100644
index 000000000000..610edb6399b4
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/LocationCivic.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2018 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.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Location Civic Report (LCR).
+ * <p>
+ * The information matches the IEEE 802.11-2016 LCR report.
+ * <p>
+ * Note: depending on the mechanism by which this information is returned (i.e. the API which
+ * returns an instance of this class) it is possibly Self Reported (by the peer). In such a case
+ * the information is NOT validated - use with caution. Consider validating it with other sources
+ * of information before using it.
+ */
+public final class LocationCivic implements Parcelable {
+ private final byte[] mData;
+
+ /**
+ * Parse the raw LCR information element (byte array) and extract the LocationCivic structure.
+ *
+ * Note: any parsing errors or invalid/unexpected errors will result in a null being returned.
+ *
+ * @hide
+ */
+ @Nullable
+ public static LocationCivic parseInformationElement(byte id, byte[] data) {
+ // TODO
+ return null;
+ }
+
+ /** @hide */
+ public LocationCivic(byte[] data) {
+ mData = data;
+ }
+
+ /**
+ * Return the Location Civic data reported by the peer.
+ *
+ * @return An arbitrary location information.
+ */
+ public byte[] getData() {
+ return mData;
+ }
+
+ /** @hide */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeByteArray(mData);
+ }
+
+ public static final Parcelable.Creator<LocationCivic> CREATOR =
+ new Parcelable.Creator<LocationCivic>() {
+ @Override
+ public LocationCivic[] newArray(int size) {
+ return new LocationCivic[size];
+ }
+
+ @Override
+ public LocationCivic createFromParcel(Parcel in) {
+ byte[] data = in.createByteArray();
+
+ return new LocationCivic(data);
+ }
+ };
+
+ /** @hide */
+ @Override
+ public String toString() {
+ return new StringBuilder("LCR: data=").append(Arrays.toString(mData)).toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof LocationCivic)) {
+ return false;
+ }
+
+ LocationCivic lhs = (LocationCivic) o;
+
+ return Arrays.equals(mData, lhs.mData);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mData);
+ }
+}
diff --git a/wifi/java/android/net/wifi/rtt/LocationConfigurationInformation.java b/wifi/java/android/net/wifi/rtt/LocationConfigurationInformation.java
new file mode 100644
index 000000000000..8aba56aa0ee7
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/LocationConfigurationInformation.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2018 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.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * The Device Location Configuration Information (LCI) specifies the location information of a peer
+ * device (e.g. an Access Point).
+ * <p>
+ * The information matches the IEEE 802.11-2016 LCI report (Location configuration information
+ * report).
+ * <p>
+ * Note: depending on the mechanism by which this information is returned (i.e. the API which
+ * returns an instance of this class) it is possibly Self Reported (by the peer). In such a case
+ * the information is NOT validated - use with caution. Consider validating it with other sources
+ * of information before using it.
+ */
+public final class LocationConfigurationInformation implements Parcelable {
+ /** @hide */
+ @IntDef({
+ ALTITUDE_UNKNOWN, ALTITUDE_IN_METERS, ALTITUDE_IN_FLOORS })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AltitudeTypes {
+ }
+
+ /**
+ * Define an Altitude Type returned by {@link #getAltitudeType()}. Indicates that the location
+ * does not specify an altitude or altitude uncertainty. The corresponding methods,
+ * {@link #getAltitude()} and {@link #getAltitudeUncertainty()} are not valid and will throw
+ * an exception.
+ */
+ public static final int ALTITUDE_UNKNOWN = 0;
+
+ /**
+ * Define an Altitude Type returned by {@link #getAltitudeType()}. Indicates that the location
+ * specifies the altitude and altitude uncertainty in meters. The corresponding methods,
+ * {@link #getAltitude()} and {@link #getAltitudeUncertainty()} return a valid value in meters.
+ */
+ public static final int ALTITUDE_IN_METERS = 1;
+
+ /**
+ * Define an Altitude Type returned by {@link #getAltitudeType()}. Indicates that the
+ * location specifies the altitude in floors, and does not specify an altitude uncertainty.
+ * The {@link #getAltitude()} method returns valid value in floors, and the
+ * {@link #getAltitudeUncertainty()} method is not valid and will throw an exception.
+ */
+ public static final int ALTITUDE_IN_FLOORS = 2;
+
+ private final double mLatitude;
+ private final double mLatitudeUncertainty;
+ private final double mLongitude;
+ private final double mLongitudeUncertainty;
+ private final int mAltitudeType;
+ private final double mAltitude;
+ private final double mAltitudeUncertainty;
+
+ /**
+ * Parse the raw LCI information element (byte array) and extract the
+ * LocationConfigurationInformation structure.
+ *
+ * Note: any parsing errors or invalid/unexpected errors will result in a null being returned.
+ *
+ * @hide
+ */
+ @Nullable
+ public static LocationConfigurationInformation parseInformationElement(byte id, byte[] data) {
+ // TODO
+ return null;
+ }
+
+ /** @hide */
+ public LocationConfigurationInformation(double latitude, double latitudeUncertainty,
+ double longitude, double longitudeUncertainty, @AltitudeTypes int altitudeType,
+ double altitude, double altitudeUncertainty) {
+ mLatitude = latitude;
+ mLatitudeUncertainty = latitudeUncertainty;
+ mLongitude = longitude;
+ mLongitudeUncertainty = longitudeUncertainty;
+ mAltitudeType = altitudeType;
+ mAltitude = altitude;
+ mAltitudeUncertainty = altitudeUncertainty;
+ }
+
+ /**
+ * Get latitude in degrees. Values are per WGS 84 reference system. Valid values are between
+ * -90 and 90.
+ *
+ * @return Latitude in degrees.
+ */
+ public double getLatitude() {
+ return mLatitude;
+ }
+
+ /**
+ * Get the uncertainty of the latitude {@link #getLatitude()} in degrees. A value of 0 indicates
+ * an unknown uncertainty.
+ *
+ * @return Uncertainty of the latitude in degrees.
+ */
+ public double getLatitudeUncertainty() {
+ return mLatitudeUncertainty;
+ }
+
+ /**
+ * Get longitude in degrees. Values are per WGS 84 reference system. Valid values are between
+ * -180 and 180.
+ *
+ * @return Longitude in degrees.
+ */
+ public double getLongitude() {
+ return mLongitude;
+ }
+
+ /**
+ * Get the uncertainty of the longitude {@link #getLongitude()} ()} in degrees. A value of 0
+ * indicates an unknown uncertainty.
+ *
+ * @return Uncertainty of the longitude in degrees.
+ */
+ public double getLongitudeUncertainty() {
+ return mLongitudeUncertainty;
+ }
+
+ /**
+ * Specifies the type of the altitude measurement returned by {@link #getAltitude()} and
+ * {@link #getAltitudeUncertainty()}. The possible values are:
+ * <li>{@link #ALTITUDE_UNKNOWN}: The altitude and altitude uncertainty are not provided.
+ * <li>{@link #ALTITUDE_IN_METERS}: The altitude and altitude uncertainty are provided in
+ * meters. Values are per WGS 84 reference system.
+ * <li>{@link #ALTITUDE_IN_FLOORS}: The altitude is provided in floors, the altitude uncertainty
+ * is not provided.
+ *
+ * @return The type of the altitude and altitude uncertainty.
+ */
+ public @AltitudeTypes int getAltitudeType() {
+ return mAltitudeType;
+ }
+
+ /**
+ * The altitude is interpreted according to the {@link #getAltitudeType()}. The possible values
+ * are:
+ * <li>{@link #ALTITUDE_UNKNOWN}: The altitude is not provided - this method will throw an
+ * exception.
+ * <li>{@link #ALTITUDE_IN_METERS}: The altitude is provided in meters. Values are per WGS 84
+ * reference system.
+ * <li>{@link #ALTITUDE_IN_FLOORS}: The altitude is provided in floors.
+ *
+ * @return Altitude value whose meaning is specified by {@link #getAltitudeType()}.
+ */
+ public double getAltitude() {
+ if (mAltitudeType == ALTITUDE_UNKNOWN) {
+ throw new IllegalStateException(
+ "getAltitude(): invoked on an invalid type: getAltitudeType()==UNKNOWN");
+ }
+ return mAltitude;
+ }
+
+ /**
+ * Only valid if the the {@link #getAltitudeType()} is equal to {@link #ALTITUDE_IN_METERS} -
+ * otherwise this method will throw an exception.
+ * <p>
+ * Get the uncertainty of the altitude {@link #getAltitude()} in meters. A value of 0
+ * indicates an unknown uncertainty.
+ *
+ * @return Uncertainty of the altitude in meters.
+ */
+ public double getAltitudeUncertainty() {
+ if (mAltitudeType != ALTITUDE_IN_METERS) {
+ throw new IllegalStateException(
+ "getAltitude(): invoked on an invalid type: getAltitudeType()!=IN_METERS");
+ }
+ return mAltitudeUncertainty;
+ }
+
+ /** @hide */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeDouble(mLatitude);
+ dest.writeDouble(mLatitudeUncertainty);
+ dest.writeDouble(mLongitude);
+ dest.writeDouble(mLongitudeUncertainty);
+ dest.writeInt(mAltitudeType);
+ dest.writeDouble(mAltitude);
+ dest.writeDouble(mAltitudeUncertainty);
+ }
+
+ public static final Creator<LocationConfigurationInformation> CREATOR =
+ new Creator<LocationConfigurationInformation>() {
+ @Override
+ public LocationConfigurationInformation[] newArray(int size) {
+ return new LocationConfigurationInformation[size];
+ }
+
+ @Override
+ public LocationConfigurationInformation createFromParcel(Parcel in) {
+ double latitude = in.readDouble();
+ double latitudeUnc = in.readDouble();
+ double longitude = in.readDouble();
+ double longitudeUnc = in.readDouble();
+ int altitudeType = in.readInt();
+ double altitude = in.readDouble();
+ double altitudeUnc = in.readDouble();
+
+ return new LocationConfigurationInformation(latitude, latitudeUnc, longitude,
+ longitudeUnc, altitudeType, altitude, altitudeUnc);
+ }
+ };
+
+ /** @hide */
+ @Override
+ public String toString() {
+ return new StringBuilder("LCI: latitude=").append(mLatitude).append(
+ ", latitudeUncertainty=").append(mLatitudeUncertainty).append(
+ ", longitude=").append(mLongitude).append(", longitudeUncertainty=").append(
+ mLongitudeUncertainty).append(", altitudeType=").append(mAltitudeType).append(
+ ", altitude=").append(mAltitude).append(", altitudeUncertainty=").append(
+ mAltitudeUncertainty).toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof LocationConfigurationInformation)) {
+ return false;
+ }
+
+ LocationConfigurationInformation lhs = (LocationConfigurationInformation) o;
+
+ return mLatitude == lhs.mLatitude && mLatitudeUncertainty == lhs.mLatitudeUncertainty
+ && mLongitude == lhs.mLongitude
+ && mLongitudeUncertainty == lhs.mLongitudeUncertainty
+ && mAltitudeType == lhs.mAltitudeType && mAltitude == lhs.mAltitude
+ && mAltitudeUncertainty == lhs.mAltitudeUncertainty;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mLatitude, mLatitudeUncertainty, mLongitude, mLongitudeUncertainty,
+ mAltitudeType, mAltitude, mAltitudeUncertainty);
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiConnectionStatistics.aidl b/wifi/java/android/net/wifi/rtt/RangingRequest.aidl
index 601facea37ba..8053c9416aeb 100644
--- a/wifi/java/android/net/wifi/WifiConnectionStatistics.aidl
+++ b/wifi/java/android/net/wifi/rtt/RangingRequest.aidl
@@ -1,19 +1,19 @@
-/**
- * Copyright (c) 2014, The Android Open Source Project
+/*
+ * 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
+ * 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
+ * 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
+ * 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;
+package android.net.wifi.rtt;
-parcelable WifiConnectionStatistics;
+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..52b3d8691c79
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/RangingRequest.java
@@ -0,0 +1,256 @@
+/*
+ * 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.annotation.SystemApi;
+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)}).
+ */
+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.
+ * <p>
+ * 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)}.
+ * <p>
+ * Note: in order to use this API the device must support Wi-Fi Aware
+ * {@link android.net.wifi.aware}. The peer device which is being ranged to must be
+ * configured to publish a service (with any name) with:
+ * <li>Type {@link android.net.wifi.aware.PublishConfig#PUBLISH_TYPE_UNSOLICITED}.
+ * <li>Ranging enabled
+ * {@link android.net.wifi.aware.PublishConfig.Builder#setRangingEnabled(boolean)}.
+ *
+ * @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.
+ * <p>
+ * The {@link PeerHandle} may be obtained as part of the Wi-Fi Aware discovery process. E.g.
+ * using {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], List)}.
+ * <p>
+ * Note: in order to use this API the device must support Wi-Fi Aware
+ * {@link android.net.wifi.aware}. The peer device which is being ranged to must be
+ * configured to publish a service (with any name) with:
+ * <li>Type {@link android.net.wifi.aware.PublishConfig#PUBLISH_TYPE_UNSOLICITED}.
+ * <li>Ranging enabled
+ * {@link android.net.wifi.aware.PublishConfig.Builder#setRangingEnabled(boolean)}.
+ *
+ * @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..f7c85671c220
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/RangingResult.java
@@ -0,0 +1,354 @@
+/*
+ * 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.annotation.Nullable;
+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}.
+ */
+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;
+
+ /**
+ * Individual range request status, {@link #getStatus()}. Indicates that the ranging operation
+ * failed because the specified peer does not support IEEE 802.11mc RTT operations. Support by
+ * an Access Point can be confirmed using
+ * {@link android.net.wifi.ScanResult#is80211mcResponder()}.
+ * <p>
+ * On such a failure, the individual result fields of {@link RangingResult} such as
+ * {@link RangingResult#getDistanceMm()} are invalid.
+ *
+ * @hide
+ */
+ public static final int STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC = 2;
+
+ 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 LocationConfigurationInformation mLci;
+ private final LocationCivic mLcr;
+ private final long mTimestamp;
+
+ /** @hide */
+ public RangingResult(@RangeResultStatus int status, @NonNull MacAddress mac, int distanceMm,
+ int distanceStdDevMm, int rssi, LocationConfigurationInformation lci, LocationCivic lcr,
+ long timestamp) {
+ mStatus = status;
+ mMac = mac;
+ mPeerHandle = null;
+ mDistanceMm = distanceMm;
+ mDistanceStdDevMm = distanceStdDevMm;
+ mRssi = rssi;
+ mLci = lci;
+ mLcr = lcr;
+ mTimestamp = timestamp;
+ }
+
+ /** @hide */
+ public RangingResult(@RangeResultStatus int status, PeerHandle peerHandle, int distanceMm,
+ int distanceStdDevMm, int rssi, LocationConfigurationInformation lci, LocationCivic lcr,
+ long timestamp) {
+ mStatus = status;
+ mMac = null;
+ mPeerHandle = peerHandle;
+ mDistanceMm = distanceMm;
+ mDistanceStdDevMm = distanceStdDevMm;
+ mRssi = rssi;
+ mLci = lci;
+ mLcr = lcr;
+ 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.
+ */
+ @Nullable
+ 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.
+ */
+ @Nullable 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 Location Configuration Information (LCI) as self-reported by the peer.
+ * <p>
+ * Note: the information is NOT validated - use with caution. Consider validating it with
+ * other sources of information before using it.
+ */
+ @Nullable
+ public LocationConfigurationInformation getReportedLocationConfigurationInformation() {
+ if (mStatus != STATUS_SUCCESS) {
+ throw new IllegalStateException(
+ "getReportedLocationConfigurationInformation(): invoked on an invalid result: "
+ + "getStatus()=" + mStatus);
+ }
+ return mLci;
+ }
+
+ /**
+ * @return The Location Civic report (LCR) as self-reported by the peer.
+ * <p>
+ * Note: the information is NOT validated - use with caution. Consider validating it with
+ * other sources of information before using it.
+ */
+ @Nullable
+ public LocationCivic getReportedLocationCivic() {
+ if (mStatus != STATUS_SUCCESS) {
+ throw new IllegalStateException(
+ "getReportedLocationCivic(): invoked on an invalid result: getStatus()="
+ + mStatus);
+ }
+ return mLcr;
+ }
+
+ /**
+ * @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;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @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);
+ if (mLci == null) {
+ dest.writeBoolean(false);
+ } else {
+ dest.writeBoolean(true);
+ mLci.writeToParcel(dest, flags);
+ }
+ if (mLcr == null) {
+ dest.writeBoolean(false);
+ } else {
+ dest.writeBoolean(true);
+ mLcr.writeToParcel(dest, flags);
+ }
+ dest.writeLong(mTimestamp);
+ }
+
+ 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();
+ boolean lciPresent = in.readBoolean();
+ LocationConfigurationInformation lci = null;
+ if (lciPresent) {
+ lci = LocationConfigurationInformation.CREATOR.createFromParcel(in);
+ }
+ boolean lcrPresent = in.readBoolean();
+ LocationCivic lcr = null;
+ if (lcrPresent) {
+ lcr = LocationCivic.CREATOR.createFromParcel(in);
+ }
+ long timestamp = in.readLong();
+ if (peerHandlePresent) {
+ return new RangingResult(status, peerHandle, distanceMm, distanceStdDevMm, rssi,
+ lci, lcr, timestamp);
+ } else {
+ return new RangingResult(status, mac, distanceMm, distanceStdDevMm, rssi,
+ lci, lcr, 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(", lci=").append(mLci).append(", lcr=").append(
+ mLcr).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
+ && Objects.equals(mLci, lhs.mLci) && Objects.equals(mLcr, lhs.mLcr)
+ && mTimestamp == lhs.mTimestamp;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mStatus, mMac, mPeerHandle, mDistanceMm, mDistanceStdDevMm, mRssi,
+ mLci, mLcr, 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..9639dc803a7d
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/RangingResultCallback.java
@@ -0,0 +1,71 @@
+/*
+ * 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.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()}.
+ */
+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(@NonNull 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..fb723c594e15
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/ResponderConfig.java
@@ -0,0 +1,476 @@
+/*
+ * 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.annotation.SystemApi;
+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 final 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.
+ */
+ public final 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 final 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, using a MAC address to identify the Responder.
+ *
+ * @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, using a Wi-Fi Aware PeerHandle to identify the Responder.
+ *
+ * @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;
+ }
+
+ /**
+ * Constructs Responder configuration. This is an internal-only constructor which specifies both
+ * a MAC address and a Wi-Fi PeerHandle to identify the Responder.
+ *
+ * @param macAddress The MAC address of the Responder.
+ * @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}.
+ * @hide
+ */
+ public ResponderConfig(@NonNull MacAddress macAddress, @NonNull PeerHandle peerHandle,
+ @ResponderType int responderType, boolean supports80211mc,
+ @ChannelWidth int channelWidth, int frequency, int centerFreq0, int centerFreq1,
+ @PreambleType int preamble) {
+ this.macAddress = macAddress;
+ 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 = translateScanResultChannelWidth(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 translateScanResultChannelWidth(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(
+ "translateScanResultChannelWidth: 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..ec6c46ec4a7d
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 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 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.NonNull;
+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.
+ */
+@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.
+ * <p>Note: availability of RTT does not mean that the app can use the API. The app's
+ * permissions and platform Location Mode are validated at run-time.
+ *
+ * @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(@NonNull RangingRequest request,
+ @NonNull 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, @NonNull RangingRequest request,
+ @NonNull RangingResultCallback callback, @Nullable Handler handler) {
+ if (VDBG) {
+ Log.v(TAG, "startRanging: workSource=" + workSource + ", request=" + request
+ + ", callback=" + callback + ", handler=" + handler);
+ }
+
+ if (callback == null) {
+ throw new IllegalArgumentException("Null callback provided");
+ }
+
+ 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(@Nullable 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..11ac05800a7c
--- /dev/null
+++ b/wifi/java/android/net/wifi/rtt/package.html
@@ -0,0 +1,41 @@
+<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>Usage of the API is also gated by the device's Location Mode: whether it permits Wi-Fi based
+location to be queried.</p>
+
+<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>