1/*
2 * Copyright 2017 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
17package android.hardware.usb;
18
19import android.annotation.NonNull;
20import android.service.usb.UsbAccessoryFilterProto;
21
22import com.android.internal.util.dump.DualDumpOutputStream;
23
24import org.xmlpull.v1.XmlPullParser;
25import org.xmlpull.v1.XmlPullParserException;
26import org.xmlpull.v1.XmlSerializer;
27
28import java.io.IOException;
29import java.util.Objects;
30
31/**
32 * This class is used to describe a USB accessory.
33 * When used in HashMaps all values must be specified,
34 * but wildcards can be used for any of the fields in
35 * the package meta-data.
36 *
37 * @hide
38 */
39public class AccessoryFilter {
40    // USB accessory manufacturer (or null for unspecified)
41    public final String mManufacturer;
42    // USB accessory model (or null for unspecified)
43    public final String mModel;
44    // USB accessory version (or null for unspecified)
45    public final String mVersion;
46
47    public AccessoryFilter(String manufacturer, String model, String version) {
48        mManufacturer = manufacturer;
49        mModel = model;
50        mVersion = version;
51    }
52
53    public AccessoryFilter(UsbAccessory accessory) {
54        mManufacturer = accessory.getManufacturer();
55        mModel = accessory.getModel();
56        mVersion = accessory.getVersion();
57    }
58
59    public static AccessoryFilter read(XmlPullParser parser)
60            throws XmlPullParserException, IOException {
61        String manufacturer = null;
62        String model = null;
63        String version = null;
64
65        int count = parser.getAttributeCount();
66        for (int i = 0; i < count; i++) {
67            String name = parser.getAttributeName(i);
68            String value = parser.getAttributeValue(i);
69
70            if ("manufacturer".equals(name)) {
71                manufacturer = value;
72            } else if ("model".equals(name)) {
73                model = value;
74            } else if ("version".equals(name)) {
75                version = value;
76            }
77        }
78        return new AccessoryFilter(manufacturer, model, version);
79    }
80
81    public void write(XmlSerializer serializer)throws IOException {
82        serializer.startTag(null, "usb-accessory");
83        if (mManufacturer != null) {
84            serializer.attribute(null, "manufacturer", mManufacturer);
85        }
86        if (mModel != null) {
87            serializer.attribute(null, "model", mModel);
88        }
89        if (mVersion != null) {
90            serializer.attribute(null, "version", mVersion);
91        }
92        serializer.endTag(null, "usb-accessory");
93    }
94
95    public boolean matches(UsbAccessory acc) {
96        if (mManufacturer != null && !acc.getManufacturer().equals(mManufacturer)) return false;
97        if (mModel != null && !acc.getModel().equals(mModel)) return false;
98        return !(mVersion != null && !acc.getVersion().equals(mVersion));
99    }
100
101    /**
102     * Is the accessories described {@code accessory} covered by this filter?
103     *
104     * @param accessory A filter describing the accessory
105     *
106     * @return {@code true} iff this the filter covers the accessory
107     */
108    public boolean contains(AccessoryFilter accessory) {
109        if (mManufacturer != null && !Objects.equals(accessory.mManufacturer, mManufacturer)) {
110            return false;
111        }
112        if (mModel != null && !Objects.equals(accessory.mModel, mModel)) return false;
113        return !(mVersion != null && !Objects.equals(accessory.mVersion, mVersion));
114    }
115
116    @Override
117    public boolean equals(Object obj) {
118        // can't compare if we have wildcard strings
119        if (mManufacturer == null || mModel == null || mVersion == null) {
120            return false;
121        }
122        if (obj instanceof AccessoryFilter) {
123            AccessoryFilter filter = (AccessoryFilter)obj;
124            return (mManufacturer.equals(filter.mManufacturer) &&
125                    mModel.equals(filter.mModel) &&
126                    mVersion.equals(filter.mVersion));
127        }
128        if (obj instanceof UsbAccessory) {
129            UsbAccessory accessory = (UsbAccessory)obj;
130            return (mManufacturer.equals(accessory.getManufacturer()) &&
131                    mModel.equals(accessory.getModel()) &&
132                    mVersion.equals(accessory.getVersion()));
133        }
134        return false;
135    }
136
137    @Override
138    public int hashCode() {
139        return ((mManufacturer == null ? 0 : mManufacturer.hashCode()) ^
140                (mModel == null ? 0 : mModel.hashCode()) ^
141                (mVersion == null ? 0 : mVersion.hashCode()));
142    }
143
144    @Override
145    public String toString() {
146        return "AccessoryFilter[mManufacturer=\"" + mManufacturer +
147                "\", mModel=\"" + mModel +
148                "\", mVersion=\"" + mVersion + "\"]";
149    }
150
151    /**
152     * Write a description of the filter to a dump stream.
153     */
154    public void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
155        long token = dump.start(idName, id);
156
157        dump.write("manufacturer", UsbAccessoryFilterProto.MANUFACTURER, mManufacturer);
158        dump.write("model", UsbAccessoryFilterProto.MODEL, mModel);
159        dump.write("version", UsbAccessoryFilterProto.VERSION, mVersion);
160
161        dump.end(token);
162    }
163}
164