Merge "Use ConnectivityThread for RttManager." into nyc-dev

This commit is contained in:
Wei Wang
2016-04-18 21:17:24 +00:00
committed by Android (Google) Code Review
2 changed files with 62 additions and 96 deletions

View File

@@ -542,7 +542,8 @@ final class SystemServiceRegistry {
public RttManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.WIFI_RTT_SERVICE);
IRttManager service = IRttManager.Stub.asInterface(b);
return new RttManager(ctx.getOuterContext(), service);
return new RttManager(ctx.getOuterContext(), service,
ConnectivityThread.getInstanceLooper());
}});
registerService(Context.ETHERNET_SERVICE, EthernetManager.class,

View File

@@ -5,7 +5,6 @@ import android.annotation.SystemApi;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
@@ -19,8 +18,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import java.util.concurrent.CountDownLatch;
/** @hide */
@SystemApi
public class RttManager {
@@ -311,7 +308,7 @@ public class RttManager {
}
public RttCapabilities getRttCapabilities() {
synchronized (sCapabilitiesLock) {
synchronized (mCapabilitiesLock) {
if (mRttCapabilities == null) {
try {
mRttCapabilities = mService.getRttCapabilities();
@@ -932,13 +929,13 @@ public class RttManager {
validateChannel();
ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
Log.i(TAG, "Send RTT request to RTT Service");
sAsyncChannel.sendMessage(CMD_OP_START_RANGING,
mAsyncChannel.sendMessage(CMD_OP_START_RANGING,
0, putListener(listener), parcelableParams);
}
public void stopRanging(RttListener listener) {
validateChannel();
sAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
mAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
}
/**
@@ -975,7 +972,7 @@ public class RttManager {
}
validateChannel();
int key = putListenerIfAbsent(callback);
sAsyncChannel.sendMessage(CMD_OP_ENABLE_RESPONDER, 0, key);
mAsyncChannel.sendMessage(CMD_OP_ENABLE_RESPONDER, 0, key);
}
/**
@@ -998,7 +995,7 @@ public class RttManager {
Log.e(TAG, "responder not enabled yet");
return;
}
sAsyncChannel.sendMessage(CMD_OP_DISABLE_RESPONDER, 0, key);
mAsyncChannel.sendMessage(CMD_OP_DISABLE_RESPONDER, 0, key);
}
/**
@@ -1110,23 +1107,17 @@ public class RttManager {
public static final int
CMD_OP_ENALBE_RESPONDER_FAILED = BASE + 8;
private Context mContext;
private IRttManager mService;
private RttCapabilities mRttCapabilities;
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 final Object sCapabilitiesLock = new Object();
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 static AsyncChannel sAsyncChannel;
private static CountDownLatch sConnected;
private static final Object sThreadRefLock = new Object();
private static int sThreadRefCount;
private static HandlerThread sHandlerThread;
private RttCapabilities mRttCapabilities;
private int mListenerKey = 1;
private AsyncChannel mAsyncChannel;
/**
* Create a new WifiScanner instance.
@@ -1135,122 +1126,107 @@ public class RttManager {
* 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.
*
* @hide
*/
public RttManager(Context context, IRttManager service) {
public RttManager(Context context, IRttManager service, Looper looper) {
mContext = context;
mService = service;
init();
}
private void init() {
synchronized (sThreadRefLock) {
if (++sThreadRefCount == 1) {
Messenger messenger = null;
try {
Log.d(TAG, "Get the messenger from " + mService);
messenger = mService.getMessenger();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (SecurityException e) {
/* do nothing */
}
if (messenger == null) {
sAsyncChannel = null;
return;
}
sHandlerThread = new HandlerThread("RttManager");
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");
}
}
Messenger messenger = null;
try {
Log.d(TAG, "Get the messenger from " + mService);
messenger = mService.getMessenger();
} 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);
}
private void validateChannel() {
if (sAsyncChannel == null) throw new IllegalStateException(
if (mAsyncChannel == null) throw new IllegalStateException(
"No permission to access and change wifi or a bad initialization");
}
private static int putListener(Object listener) {
private int putListener(Object listener) {
if (listener == null) return INVALID_KEY;
int key;
synchronized (sListenerMapLock) {
synchronized (mListenerMapLock) {
do {
key = sListenerKey++;
key = mListenerKey++;
} while (key == INVALID_KEY);
sListenerMap.put(key, listener);
mListenerMap.put(key, listener);
}
return key;
}
// Insert a listener if it doesn't exist in sListenerMap. Returns the key of the listener.
private static int putListenerIfAbsent(Object listener) {
// 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 (sListenerMapLock) {
synchronized (mListenerMapLock) {
int key = getListenerKey(listener);
if (key != INVALID_KEY) {
return key;
}
do {
key = sListenerKey++;
key = mListenerKey++;
} while (key == INVALID_KEY);
sListenerMap.put(key, listener);
mListenerMap.put(key, listener);
return key;
}
}
private static Object getListener(int key) {
private Object getListener(int key) {
if (key == INVALID_KEY) return null;
synchronized (sListenerMapLock) {
Object listener = sListenerMap.get(key);
synchronized (mListenerMapLock) {
Object listener = mListenerMap.get(key);
return listener;
}
}
private static int getListenerKey(Object listener) {
private int getListenerKey(Object listener) {
if (listener == null) return INVALID_KEY;
synchronized (sListenerMapLock) {
int index = sListenerMap.indexOfValue(listener);
synchronized (mListenerMapLock) {
int index = mListenerMap.indexOfValue(listener);
if (index == -1) {
return INVALID_KEY;
} else {
return sListenerMap.keyAt(index);
return mListenerMap.keyAt(index);
}
}
}
private static Object removeListener(int key) {
private Object removeListener(int key) {
if (key == INVALID_KEY) return null;
synchronized (sListenerMapLock) {
Object listener = sListenerMap.get(key);
sListenerMap.remove(key);
synchronized (mListenerMapLock) {
Object listener = mListenerMap.get(key);
mListenerMap.remove(key);
return listener;
}
}
private static int removeListener(Object listener) {
private int removeListener(Object listener) {
int key = getListenerKey(listener);
if (key == INVALID_KEY) return key;
synchronized (sListenerMapLock) {
sListenerMap.remove(key);
synchronized (mListenerMapLock) {
mListenerMap.remove(key);
return key;
}
}
private static class ServiceHandler extends Handler {
private class ServiceHandler extends Handler {
ServiceHandler(Looper looper) {
super(looper);
}
@@ -1258,24 +1234,13 @@ public class RttManager {
public void handleMessage(Message msg) {
Log.i(TAG, "RTT manager get message: " + msg.what);
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;
}
return;
case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
sConnected.countDown();
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;
mAsyncChannel = null;
getLooper().quit();
return;
}