summaryrefslogtreecommitdiffstats
path: root/wifi/java/android/net/wifi/RttManager.java
diff options
context:
space:
mode:
authorVinit Deshpande <vinitd@google.com>2014-06-30 15:25:01 -0700
committerVinit Deshpande <vinitd@google.com>2014-07-17 00:45:20 +0000
commit7686c061b7c5c981c79e566e3b31f68b9e21c730 (patch)
tree5f6dcba011d43654a5c5dcd03b8e764a13ead852 /wifi/java/android/net/wifi/RttManager.java
parent6d32e725233b2bd4b1e3c1c01707f8ca8b9835c9 (diff)
downloadframeworks_base-7686c061b7c5c981c79e566e3b31f68b9e21c730.zip
frameworks_base-7686c061b7c5c981c79e566e3b31f68b9e21c730.tar.gz
frameworks_base-7686c061b7c5c981c79e566e3b31f68b9e21c730.tar.bz2
Introduce RTT Manager
Change-Id: Ic9a16d587897b272f85cdb2b8c52b51bca060d18
Diffstat (limited to 'wifi/java/android/net/wifi/RttManager.java')
-rw-r--r--wifi/java/android/net/wifi/RttManager.java334
1 files changed, 334 insertions, 0 deletions
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
new file mode 100644
index 0000000..50fd260
--- /dev/null
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -0,0 +1,334 @@
+package android.net.wifi;
+
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.util.AsyncChannel;
+
+import java.util.concurrent.CountDownLatch;
+
+/** @hide */
+@SystemApi
+public class RttManager {
+
+ private static final boolean DBG = true;
+ private static final String TAG = "RttManager";
+
+ public static final int RTT_TYPE_UNSPECIFIED = 0;
+ public static final int RTT_TYPE_ONE_SIDED = 1;
+ public static final int RTT_TYPE_11_V = 2;
+ public static final int RTT_TYPE_11_MC = 4;
+
+ public static final int RTT_PEER_TYPE_UNSPECIFIED = 0;
+ public static final int RTT_PEER_TYPE_AP = 1;
+ public static final int RTT_PEER_TYPE_STA = 2; /* requires NAN */
+
+ public static final int RTT_CHANNEL_WIDTH_20 = 0;
+ public static final int RTT_CHANNEL_WIDTH_40 = 1;
+ public static final int RTT_CHANNEL_WIDTH_80 = 2;
+ public static final int RTT_CHANNEL_WIDTH_160 = 3;
+ public static final int RTT_CHANNEL_WIDTH_80P80 = 4;
+ public static final int RTT_CHANNEL_WIDTH_5 = 5;
+ public static final int RTT_CHANNEL_WIDTH_10 = 6;
+ public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1;
+
+ public static final int RTT_STATUS_SUCCESS = 0;
+ public static final int RTT_STATUS_FAILURE = 1;
+ public static final int RTT_STATUS_FAIL_NO_RSP = 2;
+ public static final int RTT_STATUS_FAIL_REJECTED = 3;
+ public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4;
+ public static final int RTT_STATUS_FAIL_TM_TIMEOUT = 5;
+ public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6;
+ public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7;
+ public static final int RTT_STATUS_ABORTED = 8;
+
+ public static final int REASON_UNSPECIFIED = -1;
+ public static final int REASON_INVALID_LISTENER = -2;
+ public static final int REASON_INVALID_REQUEST = -3;
+
+ public class Capabilities {
+ int supportedType;
+ int supportedPeerType;
+ }
+
+ public Capabilities getCapabilities() {
+ return new Capabilities();
+ }
+
+ /** specifies parameters for RTT request */
+ public static class RttParams {
+
+ /** type of device being ranged; one of RTT_PEER_TYPE_AP or RTT_PEER_TYPE_STA */
+ public int deviceType;
+
+ /** type of RTT being sought; one of RTT_TYPE_ONE_SIDED
+ * RTT_TYPE_11_V or RTT_TYPE_11_MC or RTT_TYPE_UNSPECIFIED */
+ public int requestType;
+
+ /** mac address of the device being ranged */
+ public String bssid;
+
+ /** channel frequency that the device is on; optional */
+ public int frequency;
+
+ /** optional channel width. wider channels result in better accuracy,
+ * but they take longer time, and even get aborted may times; use
+ * RTT_CHANNEL_WIDTH_UNSPECIFIED if not specifying */
+ public int channelWidth;
+
+ /** number of samples to be taken */
+ public int num_samples;
+
+ /** number of retries if a sample fails */
+ public int num_retries;
+ }
+
+ /** specifies RTT results */
+ public static class RttResult {
+ /** mac address of the device being ranged */
+ public String bssid;
+
+ /** status of the request */
+ public int status;
+
+ /** timestamp of completion, in microsecond since boot */
+ public long ts;
+
+ /** average RSSI observed */
+ public int rssi;
+
+ /** RSSI spread (i.e. max - min) */
+ public int rssi_spread;
+
+ /** average transmit rate */
+ public int tx_rate;
+
+ /** average round trip time in nano second */
+ public long rtt_ns;
+
+ /** standard deviation observed in round trip time */
+ public long rtt_sd_ns;
+
+ /** spread (i.e. max - min) round trip time */
+ public long rtt_spread_ns;
+
+ /** average distance in centimeter, computed based on rtt_ns */
+ public long distance_cm;
+
+ /** standard deviation observed in distance */
+ public long distance_sd_cm;
+
+ /** spread (i.e. max - min) distance */
+ public long distance_spread_cm;
+ }
+
+ public static interface RttListener {
+ public void onSuccess(RttResult results[]);
+ public void onFailure(int reason, String description);
+ public void onAborted();
+ }
+
+ public void startRanging(RttParams params[], RttListener listener) {
+ validateChannel();
+ sAsyncChannel.sendMessage(CMD_OP_START_RANGING, 0, removeListener(listener), params);
+ }
+
+ public void stopRanging(RttListener listener) {
+ validateChannel();
+ sAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
+ }
+
+ /* private methods */
+ public static final int CMD_OP_START_RANGING = 0;
+ public static final int CMD_OP_STOP_RANGING = 1;
+ public static final int CMD_OP_FAILED = 2;
+ public static final int CMD_OP_SUCCEEDED = 3;
+ public static final int CMD_OP_ABORTED = 4;
+
+ private Context mContext;
+ private IRttManager mService;
+
+ private static final int INVALID_KEY = 0;
+ private static int sListenerKey = 1;
+
+ private static final SparseArray sListenerMap = new SparseArray();
+ private static final Object sListenerMapLock = new Object();
+
+ private static AsyncChannel sAsyncChannel;
+ private static CountDownLatch sConnected;
+
+ private static final Object sThreadRefLock = new Object();
+ private static int sThreadRefCount;
+ private static HandlerThread sHandlerThread;
+
+ /**
+ * 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_SERVICE Context.WIFI_SERVICE}.
+ * @param context the application context
+ * @param service the Binder interface
+ * @hide
+ */
+
+ public RttManager(Context context, IRttManager service) {
+ mContext = context;
+ mService = service;
+ init();
+ }
+
+ private void init() {
+ synchronized (sThreadRefLock) {
+ if (++sThreadRefCount == 1) {
+ Messenger messenger = null;
+ try {
+ messenger = mService.getMessenger();
+ } catch (RemoteException e) {
+ /* do nothing */
+ } catch (SecurityException e) {
+ /* do nothing */
+ }
+
+ if (messenger == null) {
+ sAsyncChannel = null;
+ return;
+ }
+
+ sHandlerThread = new HandlerThread("WifiScanner");
+ sAsyncChannel = new AsyncChannel();
+ sConnected = new CountDownLatch(1);
+
+ sHandlerThread.start();
+ Handler handler = new ServiceHandler(sHandlerThread.getLooper());
+ sAsyncChannel.connect(mContext, handler, messenger);
+ try {
+ sConnected.await();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "interrupted wait at init");
+ }
+ }
+ }
+ }
+
+ private void validateChannel() {
+ if (sAsyncChannel == null) throw new IllegalStateException(
+ "No permission to access and change wifi or a bad initialization");
+ }
+
+ private static int putListener(Object listener) {
+ if (listener == null) return INVALID_KEY;
+ int key;
+ synchronized (sListenerMapLock) {
+ do {
+ key = sListenerKey++;
+ } while (key == INVALID_KEY);
+ sListenerMap.put(key, listener);
+ }
+ return key;
+ }
+
+ private static Object getListener(int key) {
+ if (key == INVALID_KEY) return null;
+ synchronized (sListenerMapLock) {
+ Object listener = sListenerMap.get(key);
+ return listener;
+ }
+ }
+
+ private static int getListenerKey(Object listener) {
+ if (listener == null) return INVALID_KEY;
+ synchronized (sListenerMapLock) {
+ int index = sListenerMap.indexOfValue(listener);
+ if (index == -1) {
+ return INVALID_KEY;
+ } else {
+ return sListenerMap.keyAt(index);
+ }
+ }
+ }
+
+ private static Object removeListener(int key) {
+ if (key == INVALID_KEY) return null;
+ synchronized (sListenerMapLock) {
+ Object listener = sListenerMap.get(key);
+ sListenerMap.remove(key);
+ return listener;
+ }
+ }
+
+ private static int removeListener(Object listener) {
+ int key = getListenerKey(listener);
+ if (key == INVALID_KEY) return key;
+ synchronized (sListenerMapLock) {
+ sListenerMap.remove(key);
+ return key;
+ }
+ }
+
+ private static class ServiceHandler extends Handler {
+ ServiceHandler(Looper looper) {
+ super(looper);
+ }
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+ if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+ sAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+ } else {
+ Log.e(TAG, "Failed to set up channel connection");
+ // This will cause all further async API calls on the WifiManager
+ // to fail and throw an exception
+ sAsyncChannel = null;
+ }
+ sConnected.countDown();
+ return;
+ 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
+ sAsyncChannel = null;
+ getLooper().quit();
+ return;
+ }
+
+ Object listener = getListener(msg.arg2);
+ if (listener == null) {
+ if (DBG) Log.d(TAG, "invalid listener key = " + msg.arg2);
+ return;
+ } else {
+ if (DBG) Log.d(TAG, "listener key = " + msg.arg2);
+ }
+
+ switch (msg.what) {
+ /* ActionListeners grouped together */
+ case CMD_OP_SUCCEEDED :
+ ((RttListener) listener).onSuccess((RttResult[])msg.obj);
+ break;
+ case CMD_OP_FAILED :
+ ((RttListener) listener).onFailure(msg.arg1, (String)msg.obj);
+ removeListener(msg.arg2);
+ break;
+ case CMD_OP_ABORTED :
+ ((RttListener) listener).onAborted();
+ removeListener(msg.arg2);
+ break;
+ default:
+ if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
+ return;
+ }
+ }
+ }
+
+}
+