1 /*
2  * Copyright (C) 2013 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 android.printservice;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.content.ComponentName;
23 import android.content.Context;
24 import android.content.pm.PackageManager;
25 import android.content.pm.PackageManager.NameNotFoundException;
26 import android.content.pm.ResolveInfo;
27 import android.content.res.Resources;
28 import android.content.res.TypedArray;
29 import android.content.res.XmlResourceParser;
30 import android.os.Parcel;
31 import android.os.Parcelable;
32 import android.util.AttributeSet;
33 import android.util.Log;
34 import android.util.Xml;
35 
36 import org.xmlpull.v1.XmlPullParser;
37 import org.xmlpull.v1.XmlPullParserException;
38 
39 import java.io.IOException;
40 
41 /**
42  * This class describes a {@link PrintService}. A print service knows
43  * how to communicate with one or more printers over one or more protocols
44  * and exposes printers for use by the applications via the platform print
45  * APIs.
46  *
47  * @see PrintService
48  * @see android.print.PrintManager
49  *
50  * @hide
51  */
52 @SystemApi
53 public final class PrintServiceInfo implements Parcelable {
54 
55     private static final String LOG_TAG = PrintServiceInfo.class.getSimpleName();
56 
57     private static final String TAG_PRINT_SERVICE = "print-service";
58 
59     private final String mId;
60 
61     private boolean mIsEnabled;
62 
63     private final ResolveInfo mResolveInfo;
64 
65     private final String mSettingsActivityName;
66 
67     private final String mAddPrintersActivityName;
68 
69     private final String mAdvancedPrintOptionsActivityName;
70 
71     /**
72      * Creates a new instance.
73      *
74      * @hide
75      */
PrintServiceInfo(Parcel parcel)76     public PrintServiceInfo(Parcel parcel) {
77         mId = parcel.readString();
78         mIsEnabled = parcel.readByte() != 0;
79         mResolveInfo = parcel.readParcelable(null);
80         mSettingsActivityName = parcel.readString();
81         mAddPrintersActivityName = parcel.readString();
82         mAdvancedPrintOptionsActivityName = parcel.readString();
83     }
84 
85     /**
86      * Creates a new instance.
87      *
88      * @param resolveInfo The service resolve info.
89      * @param settingsActivityName Optional settings activity name.
90      * @param addPrintersActivityName Optional add printers activity name.
91      * @param advancedPrintOptionsActivityName Optional advanced print options activity.
92      *
93      * @hide
94      */
PrintServiceInfo(ResolveInfo resolveInfo, String settingsActivityName, String addPrintersActivityName, String advancedPrintOptionsActivityName)95     public PrintServiceInfo(ResolveInfo resolveInfo, String settingsActivityName,
96             String addPrintersActivityName, String advancedPrintOptionsActivityName) {
97         mId = new ComponentName(resolveInfo.serviceInfo.packageName,
98                 resolveInfo.serviceInfo.name).flattenToString();
99         mResolveInfo = resolveInfo;
100         mSettingsActivityName = settingsActivityName;
101         mAddPrintersActivityName = addPrintersActivityName;
102         mAdvancedPrintOptionsActivityName = advancedPrintOptionsActivityName;
103     }
104 
105     /**
106      * Return the component name for this print service.
107      *
108      * @return The component name for this print service.
109      */
getComponentName()110     public @NonNull ComponentName getComponentName() {
111         return new ComponentName(mResolveInfo.serviceInfo.packageName,
112                 mResolveInfo.serviceInfo.name);
113     }
114 
115     /**
116      * Creates a new instance.
117      *
118      * @param context Context for accessing resources.
119      * @param resolveInfo The service resolve info.
120      * @return The created instance.
121      *
122      * @hide
123      */
create(Context context, ResolveInfo resolveInfo)124     public static PrintServiceInfo create(Context context, ResolveInfo resolveInfo) {
125         String settingsActivityName = null;
126         String addPrintersActivityName = null;
127         String advancedPrintOptionsActivityName = null;
128 
129         XmlResourceParser parser = null;
130         PackageManager packageManager = context.getPackageManager();
131         parser = resolveInfo.serviceInfo.loadXmlMetaData(packageManager,
132                 PrintService.SERVICE_META_DATA);
133         if (parser != null) {
134             try {
135                 int type = 0;
136                 while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
137                     type = parser.next();
138                 }
139 
140                 String nodeName = parser.getName();
141                 if (!TAG_PRINT_SERVICE.equals(nodeName)) {
142                     Log.e(LOG_TAG, "Ignoring meta-data that does not start with "
143                             + TAG_PRINT_SERVICE + " tag");
144                 } else {
145                     Resources resources = packageManager.getResourcesForApplication(
146                             resolveInfo.serviceInfo.applicationInfo);
147                     AttributeSet allAttributes = Xml.asAttributeSet(parser);
148                     TypedArray attributes = resources.obtainAttributes(allAttributes,
149                             com.android.internal.R.styleable.PrintService);
150 
151                     settingsActivityName = attributes.getString(
152                             com.android.internal.R.styleable.PrintService_settingsActivity);
153 
154                     addPrintersActivityName = attributes.getString(
155                             com.android.internal.R.styleable.PrintService_addPrintersActivity);
156 
157                     advancedPrintOptionsActivityName = attributes.getString(com.android.internal
158                             .R.styleable.PrintService_advancedPrintOptionsActivity);
159 
160                     attributes.recycle();
161                 }
162             } catch (IOException ioe) {
163                 Log.w(LOG_TAG, "Error reading meta-data:" + ioe);
164             } catch (XmlPullParserException xppe) {
165                 Log.w(LOG_TAG, "Error reading meta-data:" + xppe);
166             } catch (NameNotFoundException e) {
167                 Log.e(LOG_TAG, "Unable to load resources for: "
168                         + resolveInfo.serviceInfo.packageName);
169             } finally {
170                 if (parser != null) {
171                     parser.close();
172                 }
173             }
174         }
175 
176         return new PrintServiceInfo(resolveInfo, settingsActivityName,
177                 addPrintersActivityName, advancedPrintOptionsActivityName);
178     }
179 
180     /**
181      * The accessibility service id.
182      * <p>
183      * <strong>Generated by the system.</strong>
184      * </p>
185      *
186      * @return The id.
187      *
188      * @hide
189      */
getId()190     public String getId() {
191         return mId;
192     }
193 
194     /**
195      * If the service was enabled when it was read from the system.
196      *
197      * @return The id.
198      *
199      * @hide
200      */
isEnabled()201     public boolean isEnabled() {
202         return mIsEnabled;
203     }
204 
205     /**
206      * Mark a service as enabled or not
207      *
208      * @param isEnabled If the service should be marked as enabled.
209      *
210      * @hide
211      */
setIsEnabled(boolean isEnabled)212     public void setIsEnabled(boolean isEnabled) {
213         mIsEnabled = isEnabled;
214     }
215 
216     /**
217      * The service {@link ResolveInfo}.
218      *
219      * @return The info.
220      *
221      * @hide
222      */
getResolveInfo()223     public ResolveInfo getResolveInfo() {
224         return mResolveInfo;
225     }
226 
227     /**
228      * The settings activity name.
229      * <p>
230      * <strong>Statically set from
231      * {@link PrintService#SERVICE_META_DATA meta-data}.</strong>
232      * </p>
233      *
234      * @return The settings activity name.
235      *
236      * @hide
237      */
getSettingsActivityName()238     public String getSettingsActivityName() {
239         return mSettingsActivityName;
240     }
241 
242     /**
243      * The add printers activity name.
244      * <p>
245      * <strong>Statically set from
246      * {@link PrintService#SERVICE_META_DATA meta-data}.</strong>
247      * </p>
248      *
249      * @return The add printers activity name.
250      *
251      * @hide
252      */
getAddPrintersActivityName()253     public String getAddPrintersActivityName() {
254         return mAddPrintersActivityName;
255     }
256 
257     /**
258      * The advanced print options activity name.
259      * <p>
260      * <strong>Statically set from
261      * {@link PrintService#SERVICE_META_DATA meta-data}.</strong>
262      * </p>
263      *
264      * @return The advanced print options activity name.
265      *
266      * @hide
267      */
getAdvancedOptionsActivityName()268     public String getAdvancedOptionsActivityName() {
269         return mAdvancedPrintOptionsActivityName;
270     }
271 
272     /**
273      * {@inheritDoc}
274      */
275     @Override
describeContents()276     public int describeContents() {
277         return 0;
278     }
279 
280     @Override
writeToParcel(Parcel parcel, int flagz)281     public void writeToParcel(Parcel parcel, int flagz) {
282         parcel.writeString(mId);
283         parcel.writeByte((byte)(mIsEnabled ? 1 : 0));
284         parcel.writeParcelable(mResolveInfo, 0);
285         parcel.writeString(mSettingsActivityName);
286         parcel.writeString(mAddPrintersActivityName);
287         parcel.writeString(mAdvancedPrintOptionsActivityName);
288     }
289 
290     @Override
hashCode()291     public int hashCode() {
292         return 31 + ((mId == null) ? 0 : mId.hashCode());
293     }
294 
295     @Override
equals(@ullable Object obj)296     public boolean equals(@Nullable Object obj) {
297         if (this == obj) {
298             return true;
299         }
300         if (obj == null) {
301             return false;
302         }
303         if (getClass() != obj.getClass()) {
304             return false;
305         }
306         PrintServiceInfo other = (PrintServiceInfo) obj;
307         if (mId == null) {
308             if (other.mId != null) {
309                 return false;
310             }
311         } else if (!mId.equals(other.mId)) {
312             return false;
313         }
314         return true;
315     }
316 
317     @NonNull
318     @Override
toString()319     public String toString() {
320         StringBuilder builder = new StringBuilder();
321         builder.append("PrintServiceInfo{");
322         builder.append("id=").append(mId);
323         builder.append("isEnabled=").append(mIsEnabled);
324         builder.append(", resolveInfo=").append(mResolveInfo);
325         builder.append(", settingsActivityName=").append(mSettingsActivityName);
326         builder.append(", addPrintersActivityName=").append(mAddPrintersActivityName);
327         builder.append(", advancedPrintOptionsActivityName=")
328                 .append(mAdvancedPrintOptionsActivityName);
329         builder.append("}");
330         return builder.toString();
331     }
332 
333     public static final @android.annotation.NonNull Parcelable.Creator<PrintServiceInfo> CREATOR =
334             new Parcelable.Creator<PrintServiceInfo>() {
335         @Override
336         public PrintServiceInfo createFromParcel(Parcel parcel) {
337             return new PrintServiceInfo(parcel);
338         }
339 
340         @Override
341         public PrintServiceInfo[] newArray(int size) {
342             return new PrintServiceInfo[size];
343         }
344     };
345 }
346