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 */ 16package com.android.printservice.recommendation.plugin.xerox; 17 18import android.content.Context; 19import android.net.nsd.NsdManager; 20import android.net.nsd.NsdServiceInfo; 21import android.text.TextUtils; 22import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer; 23import com.android.printservice.recommendation.util.NsdResolveQueue; 24 25import java.util.ArrayList; 26import java.util.LinkedList; 27import java.util.List; 28 29class ServiceResolver { 30 31 private final NsdManager mNSDManager; 32 private final String[] mServiceType; 33 private final Observer mObserver; 34 private final VendorInfo mVendorInfo; 35 private final String[] mPDLs; 36 private final PrinterHashMap mPrinterHashMap = new PrinterHashMap(); 37 private final List<NsdManager.DiscoveryListener> mListeners = new ArrayList<>(); 38 private final NsdResolveQueue mNsdResolveQueue; 39 40 public interface Observer { 41 void dataSetChanged(); 42 } 43 44 public ServiceResolver(Context context, Observer observer, VendorInfo vendorInfo, String[] serviceTypes, String[] pdls) { 45 mNsdResolveQueue = NsdResolveQueue.getInstance(); 46 mObserver = observer; 47 mServiceType = serviceTypes; 48 mNSDManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE); 49 mVendorInfo = vendorInfo; 50 mPDLs = pdls; 51 } 52 53 public void start() { 54 stop(); 55 for (final String service : mServiceType) { 56 NsdManager.DiscoveryListener listener = new NsdManager.DiscoveryListener() { 57 @Override 58 public void onStartDiscoveryFailed(String s, int i) { 59 60 } 61 62 @Override 63 public void onStopDiscoveryFailed(String s, int i) { 64 65 } 66 67 @Override 68 public void onDiscoveryStarted(String s) { 69 70 } 71 72 @Override 73 public void onDiscoveryStopped(String s) { 74 75 } 76 77 @Override 78 public void onServiceFound(NsdServiceInfo nsdServiceInfo) { 79 queueRequest(nsdServiceInfo); 80 } 81 82 @Override 83 public void onServiceLost(NsdServiceInfo nsdServiceInfo) { 84 removeRequest(nsdServiceInfo); 85 printerRemoved(nsdServiceInfo); 86 } 87 }; 88 DiscoveryListenerMultiplexer.addListener(mNSDManager, service, listener); 89 mListeners.add(listener); 90 } 91 } 92 93 public void stop() { 94 for (NsdManager.DiscoveryListener listener : mListeners) { 95 DiscoveryListenerMultiplexer.removeListener(mNSDManager, listener); 96 } 97 mListeners.clear(); 98 clearRequests(); 99 } 100 101 //Resolving nsd services 102 private final LinkedList<NsdServiceInfo> mQueue = new LinkedList<>(); 103 private final Object mLock = new Object(); 104 private NsdServiceInfo mCurrentRequest = null; 105 106 private void queueRequest(NsdServiceInfo serviceInfo) { 107 synchronized (mLock) { 108 if (mQueue.contains(serviceInfo)) return; 109 mQueue.add(serviceInfo); 110 makeNextRequest(); 111 } 112 } 113 114 private void removeRequest(NsdServiceInfo serviceInfo) { 115 synchronized (mLock) { 116 mQueue.remove(serviceInfo); 117 if ((mCurrentRequest != null) && serviceInfo.equals(mCurrentRequest)) 118 mCurrentRequest = null; 119 } 120 } 121 122 private void clearRequests() { 123 synchronized (mLock) { 124 mQueue.clear(); 125 } 126 } 127 128 private void makeNextRequest() { 129 synchronized (mLock) { 130 if (mCurrentRequest != null) return; 131 if (mQueue.isEmpty()) return; 132 mCurrentRequest = mQueue.removeFirst(); 133 mNsdResolveQueue.resolve(mNSDManager, mCurrentRequest, new NsdManager.ResolveListener() { 134 @Override 135 public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int i) { 136 synchronized (mLock) { 137 if (mCurrentRequest != null) mQueue.add(mCurrentRequest); 138 makeNextRequest(); 139 } 140 } 141 142 @Override 143 public void onServiceResolved(NsdServiceInfo nsdServiceInfo) { 144 synchronized (mLock) { 145 if (mCurrentRequest != null) { 146 printerFound(nsdServiceInfo); 147 mCurrentRequest = null; 148 } 149 makeNextRequest(); 150 } 151 } 152 }); 153 154 } 155 } 156 157 private void printerFound(NsdServiceInfo nsdServiceInfo) { 158 if (nsdServiceInfo == null) return; 159 if (TextUtils.isEmpty(PrinterHashMap.getKey(nsdServiceInfo))) return; 160 String vendor = MDnsUtils.getVendor(nsdServiceInfo); 161 if (vendor == null) vendor = ""; 162 163 for (String vendorValues : mVendorInfo.mDNSValues) { 164 if (vendor.equalsIgnoreCase(vendorValues)) { 165 vendor = mVendorInfo.mVendorID; 166 break; 167 } 168 } 169 170 if ((vendor != mVendorInfo.mVendorID) && 171 MDnsUtils.isVendorPrinter(nsdServiceInfo, mVendorInfo.mDNSValues)) { 172 vendor = mVendorInfo.mVendorID; 173 } 174 175 if (!(vendor == mVendorInfo.mVendorID)) { 176 return; 177 } 178 179 if (!MDnsUtils.checkPDLSupport(nsdServiceInfo, mPDLs)) { 180 return; 181 } 182 183 if ((mPrinterHashMap.addPrinter(nsdServiceInfo) == null)) { 184 mObserver.dataSetChanged(); 185 } 186 187 } 188 189 private void printerRemoved(NsdServiceInfo nsdServiceInfo) { 190 if ((mPrinterHashMap.removePrinter(nsdServiceInfo) != null)) { 191 mObserver.dataSetChanged(); 192 } 193 } 194 195 public int getCount() { 196 return mPrinterHashMap.size(); 197 } 198 199} 200