Home | History | Annotate | Download | only in hp
      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 
     17 package com.android.printservice.recommendation.plugin.hp;
     18 
     19 import android.content.Context;
     20 import android.content.res.TypedArray;
     21 import android.net.nsd.NsdManager;
     22 import android.net.nsd.NsdServiceInfo;
     23 import android.text.TextUtils;
     24 
     25 import com.android.printservice.recommendation.R;
     26 import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer;
     27 
     28 import java.net.InetAddress;
     29 import java.util.ArrayList;
     30 import java.util.HashMap;
     31 import java.util.List;
     32 import java.util.Map;
     33 import java.util.Set;
     34 
     35 public 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     /**
    180      * @return The {@link InetAddress addresses} of the discovered printers
    181      */
    182     public ArrayList<InetAddress> getPrinters() {
    183         ArrayList<InetAddress> printerAddressess = new ArrayList<>();
    184 
    185         for (PrinterHashMap oneVendorPrinters : mVendorHashMap.values()) {
    186             for (NsdServiceInfo printer : oneVendorPrinters.values()) {
    187                 printerAddressess.add(printer.getHost());
    188             }
    189         }
    190 
    191         return printerAddressess;
    192     }
    193 }
    194