1/*
2 * Copyright (C) 2009 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.app;
18
19import org.xmlpull.v1.XmlPullParser;
20import org.xmlpull.v1.XmlPullParserException;
21
22import android.content.ComponentName;
23import android.content.Context;
24import android.content.pm.ApplicationInfo;
25import android.content.pm.PackageManager;
26import android.content.pm.ResolveInfo;
27import android.content.pm.ServiceInfo;
28import android.content.pm.PackageManager.NameNotFoundException;
29import android.content.res.Resources.NotFoundException;
30import android.content.res.Resources;
31import android.content.res.TypedArray;
32import android.content.res.XmlResourceParser;
33import android.graphics.drawable.Drawable;
34import android.os.Parcel;
35import android.os.Parcelable;
36import android.service.wallpaper.WallpaperService;
37import android.util.AttributeSet;
38import android.util.Printer;
39import android.util.Xml;
40
41import java.io.IOException;
42
43/**
44 * This class is used to specify meta information of a wallpaper service.
45 */
46public final class WallpaperInfo implements Parcelable {
47    static final String TAG = "WallpaperInfo";
48
49    /**
50     * The Service that implements this wallpaper component.
51     */
52    final ResolveInfo mService;
53
54    /**
55     * The wallpaper setting activity's name, to
56     * launch the setting activity of this wallpaper.
57     */
58    final String mSettingsActivityName;
59
60    /**
61     * Resource identifier for this wallpaper's thumbnail image.
62     */
63    final int mThumbnailResource;
64
65    /**
66     * Resource identifier for a string indicating the author of the wallpaper.
67     */
68    final int mAuthorResource;
69
70    /**
71     * Resource identifier for a string containing a short description of the wallpaper.
72     */
73    final int mDescriptionResource;
74
75    /**
76     * Constructor.
77     *
78     * @param context The Context in which we are parsing the wallpaper.
79     * @param service The ResolveInfo returned from the package manager about
80     * this wallpaper's component.
81     */
82    public WallpaperInfo(Context context, ResolveInfo service)
83            throws XmlPullParserException, IOException {
84        mService = service;
85        ServiceInfo si = service.serviceInfo;
86
87        PackageManager pm = context.getPackageManager();
88        String settingsActivityComponent = null;
89        int thumbnailRes = -1;
90        int authorRes = -1;
91        int descriptionRes = -1;
92
93        XmlResourceParser parser = null;
94        try {
95            parser = si.loadXmlMetaData(pm, WallpaperService.SERVICE_META_DATA);
96            if (parser == null) {
97                throw new XmlPullParserException("No "
98                        + WallpaperService.SERVICE_META_DATA + " meta-data");
99            }
100
101            Resources res = pm.getResourcesForApplication(si.applicationInfo);
102
103            AttributeSet attrs = Xml.asAttributeSet(parser);
104
105            int type;
106            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
107                    && type != XmlPullParser.START_TAG) {
108            }
109
110            String nodeName = parser.getName();
111            if (!"wallpaper".equals(nodeName)) {
112                throw new XmlPullParserException(
113                        "Meta-data does not start with wallpaper tag");
114            }
115
116            TypedArray sa = res.obtainAttributes(attrs,
117                    com.android.internal.R.styleable.Wallpaper);
118            settingsActivityComponent = sa.getString(
119                    com.android.internal.R.styleable.Wallpaper_settingsActivity);
120
121            thumbnailRes = sa.getResourceId(
122                    com.android.internal.R.styleable.Wallpaper_thumbnail,
123                    -1);
124            authorRes = sa.getResourceId(
125                    com.android.internal.R.styleable.Wallpaper_author,
126                    -1);
127            descriptionRes = sa.getResourceId(
128                    com.android.internal.R.styleable.Wallpaper_description,
129                    -1);
130
131            sa.recycle();
132        } catch (NameNotFoundException e) {
133            throw new XmlPullParserException(
134                    "Unable to create context for: " + si.packageName);
135        } finally {
136            if (parser != null) parser.close();
137        }
138
139        mSettingsActivityName = settingsActivityComponent;
140        mThumbnailResource = thumbnailRes;
141        mAuthorResource = authorRes;
142        mDescriptionResource = descriptionRes;
143    }
144
145    WallpaperInfo(Parcel source) {
146        mSettingsActivityName = source.readString();
147        mThumbnailResource = source.readInt();
148        mAuthorResource = source.readInt();
149        mDescriptionResource = source.readInt();
150        mService = ResolveInfo.CREATOR.createFromParcel(source);
151    }
152
153    /**
154     * Return the .apk package that implements this wallpaper.
155     */
156    public String getPackageName() {
157        return mService.serviceInfo.packageName;
158    }
159
160    /**
161     * Return the class name of the service component that implements
162     * this wallpaper.
163     */
164    public String getServiceName() {
165        return mService.serviceInfo.name;
166    }
167
168    /**
169     * Return the raw information about the Service implementing this
170     * wallpaper.  Do not modify the returned object.
171     */
172    public ServiceInfo getServiceInfo() {
173        return mService.serviceInfo;
174    }
175
176    /**
177     * Return the component of the service that implements this wallpaper.
178     */
179    public ComponentName getComponent() {
180        return new ComponentName(mService.serviceInfo.packageName,
181                mService.serviceInfo.name);
182    }
183
184    /**
185     * Load the user-displayed label for this wallpaper.
186     *
187     * @param pm Supply a PackageManager used to load the wallpaper's
188     * resources.
189     */
190    public CharSequence loadLabel(PackageManager pm) {
191        return mService.loadLabel(pm);
192    }
193
194    /**
195     * Load the user-displayed icon for this wallpaper.
196     *
197     * @param pm Supply a PackageManager used to load the wallpaper's
198     * resources.
199     */
200    public Drawable loadIcon(PackageManager pm) {
201        return mService.loadIcon(pm);
202    }
203
204    /**
205     * Load the thumbnail image for this wallpaper.
206     *
207     * @param pm Supply a PackageManager used to load the wallpaper's
208     * resources.
209     */
210    public Drawable loadThumbnail(PackageManager pm) {
211        if (mThumbnailResource < 0) return null;
212
213        return pm.getDrawable(mService.serviceInfo.packageName,
214                              mThumbnailResource,
215                              mService.serviceInfo.applicationInfo);
216    }
217
218    /**
219     * Return a string indicating the author(s) of this wallpaper.
220     */
221    public CharSequence loadAuthor(PackageManager pm) throws NotFoundException {
222        if (mAuthorResource <= 0) throw new NotFoundException();
223        String packageName = mService.resolvePackageName;
224        ApplicationInfo applicationInfo = null;
225        if (packageName == null) {
226            packageName = mService.serviceInfo.packageName;
227            applicationInfo = mService.serviceInfo.applicationInfo;
228        }
229        return pm.getText(packageName, mAuthorResource, applicationInfo);
230    }
231
232    /**
233     * Return a brief summary of this wallpaper's behavior.
234     */
235    public CharSequence loadDescription(PackageManager pm) throws NotFoundException {
236        String packageName = mService.resolvePackageName;
237        ApplicationInfo applicationInfo = null;
238        if (packageName == null) {
239            packageName = mService.serviceInfo.packageName;
240            applicationInfo = mService.serviceInfo.applicationInfo;
241        }
242        if (mService.serviceInfo.descriptionRes != 0) {
243            return pm.getText(packageName, mService.serviceInfo.descriptionRes,
244                    applicationInfo);
245
246        }
247        if (mDescriptionResource <= 0) throw new NotFoundException();
248        return pm.getText(packageName, mDescriptionResource,
249                mService.serviceInfo.applicationInfo);
250    }
251
252    /**
253     * Return the class name of an activity that provides a settings UI for
254     * the wallpaper.  You can launch this activity be starting it with
255     * an {@link android.content.Intent} whose action is MAIN and with an
256     * explicit {@link android.content.ComponentName}
257     * composed of {@link #getPackageName} and the class name returned here.
258     *
259     * <p>A null will be returned if there is no settings activity associated
260     * with the wallpaper.
261     */
262    public String getSettingsActivity() {
263        return mSettingsActivityName;
264    }
265
266    public void dump(Printer pw, String prefix) {
267        pw.println(prefix + "Service:");
268        mService.dump(pw, prefix + "  ");
269        pw.println(prefix + "mSettingsActivityName=" + mSettingsActivityName);
270    }
271
272    @Override
273    public String toString() {
274        return "WallpaperInfo{" + mService.serviceInfo.name
275                + ", settings: "
276                + mSettingsActivityName + "}";
277    }
278
279    /**
280     * Used to package this object into a {@link Parcel}.
281     *
282     * @param dest The {@link Parcel} to be written.
283     * @param flags The flags used for parceling.
284     */
285    public void writeToParcel(Parcel dest, int flags) {
286        dest.writeString(mSettingsActivityName);
287        dest.writeInt(mThumbnailResource);
288        dest.writeInt(mAuthorResource);
289        dest.writeInt(mDescriptionResource);
290        mService.writeToParcel(dest, flags);
291    }
292
293    /**
294     * Used to make this class parcelable.
295     */
296    public static final Parcelable.Creator<WallpaperInfo> CREATOR = new Parcelable.Creator<WallpaperInfo>() {
297        public WallpaperInfo createFromParcel(Parcel source) {
298            return new WallpaperInfo(source);
299        }
300
301        public WallpaperInfo[] newArray(int size) {
302            return new WallpaperInfo[size];
303        }
304    };
305
306    public int describeContents() {
307        return 0;
308    }
309}
310