1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.printservice.recommendation.plugin.xerox; 17 18 import android.content.Context; 19 import android.net.nsd.NsdManager; 20 import android.net.nsd.NsdServiceInfo; 21 import android.text.TextUtils; 22 23 import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer; 24 import com.android.printservice.recommendation.util.NsdResolveQueue; 25 26 import java.net.InetAddress; 27 import java.util.ArrayList; 28 import java.util.LinkedList; 29 import java.util.List; 30 31 class ServiceResolver { 32 33 private final NsdManager mNSDManager; 34 private final String[] mServiceType; 35 private final Observer mObserver; 36 private final VendorInfo mVendorInfo; 37 private final String[] mPDLs; 38 private final PrinterHashMap mPrinterHashMap = new PrinterHashMap(); 39 private final List<NsdManager.DiscoveryListener> mListeners = new ArrayList<>(); 40 private final NsdResolveQueue mNsdResolveQueue; 41 42 public interface Observer { 43 void dataSetChanged(); 44 } 45 46 public ServiceResolver(Context context, Observer observer, VendorInfo vendorInfo, String[] serviceTypes, String[] pdls) { 47 mNsdResolveQueue = NsdResolveQueue.getInstance(); 48 mObserver = observer; 49 mServiceType = serviceTypes; 50 mNSDManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE); 51 mVendorInfo = vendorInfo; 52 mPDLs = pdls; 53 } 54 55 public void start() { 56 stop(); 57 for (final String service : mServiceType) { 58 NsdManager.DiscoveryListener listener = new NsdManager.DiscoveryListener() { 59 @Override 60 public void onStartDiscoveryFailed(String s, int i) { 61 62 } 63 64 @Override 65 public void onStopDiscoveryFailed(String s, int i) { 66 67 } 68 69 @Override 70 public void onDiscoveryStarted(String s) { 71 72 } 73 74 @Override 75 public void onDiscoveryStopped(String s) { 76 77 } 78 79 @Override 80 public void onServiceFound(NsdServiceInfo nsdServiceInfo) { 81 queueRequest(nsdServiceInfo); 82 } 83 84 @Override 85 public void onServiceLost(NsdServiceInfo nsdServiceInfo) { 86 removeRequest(nsdServiceInfo); 87 printerRemoved(nsdServiceInfo); 88 } 89 }; 90 DiscoveryListenerMultiplexer.addListener(mNSDManager, service, listener); 91 mListeners.add(listener); 92 } 93 } 94 95 public void stop() { 96 for (NsdManager.DiscoveryListener listener : mListeners) { 97 DiscoveryListenerMultiplexer.removeListener(mNSDManager, listener); 98 } 99 mListeners.clear(); 100 clearRequests(); 101 } 102 103 //Resolving nsd services 104 private final LinkedList<NsdServiceInfo> mQueue = new LinkedList<>(); 105 private final Object mLock = new Object(); 106 private NsdServiceInfo mCurrentRequest = null; 107 108 private void queueRequest(NsdServiceInfo serviceInfo) { 109 synchronized (mLock) { 110 if (mQueue.contains(serviceInfo)) return; 111 mQueue.add(serviceInfo); 112 makeNextRequest(); 113 } 114 } 115 116 private void removeRequest(NsdServiceInfo serviceInfo) { 117 synchronized (mLock) { 118 mQueue.remove(serviceInfo); 119 if ((mCurrentRequest != null) && serviceInfo.equals(mCurrentRequest)) 120 mCurrentRequest = null; 121 } 122 } 123 124 private void clearRequests() { 125 synchronized (mLock) { 126 mQueue.clear(); 127 } 128 } 129 130 private void makeNextRequest() { 131 synchronized (mLock) { 132 if (mCurrentRequest != null) return; 133 if (mQueue.isEmpty()) return; 134 mCurrentRequest = mQueue.removeFirst(); 135 mNsdResolveQueue.resolve(mNSDManager, mCurrentRequest, new NsdManager.ResolveListener() { 136 @Override 137 public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int i) { 138 synchronized (mLock) { 139 if (mCurrentRequest != null) mQueue.add(mCurrentRequest); 140 makeNextRequest(); 141 } 142 } 143 144 @Override 145 public void onServiceResolved(NsdServiceInfo nsdServiceInfo) { 146 synchronized (mLock) { 147 if (mCurrentRequest != null) { 148 printerFound(nsdServiceInfo); 149 mCurrentRequest = null; 150 } 151 makeNextRequest(); 152 } 153 } 154 }); 155 156 } 157 } 158 159 private void printerFound(NsdServiceInfo nsdServiceInfo) { 160 if (nsdServiceInfo == null) return; 161 if (TextUtils.isEmpty(PrinterHashMap.getKey(nsdServiceInfo))) return; 162 String vendor = MDnsUtils.getVendor(nsdServiceInfo); 163 if (vendor == null) vendor = ""; 164 165 for (String vendorValues : mVendorInfo.mDNSValues) { 166 if (vendor.equalsIgnoreCase(vendorValues)) { 167 vendor = mVendorInfo.mVendorID; 168 break; 169 } 170 } 171 172 if ((vendor != mVendorInfo.mVendorID) && 173 MDnsUtils.isVendorPrinter(nsdServiceInfo, mVendorInfo.mDNSValues)) { 174 vendor = mVendorInfo.mVendorID; 175 } 176 177 if (!(vendor == mVendorInfo.mVendorID)) { 178 return; 179 } 180 181 if (!MDnsUtils.checkPDLSupport(nsdServiceInfo, mPDLs)) { 182 return; 183 } 184 185 if ((mPrinterHashMap.addPrinter(nsdServiceInfo) == null)) { 186 mObserver.dataSetChanged(); 187 } 188 189 } 190 191 private void printerRemoved(NsdServiceInfo nsdServiceInfo) { 192 if ((mPrinterHashMap.removePrinter(nsdServiceInfo) != null)) { 193 mObserver.dataSetChanged(); 194 } 195 } 196 197 public ArrayList<InetAddress> getPrinters() { 198 ArrayList<InetAddress> printerAddresses = new ArrayList<>(); 199 for (NsdServiceInfo printer : mPrinterHashMap.values()) { 200 printerAddresses.add(printer.getHost()); 201 } 202 203 return printerAddresses; 204 } 205 206 } 207