From 63498afff8079a5b70d763688d634ecdf7086f72 Mon Sep 17 00:00:00 2001 From: "Philip P. Moltmann" Date: Fri, 27 May 2016 14:10:54 -0700 Subject: [PATCH] Move Xerox recommendation plugin to service. Only minimal changes just to make it work together with the other plugins. Bug: 28908572 Change-Id: Icac226b45e8a6885036466451d0e9f54a3b3c640 (cherry picked from commit d97fdfd943295ea90d37b092e66b7ad1701587a1) --- .../res/values/donottranslate.xml | 8 + .../res/xml/vendorconfigs.xml | 8 - .../recommendation/RecommendationServiceImpl.java | 9 + .../recommendation/plugin/xerox/MDnsUtils.java | 91 ++++++++++ .../plugin/xerox/PrinterHashMap.java | 34 ++++ .../plugin/xerox/ServiceResolver.java | 199 +++++++++++++++++++++ .../recommendation/plugin/xerox/VendorInfo.java | 39 ++++ .../XeroxPrintServiceRecommendationPlugin.java | 79 ++++++++ 8 files changed, 459 insertions(+), 8 deletions(-) create mode 100755 packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/MDnsUtils.java create mode 100755 packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/PrinterHashMap.java create mode 100755 packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java create mode 100755 packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/VendorInfo.java create mode 100755 packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/XeroxPrintServiceRecommendationPlugin.java diff --git a/packages/PrintRecommendationService/res/values/donottranslate.xml b/packages/PrintRecommendationService/res/values/donottranslate.xml index 86027cda405a..e9b97a3d629d 100644 --- a/packages/PrintRecommendationService/res/values/donottranslate.xml +++ b/packages/PrintRecommendationService/res/values/donottranslate.xml @@ -32,12 +32,20 @@ Hewlett Packard + com.sec.app.samsungprintservice Samsung Electronics Samsung + + + com.xerox.printservice + Xerox + Xerox + + @array/known_print_vendor_info_for_mopria @array/known_print_vendor_info_for_hp diff --git a/packages/PrintRecommendationService/res/xml/vendorconfigs.xml b/packages/PrintRecommendationService/res/xml/vendorconfigs.xml index 108ea66c404e..52889ce186a4 100644 --- a/packages/PrintRecommendationService/res/xml/vendorconfigs.xml +++ b/packages/PrintRecommendationService/res/xml/vendorconfigs.xml @@ -43,14 +43,6 @@ - @string/plugin_vendor_xerox - com.xerox.printservice - - Xerox - - - - @string/plugin_vendor_epson com.epson.mobilephone.android.epsonprintserviceplugin diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java index d95654f7a247..ac60a88e5ca6 100644 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java @@ -26,6 +26,7 @@ import com.android.printservice.recommendation.plugin.mdnsFilter.MDNSFilterPlugi import com.android.printservice.recommendation.plugin.mdnsFilter.VendorConfig; import com.android.printservice.recommendation.plugin.mopria.MopriaRecommendationPlugin; import com.android.printservice.recommendation.plugin.samsung.SamsungRecommendationPlugin; +import com.android.printservice.recommendation.plugin.xerox.XeroxPrintServiceRecommendationPlugin; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; @@ -83,6 +84,14 @@ public class RecommendationServiceImpl extends RecommendationService " plugin", e); } + try { + mPlugins.add(new RemotePrintServicePlugin( + new XeroxPrintServiceRecommendationPlugin(this), this, false)); + } catch (Exception e) { + Log.e(LOG_TAG, "Could not initiate " + getString(R.string.plugin_vendor_xerox) + + " plugin", e); + } + final int numPlugins = mPlugins.size(); for (int i = 0; i < numPlugins; i++) { try { diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/MDnsUtils.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/MDnsUtils.java new file mode 100755 index 000000000000..7a2d0d8957ea --- /dev/null +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/MDnsUtils.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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 com.android.printservice.recommendation.plugin.xerox; + +import android.net.nsd.NsdServiceInfo; +import android.text.TextUtils; + +import java.nio.charset.StandardCharsets; +import java.util.Locale; +import java.util.Map; + +class MDnsUtils { + public static final String ATTRIBUTE__TY = "ty"; + public static final String ATTRIBUTE__PRODUCT = "product"; + public static final String ATTRIBUTE__USB_MFG = "usb_MFG"; + public static final String ATTRIBUTE__USB_MDL = "usb_MDL"; + public static final String ATTRIBUTE__MFG = "mfg"; + public static final String EXCLUDE_FUJI = "fuji"; + public static final String PDL_ATTRIBUTE = "pdl"; + + public static boolean isVendorPrinter(NsdServiceInfo networkDevice, String[] vendorValues) { + + Map attributes = networkDevice.getAttributes(); + String product = getString(attributes.get(ATTRIBUTE__PRODUCT)); + String ty = getString(attributes.get(ATTRIBUTE__TY)); + String usbMfg = getString(attributes.get(ATTRIBUTE__USB_MFG)); + String usbMdl = getString(attributes.get(ATTRIBUTE__USB_MDL)); + String mfg = getString(attributes.get(ATTRIBUTE__MFG)); + return containsVendor(product, vendorValues) || containsVendor(ty, vendorValues) || containsVendor(usbMfg, vendorValues) || containsVendor(mfg, vendorValues) && !(containsString(ty, EXCLUDE_FUJI) || containsString(product, EXCLUDE_FUJI) || containsString(usbMdl, EXCLUDE_FUJI)); + + } + + public static String getVendor(NsdServiceInfo networkDevice) { + String vendor; + + Map attributes = networkDevice.getAttributes(); + vendor = getString(attributes.get(ATTRIBUTE__MFG)); + if (!TextUtils.isEmpty(vendor)) return vendor; + vendor = getString(attributes.get(ATTRIBUTE__USB_MFG)); + if (!TextUtils.isEmpty(vendor)) return vendor; + + return null; + } + + public static boolean checkPDLSupport(NsdServiceInfo networkDevice, String[] pdlFormats) { + if (pdlFormats == null) return false; + + String pdls = MDnsUtils.getString(networkDevice.getAttributes().get(PDL_ATTRIBUTE)); + if (pdls != null) { + for (String pdl : pdlFormats) { + if (pdls.contains(pdl)) { + return true; + } + } + } + return false; + } + + private static boolean containsVendor(String container, String[] vendorValues) { + if ((container == null) || (vendorValues == null)) return false; + for (String value : vendorValues) { + if (containsString(container, value) + || containsString(container.toLowerCase(Locale.US), value.toLowerCase(Locale.US)) + || containsString(container.toUpperCase(Locale.US), value.toUpperCase(Locale.US))) + return true; + } + return false; + } + + private static String getString(byte[] value) { + if (value != null) return new String(value, StandardCharsets.UTF_8); + return null; + } + + private static boolean containsString(String container, String contained) { + return (container != null) && (contained != null) && (container.equalsIgnoreCase(contained) || container.contains(contained + " ")); + } +} diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/PrinterHashMap.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/PrinterHashMap.java new file mode 100755 index 000000000000..b88c7c725349 --- /dev/null +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/PrinterHashMap.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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 com.android.printservice.recommendation.plugin.xerox; + +import android.net.nsd.NsdServiceInfo; + +import java.util.HashMap; + +final class PrinterHashMap extends HashMap { + public static String getKey(NsdServiceInfo serviceInfo) { + return serviceInfo.getServiceName(); + } + + public NsdServiceInfo addPrinter(NsdServiceInfo device) { + return put(getKey(device), device); + } + + public NsdServiceInfo removePrinter(NsdServiceInfo device) { + return remove(getKey(device)); + } +} diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java new file mode 100755 index 000000000000..f64eed47f785 --- /dev/null +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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 com.android.printservice.recommendation.plugin.xerox; + +import android.content.Context; +import android.net.nsd.NsdManager; +import android.net.nsd.NsdServiceInfo; +import android.text.TextUtils; +import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer; +import com.android.printservice.recommendation.util.NsdResolveQueue; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +class ServiceResolver { + + private final NsdManager mNSDManager; + private final String[] mServiceType; + private final Observer mObserver; + private final VendorInfo mVendorInfo; + private final String[] mPDLs; + private final PrinterHashMap mPrinterHashMap = new PrinterHashMap(); + private final List mListeners = new ArrayList<>(); + private final NsdResolveQueue mNsdResolveQueue; + + public interface Observer { + void dataSetChanged(); + } + + public ServiceResolver(Context context, Observer observer, VendorInfo vendorInfo, String[] serviceTypes, String[] pdls) { + mNsdResolveQueue = NsdResolveQueue.getInstance(); + mObserver = observer; + mServiceType = serviceTypes; + mNSDManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE); + mVendorInfo = vendorInfo; + mPDLs = pdls; + } + + public void start() { + stop(); + for (final String service : mServiceType) { + NsdManager.DiscoveryListener listener = new NsdManager.DiscoveryListener() { + @Override + public void onStartDiscoveryFailed(String s, int i) { + + } + + @Override + public void onStopDiscoveryFailed(String s, int i) { + + } + + @Override + public void onDiscoveryStarted(String s) { + + } + + @Override + public void onDiscoveryStopped(String s) { + + } + + @Override + public void onServiceFound(NsdServiceInfo nsdServiceInfo) { + queueRequest(nsdServiceInfo); + } + + @Override + public void onServiceLost(NsdServiceInfo nsdServiceInfo) { + removeRequest(nsdServiceInfo); + printerRemoved(nsdServiceInfo); + } + }; + DiscoveryListenerMultiplexer.addListener(mNSDManager, service, listener); + mListeners.add(listener); + } + } + + public void stop() { + for (NsdManager.DiscoveryListener listener : mListeners) { + DiscoveryListenerMultiplexer.removeListener(mNSDManager, listener); + } + mListeners.clear(); + clearRequests(); + } + + //Resolving nsd services + private final LinkedList mQueue = new LinkedList<>(); + private final Object mLock = new Object(); + private NsdServiceInfo mCurrentRequest = null; + + private void queueRequest(NsdServiceInfo serviceInfo) { + synchronized (mLock) { + if (mQueue.contains(serviceInfo)) return; + mQueue.add(serviceInfo); + makeNextRequest(); + } + } + + private void removeRequest(NsdServiceInfo serviceInfo) { + synchronized (mLock) { + mQueue.remove(serviceInfo); + if ((mCurrentRequest != null) && serviceInfo.equals(mCurrentRequest)) + mCurrentRequest = null; + } + } + + private void clearRequests() { + synchronized (mLock) { + mQueue.clear(); + } + } + + private void makeNextRequest() { + synchronized (mLock) { + if (mCurrentRequest != null) return; + if (mQueue.isEmpty()) return; + mCurrentRequest = mQueue.removeFirst(); + mNsdResolveQueue.resolve(mNSDManager, mCurrentRequest, new NsdManager.ResolveListener() { + @Override + public void onResolveFailed(NsdServiceInfo nsdServiceInfo, int i) { + synchronized (mLock) { + if (mCurrentRequest != null) mQueue.add(mCurrentRequest); + makeNextRequest(); + } + } + + @Override + public void onServiceResolved(NsdServiceInfo nsdServiceInfo) { + synchronized (mLock) { + if (mCurrentRequest != null) { + printerFound(nsdServiceInfo); + mCurrentRequest = null; + } + makeNextRequest(); + } + } + }); + + } + } + + private void printerFound(NsdServiceInfo nsdServiceInfo) { + if (nsdServiceInfo == null) return; + if (TextUtils.isEmpty(PrinterHashMap.getKey(nsdServiceInfo))) return; + String vendor = MDnsUtils.getVendor(nsdServiceInfo); + if (vendor == null) vendor = ""; + + for (String vendorValues : mVendorInfo.mDNSValues) { + if (vendor.equalsIgnoreCase(vendorValues)) { + vendor = mVendorInfo.mVendorID; + break; + } + } + + if ((vendor != mVendorInfo.mVendorID) && + MDnsUtils.isVendorPrinter(nsdServiceInfo, mVendorInfo.mDNSValues)) { + vendor = mVendorInfo.mVendorID; + } + + if (!(vendor == mVendorInfo.mVendorID)) { + return; + } + + if (!MDnsUtils.checkPDLSupport(nsdServiceInfo, mPDLs)) { + return; + } + + if ((mPrinterHashMap.addPrinter(nsdServiceInfo) == null)) { + mObserver.dataSetChanged(); + } + + } + + private void printerRemoved(NsdServiceInfo nsdServiceInfo) { + if ((mPrinterHashMap.removePrinter(nsdServiceInfo) != null)) { + mObserver.dataSetChanged(); + } + } + + public int getCount() { + return mPrinterHashMap.size(); + } + +} diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/VendorInfo.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/VendorInfo.java new file mode 100755 index 000000000000..20967a742896 --- /dev/null +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/VendorInfo.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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 com.android.printservice.recommendation.plugin.xerox; + +import android.content.res.Resources; + +import java.util.Arrays; + +final class VendorInfo { + + public final String mPackageName; + public final String mVendorID; + public final String[] mDNSValues; + public final int mID; + + public VendorInfo(Resources resources, int vendor_info_id) { + mID = vendor_info_id; + String[] data = resources.getStringArray(vendor_info_id); + if ((data == null) || (data.length < 2)) { + data = new String[]{null, null}; + } + mPackageName = data[0]; + mVendorID = data[1]; + mDNSValues = (data.length > 2) ? Arrays.copyOfRange(data, 2, data.length) : new String[]{}; + } +} diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/XeroxPrintServiceRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/XeroxPrintServiceRecommendationPlugin.java new file mode 100755 index 000000000000..3fb9ca239716 --- /dev/null +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/XeroxPrintServiceRecommendationPlugin.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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 com.android.printservice.recommendation.plugin.xerox; + +import android.content.Context; +import android.net.nsd.NsdManager; +import android.annotation.NonNull; +import com.android.printservice.recommendation.PrintServicePlugin; + +import com.android.printservice.recommendation.R; + +public class XeroxPrintServiceRecommendationPlugin implements PrintServicePlugin, ServiceResolver.Observer { + + protected final Object mLock = new Object(); + protected PrinterDiscoveryCallback mDiscoveryCallback = null; + protected final ServiceResolver mServiceResolver; + protected final NsdManager mNSDManager; + protected final VendorInfo mVendorInfo; + private final int mVendorStringID = R.string.plugin_vendor_xerox; + private final String PDL__PDF = "application/pdf"; + private final String[] mServices = new String[]{"_ipp._tcp"}; + + public XeroxPrintServiceRecommendationPlugin(Context context) { + mNSDManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE); + mVendorInfo = new VendorInfo(context.getResources(), R.array.known_print_vendor_info_for_xerox); + mServiceResolver = new ServiceResolver(context, this, mVendorInfo, mServices, new String[]{PDL__PDF}); + } + + @Override + public int getName() { + return mVendorStringID; + } + + @NonNull + @Override + public CharSequence getPackageName() { + return mVendorInfo.mPackageName; + } + + @Override + public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception { + synchronized (mLock) { + mDiscoveryCallback = callback; + mServiceResolver.start(); + } + } + + @Override + public void stop() throws Exception { + synchronized (mLock) { + mDiscoveryCallback = null; + mServiceResolver.stop(); + } + } + + @Override + public void dataSetChanged() { + synchronized (mLock) { + if (mDiscoveryCallback != null) mDiscoveryCallback.onChanged(getCount()); + } + } + + public int getCount() { + return mServiceResolver.getCount(); + } +} -- 2.11.0