Merge "Merge "Move some NetworkStats tests to tests/net." into oc-dev am: 74fe2cbc3a -s ours am: ea28d269ea -s ours"

This commit is contained in:
Android Build Merger (Role)
2017-05-09 06:49:20 +00:00
committed by Android (Google) Code Review
2 changed files with 142 additions and 103 deletions

View File

@@ -16,10 +16,6 @@
package android.net.nsd; package android.net.nsd;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkStringNotEmpty;
import android.annotation.SdkConstant; import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context; import android.content.Context;
@@ -245,12 +241,12 @@ public final class NsdManager {
return name; return name;
} }
private static int FIRST_LISTENER_KEY = 1;
private final INsdManager mService; private final INsdManager mService;
private final Context mContext; private final Context mContext;
private int mListenerKey = FIRST_LISTENER_KEY; private static final int INVALID_LISTENER_KEY = 0;
private static final int BUSY_LISTENER_KEY = -1;
private int mListenerKey = 1;
private final SparseArray mListenerMap = new SparseArray(); private final SparseArray mListenerMap = new SparseArray();
private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<>(); private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<>();
private final Object mMapLock = new Object(); private final Object mMapLock = new Object();
@@ -273,14 +269,6 @@ public final class NsdManager {
init(); init();
} }
/**
* @hide
*/
@VisibleForTesting
public void disconnect() {
mAsyncChannel.disconnect();
}
/** /**
* Failures are passed with {@link RegistrationListener#onRegistrationFailed}, * Failures are passed with {@link RegistrationListener#onRegistrationFailed},
* {@link RegistrationListener#onUnregistrationFailed}, * {@link RegistrationListener#onUnregistrationFailed},
@@ -316,6 +304,7 @@ public final class NsdManager {
public void onServiceFound(NsdServiceInfo serviceInfo); public void onServiceFound(NsdServiceInfo serviceInfo);
public void onServiceLost(NsdServiceInfo serviceInfo); public void onServiceLost(NsdServiceInfo serviceInfo);
} }
/** Interface for callback invocation for service registration */ /** Interface for callback invocation for service registration */
@@ -346,9 +335,8 @@ public final class NsdManager {
@Override @Override
public void handleMessage(Message message) { public void handleMessage(Message message) {
final int what = message.what; if (DBG) Log.d(TAG, "received " + nameOf(message.what));
final int key = message.arg2; switch (message.what) {
switch (what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
return; return;
@@ -361,26 +349,19 @@ public final class NsdManager {
default: default:
break; break;
} }
final Object listener; Object listener = getListener(message.arg2);
final NsdServiceInfo ns;
synchronized (mMapLock) {
listener = mListenerMap.get(key);
ns = mServiceMap.get(key);
}
if (listener == null) { if (listener == null) {
Log.d(TAG, "Stale key " + message.arg2); Log.d(TAG, "Stale key " + message.arg2);
return; return;
} }
if (DBG) { NsdServiceInfo ns = getNsdService(message.arg2);
Log.d(TAG, "received " + nameOf(what) + " for key " + key + ", service " + ns); switch (message.what) {
}
switch (what) {
case DISCOVER_SERVICES_STARTED: case DISCOVER_SERVICES_STARTED:
String s = getNsdServiceInfoType((NsdServiceInfo) message.obj); String s = getNsdServiceInfoType((NsdServiceInfo) message.obj);
((DiscoveryListener) listener).onDiscoveryStarted(s); ((DiscoveryListener) listener).onDiscoveryStarted(s);
break; break;
case DISCOVER_SERVICES_FAILED: case DISCOVER_SERVICES_FAILED:
removeListener(key); removeListener(message.arg2);
((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns), ((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns),
message.arg1); message.arg1);
break; break;
@@ -393,16 +374,16 @@ public final class NsdManager {
case STOP_DISCOVERY_FAILED: case STOP_DISCOVERY_FAILED:
// TODO: failure to stop discovery should be internal and retried internally, as // TODO: failure to stop discovery should be internal and retried internally, as
// the effect for the client is indistinguishable from STOP_DISCOVERY_SUCCEEDED // the effect for the client is indistinguishable from STOP_DISCOVERY_SUCCEEDED
removeListener(key); removeListener(message.arg2);
((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns), ((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns),
message.arg1); message.arg1);
break; break;
case STOP_DISCOVERY_SUCCEEDED: case STOP_DISCOVERY_SUCCEEDED:
removeListener(key); removeListener(message.arg2);
((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns)); ((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns));
break; break;
case REGISTER_SERVICE_FAILED: case REGISTER_SERVICE_FAILED:
removeListener(key); removeListener(message.arg2);
((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1); ((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1);
break; break;
case REGISTER_SERVICE_SUCCEEDED: case REGISTER_SERVICE_SUCCEEDED:
@@ -410,7 +391,7 @@ public final class NsdManager {
(NsdServiceInfo) message.obj); (NsdServiceInfo) message.obj);
break; break;
case UNREGISTER_SERVICE_FAILED: case UNREGISTER_SERVICE_FAILED:
removeListener(key); removeListener(message.arg2);
((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1); ((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1);
break; break;
case UNREGISTER_SERVICE_SUCCEEDED: case UNREGISTER_SERVICE_SUCCEEDED:
@@ -420,11 +401,11 @@ public final class NsdManager {
((RegistrationListener) listener).onServiceUnregistered(ns); ((RegistrationListener) listener).onServiceUnregistered(ns);
break; break;
case RESOLVE_SERVICE_FAILED: case RESOLVE_SERVICE_FAILED:
removeListener(key); removeListener(message.arg2);
((ResolveListener) listener).onResolveFailed(ns, message.arg1); ((ResolveListener) listener).onResolveFailed(ns, message.arg1);
break; break;
case RESOLVE_SERVICE_SUCCEEDED: case RESOLVE_SERVICE_SUCCEEDED:
removeListener(key); removeListener(message.arg2);
((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj); ((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj);
break; break;
default: default:
@@ -434,27 +415,40 @@ public final class NsdManager {
} }
} }
private int nextListenerKey() { // if the listener is already in the map, reject it. Otherwise, add it and
// Ensure mListenerKey >= FIRST_LISTENER_KEY; // return its key.
mListenerKey = Math.max(FIRST_LISTENER_KEY, mListenerKey + 1);
return mListenerKey;
}
// Assert that the listener is not in the map, then add it and returns its key
private int putListener(Object listener, NsdServiceInfo s) { private int putListener(Object listener, NsdServiceInfo s) {
checkListener(listener); if (listener == null) return INVALID_LISTENER_KEY;
final int key; int key;
synchronized (mMapLock) { synchronized (mMapLock) {
int valueIndex = mListenerMap.indexOfValue(listener); int valueIndex = mListenerMap.indexOfValue(listener);
checkArgument(valueIndex == -1, "listener already in use"); if (valueIndex != -1) {
key = nextListenerKey(); return BUSY_LISTENER_KEY;
}
do {
key = mListenerKey++;
} while (key == INVALID_LISTENER_KEY);
mListenerMap.put(key, listener); mListenerMap.put(key, listener);
mServiceMap.put(key, s); mServiceMap.put(key, s);
} }
return key; return key;
} }
private Object getListener(int key) {
if (key == INVALID_LISTENER_KEY) return null;
synchronized (mMapLock) {
return mListenerMap.get(key);
}
}
private NsdServiceInfo getNsdService(int key) {
synchronized (mMapLock) {
return mServiceMap.get(key);
}
}
private void removeListener(int key) { private void removeListener(int key) {
if (key == INVALID_LISTENER_KEY) return;
synchronized (mMapLock) { synchronized (mMapLock) {
mListenerMap.remove(key); mListenerMap.remove(key);
mServiceMap.remove(key); mServiceMap.remove(key);
@@ -462,15 +456,16 @@ public final class NsdManager {
} }
private int getListenerKey(Object listener) { private int getListenerKey(Object listener) {
checkListener(listener);
synchronized (mMapLock) { synchronized (mMapLock) {
int valueIndex = mListenerMap.indexOfValue(listener); int valueIndex = mListenerMap.indexOfValue(listener);
checkArgument(valueIndex != -1, "listener not registered"); if (valueIndex != -1) {
return mListenerMap.keyAt(valueIndex); return mListenerMap.keyAt(valueIndex);
}
} }
return INVALID_LISTENER_KEY;
} }
private static String getNsdServiceInfoType(NsdServiceInfo s) { private String getNsdServiceInfoType(NsdServiceInfo s) {
if (s == null) return "?"; if (s == null) return "?";
return s.getServiceType(); return s.getServiceType();
} }
@@ -480,9 +475,7 @@ public final class NsdManager {
*/ */
private void init() { private void init() {
final Messenger messenger = getMessenger(); final Messenger messenger = getMessenger();
if (messenger == null) { if (messenger == null) throw new RuntimeException("Failed to initialize");
fatal("Failed to obtain service Messenger");
}
HandlerThread t = new HandlerThread("NsdManager"); HandlerThread t = new HandlerThread("NsdManager");
t.start(); t.start();
mHandler = new ServiceHandler(t.getLooper()); mHandler = new ServiceHandler(t.getLooper());
@@ -490,15 +483,10 @@ public final class NsdManager {
try { try {
mConnected.await(); mConnected.await();
} catch (InterruptedException e) { } catch (InterruptedException e) {
fatal("Interrupted wait at init"); Log.e(TAG, "interrupted wait at init");
} }
} }
private static void fatal(String msg) {
Log.e(TAG, msg);
throw new RuntimeException(msg);
}
/** /**
* Register a service to be discovered by other services. * Register a service to be discovered by other services.
* *
@@ -518,10 +506,23 @@ public final class NsdManager {
*/ */
public void registerService(NsdServiceInfo serviceInfo, int protocolType, public void registerService(NsdServiceInfo serviceInfo, int protocolType,
RegistrationListener listener) { RegistrationListener listener) {
checkArgument(serviceInfo.getPort() > 0, "Invalid port number"); if (TextUtils.isEmpty(serviceInfo.getServiceName()) ||
checkServiceInfo(serviceInfo); TextUtils.isEmpty(serviceInfo.getServiceType())) {
checkProtocol(protocolType); throw new IllegalArgumentException("Service name or type cannot be empty");
}
if (serviceInfo.getPort() <= 0) {
throw new IllegalArgumentException("Invalid port number");
}
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}
if (protocolType != PROTOCOL_DNS_SD) {
throw new IllegalArgumentException("Unsupported protocol");
}
int key = putListener(listener, serviceInfo); int key = putListener(listener, serviceInfo);
if (key == BUSY_LISTENER_KEY) {
throw new IllegalArgumentException("listener already in use");
}
mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, key, serviceInfo); mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, key, serviceInfo);
} }
@@ -540,6 +541,12 @@ public final class NsdManager {
*/ */
public void unregisterService(RegistrationListener listener) { public void unregisterService(RegistrationListener listener) {
int id = getListenerKey(listener); int id = getListenerKey(listener);
if (id == INVALID_LISTENER_KEY) {
throw new IllegalArgumentException("listener not registered");
}
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}
mAsyncChannel.sendMessage(UNREGISTER_SERVICE, 0, id); mAsyncChannel.sendMessage(UNREGISTER_SERVICE, 0, id);
} }
@@ -572,13 +579,25 @@ public final class NsdManager {
* Cannot be null. Cannot be in use for an active service discovery. * Cannot be null. Cannot be in use for an active service discovery.
*/ */
public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
checkStringNotEmpty(serviceType, "Service type cannot be empty"); if (listener == null) {
checkProtocol(protocolType); throw new IllegalArgumentException("listener cannot be null");
}
if (TextUtils.isEmpty(serviceType)) {
throw new IllegalArgumentException("Service type cannot be empty");
}
if (protocolType != PROTOCOL_DNS_SD) {
throw new IllegalArgumentException("Unsupported protocol");
}
NsdServiceInfo s = new NsdServiceInfo(); NsdServiceInfo s = new NsdServiceInfo();
s.setServiceType(serviceType); s.setServiceType(serviceType);
int key = putListener(listener, s); int key = putListener(listener, s);
if (key == BUSY_LISTENER_KEY) {
throw new IllegalArgumentException("listener already in use");
}
mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, key, s); mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, key, s);
} }
@@ -600,6 +619,12 @@ public final class NsdManager {
*/ */
public void stopServiceDiscovery(DiscoveryListener listener) { public void stopServiceDiscovery(DiscoveryListener listener) {
int id = getListenerKey(listener); int id = getListenerKey(listener);
if (id == INVALID_LISTENER_KEY) {
throw new IllegalArgumentException("service discovery not active on listener");
}
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}
mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, id); mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, id);
} }
@@ -613,8 +638,19 @@ public final class NsdManager {
* Cannot be in use for an active service resolution. * Cannot be in use for an active service resolution.
*/ */
public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) { public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) {
checkServiceInfo(serviceInfo); if (TextUtils.isEmpty(serviceInfo.getServiceName()) ||
TextUtils.isEmpty(serviceInfo.getServiceType())) {
throw new IllegalArgumentException("Service name or type cannot be empty");
}
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}
int key = putListener(listener, serviceInfo); int key = putListener(listener, serviceInfo);
if (key == BUSY_LISTENER_KEY) {
throw new IllegalArgumentException("listener already in use");
}
mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, key, serviceInfo); mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, key, serviceInfo);
} }
@@ -628,10 +664,10 @@ public final class NsdManager {
} }
/** /**
* Get a reference to NsdService handler. This is used to establish * Get a reference to NetworkService handler. This is used to establish
* an AsyncChannel communication with the service * an AsyncChannel communication with the service
* *
* @return Messenger pointing to the NsdService handler * @return Messenger pointing to the NetworkService handler
*/ */
private Messenger getMessenger() { private Messenger getMessenger() {
try { try {
@@ -640,18 +676,4 @@ public final class NsdManager {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
} }
private static void checkListener(Object listener) {
checkNotNull(listener, "listener cannot be null");
}
private static void checkProtocol(int protocolType) {
checkArgument(protocolType == PROTOCOL_DNS_SD, "Unsupported protocol");
}
private static void checkServiceInfo(NsdServiceInfo serviceInfo) {
checkNotNull(serviceInfo, "NsdServiceInfo cannot be null");
checkStringNotEmpty(serviceInfo.getServiceName(),"Service name cannot be empty");
checkStringNotEmpty(serviceInfo.getServiceType(), "Service type cannot be empty");
}
} }

View File

@@ -35,7 +35,6 @@ import android.provider.Settings;
import android.util.Base64; import android.util.Base64;
import android.util.Slog; import android.util.Slog;
import android.util.SparseArray; import android.util.SparseArray;
import android.util.SparseIntArray;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -50,6 +49,7 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.Protocol; import com.android.internal.util.Protocol;
import com.android.internal.util.State; import com.android.internal.util.State;
import com.android.internal.util.StateMachine; import com.android.internal.util.StateMachine;
import com.android.server.NativeDaemonConnector.Command;
/** /**
* Network Service Discovery Service handles remote service discovery operation requests by * Network Service Discovery Service handles remote service discovery operation requests by
@@ -162,7 +162,7 @@ public class NsdService extends INsdManager.Stub {
} }
//Last client //Last client
if (mClients.size() == 0) { if (mClients.size() == 0) {
mDaemon.stop(); stopMDnsDaemon();
} }
break; break;
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
@@ -222,14 +222,14 @@ public class NsdService extends INsdManager.Stub {
public void enter() { public void enter() {
sendNsdStateChangeBroadcast(true); sendNsdStateChangeBroadcast(true);
if (mClients.size() > 0) { if (mClients.size() > 0) {
mDaemon.start(); startMDnsDaemon();
} }
} }
@Override @Override
public void exit() { public void exit() {
if (mClients.size() > 0) { if (mClients.size() > 0) {
mDaemon.stop(); stopMDnsDaemon();
} }
} }
@@ -248,8 +248,8 @@ public class NsdService extends INsdManager.Stub {
} }
private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
clientInfo.mClientIds.delete(clientId); clientInfo.mClientIds.remove(clientId);
clientInfo.mClientRequests.delete(clientId); clientInfo.mClientRequests.remove(clientId);
mIdToClientInfoMap.remove(globalId); mIdToClientInfoMap.remove(globalId);
} }
@@ -263,7 +263,7 @@ public class NsdService extends INsdManager.Stub {
//First client //First client
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL && if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL &&
mClients.size() == 0) { mClients.size() == 0) {
mDaemon.start(); startMDnsDaemon();
} }
return NOT_HANDLED; return NOT_HANDLED;
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
@@ -302,7 +302,7 @@ public class NsdService extends INsdManager.Stub {
clientInfo = mClients.get(msg.replyTo); clientInfo = mClients.get(msg.replyTo);
try { try {
id = clientInfo.mClientIds.get(msg.arg2); id = clientInfo.mClientIds.get(msg.arg2).intValue();
} catch (NullPointerException e) { } catch (NullPointerException e) {
replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
NsdManager.FAILURE_INTERNAL_ERROR); NsdManager.FAILURE_INTERNAL_ERROR);
@@ -340,7 +340,7 @@ public class NsdService extends INsdManager.Stub {
if (DBG) Slog.d(TAG, "unregister service"); if (DBG) Slog.d(TAG, "unregister service");
clientInfo = mClients.get(msg.replyTo); clientInfo = mClients.get(msg.replyTo);
try { try {
id = clientInfo.mClientIds.get(msg.arg2); id = clientInfo.mClientIds.get(msg.arg2).intValue();
} catch (NullPointerException e) { } catch (NullPointerException e) {
replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
NsdManager.FAILURE_INTERNAL_ERROR); NsdManager.FAILURE_INTERNAL_ERROR);
@@ -713,13 +713,26 @@ public class NsdService extends INsdManager.Stub {
return true; return true;
} }
public void start() { public boolean execute(Command cmd) {
execute("start-service"); if (DBG) {
Slog.d(TAG, cmd.toString());
}
try {
mNativeConnector.execute(cmd);
} catch (NativeDaemonConnectorException e) {
Slog.e(TAG, "Failed to execute " + cmd, e);
return false;
}
return true;
} }
}
public void stop() { private boolean startMDnsDaemon() {
execute("stop-service"); return mDaemon.execute("start-service");
} }
private boolean stopMDnsDaemon() {
return mDaemon.execute("stop-service");
} }
private boolean registerService(int regId, NsdServiceInfo service) { private boolean registerService(int regId, NsdServiceInfo service) {
@@ -731,7 +744,8 @@ public class NsdService extends INsdManager.Stub {
int port = service.getPort(); int port = service.getPort();
byte[] textRecord = service.getTxtRecord(); byte[] textRecord = service.getTxtRecord();
String record = Base64.encodeToString(textRecord, Base64.DEFAULT).replace("\n", ""); String record = Base64.encodeToString(textRecord, Base64.DEFAULT).replace("\n", "");
return mDaemon.execute("register", regId, name, type, port, record); Command cmd = new Command("mdnssd", "register", regId, name, type, port, record);
return mDaemon.execute(cmd);
} }
private boolean unregisterService(int regId) { private boolean unregisterService(int regId) {
@@ -824,10 +838,10 @@ public class NsdService extends INsdManager.Stub {
private NsdServiceInfo mResolvedService; private NsdServiceInfo mResolvedService;
/* A map from client id to unique id sent to mDns */ /* A map from client id to unique id sent to mDns */
private final SparseIntArray mClientIds = new SparseIntArray(); private final SparseArray<Integer> mClientIds = new SparseArray<>();
/* A map from client id to the type of the request we had received */ /* A map from client id to the type of the request we had received */
private final SparseIntArray mClientRequests = new SparseIntArray(); private final SparseArray<Integer> mClientRequests = new SparseArray<>();
private ClientInfo(AsyncChannel c, Messenger m) { private ClientInfo(AsyncChannel c, Messenger m) {
mChannel = c; mChannel = c;
@@ -854,7 +868,6 @@ public class NsdService extends INsdManager.Stub {
// and send cancellations to the daemon. // and send cancellations to the daemon.
private void expungeAllRequests() { private void expungeAllRequests() {
int globalId, clientId, i; int globalId, clientId, i;
// TODO: to keep handler responsive, do not clean all requests for that client at once.
for (i = 0; i < mClientIds.size(); i++) { for (i = 0; i < mClientIds.size(); i++) {
clientId = mClientIds.keyAt(i); clientId = mClientIds.keyAt(i);
globalId = mClientIds.valueAt(i); globalId = mClientIds.valueAt(i);
@@ -882,11 +895,15 @@ public class NsdService extends INsdManager.Stub {
// mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id, // mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id,
// return the corresponding listener id. mDnsClient id is also called a global id. // return the corresponding listener id. mDnsClient id is also called a global id.
private int getClientId(final int globalId) { private int getClientId(final int globalId) {
int idx = mClientIds.indexOfValue(globalId); // This doesn't use mClientIds.indexOfValue because indexOfValue uses == (not .equals)
if (idx < 0) { // while also coercing the int primitives to Integer objects.
return idx; for (int i = 0, nSize = mClientIds.size(); i < nSize; i++) {
int mDnsId = mClientIds.valueAt(i);
if (globalId == mDnsId) {
return mClientIds.keyAt(i);
}
} }
return mClientIds.keyAt(idx); return -1;
} }
} }