blob: 4e6bfc70d05f6d7be9b31d16e1d722d9e029dc20 [file] [log] [blame]
/*
* Copyright (c) 2021 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package chip.platform;
import android.content.Context;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
public class NsdManagerServiceBrowser implements ServiceBrowser {
private static final String TAG = NsdManagerServiceBrowser.class.getSimpleName();
private static final long BROWSE_SERVICE_TIMEOUT = 5000;
private final NsdManager nsdManager;
private MulticastLock multicastLock;
private Handler mainThreadHandler;
private HashMap<Long, NsdManagerDiscovery> callbackMap;
public NsdManagerServiceBrowser(Context context) {
this.nsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
this.mainThreadHandler = new Handler(Looper.getMainLooper());
this.multicastLock =
((WifiManager) context.getSystemService(Context.WIFI_SERVICE))
.createMulticastLock("chipBrowseMulticastLock");
this.multicastLock.setReferenceCounted(true);
callbackMap = new HashMap<>();
}
@Override
public void browse(
final String serviceType,
final long callbackHandle,
final long contextHandle,
final ChipMdnsCallback chipMdnsCallback) {
Runnable timeoutRunnable =
new Runnable() {
@Override
public void run() {
stopDiscover(callbackHandle, chipMdnsCallback);
}
};
startDiscover(serviceType, callbackHandle, contextHandle, chipMdnsCallback);
mainThreadHandler.postDelayed(timeoutRunnable, BROWSE_SERVICE_TIMEOUT);
}
public void startDiscover(
final String serviceType,
final long callbackHandle,
final long contextHandle,
final ChipMdnsCallback chipMdnsCallback) {
if (callbackMap.containsKey(callbackHandle)) {
Log.d(TAG, "Invalid callbackHandle");
return;
}
NsdManagerDiscovery discovery =
new NsdManagerDiscovery(serviceType, callbackHandle, contextHandle);
multicastLock.acquire();
Log.d(TAG, "Starting service discovering for '" + serviceType + "'");
this.nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, discovery);
callbackMap.put(callbackHandle, discovery);
}
public void stopDiscover(final long callbackHandle, final ChipMdnsCallback chipMdnsCallback) {
if (!callbackMap.containsKey(callbackHandle)) {
Log.d(TAG, "Invalid callbackHandle");
return;
}
NsdManagerDiscovery discovery = callbackMap.remove(callbackHandle);
if (multicastLock.isHeld()) {
multicastLock.release();
}
this.nsdManager.stopServiceDiscovery(discovery);
discovery.handleServiceBrowse(chipMdnsCallback);
}
public class NsdManagerDiscovery implements NsdManager.DiscoveryListener {
private String serviceType;
private long callbackHandle;
private long contextHandle;
private ArrayList<String> serviceNameList = new ArrayList<>();
public NsdManagerDiscovery(String serviceType, long callbackHandle, long contextHandle) {
this.serviceType = serviceType;
this.callbackHandle = callbackHandle;
this.contextHandle = contextHandle;
}
@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
Log.w(TAG, "Failed to start discovery service '" + serviceType + "': " + errorCode);
}
@Override
public void onDiscoveryStarted(String serviceType) {
Log.i(TAG, "Started service '" + serviceType + "'");
}
@Override
public void onServiceFound(NsdServiceInfo serviceInfo) {
Log.i(TAG, "Found service '" + serviceInfo.getServiceName() + "'");
serviceNameList.add(serviceInfo.getServiceName());
}
@Override
public void onServiceLost(NsdServiceInfo serviceInfo) {
Log.i(TAG, "Lost service '" + serviceType + "'");
}
@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
Log.w(TAG, "Failed to stop discovery service '" + serviceType + "': " + errorCode);
}
@Override
public void onDiscoveryStopped(String serviceType) {
Log.w(TAG, "Succeed to stop discovery service '" + serviceType);
}
public void handleServiceBrowse(ChipMdnsCallback chipMdnsCallback) {
chipMdnsCallback.handleServiceBrowse(
serviceNameList.toArray(new String[serviceNameList.size()]),
serviceType,
callbackHandle,
contextHandle);
}
}
}