am ff5ceb0d: am 0b4d73dd: Merge "Introduce RTT Manager" into lmp-dev
* commit 'ff5ceb0d89c549682b498522f052d61c776bff03': Introduce RTT Manager
This commit is contained in:
@@ -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 \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
@@ -2461,6 +2462,17 @@ public abstract class Context {
|
||||
@SystemApi
|
||||
public static final String WIFI_SCANNING_SERVICE = "wifiscanner";
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
27
wifi/java/android/net/wifi/IRttManager.aidl
Normal file
27
wifi/java/android/net/wifi/IRttManager.aidl
Normal file
@@ -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();
|
||||
}
|
||||
334
wifi/java/android/net/wifi/RttManager.java
Normal file
334
wifi/java/android/net/wifi/RttManager.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user