1 /*
2  * (c) Copyright 2016 Mopria Alliance, Inc.
3  * (c) Copyright 2016 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.printservice.recommendation.util;
19 
20 import android.net.nsd.NsdServiceInfo;
21 
22 import androidx.annotation.NonNull;
23 
24 import java.nio.charset.StandardCharsets;
25 import java.util.Map;
26 import java.util.Set;
27 
28 /**
29  * Utils for dealing with mDNS attributes
30  */
31 public class MDNSUtils {
32     public static final String ATTRIBUTE_TY = "ty";
33     public static final String ATTRIBUTE_PRODUCT = "product";
34     public static final String ATTRIBUTE_USB_MFG = "usb_mfg";
35     public static final String ATTRIBUTE_MFG = "mfg";
36 
MDNSUtils()37     private MDNSUtils() {
38     }
39 
40     /**
41      * Check if the service has any of a set of vendor names.
42      *
43      * @param serviceInfo The service
44      * @param vendorNames The vendors
45      *
46      * @return true iff the has any of the set of vendor names
47      */
isVendorPrinter(@onNull NsdServiceInfo serviceInfo, @NonNull Set<String> vendorNames)48     public static boolean isVendorPrinter(@NonNull NsdServiceInfo serviceInfo,
49             @NonNull Set<String> vendorNames) {
50         for (Map.Entry<String, byte[]> entry : serviceInfo.getAttributes().entrySet()) {
51             // keys are case insensitive
52             String key = entry.getKey().toLowerCase();
53 
54             switch (key) {
55                 case ATTRIBUTE_TY:
56                 case ATTRIBUTE_PRODUCT:
57                 case ATTRIBUTE_USB_MFG:
58                 case ATTRIBUTE_MFG:
59                     if (entry.getValue() != null) {
60                         if (containsVendor(new String(entry.getValue(), StandardCharsets.UTF_8),
61                                 vendorNames)) {
62                             return true;
63                         }
64                     }
65                     break;
66                 default:
67                     break;
68             }
69         }
70 
71         return false;
72     }
73 
74     /**
75      * Check if the attribute matches any of the vendor names, ignoring capitalization.
76      *
77      * @param attr        The attribute
78      * @param vendorNames The vendor names
79      *
80      * @return true iff the attribute matches any of the vendor names
81      */
containsVendor(@onNull String attr, @NonNull Set<String> vendorNames)82     private static boolean containsVendor(@NonNull String attr, @NonNull Set<String> vendorNames) {
83         for (String name : vendorNames) {
84             if (containsString(attr.toLowerCase(), name.toLowerCase())) {
85                 return true;
86             }
87         }
88         return false;
89     }
90 
91     /**
92      * Check if a string in another string.
93      *
94      * @param container The string that contains the string
95      * @param contained The string that is contained
96      *
97      * @return true if the string is contained in the other
98      */
containsString(@onNull String container, @NonNull String contained)99     private static boolean containsString(@NonNull String container, @NonNull String contained) {
100         return container.equalsIgnoreCase(contained) || container.contains(contained + " ");
101     }
102 
103     /**
104      * Return String from mDNS attribute byte array
105      *
106      * @param value the byte array with string data
107      *
108      * @return constructed string
109      */
getString(byte[] value)110     public static String getString(byte[] value) {
111         if (value != null) return new String(value, StandardCharsets.UTF_8);
112         return null;
113     }
114 
115     /**
116      * Check if service has a type of supported types set
117      *
118      * @param serviceInfo   The service
119      * @param serviceTypes  The supported service types set
120      *
121      * @return true if service has a type of supported types set
122      */
isSupportedServiceType(@onNull NsdServiceInfo serviceInfo, @NonNull Set<String> serviceTypes)123     public static boolean isSupportedServiceType(@NonNull NsdServiceInfo serviceInfo,
124             @NonNull Set<String> serviceTypes) {
125         String curType = serviceInfo.getServiceType().toLowerCase();
126         for (String type : serviceTypes) {
127             if (curType.contains(type.toLowerCase())) {
128                 return true;
129             }
130         }
131         return false;
132     }
133 }
134