Merge "Make NsdService only start the native daemon when needed and automatically clean it up." into sc-dev

This commit is contained in:
Luke Huang
2021-06-15 04:52:43 +00:00
committed by Android (Google) Code Review
2 changed files with 66 additions and 19 deletions

View File

@@ -199,6 +199,9 @@ public final class NsdManager {
/** @hide */
public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 20;
/** @hide */
public static final int DAEMON_CLEANUP = BASE + 21;
/** @hide */
public static final int ENABLE = BASE + 24;
/** @hide */

View File

@@ -61,6 +61,7 @@ public class NsdService extends INsdManager.Stub {
private static final String MDNS_TAG = "mDnsConnector";
private static final boolean DBG = true;
private static final long CLEANUP_DELAY_MS = 3000;
private final Context mContext;
private final NsdSettings mNsdSettings;
@@ -77,6 +78,7 @@ public class NsdService extends INsdManager.Stub {
private final SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<>();
private final AsyncChannel mReplyChannel = new AsyncChannel();
private final long mCleanupDelayMs;
private static final int INVALID_ID = 0;
private int mUniqueId = 1;
@@ -92,6 +94,22 @@ public class NsdService extends INsdManager.Stub {
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.
*/
@@ -151,10 +169,6 @@ public class NsdService extends INsdManager.Stub {
cInfo.expungeAllRequests();
mClients.remove(msg.replyTo);
}
//Last client
if (mClients.size() == 0) {
mDaemon.stop();
}
break;
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
AsyncChannel ac = new AsyncChannel();
@@ -180,6 +194,9 @@ public class NsdService extends INsdManager.Stub {
replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
NsdManager.FAILURE_INTERNAL_ERROR);
break;
case NsdManager.DAEMON_CLEANUP:
mDaemon.maybeStop();
break;
case NsdManager.NATIVE_DAEMON_EVENT:
default:
Slog.e(TAG, "Unhandled " + msg);
@@ -212,16 +229,13 @@ public class NsdService extends INsdManager.Stub {
@Override
public void enter() {
sendNsdStateChangeBroadcast(true);
if (mClients.size() > 0) {
mDaemon.start();
}
}
@Override
public void exit() {
if (mClients.size() > 0) {
mDaemon.stop();
}
// TODO: it is incorrect to stop the daemon without expunging all requests
// and sending error callbacks to clients.
maybeScheduleStop();
}
private boolean requestLimitReached(ClientInfo clientInfo) {
@@ -236,12 +250,15 @@ public class NsdService extends INsdManager.Stub {
clientInfo.mClientIds.put(clientId, globalId);
clientInfo.mClientRequests.put(clientId, what);
mIdToClientInfoMap.put(globalId, clientInfo);
// Remove the cleanup event because here comes a new request.
cancelStop();
}
private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
clientInfo.mClientIds.delete(clientId);
clientInfo.mClientRequests.delete(clientId);
mIdToClientInfoMap.remove(globalId);
maybeScheduleStop();
}
@Override
@@ -251,14 +268,12 @@ public class NsdService extends INsdManager.Stub {
int id;
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
//First client
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL &&
mClients.size() == 0) {
mDaemon.start();
}
return NOT_HANDLED;
case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
return NOT_HANDLED;
}
switch (msg.what) {
case NsdManager.DISABLE:
//TODO: cleanup clients
transitionTo(mDisabledState);
@@ -274,6 +289,7 @@ public class NsdService extends INsdManager.Stub {
break;
}
maybeStartDaemon();
id = getUniqueId();
if (discoverServices(id, servInfo.getServiceType())) {
if (DBG) {
@@ -316,6 +332,7 @@ public class NsdService extends INsdManager.Stub {
break;
}
maybeStartDaemon();
id = getUniqueId();
if (registerService(id, (NsdServiceInfo) msg.obj)) {
if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id);
@@ -357,6 +374,7 @@ public class NsdService extends INsdManager.Stub {
break;
}
maybeStartDaemon();
id = getUniqueId();
if (resolveService(id, servInfo)) {
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) {
StringBuilder sb = new StringBuilder(s.length());
for (int i = 0; i < s.length(); ++i) {
@@ -538,7 +560,9 @@ public class NsdService extends INsdManager.Stub {
}
@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;
mNsdSettings = settings;
mNsdStateMachine = new NsdStateMachine(TAG, handler);
@@ -552,7 +576,8 @@ public class NsdService extends INsdManager.Stub {
HandlerThread thread = new HandlerThread(TAG);
thread.start();
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();
return service;
}
@@ -681,12 +706,16 @@ public class NsdService extends INsdManager.Stub {
@VisibleForTesting
public static class DaemonConnection {
final NativeDaemonConnector mNativeConnector;
boolean mIsStarted = false;
DaemonConnection(NativeCallbackReceiver callback) {
mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null);
new Thread(mNativeConnector, MDNS_TAG).start();
}
/**
* Executes the specified cmd on the daemon.
*/
public boolean execute(Object... args) {
if (DBG) {
Slog.d(TAG, "mdnssd " + Arrays.toString(args));
@@ -700,12 +729,26 @@ public class NsdService extends INsdManager.Stub {
return true;
}
public void start() {
/**
* Starts the daemon if it is not already started.
*/
public void maybeStart() {
if (mIsStarted) {
return;
}
execute("start-service");
mIsStarted = true;
}
public void stop() {
/**
* Stops the daemon if it is started.
*/
public void maybeStop() {
if (!mIsStarted) {
return;
}
execute("stop-service");
mIsStarted = false;
}
}
@@ -864,6 +907,7 @@ public class NsdService extends INsdManager.Stub {
}
mClientIds.clear();
mClientRequests.clear();
mNsdStateMachine.maybeScheduleStop();
}
// mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id,