summaryrefslogtreecommitdiffstats
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
parent6d32e725233b2bd4b1e3c1c01707f8ca8b9835c9 (diff)
downloadframeworks_base-7686c061b7c5c981c79e566e3b31f68b9e21c730.zip
frameworks_base-7686c061b7c5c981c79e566e3b31f68b9e21c730.tar.gz
frameworks_base-7686c061b7c5c981c79e566e3b31f68b9e21c730.tar.bz2
Introduce RTT Manager
Change-Id: Ic9a16d587897b272f85cdb2b8c52b51bca060d18
-rw-r--r--Android.mk1
-rw-r--r--core/java/android/app/ContextImpl.java13
-rw-r--r--core/java/android/content/Context.java12
-rw-r--r--wifi/java/android/net/wifi/IRttManager.aidl27
-rw-r--r--wifi/java/android/net/wifi/RttManager.java334
-rw-r--r--wifi/java/android/net/wifi/WifiScanner.java8
6 files changed, 392 insertions, 3 deletions
diff --git a/Android.mk b/Android.mk
index e2fa7d1..9cda341 100644
--- a/Android.mk
+++ b/Android.mk
@@ -368,6 +368,7 @@ LOCAL_SRC_FILES += \
wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl \
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
wifi/java/android/net/wifi/IWifiScanner.aidl \
+ wifi/java/android/net/wifi/IRttManager.aidl \
packages/services/PacProcessor/com/android/net/IProxyService.aidl \
packages/services/Proxy/com/android/net/IProxyCallback.aidl \
packages/services/Proxy/com/android/net/IProxyPortListener.aidl \
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e274f09..d7c384a 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -16,8 +16,6 @@
package android.app;
-import android.net.wifi.IWifiScanner;
-import android.net.wifi.WifiScanner;
import android.os.Build;
import android.service.persistentdata.IPersistentDataBlockService;
@@ -93,6 +91,10 @@ import android.net.wifi.passpoint.IWifiPasspointManager;
import android.net.wifi.passpoint.WifiPasspointManager;
import android.net.wifi.p2p.IWifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.IWifiScanner;
+import android.net.wifi.WifiScanner;
+import android.net.wifi.IRttManager;
+import android.net.wifi.RttManager;
import android.nfc.NfcManager;
import android.os.BatteryManager;
import android.os.Binder;
@@ -622,6 +624,13 @@ class ContextImpl extends Context {
return new WifiScanner(ctx.getOuterContext(), service);
}});
+ registerService(WIFI_RTT_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(WIFI_RTT_SERVICE);
+ IRttManager service = IRttManager.Stub.asInterface(b);
+ return new RttManager(ctx.getOuterContext(), service);
+ }});
+
registerService(ETHERNET_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(ETHERNET_SERVICE);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 1569b9f..7d15233 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2067,6 +2067,7 @@ public abstract class Context {
WIFI_P2P_SERVICE,
WIFI_SCANNING_SERVICE,
//@hide: ETHERNET_SERVICE,
+ WIFI_RTT_SERVICE,
NSD_SERVICE,
AUDIO_SERVICE,
MEDIA_ROUTER_SERVICE,
@@ -2463,6 +2464,17 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a {@link
+ * android.net.wifi.RttManager} for ranging devices with wifi
+ *
+ * @see #getSystemService
+ * @see android.net.wifi.RttManager
+ * @hide
+ */
+ @SystemApi
+ public static final String WIFI_RTT_SERVICE = "rttmanager";
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a {@link
* android.net.ethernet.EthernetManager} for handling management of
* Ethernet access.
*
diff --git a/wifi/java/android/net/wifi/IRttManager.aidl b/wifi/java/android/net/wifi/IRttManager.aidl
new file mode 100644
index 0000000..d929f55
--- /dev/null
+++ b/wifi/java/android/net/wifi/IRttManager.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2008 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.Messenger;
+
+/**
+ * {@hide}
+ */
+interface IRttManager
+{
+ Messenger getMessenger();
+}
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;
+ }
+ }
+ }
+
+}
+
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index f3294bb..4cdbc44 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -771,7 +771,13 @@ public class WifiScanner {
}
Object listener = getListener(msg.arg2);
- if (DBG) Log.d(TAG, "listener key = " + 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 */