diff options
Diffstat (limited to 'services/java/com')
5 files changed, 335 insertions, 232 deletions
diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java index f33bf8b..cc8e6a4 100644 --- a/services/java/com/android/server/NsdService.java +++ b/services/java/com/android/server/NsdService.java @@ -20,7 +20,7 @@ import android.content.Context; import android.content.ContentResolver; import android.content.Intent; import android.content.pm.PackageManager; -import android.net.nsd.DnsSdServiceInfo; +import android.net.nsd.NsdServiceInfo; import android.net.nsd.DnsSdTxtRecord; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; @@ -32,6 +32,7 @@ import android.os.Messenger; import android.os.IBinder; import android.provider.Settings; import android.util.Slog; +import android.util.SparseArray; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -72,13 +73,16 @@ public class NsdService extends INsdManager.Stub { */ private HashMap<Messenger, ClientInfo> mClients = new HashMap<Messenger, ClientInfo>(); + /* A map from unique id to client info */ + private SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<ClientInfo>(); + private AsyncChannel mReplyChannel = new AsyncChannel(); private int INVALID_ID = 0; private int mUniqueId = 1; private static final int BASE = Protocol.BASE_NSD_MANAGER; - private static final int CMD_TO_STRING_COUNT = NsdManager.STOP_RESOLVE - BASE + 1; + private static final int CMD_TO_STRING_COUNT = NsdManager.RESOLVE_SERVICE - BASE + 1; private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT]; static { @@ -87,7 +91,6 @@ public class NsdService extends INsdManager.Stub { sCmdToString[NsdManager.REGISTER_SERVICE - BASE] = "REGISTER"; sCmdToString[NsdManager.UNREGISTER_SERVICE - BASE] = "UNREGISTER"; sCmdToString[NsdManager.RESOLVE_SERVICE - BASE] = "RESOLVE"; - sCmdToString[NsdManager.STOP_RESOLVE - BASE] = "STOP-RESOLVE"; } private static String cmdToString(int cmd) { @@ -101,9 +104,9 @@ public class NsdService extends INsdManager.Stub { private class NsdStateMachine extends StateMachine { - private DefaultState mDefaultState = new DefaultState(); - private DisabledState mDisabledState = new DisabledState(); - private EnabledState mEnabledState = new EnabledState(); + private final DefaultState mDefaultState = new DefaultState(); + private final DisabledState mDisabledState = new DisabledState(); + private final EnabledState mEnabledState = new EnabledState(); @Override protected String getMessageInfo(Message msg) { @@ -151,29 +154,26 @@ public class NsdService extends INsdManager.Stub { ac.connect(mContext, getHandler(), msg.replyTo); break; case NsdManager.DISCOVER_SERVICES: - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.BUSY); + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.STOP_DISCOVERY: - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.REGISTER_SERVICE: - mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.UNREGISTER_SERVICE: - mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; case NsdManager.RESOLVE_SERVICE: - mReplyChannel.replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - break; - case NsdManager.STOP_RESOLVE: - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; + case NsdManager.NATIVE_DAEMON_EVENT: default: Slog.e(TAG, "Unhandled " + msg); return NOT_HANDLED; @@ -217,11 +217,30 @@ public class NsdService extends INsdManager.Stub { } } + private boolean requestLimitReached(ClientInfo clientInfo) { + if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) { + if (DBG) Slog.d(TAG, "Exceeded max outstanding requests " + clientInfo); + return true; + } + return false; + } + + private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { + clientInfo.mClientIds.put(clientId, globalId); + mIdToClientInfoMap.put(globalId, clientInfo); + } + + private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { + clientInfo.mClientIds.remove(clientId); + mIdToClientInfoMap.remove(globalId); + } + @Override public boolean processMessage(Message msg) { ClientInfo clientInfo; - DnsSdServiceInfo servInfo; + NsdServiceInfo servInfo; boolean result = HANDLED; + int id; switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: //First client @@ -244,111 +263,112 @@ public class NsdService extends INsdManager.Stub { break; case NsdManager.DISCOVER_SERVICES: if (DBG) Slog.d(TAG, "Discover services"); - servInfo = (DnsSdServiceInfo) msg.obj; + servInfo = (NsdServiceInfo) msg.obj; clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mDiscoveryId != INVALID_ID) { - //discovery already in progress - if (DBG) Slog.d(TAG, "discovery in progress"); - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.ALREADY_ACTIVE); + + if (requestLimitReached(clientInfo)) { + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_MAX_LIMIT); break; } - clientInfo.mDiscoveryId = getUniqueId(); - if (discoverServices(clientInfo.mDiscoveryId, servInfo.getServiceType())) { - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED); + + id = getUniqueId(); + if (discoverServices(id, servInfo.getServiceType())) { + if (DBG) { + Slog.d(TAG, "Discover " + msg.arg2 + " " + id + + servInfo.getServiceType()); + } + storeRequestMap(msg.arg2, id, clientInfo); + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo); } else { - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.ERROR); - clientInfo.mDiscoveryId = INVALID_ID; + stopServiceDiscovery(id); + replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.STOP_DISCOVERY: if (DBG) Slog.d(TAG, "Stop service discovery"); clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mDiscoveryId == INVALID_ID) { - //already stopped - if (DBG) Slog.d(TAG, "discovery already stopped"); - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.ALREADY_ACTIVE); + + try { + id = clientInfo.mClientIds.get(msg.arg2).intValue(); + } catch (NullPointerException e) { + replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); break; } - if (stopServiceDiscovery(clientInfo.mDiscoveryId)) { - clientInfo.mDiscoveryId = INVALID_ID; - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED); + removeRequestMap(msg.arg2, id, clientInfo); + if (stopServiceDiscovery(id)) { + replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED); } else { - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.REGISTER_SERVICE: if (DBG) Slog.d(TAG, "Register service"); clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mRegisteredIds.size() >= ClientInfo.MAX_REG) { - if (DBG) Slog.d(TAG, "register service exceeds limit"); - mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.MAX_REGS_REACHED); + if (requestLimitReached(clientInfo)) { + replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_MAX_LIMIT); + break; } - int id = getUniqueId(); - if (registerService(id, (DnsSdServiceInfo) msg.obj)) { - clientInfo.mRegisteredIds.add(id); + id = getUniqueId(); + if (registerService(id, (NsdServiceInfo) msg.obj)) { + if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id); + storeRequestMap(msg.arg2, id, clientInfo); + // Return success after mDns reports success } else { - mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.ERROR); + unregisterService(id); + replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.UNREGISTER_SERVICE: if (DBG) Slog.d(TAG, "unregister service"); clientInfo = mClients.get(msg.replyTo); - int regId = msg.arg1; - if (clientInfo.mRegisteredIds.remove(new Integer(regId)) && - unregisterService(regId)) { - mReplyChannel.replyToMessage(msg, - NsdManager.UNREGISTER_SERVICE_SUCCEEDED); + try { + id = clientInfo.mClientIds.get(msg.arg2).intValue(); + } catch (NullPointerException e) { + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); + break; + } + removeRequestMap(msg.arg2, id, clientInfo); + if (unregisterService(id)) { + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED); } else { - mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; - case NsdManager.UPDATE_SERVICE: - if (DBG) Slog.d(TAG, "Update service"); - //TODO: implement - mReplyChannel.replyToMessage(msg, NsdManager.UPDATE_SERVICE_FAILED); - break; case NsdManager.RESOLVE_SERVICE: if (DBG) Slog.d(TAG, "Resolve service"); - servInfo = (DnsSdServiceInfo) msg.obj; + servInfo = (NsdServiceInfo) msg.obj; clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mResolveId != INVALID_ID) { - //first cancel existing resolve - stopResolveService(clientInfo.mResolveId); - } - clientInfo.mResolveId = getUniqueId(); - if (!resolveService(clientInfo.mResolveId, servInfo)) { - mReplyChannel.replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - clientInfo.mResolveId = INVALID_ID; - } - break; - case NsdManager.STOP_RESOLVE: - if (DBG) Slog.d(TAG, "Stop resolve"); - clientInfo = mClients.get(msg.replyTo); - if (clientInfo.mResolveId == INVALID_ID) { - //already stopped - if (DBG) Slog.d(TAG, "resolve already stopped"); - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, - NsdManager.ALREADY_ACTIVE); + + if (clientInfo.mResolvedService != null) { + replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_ALREADY_ACTIVE); break; } - if (stopResolveService(clientInfo.mResolveId)) { - clientInfo.mResolveId = INVALID_ID; - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_SUCCEEDED); + + id = getUniqueId(); + if (resolveService(id, servInfo)) { + clientInfo.mResolvedService = new NsdServiceInfo(); + storeRequestMap(msg.arg2, id, clientInfo); } else { - mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, - NsdManager.ERROR); + replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR); } break; + case NsdManager.NATIVE_DAEMON_EVENT: + NativeEvent event = (NativeEvent) msg.obj; + handleNativeEvent(event.code, event.raw, + NativeDaemonEvent.unescapeArgs(event.raw)); + break; default: result = NOT_HANDLED; break; @@ -439,121 +459,144 @@ public class NsdService extends INsdManager.Stub { public static final int SERVICE_GET_ADDR_SUCCESS = 612; } + private class NativeEvent { + int code; + String raw; + + NativeEvent(int code, String raw) { + this.code = code; + this.raw = raw; + } + } + class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks { public void onDaemonConnected() { mNativeDaemonConnected.countDown(); } public boolean onEvent(int code, String raw, String[] cooked) { - ClientInfo clientInfo; - DnsSdServiceInfo servInfo; - int id = Integer.parseInt(cooked[1]); - switch (code) { - case NativeResponseCode.SERVICE_FOUND: - /* NNN uniqueId serviceName regType domain */ - if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw); - clientInfo = getClientByDiscovery(id); - if (clientInfo == null) break; - - servInfo = new DnsSdServiceInfo(cooked[2], cooked[3], null); - clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, servInfo); - break; - case NativeResponseCode.SERVICE_LOST: - /* NNN uniqueId serviceName regType domain */ - if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw); - clientInfo = getClientByDiscovery(id); - if (clientInfo == null) break; - - servInfo = new DnsSdServiceInfo(cooked[2], cooked[3], null); - clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, servInfo); - break; - case NativeResponseCode.SERVICE_DISCOVERY_FAILED: - /* NNN uniqueId errorCode */ - if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw); - clientInfo = getClientByDiscovery(id); - if (clientInfo == null) break; - - clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.ERROR); - break; - case NativeResponseCode.SERVICE_REGISTERED: - /* NNN regId serviceName regType */ - if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw); - clientInfo = getClientByRegistration(id); - if (clientInfo == null) break; - - servInfo = new DnsSdServiceInfo(cooked[2], null, null); - clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED, - id, 0, servInfo); - break; - case NativeResponseCode.SERVICE_REGISTRATION_FAILED: - /* NNN regId errorCode */ - if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw); - clientInfo = getClientByRegistration(id); - if (clientInfo == null) break; - - clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.ERROR); - break; - case NativeResponseCode.SERVICE_UPDATED: - /* NNN regId */ - break; - case NativeResponseCode.SERVICE_UPDATE_FAILED: - /* NNN regId errorCode */ - break; - case NativeResponseCode.SERVICE_RESOLVED: - /* NNN resolveId fullName hostName port txtlen txtdata */ - if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw); - clientInfo = getClientByResolve(id); - if (clientInfo == null) break; - - int index = cooked[2].indexOf("."); - if (index == -1) { - Slog.e(TAG, "Invalid service found " + raw); - break; - } - String name = cooked[2].substring(0, index); - String rest = cooked[2].substring(index); - String type = rest.replace(".local.", ""); + // TODO: NDC translates a message to a callback, we could enhance NDC to + // directly interact with a state machine through messages + NativeEvent event = new NativeEvent(code, raw); + mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event); + return true; + } + } - clientInfo.mResolvedService = new DnsSdServiceInfo(name, type, null); - clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); + private void handleNativeEvent(int code, String raw, String[] cooked) { + NsdServiceInfo servInfo; + int id = Integer.parseInt(cooked[1]); + ClientInfo clientInfo = mIdToClientInfoMap.get(id); + if (clientInfo == null) { + Slog.e(TAG, "Unique id with no client mapping: " + id); + return; + } - stopResolveService(id); - getAddrInfo(id, cooked[3]); + /* This goes in response as msg.arg2 */ + int clientId = -1; + int keyId = clientInfo.mClientIds.indexOfValue(id); + if (keyId != -1) { + clientId = clientInfo.mClientIds.keyAt(keyId); + } + switch (code) { + case NativeResponseCode.SERVICE_FOUND: + /* NNN uniqueId serviceName regType domain */ + if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw); + servInfo = new NsdServiceInfo(cooked[2], cooked[3], null); + clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0, + clientId, servInfo); + break; + case NativeResponseCode.SERVICE_LOST: + /* NNN uniqueId serviceName regType domain */ + if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw); + servInfo = new NsdServiceInfo(cooked[2], cooked[3], null); + clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0, + clientId, servInfo); + break; + case NativeResponseCode.SERVICE_DISCOVERY_FAILED: + /* NNN uniqueId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw); + clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_REGISTERED: + /* NNN regId serviceName regType */ + if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw); + servInfo = new NsdServiceInfo(cooked[2], null, null); + clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED, + id, clientId, servInfo); + break; + case NativeResponseCode.SERVICE_REGISTRATION_FAILED: + /* NNN regId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw); + clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_UPDATED: + /* NNN regId */ + break; + case NativeResponseCode.SERVICE_UPDATE_FAILED: + /* NNN regId errorCode */ + break; + case NativeResponseCode.SERVICE_RESOLVED: + /* NNN resolveId fullName hostName port txtlen txtdata */ + if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw); + int index = cooked[2].indexOf("."); + if (index == -1) { + Slog.e(TAG, "Invalid service found " + raw); break; - case NativeResponseCode.SERVICE_RESOLUTION_FAILED: - case NativeResponseCode.SERVICE_GET_ADDR_FAILED: - /* NNN resolveId errorCode */ - if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); - clientInfo = getClientByResolve(id); - if (clientInfo == null) break; + } + String name = cooked[2].substring(0, index); + String rest = cooked[2].substring(index); + String type = rest.replace(".local.", ""); + + clientInfo.mResolvedService.setServiceName(name); + clientInfo.mResolvedService.setServiceType(type); + clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); + stopResolveService(id); + if (!getAddrInfo(id, cooked[3])) { clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - break; - case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: - /* NNN resolveId hostname ttl addr */ - if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw); - clientInfo = getClientByResolve(id); - if (clientInfo == null || clientInfo.mResolvedService == null) break; - - try { - clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED, - clientInfo.mResolvedService); - clientInfo.mResolvedService = null; - clientInfo.mResolveId = INVALID_ID; - } catch (java.net.UnknownHostException e) { - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.ERROR); - } - stopGetAddrInfo(id); - break; - default: - break; - } - return false; + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + } + break; + case NativeResponseCode.SERVICE_RESOLUTION_FAILED: + /* NNN resolveId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); + stopResolveService(id); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_GET_ADDR_FAILED: + /* NNN resolveId errorCode */ + stopGetAddrInfo(id); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + break; + case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: + /* NNN resolveId hostname ttl addr */ + if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw); + try { + clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED, + 0, clientId, clientInfo.mResolvedService); + } catch (java.net.UnknownHostException e) { + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.FAILURE_INTERNAL_ERROR, clientId); + } + stopGetAddrInfo(id); + mIdToClientInfoMap.remove(id); + clientInfo.mResolvedService = null; + break; + default: + break; } } @@ -579,7 +622,7 @@ public class NsdService extends INsdManager.Stub { return true; } - private boolean registerService(int regId, DnsSdServiceInfo service) { + private boolean registerService(int regId, NsdServiceInfo service) { if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service); try { //Add txtlen and txtdata @@ -637,7 +680,7 @@ public class NsdService extends INsdManager.Stub { return true; } - private boolean resolveService(int resolveId, DnsSdServiceInfo service) { + private boolean resolveService(int resolveId, NsdServiceInfo service) { if (DBG) Slog.d(TAG, "resolveService: " + resolveId + " " + service); try { mNativeConnector.execute("mdnssd", "resolve", resolveId, service.getServiceName(), @@ -700,49 +743,52 @@ public class NsdService extends INsdManager.Stub { mNsdStateMachine.dump(fd, pw, args); } - private ClientInfo getClientByDiscovery(int discoveryId) { - for (ClientInfo c: mClients.values()) { - if (c.mDiscoveryId == discoveryId) { - return c; - } - } - return null; + /* arg2 on the source message has an id that needs to be retained in replies + * see NsdManager for details */ + private Message obtainMessage(Message srcMsg) { + Message msg = Message.obtain(); + msg.arg2 = srcMsg.arg2; + return msg; } - private ClientInfo getClientByResolve(int resolveId) { - for (ClientInfo c: mClients.values()) { - if (c.mResolveId == resolveId) { - return c; - } - } - return null; + private void replyToMessage(Message msg, int what) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessage(msg); + dstMsg.what = what; + mReplyChannel.replyToMessage(msg, dstMsg); } - private ClientInfo getClientByRegistration(int regId) { - for (ClientInfo c: mClients.values()) { - if (c.mRegisteredIds.contains(regId)) { - return c; - } - } - return null; + private void replyToMessage(Message msg, int what, int arg1) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessage(msg); + dstMsg.what = what; + dstMsg.arg1 = arg1; + mReplyChannel.replyToMessage(msg, dstMsg); + } + + private void replyToMessage(Message msg, int what, Object obj) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessage(msg); + dstMsg.what = what; + dstMsg.obj = obj; + mReplyChannel.replyToMessage(msg, dstMsg); } /* Information tracked per client */ private class ClientInfo { - private static final int MAX_REG = 5; + private static final int MAX_LIMIT = 10; private AsyncChannel mChannel; private Messenger mMessenger; - private int mDiscoveryId; - private int mResolveId; /* Remembers a resolved service until getaddrinfo completes */ - private DnsSdServiceInfo mResolvedService; - private ArrayList<Integer> mRegisteredIds = new ArrayList<Integer>(); + private NsdServiceInfo mResolvedService; + + /* A map from client id to unique id sent to mDns */ + private SparseArray<Integer> mClientIds = new SparseArray<Integer>(); private ClientInfo(AsyncChannel c, Messenger m) { mChannel = c; mMessenger = m; - mDiscoveryId = mResolveId = INVALID_ID; if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m); } @@ -751,11 +797,10 @@ public class NsdService extends INsdManager.Stub { StringBuffer sb = new StringBuffer(); sb.append("mChannel ").append(mChannel).append("\n"); sb.append("mMessenger ").append(mMessenger).append("\n"); - sb.append("mDiscoveryId ").append(mDiscoveryId).append("\n"); - sb.append("mResolveId ").append(mResolveId).append("\n"); sb.append("mResolvedService ").append(mResolvedService).append("\n"); - for(int regId : mRegisteredIds) { - sb.append("regId ").append(regId).append("\n"); + for(int i = 0; i< mClientIds.size(); i++) { + sb.append("clientId ").append(mClientIds.keyAt(i)); + sb.append(" mDnsId ").append(mClientIds.valueAt(i)).append("\n"); } return sb.toString(); } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 40f64bf..aa7de82 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1567,6 +1567,31 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { + if (code == SYSPROPS_TRANSACTION) { + // We need to tell all apps about the system property change. + ArrayList<IBinder> procs = new ArrayList<IBinder>(); + synchronized(this) { + for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) { + final int NA = apps.size(); + for (int ia=0; ia<NA; ia++) { + ProcessRecord app = apps.valueAt(ia); + if (app.thread != null) { + procs.add(app.thread.asBinder()); + } + } + } + } + + int N = procs.size(); + for (int i=0; i<N; i++) { + Parcel data2 = Parcel.obtain(); + try { + procs.get(i).transact(IBinder.SYSPROPS_TRANSACTION, data2, null, 0); + } catch (RemoteException e) { + } + data2.recycle(); + } + } try { return super.onTransact(code, data, reply, flags); } catch (RuntimeException e) { diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 1e14f5b..c300411 100755 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -1794,10 +1794,6 @@ final class ActivityStack { mService.mWindowManager.prepareAppTransition( WindowManagerPolicy.TRANSIT_NONE, keepCurTransition); mNoAnimActivities.add(r); - } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { - mService.mWindowManager.prepareAppTransition( - WindowManagerPolicy.TRANSIT_TASK_OPEN, keepCurTransition); - mNoAnimActivities.remove(r); } else { mService.mWindowManager.prepareAppTransition(newTask ? WindowManagerPolicy.TRANSIT_TASK_OPEN diff --git a/services/java/com/android/server/net/NetworkStatsRecorder.java b/services/java/com/android/server/net/NetworkStatsRecorder.java index 2ce7771..c3ecf54 100644 --- a/services/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/java/com/android/server/net/NetworkStatsRecorder.java @@ -26,6 +26,7 @@ import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; +import android.os.DropBoxManager; import android.util.Log; import android.util.MathUtils; import android.util.Slog; @@ -34,6 +35,7 @@ import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; import com.google.android.collect.Sets; +import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; @@ -43,6 +45,8 @@ import java.lang.ref.WeakReference; import java.util.HashSet; import java.util.Map; +import libcore.io.IoUtils; + /** * Logic to record deltas between periodic {@link NetworkStats} snapshots into * {@link NetworkStatsHistory} that belong to {@link NetworkStatsCollection}. @@ -56,8 +60,14 @@ public class NetworkStatsRecorder { private static final boolean LOGD = false; private static final boolean LOGV = false; + private static final String TAG_NETSTATS_DUMP = "netstats_dump"; + + /** Dump before deleting in {@link #recoverFromWtf()}. */ + private static final boolean DUMP_BEFORE_DELETE = true; + private final FileRotator mRotator; private final NonMonotonicObserver<String> mObserver; + private final DropBoxManager mDropBox; private final String mCookie; private final long mBucketDuration; @@ -74,9 +84,10 @@ public class NetworkStatsRecorder { private WeakReference<NetworkStatsCollection> mComplete; public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer, - String cookie, long bucketDuration, boolean onlyTags) { + DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags) { mRotator = checkNotNull(rotator, "missing FileRotator"); mObserver = checkNotNull(observer, "missing NonMonotonicObserver"); + mDropBox = checkNotNull(dropBox, "missing DropBoxManager"); mCookie = cookie; mBucketDuration = bucketDuration; @@ -122,6 +133,7 @@ public class NetworkStatsRecorder { mComplete = new WeakReference<NetworkStatsCollection>(complete); } catch (IOException e) { Log.wtf(TAG, "problem completely reading network stats", e); + recoverFromWtf(); } } return complete; @@ -212,6 +224,7 @@ public class NetworkStatsRecorder { mPending.reset(); } catch (IOException e) { Log.wtf(TAG, "problem persisting pending stats", e); + recoverFromWtf(); } } } @@ -226,6 +239,7 @@ public class NetworkStatsRecorder { mRotator.rewriteAll(new RemoveUidRewriter(mBucketDuration, uid)); } catch (IOException e) { Log.wtf(TAG, "problem removing UID " + uid, e); + recoverFromWtf(); } // clear UID from current stats snapshot @@ -355,4 +369,25 @@ public class NetworkStatsRecorder { mSinceBoot.dump(pw); } } + + /** + * Recover from {@link FileRotator} failure by dumping state to + * {@link DropBoxManager} and deleting contents. + */ + private void recoverFromWtf() { + if (DUMP_BEFORE_DELETE) { + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + try { + mRotator.dumpAll(os); + } catch (IOException e) { + // ignore partial contents + os.reset(); + } finally { + IoUtils.closeQuietly(os); + } + mDropBox.addData(TAG_NETSTATS_DUMP, os.toByteArray(), 0); + } + + mRotator.deleteAll(); + } } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 1a56b80..e710b33 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -338,9 +338,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStatsRecorder buildRecorder( String prefix, NetworkStatsSettings.Config config, boolean includeTags) { + final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService( + Context.DROPBOX_SERVICE); return new NetworkStatsRecorder(new FileRotator( mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis), - mNonMonotonicObserver, prefix, config.bucketDuration, includeTags); + mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags); } private void shutdownLocked() { |