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
18package com.android.printservice.recommendation.util;
19
20import android.annotation.NonNull;
21import android.net.nsd.NsdServiceInfo;
22
23import java.nio.charset.StandardCharsets;
24import java.util.Map;
25import java.util.Set;
26
27/**
28 * Utils for dealing with mDNS attributes
29 */
30public class MDNSUtils {
31    public static final String ATTRIBUTE_TY = "ty";
32    public static final String ATTRIBUTE_PRODUCT = "product";
33    public static final String ATTRIBUTE_USB_MFG = "usb_mfg";
34    public static final String ATTRIBUTE_MFG = "mfg";
35
36    private MDNSUtils() {
37    }
38
39    /**
40     * Check if the service has any of a set of vendor names.
41     *
42     * @param serviceInfo The service
43     * @param vendorNames The vendors
44     *
45     * @return true iff the has any of the set of vendor names
46     */
47    public static boolean isVendorPrinter(@NonNull NsdServiceInfo serviceInfo,
48            @NonNull Set<String> vendorNames) {
49        for (Map.Entry<String, byte[]> entry : serviceInfo.getAttributes().entrySet()) {
50            // keys are case insensitive
51            String key = entry.getKey().toLowerCase();
52
53            switch (key) {
54                case ATTRIBUTE_TY:
55                case ATTRIBUTE_PRODUCT:
56                case ATTRIBUTE_USB_MFG:
57                case ATTRIBUTE_MFG:
58                    if (entry.getValue() != null) {
59                        if (containsVendor(new String(entry.getValue(), StandardCharsets.UTF_8),
60                                vendorNames)) {
61                            return true;
62                        }
63                    }
64                    break;
65                default:
66                    break;
67            }
68        }
69
70        return false;
71    }
72
73    /**
74     * Check if the attribute matches any of the vendor names, ignoring capitalization.
75     *
76     * @param attr        The attribute
77     * @param vendorNames The vendor names
78     *
79     * @return true iff the attribute matches any of the vendor names
80     */
81    private static boolean containsVendor(@NonNull String attr, @NonNull Set<String> vendorNames) {
82        for (String name : vendorNames) {
83            if (containsString(attr.toLowerCase(), name.toLowerCase())) {
84                return true;
85            }
86        }
87        return false;
88    }
89
90    /**
91     * Check if a string in another string.
92     *
93     * @param container The string that contains the string
94     * @param contained The string that is contained
95     *
96     * @return true if the string is contained in the other
97     */
98    private static boolean containsString(@NonNull String container, @NonNull String contained) {
99        return container.equalsIgnoreCase(contained) || container.contains(contained + " ");
100    }
101
102    /**
103     * Return String from mDNS attribute byte array
104     *
105     * @param value the byte array with string data
106     *
107     * @return constructed string
108     */
109    public static String getString(byte[] value) {
110        if (value != null) return new String(value, StandardCharsets.UTF_8);
111        return null;
112    }
113
114    /**
115     * Check if service has a type of supported types set
116     *
117     * @param serviceInfo   The service
118     * @param serviceTypes  The supported service types set
119     *
120     * @return true if service has a type of supported types set
121     */
122    public static boolean isSupportedServiceType(@NonNull NsdServiceInfo serviceInfo,
123            @NonNull Set<String> serviceTypes) {
124        String curType = serviceInfo.getServiceType().toLowerCase();
125        for (String type : serviceTypes) {
126            if (curType.contains(type.toLowerCase())) {
127                return true;
128            }
129        }
130        return false;
131    }
132}
133