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
17package android.printservice.recommendation;
18
19import android.annotation.IntRange;
20import android.annotation.NonNull;
21import android.annotation.SystemApi;
22import android.os.Parcel;
23import android.os.Parcelable;
24import android.printservice.PrintService;
25
26import com.android.internal.util.Preconditions;
27
28import java.net.InetAddress;
29import java.net.UnknownHostException;
30import java.util.ArrayList;
31import java.util.List;
32
33/**
34 * A recommendation to install a {@link PrintService print service}.
35 *
36 * @hide
37 */
38@SystemApi
39public final class RecommendationInfo implements Parcelable {
40    /** Package name of the print service. */
41    private @NonNull final CharSequence mPackageName;
42
43    /** Display name of the print service. */
44    private @NonNull final CharSequence mName;
45
46    /** Printers the print service would discover if installed. */
47    @NonNull private final List<InetAddress> mDiscoveredPrinters;
48
49    /** If the service detects printer from multiple vendors. */
50    private final boolean mRecommendsMultiVendorService;
51
52    /**
53     * Create a new recommendation.
54     *
55     * @param packageName                  Package name of the print service
56     * @param name                         Display name of the print service
57     * @param discoveredPrinters           The {@link InetAddress addresses} of the discovered
58     *                                     printers. Cannot be null or empty.
59     * @param recommendsMultiVendorService If the service detects printer from multiple vendor
60     */
61    public RecommendationInfo(@NonNull CharSequence packageName, @NonNull CharSequence name,
62            @NonNull List<InetAddress> discoveredPrinters, boolean recommendsMultiVendorService) {
63        mPackageName = Preconditions.checkStringNotEmpty(packageName);
64        mName = Preconditions.checkStringNotEmpty(name);
65        mDiscoveredPrinters = Preconditions.checkCollectionElementsNotNull(discoveredPrinters,
66                    "discoveredPrinters");
67        mRecommendsMultiVendorService = recommendsMultiVendorService;
68    }
69
70    /**
71     * Create a new recommendation.
72     *
73     * @param packageName                  Package name of the print service
74     * @param name                         Display name of the print service
75     * @param numDiscoveredPrinters        Number of printers the print service would discover if
76     *                                     installed
77     * @param recommendsMultiVendorService If the service detects printer from multiple vendor
78     *
79     * @deprecated Use {@link RecommendationInfo(String, String, List<InetAddress>, boolean)}
80     *             instead
81     */
82    @Deprecated
83    public RecommendationInfo(@NonNull CharSequence packageName, @NonNull CharSequence name,
84            @IntRange(from = 0) int numDiscoveredPrinters, boolean recommendsMultiVendorService) {
85        throw new IllegalArgumentException("This constructor has been deprecated");
86    }
87
88    /**
89     * Read a list of blobs from the parcel and return it as a list of {@link InetAddress
90     * addresses}.
91     *
92     * @param parcel the parcel to read the blobs from
93     *
94     * @return The list of {@link InetAddress addresses} or null if no printers were found.
95     *
96     * @see #writeToParcel(Parcel, int)
97     */
98    @NonNull private static ArrayList<InetAddress> readDiscoveredPrinters(@NonNull Parcel parcel) {
99        int numDiscoveredPrinters = parcel.readInt();
100        ArrayList<InetAddress> discoveredPrinters = new ArrayList<>(numDiscoveredPrinters);
101
102        for (int i = 0; i < numDiscoveredPrinters; i++) {
103            try {
104                discoveredPrinters.add(InetAddress.getByAddress(parcel.readBlob()));
105            } catch (UnknownHostException e) {
106                throw new IllegalArgumentException(e);
107            }
108        }
109
110        return discoveredPrinters;
111    }
112
113    /**
114     * Create a new recommendation from a parcel.
115     *
116     * @param parcel The parcel containing the data
117     *
118     * @see #CREATOR
119     */
120    private RecommendationInfo(@NonNull Parcel parcel) {
121        this(parcel.readCharSequence(), parcel.readCharSequence(), readDiscoveredPrinters(parcel),
122                parcel.readByte() != 0);
123    }
124
125    /**
126     * @return The package name the recommendations recommends.
127     */
128    public CharSequence getPackageName() {
129        return mPackageName;
130    }
131
132    /**
133     * @return Whether the recommended print service detects printers of more than one vendor.
134     */
135    public boolean recommendsMultiVendorService() {
136        return mRecommendsMultiVendorService;
137    }
138
139    /**
140     * @return The {@link InetAddress address} of the printers the print service would detect.
141     */
142    @NonNull public List<InetAddress> getDiscoveredPrinters() {
143        return mDiscoveredPrinters;
144    }
145
146    /**
147     * @return The number of printer the print service would detect.
148     */
149    public int getNumDiscoveredPrinters() {
150        return mDiscoveredPrinters.size();
151    }
152
153    /**
154     * @return The name of the recommended print service.
155     */
156    public CharSequence getName() {
157        return mName;
158    }
159
160    @Override
161    public int describeContents() {
162        return 0;
163    }
164
165    @Override
166    public void writeToParcel(Parcel dest, int flags) {
167        dest.writeCharSequence(mPackageName);
168        dest.writeCharSequence(mName);
169
170        int numDiscoveredPrinters = mDiscoveredPrinters.size();
171        dest.writeInt(numDiscoveredPrinters);
172
173        for (InetAddress printer : mDiscoveredPrinters) {
174            dest.writeBlob(printer.getAddress());
175        }
176
177        dest.writeByte((byte) (mRecommendsMultiVendorService ? 1 : 0));
178    }
179
180    /**
181     * Utility class used to create new print service recommendation objects from parcels.
182     *
183     * @see #RecommendationInfo(Parcel)
184     */
185    public static final Creator<RecommendationInfo> CREATOR =
186            new Creator<RecommendationInfo>() {
187                @Override
188                public RecommendationInfo createFromParcel(Parcel in) {
189                    return new RecommendationInfo(in);
190                }
191
192                @Override
193                public RecommendationInfo[] newArray(int size) {
194                    return new RecommendationInfo[size];
195                }
196    };
197}
198