OSDN Git Service

Move Xerox recommendation plugin to service.
authorPhilip P. Moltmann <moltmann@google.com>
Fri, 27 May 2016 21:10:54 +0000 (14:10 -0700)
committerPhilip P. Moltmann <moltmann@google.com>
Tue, 31 May 2016 23:35:17 +0000 (23:35 +0000)
Only minimal changes just to make it work together with the other
plugins.

Bug: 28908572
Change-Id: Icac226b45e8a6885036466451d0e9f54a3b3c640
(cherry picked from commit d97fdfd943295ea90d37b092e66b7ad1701587a1)

packages/PrintRecommendationService/res/values/donottranslate.xml
packages/PrintRecommendationService/res/xml/vendorconfigs.xml
packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/MDnsUtils.java [new file with mode: 0755]
packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/PrinterHashMap.java [new file with mode: 0755]
packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java [new file with mode: 0755]
packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/VendorInfo.java [new file with mode: 0755]
packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/XeroxPrintServiceRecommendationPlugin.java [new file with mode: 0755]

index 86027cd..e9b97a3 100644 (file)
         <item>Hewlett Packard</item>
     </string-array>
 
+    <!-- Samsung plugin -->
     <string-array name="known_print_vendor_info_for_samsung" translatable="false">
         <item>com.sec.app.samsungprintservice</item>
         <item>Samsung Electronics</item>
         <item>Samsung</item>
     </string-array>
 
+    <!-- Xerox plugin -->
+    <string-array name="known_print_vendor_info_for_xerox" translatable="false">
+        <item>com.xerox.printservice</item>
+        <item>Xerox</item>
+        <item>Xerox</item>
+    </string-array>
+
     <array name="known_print_plugin_vendors" translatable="false">
         <item>@array/known_print_vendor_info_for_mopria</item>
         <item>@array/known_print_vendor_info_for_hp</item>
index 108ea66..52889ce 100644 (file)
     </vendor>
 
     <vendor>
-        <name>@string/plugin_vendor_xerox</name>
-        <package>com.xerox.printservice</package>
-        <mdns-names>
-            <mdns-name>Xerox</mdns-name>
-        </mdns-names>
-    </vendor>
-
-    <vendor>
         <name>@string/plugin_vendor_epson</name>
         <package>com.epson.mobilephone.android.epsonprintserviceplugin</package>
         <mdns-names>
index d95654f..ac60a88 100644 (file)
@@ -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 (executable)
index 0000000..7a2d0d8
--- /dev/null
@@ -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<String, byte[]> 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<String, byte[]> 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 (executable)
index 0000000..b88c7c7
--- /dev/null
@@ -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<String, NsdServiceInfo> {
+    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 (executable)
index 0000000..f64eed4
--- /dev/null
@@ -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<NsdManager.DiscoveryListener> 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<NsdServiceInfo> 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 (executable)
index 0000000..20967a7
--- /dev/null
@@ -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 (executable)
index 0000000..3fb9ca2
--- /dev/null
@@ -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();
+    }
+}