Merge "Make NsdService only start the native daemon when needed and automatically clean it up." am: 05081aa3b0
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1717479 Change-Id: I6caa9933f307118414039b9dd2391939aeb15c0f
This commit is contained in:
@@ -199,6 +199,9 @@ public final class NsdManager {
|
|||||||
/** @hide */
|
/** @hide */
|
||||||
public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 20;
|
public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 20;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public static final int DAEMON_CLEANUP = BASE + 21;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public static final int ENABLE = BASE + 24;
|
public static final int ENABLE = BASE + 24;
|
||||||
/** @hide */
|
/** @hide */
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
private static final String MDNS_TAG = "mDnsConnector";
|
private static final String MDNS_TAG = "mDnsConnector";
|
||||||
|
|
||||||
private static final boolean DBG = true;
|
private static final boolean DBG = true;
|
||||||
|
private static final long CLEANUP_DELAY_MS = 3000;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final NsdSettings mNsdSettings;
|
private final NsdSettings mNsdSettings;
|
||||||
@@ -77,6 +78,7 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
private final SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<>();
|
private final SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<>();
|
||||||
|
|
||||||
private final AsyncChannel mReplyChannel = new AsyncChannel();
|
private final AsyncChannel mReplyChannel = new AsyncChannel();
|
||||||
|
private final long mCleanupDelayMs;
|
||||||
|
|
||||||
private static final int INVALID_ID = 0;
|
private static final int INVALID_ID = 0;
|
||||||
private int mUniqueId = 1;
|
private int mUniqueId = 1;
|
||||||
@@ -92,6 +94,22 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
return NsdManager.nameOf(what);
|
return NsdManager.nameOf(what);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void maybeStartDaemon() {
|
||||||
|
mDaemon.maybeStart();
|
||||||
|
maybeScheduleStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void maybeScheduleStop() {
|
||||||
|
if (!isAnyRequestActive()) {
|
||||||
|
cancelStop();
|
||||||
|
sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancelStop() {
|
||||||
|
this.removeMessages(NsdManager.DAEMON_CLEANUP);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observes the NSD on/off setting, and takes action when changed.
|
* Observes the NSD on/off setting, and takes action when changed.
|
||||||
*/
|
*/
|
||||||
@@ -151,10 +169,6 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
cInfo.expungeAllRequests();
|
cInfo.expungeAllRequests();
|
||||||
mClients.remove(msg.replyTo);
|
mClients.remove(msg.replyTo);
|
||||||
}
|
}
|
||||||
//Last client
|
|
||||||
if (mClients.size() == 0) {
|
|
||||||
mDaemon.stop();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
|
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
|
||||||
AsyncChannel ac = new AsyncChannel();
|
AsyncChannel ac = new AsyncChannel();
|
||||||
@@ -180,6 +194,9 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
|
replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
|
||||||
NsdManager.FAILURE_INTERNAL_ERROR);
|
NsdManager.FAILURE_INTERNAL_ERROR);
|
||||||
break;
|
break;
|
||||||
|
case NsdManager.DAEMON_CLEANUP:
|
||||||
|
mDaemon.maybeStop();
|
||||||
|
break;
|
||||||
case NsdManager.NATIVE_DAEMON_EVENT:
|
case NsdManager.NATIVE_DAEMON_EVENT:
|
||||||
default:
|
default:
|
||||||
Slog.e(TAG, "Unhandled " + msg);
|
Slog.e(TAG, "Unhandled " + msg);
|
||||||
@@ -212,16 +229,13 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void enter() {
|
public void enter() {
|
||||||
sendNsdStateChangeBroadcast(true);
|
sendNsdStateChangeBroadcast(true);
|
||||||
if (mClients.size() > 0) {
|
|
||||||
mDaemon.start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exit() {
|
public void exit() {
|
||||||
if (mClients.size() > 0) {
|
// TODO: it is incorrect to stop the daemon without expunging all requests
|
||||||
mDaemon.stop();
|
// and sending error callbacks to clients.
|
||||||
}
|
maybeScheduleStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean requestLimitReached(ClientInfo clientInfo) {
|
private boolean requestLimitReached(ClientInfo clientInfo) {
|
||||||
@@ -236,12 +250,15 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
clientInfo.mClientIds.put(clientId, globalId);
|
clientInfo.mClientIds.put(clientId, globalId);
|
||||||
clientInfo.mClientRequests.put(clientId, what);
|
clientInfo.mClientRequests.put(clientId, what);
|
||||||
mIdToClientInfoMap.put(globalId, clientInfo);
|
mIdToClientInfoMap.put(globalId, clientInfo);
|
||||||
|
// Remove the cleanup event because here comes a new request.
|
||||||
|
cancelStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
|
private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
|
||||||
clientInfo.mClientIds.delete(clientId);
|
clientInfo.mClientIds.delete(clientId);
|
||||||
clientInfo.mClientRequests.delete(clientId);
|
clientInfo.mClientRequests.delete(clientId);
|
||||||
mIdToClientInfoMap.remove(globalId);
|
mIdToClientInfoMap.remove(globalId);
|
||||||
|
maybeScheduleStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -251,14 +268,12 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
int id;
|
int id;
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
|
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
|
||||||
//First client
|
|
||||||
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL &&
|
|
||||||
mClients.size() == 0) {
|
|
||||||
mDaemon.start();
|
|
||||||
}
|
|
||||||
return NOT_HANDLED;
|
return NOT_HANDLED;
|
||||||
case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
|
case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
|
||||||
return NOT_HANDLED;
|
return NOT_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (msg.what) {
|
||||||
case NsdManager.DISABLE:
|
case NsdManager.DISABLE:
|
||||||
//TODO: cleanup clients
|
//TODO: cleanup clients
|
||||||
transitionTo(mDisabledState);
|
transitionTo(mDisabledState);
|
||||||
@@ -274,6 +289,7 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maybeStartDaemon();
|
||||||
id = getUniqueId();
|
id = getUniqueId();
|
||||||
if (discoverServices(id, servInfo.getServiceType())) {
|
if (discoverServices(id, servInfo.getServiceType())) {
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
@@ -316,6 +332,7 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maybeStartDaemon();
|
||||||
id = getUniqueId();
|
id = getUniqueId();
|
||||||
if (registerService(id, (NsdServiceInfo) msg.obj)) {
|
if (registerService(id, (NsdServiceInfo) msg.obj)) {
|
||||||
if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id);
|
if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id);
|
||||||
@@ -357,6 +374,7 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maybeStartDaemon();
|
||||||
id = getUniqueId();
|
id = getUniqueId();
|
||||||
if (resolveService(id, servInfo)) {
|
if (resolveService(id, servInfo)) {
|
||||||
clientInfo.mResolvedService = new NsdServiceInfo();
|
clientInfo.mResolvedService = new NsdServiceInfo();
|
||||||
@@ -513,6 +531,10 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAnyRequestActive() {
|
||||||
|
return mIdToClientInfoMap.size() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
private String unescape(String s) {
|
private String unescape(String s) {
|
||||||
StringBuilder sb = new StringBuilder(s.length());
|
StringBuilder sb = new StringBuilder(s.length());
|
||||||
for (int i = 0; i < s.length(); ++i) {
|
for (int i = 0; i < s.length(); ++i) {
|
||||||
@@ -538,7 +560,9 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
NsdService(Context ctx, NsdSettings settings, Handler handler, DaemonConnectionSupplier fn) {
|
NsdService(Context ctx, NsdSettings settings, Handler handler,
|
||||||
|
DaemonConnectionSupplier fn, long cleanupDelayMs) {
|
||||||
|
mCleanupDelayMs = cleanupDelayMs;
|
||||||
mContext = ctx;
|
mContext = ctx;
|
||||||
mNsdSettings = settings;
|
mNsdSettings = settings;
|
||||||
mNsdStateMachine = new NsdStateMachine(TAG, handler);
|
mNsdStateMachine = new NsdStateMachine(TAG, handler);
|
||||||
@@ -552,7 +576,8 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
HandlerThread thread = new HandlerThread(TAG);
|
HandlerThread thread = new HandlerThread(TAG);
|
||||||
thread.start();
|
thread.start();
|
||||||
Handler handler = new Handler(thread.getLooper());
|
Handler handler = new Handler(thread.getLooper());
|
||||||
NsdService service = new NsdService(context, settings, handler, DaemonConnection::new);
|
NsdService service = new NsdService(context, settings, handler,
|
||||||
|
DaemonConnection::new, CLEANUP_DELAY_MS);
|
||||||
service.mDaemonCallback.awaitConnection();
|
service.mDaemonCallback.awaitConnection();
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
@@ -681,12 +706,16 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static class DaemonConnection {
|
public static class DaemonConnection {
|
||||||
final NativeDaemonConnector mNativeConnector;
|
final NativeDaemonConnector mNativeConnector;
|
||||||
|
boolean mIsStarted = false;
|
||||||
|
|
||||||
DaemonConnection(NativeCallbackReceiver callback) {
|
DaemonConnection(NativeCallbackReceiver callback) {
|
||||||
mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null);
|
mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null);
|
||||||
new Thread(mNativeConnector, MDNS_TAG).start();
|
new Thread(mNativeConnector, MDNS_TAG).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the specified cmd on the daemon.
|
||||||
|
*/
|
||||||
public boolean execute(Object... args) {
|
public boolean execute(Object... args) {
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
Slog.d(TAG, "mdnssd " + Arrays.toString(args));
|
Slog.d(TAG, "mdnssd " + Arrays.toString(args));
|
||||||
@@ -700,12 +729,26 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
/**
|
||||||
|
* Starts the daemon if it is not already started.
|
||||||
|
*/
|
||||||
|
public void maybeStart() {
|
||||||
|
if (mIsStarted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
execute("start-service");
|
execute("start-service");
|
||||||
|
mIsStarted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
/**
|
||||||
|
* Stops the daemon if it is started.
|
||||||
|
*/
|
||||||
|
public void maybeStop() {
|
||||||
|
if (!mIsStarted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
execute("stop-service");
|
execute("stop-service");
|
||||||
|
mIsStarted = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -864,6 +907,7 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
}
|
}
|
||||||
mClientIds.clear();
|
mClientIds.clear();
|
||||||
mClientRequests.clear();
|
mClientRequests.clear();
|
||||||
|
mNsdStateMachine.maybeScheduleStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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,
|
||||||
|
|||||||
Reference in New Issue
Block a user