blob: 7bb83c9384f757e09a2cca374c7c2f1664057bd6 [file] [log] [blame]
Philip P. Moltmanna26b7752016-05-23 10:33:57 -07001/*
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
17package com.android.printservice.recommendation.plugin.samsung;
18
19import android.content.Context;
20import android.content.res.TypedArray;
21import android.net.nsd.NsdManager;
22import android.net.nsd.NsdServiceInfo;
23import android.text.TextUtils;
24import android.util.Pair;
25
26import java.util.ArrayList;
27import java.util.HashMap;
28import java.util.List;
29import java.util.Map;
30import java.util.Set;
31
32import com.android.printservice.recommendation.R;
33import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer;
34
35public class ServiceListener implements ServiceResolveQueue.ResolveCallback {
36
37 private final NsdManager mNSDManager;
38 private final Map<String, VendorInfo> mVendorInfoHashMap;
39 private final String[] mServiceType;
40 private final Observer mObserver;
41 private final ServiceResolveQueue mResolveQueue;
42 private List<NsdManager.DiscoveryListener> mListeners = new ArrayList<>();
43 public HashMap<String, PrinterHashMap> mVendorHashMap = new HashMap<>();
44
45 public interface Observer {
46 boolean matchesCriteria(String vendor, NsdServiceInfo serviceInfo);
47 void dataSetChanged();
48 }
49
50 public ServiceListener(Context context, Observer observer, String[] serviceTypes) {
51 mObserver = observer;
52 mServiceType = serviceTypes;
53 mNSDManager = (NsdManager)context.getSystemService(Context.NSD_SERVICE);
54 mResolveQueue = ServiceResolveQueue.getInstance(mNSDManager);
55
56 Map<String, VendorInfo> vendorInfoMap = new HashMap<>();
57 TypedArray testArray = context.getResources().obtainTypedArray(R.array.known_print_plugin_vendors);
58 for(int i = 0; i < testArray.length(); i++) {
59 int arrayID = testArray.getResourceId(i, 0);
60 if (arrayID != 0) {
61 VendorInfo info = new VendorInfo(context.getResources(), arrayID);
62 vendorInfoMap.put(info.mVendorID, info);
63 vendorInfoMap.put(info.mPackageName, info);
64 }
65 }
66 testArray.recycle();
67 mVendorInfoHashMap = vendorInfoMap;
68 }
69
70 @Override
71 public void serviceResolved(NsdServiceInfo nsdServiceInfo) {
72 printerFound(nsdServiceInfo);
73 }
74
75 private synchronized void printerFound(NsdServiceInfo nsdServiceInfo) {
76 if (nsdServiceInfo == null) return;
77 if (TextUtils.isEmpty(PrinterHashMap.getKey(nsdServiceInfo))) return;
78 String vendor = MDnsUtils.getVendor(nsdServiceInfo);
79 if (vendor == null) vendor = "";
80 for(Map.Entry<String,VendorInfo> entry : mVendorInfoHashMap.entrySet()) {
81 for(String vendorValues : entry.getValue().mDNSValues) {
82 if (vendor.equalsIgnoreCase(vendorValues)) {
83 vendor = entry.getValue().mVendorID;
84 break;
85 }
86 }
87 // intentional pointer check
88 //noinspection StringEquality
89 if ((vendor != entry.getValue().mVendorID) &&
90 MDnsUtils.isVendorPrinter(nsdServiceInfo, entry.getValue().mDNSValues)) {
91 vendor = entry.getValue().mVendorID;
92 }
93 // intentional pointer check
94 //noinspection StringEquality
95 if (vendor == entry.getValue().mVendorID) break;
96 }
97
98 if (TextUtils.isEmpty(vendor)) {
99 return;
100 }
101
102 if (!mObserver.matchesCriteria(vendor, nsdServiceInfo))
103 return;
104 boolean mapsChanged;
105
106 PrinterHashMap vendorHash = mVendorHashMap.get(vendor);
107 if (vendorHash == null) {
108 vendorHash = new PrinterHashMap();
109 }
110 mapsChanged = (vendorHash.addPrinter(nsdServiceInfo) == null);
111 mVendorHashMap.put(vendor, vendorHash);
112
113 if (mapsChanged) {
114 mObserver.dataSetChanged();
115 }
116 }
117
118 private synchronized void printerRemoved(NsdServiceInfo nsdServiceInfo) {
119 boolean wasRemoved = false;
120 Set<String> vendors = mVendorHashMap.keySet();
121 for(String vendor : vendors) {
122 PrinterHashMap map = mVendorHashMap.get(vendor);
123 wasRemoved |= (map.removePrinter(nsdServiceInfo) != null);
124 if (map.isEmpty()) wasRemoved |= (mVendorHashMap.remove(vendor) != null);
125 }
126 if (wasRemoved) {
127 mObserver.dataSetChanged();
128 }
129 }
130
131 public void start() {
132 stop();
133 for(final String service :mServiceType) {
134 NsdManager.DiscoveryListener listener = new NsdManager.DiscoveryListener() {
135 @Override
136 public void onStartDiscoveryFailed(String s, int i) {
137
138 }
139
140 @Override
141 public void onStopDiscoveryFailed(String s, int i) {
142
143 }
144
145 @Override
146 public void onDiscoveryStarted(String s) {
147
148 }
149
150 @Override
151 public void onDiscoveryStopped(String s) {
152
153 }
154
155 @Override
156 public void onServiceFound(NsdServiceInfo nsdServiceInfo) {
157 mResolveQueue.queueRequest(nsdServiceInfo, ServiceListener.this);
158 }
159
160 @Override
161 public void onServiceLost(NsdServiceInfo nsdServiceInfo) {
162 mResolveQueue.removeRequest(nsdServiceInfo, ServiceListener.this);
163 printerRemoved(nsdServiceInfo);
164 }
165 };
166 DiscoveryListenerMultiplexer.addListener(mNSDManager, service, listener);
167 mListeners.add(listener);
168 }
169 }
170
171 public void stop() {
172 for(NsdManager.DiscoveryListener listener : mListeners) {
173 DiscoveryListenerMultiplexer.removeListener(mNSDManager, listener);
174 }
175 mVendorHashMap.clear();
176 mListeners.clear();
177 }
178
179 public Pair<Integer, Integer> getCount() {
180 int count = 0;
181 for (PrinterHashMap map : mVendorHashMap.values()) {
182 count += map.size();
183 }
184 return Pair.create(mVendorHashMap.size(), count);
185 }
186}