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 17 package android.app; 18 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.content.pm.ApplicationInfo; 22 import android.content.pm.PackageManager; 23 import android.content.pm.PackageManager.NameNotFoundException; 24 import android.content.pm.ResolveInfo; 25 import android.content.pm.ServiceInfo; 26 import android.content.res.Resources; 27 import android.content.res.Resources.NotFoundException; 28 import android.content.res.TypedArray; 29 import android.content.res.XmlResourceParser; 30 import android.graphics.drawable.Drawable; 31 import android.net.Uri; 32 import android.os.Parcel; 33 import android.os.Parcelable; 34 import android.service.wallpaper.WallpaperService; 35 import android.util.AttributeSet; 36 import android.util.Printer; 37 import android.util.Xml; 38 39 import org.xmlpull.v1.XmlPullParser; 40 import org.xmlpull.v1.XmlPullParserException; 41 42 import java.io.IOException; 43 44 /** 45 * This class is used to specify meta information of a wallpaper service. 46 */ 47 public final class WallpaperInfo implements Parcelable { 48 static final String TAG = "WallpaperInfo"; 49 50 /** 51 * The Service that implements this wallpaper component. 52 */ 53 final ResolveInfo mService; 54 55 /** 56 * The wallpaper setting activity's name, to 57 * launch the setting activity of this wallpaper. 58 */ 59 final String mSettingsActivityName; 60 61 /** 62 * Resource identifier for this wallpaper's thumbnail image. 63 */ 64 final int mThumbnailResource; 65 66 /** 67 * Resource identifier for a string indicating the author of the wallpaper. 68 */ 69 final int mAuthorResource; 70 71 /** 72 * Resource identifier for a string containing a short description of the wallpaper. 73 */ 74 final int mDescriptionResource; 75 76 final int mContextUriResource; 77 final int mContextDescriptionResource; 78 final boolean mShowMetadataInPreview; 79 final boolean mSupportsAmbientMode; 80 81 /** 82 * Constructor. 83 * 84 * @param context The Context in which we are parsing the wallpaper. 85 * @param service The ResolveInfo returned from the package manager about 86 * this wallpaper's component. 87 */ 88 public WallpaperInfo(Context context, ResolveInfo service) 89 throws XmlPullParserException, IOException { 90 mService = service; 91 ServiceInfo si = service.serviceInfo; 92 93 final PackageManager pm = context.getPackageManager(); 94 XmlResourceParser parser = null; 95 try { 96 parser = si.loadXmlMetaData(pm, WallpaperService.SERVICE_META_DATA); 97 if (parser == null) { 98 throw new XmlPullParserException("No " 99 + WallpaperService.SERVICE_META_DATA + " meta-data"); 100 } 101 102 Resources res = pm.getResourcesForApplication(si.applicationInfo); 103 104 AttributeSet attrs = Xml.asAttributeSet(parser); 105 106 int type; 107 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 108 && type != XmlPullParser.START_TAG) { 109 } 110 111 String nodeName = parser.getName(); 112 if (!"wallpaper".equals(nodeName)) { 113 throw new XmlPullParserException( 114 "Meta-data does not start with wallpaper tag"); 115 } 116 117 TypedArray sa = res.obtainAttributes(attrs, 118 com.android.internal.R.styleable.Wallpaper); 119 mSettingsActivityName = sa.getString( 120 com.android.internal.R.styleable.Wallpaper_settingsActivity); 121 122 mThumbnailResource = sa.getResourceId( 123 com.android.internal.R.styleable.Wallpaper_thumbnail, 124 -1); 125 mAuthorResource = sa.getResourceId( 126 com.android.internal.R.styleable.Wallpaper_author, 127 -1); 128 mDescriptionResource = sa.getResourceId( 129 com.android.internal.R.styleable.Wallpaper_description, 130 -1); 131 mContextUriResource = sa.getResourceId( 132 com.android.internal.R.styleable.Wallpaper_contextUri, 133 -1); 134 mContextDescriptionResource = sa.getResourceId( 135 com.android.internal.R.styleable.Wallpaper_contextDescription, 136 -1); 137 mShowMetadataInPreview = sa.getBoolean( 138 com.android.internal.R.styleable.Wallpaper_showMetadataInPreview, 139 false); 140 mSupportsAmbientMode = sa.getBoolean( 141 com.android.internal.R.styleable.Wallpaper_supportsAmbientMode, 142 false); 143 144 sa.recycle(); 145 } catch (NameNotFoundException e) { 146 throw new XmlPullParserException( 147 "Unable to create context for: " + si.packageName); 148 } finally { 149 if (parser != null) parser.close(); 150 } 151 } 152 153 WallpaperInfo(Parcel source) { 154 mSettingsActivityName = source.readString(); 155 mThumbnailResource = source.readInt(); 156 mAuthorResource = source.readInt(); 157 mDescriptionResource = source.readInt(); 158 mContextUriResource = source.readInt(); 159 mContextDescriptionResource = source.readInt(); 160 mShowMetadataInPreview = source.readInt() != 0; 161 mSupportsAmbientMode = source.readInt() != 0; 162 mService = ResolveInfo.CREATOR.createFromParcel(source); 163 } 164 165 /** 166 * Return the .apk package that implements this wallpaper. 167 */ 168 public String getPackageName() { 169 return mService.serviceInfo.packageName; 170 } 171 172 /** 173 * Return the class name of the service component that implements 174 * this wallpaper. 175 */ 176 public String getServiceName() { 177 return mService.serviceInfo.name; 178 } 179 180 /** 181 * Return the raw information about the Service implementing this 182 * wallpaper. Do not modify the returned object. 183 */ 184 public ServiceInfo getServiceInfo() { 185 return mService.serviceInfo; 186 } 187 188 /** 189 * Return the component of the service that implements this wallpaper. 190 */ 191 public ComponentName getComponent() { 192 return new ComponentName(mService.serviceInfo.packageName, 193 mService.serviceInfo.name); 194 } 195 196 /** 197 * Load the user-displayed label for this wallpaper. 198 * 199 * @param pm Supply a PackageManager used to load the wallpaper's 200 * resources. 201 */ 202 public CharSequence loadLabel(PackageManager pm) { 203 return mService.loadLabel(pm); 204 } 205 206 /** 207 * Load the user-displayed icon for this wallpaper. 208 * 209 * @param pm Supply a PackageManager used to load the wallpaper's 210 * resources. 211 */ 212 public Drawable loadIcon(PackageManager pm) { 213 return mService.loadIcon(pm); 214 } 215 216 /** 217 * Load the thumbnail image for this wallpaper. 218 * 219 * @param pm Supply a PackageManager used to load the wallpaper's 220 * resources. 221 */ 222 public Drawable loadThumbnail(PackageManager pm) { 223 if (mThumbnailResource < 0) return null; 224 225 return pm.getDrawable(mService.serviceInfo.packageName, 226 mThumbnailResource, 227 mService.serviceInfo.applicationInfo); 228 } 229 230 /** 231 * Return a string indicating the author(s) of this wallpaper. 232 */ 233 public CharSequence loadAuthor(PackageManager pm) throws NotFoundException { 234 if (mAuthorResource <= 0) throw new NotFoundException(); 235 String packageName = mService.resolvePackageName; 236 ApplicationInfo applicationInfo = null; 237 if (packageName == null) { 238 packageName = mService.serviceInfo.packageName; 239 applicationInfo = mService.serviceInfo.applicationInfo; 240 } 241 return pm.getText(packageName, mAuthorResource, applicationInfo); 242 } 243 244 /** 245 * Return a brief summary of this wallpaper's behavior. 246 */ 247 public CharSequence loadDescription(PackageManager pm) throws NotFoundException { 248 String packageName = mService.resolvePackageName; 249 ApplicationInfo applicationInfo = null; 250 if (packageName == null) { 251 packageName = mService.serviceInfo.packageName; 252 applicationInfo = mService.serviceInfo.applicationInfo; 253 } 254 if (mService.serviceInfo.descriptionRes != 0) { 255 return pm.getText(packageName, mService.serviceInfo.descriptionRes, 256 applicationInfo); 257 258 } 259 if (mDescriptionResource <= 0) throw new NotFoundException(); 260 return pm.getText(packageName, mDescriptionResource, 261 mService.serviceInfo.applicationInfo); 262 } 263 264 /** 265 * Returns an URI that specifies a link for further context about this wallpaper. 266 * 267 * @param pm An instance of {@link PackageManager} to retrieve the URI. 268 * @return The URI. 269 */ 270 public Uri loadContextUri(PackageManager pm) throws NotFoundException { 271 if (mContextUriResource <= 0) throw new NotFoundException(); 272 String packageName = mService.resolvePackageName; 273 ApplicationInfo applicationInfo = null; 274 if (packageName == null) { 275 packageName = mService.serviceInfo.packageName; 276 applicationInfo = mService.serviceInfo.applicationInfo; 277 } 278 String contextUriString = pm.getText( 279 packageName, mContextUriResource, applicationInfo).toString(); 280 if (contextUriString == null) { 281 return null; 282 } 283 return Uri.parse(contextUriString); 284 } 285 286 /** 287 * Retrieves a title of the URI that specifies a link for further context about this wallpaper. 288 * 289 * @param pm An instance of {@link PackageManager} to retrieve the title. 290 * @return The title. 291 */ 292 public CharSequence loadContextDescription(PackageManager pm) throws NotFoundException { 293 if (mContextDescriptionResource <= 0) throw new NotFoundException(); 294 String packageName = mService.resolvePackageName; 295 ApplicationInfo applicationInfo = null; 296 if (packageName == null) { 297 packageName = mService.serviceInfo.packageName; 298 applicationInfo = mService.serviceInfo.applicationInfo; 299 } 300 return pm.getText(packageName, mContextDescriptionResource, applicationInfo).toString(); 301 } 302 303 /** 304 * Queries whether any metadata should be shown when previewing the wallpaper. If this value is 305 * set to true, any component that shows a preview of this live wallpaper should also show 306 * accompanying information like {@link #loadLabel}, 307 * {@link #loadDescription}, {@link #loadAuthor} and 308 * {@link #loadContextDescription(PackageManager)}, so the user gets to know further information 309 * about this wallpaper. 310 * 311 * @return Whether any metadata should be shown when previewing the wallpaper. 312 */ 313 public boolean getShowMetadataInPreview() { 314 return mShowMetadataInPreview; 315 } 316 317 /** 318 * Returns whether a wallpaper was optimized or not for ambient mode. 319 * 320 * @return {@code true} if wallpaper can draw in ambient mode. 321 * @hide 322 */ 323 public boolean getSupportsAmbientMode() { 324 return mSupportsAmbientMode; 325 } 326 327 /** 328 * Return the class name of an activity that provides a settings UI for 329 * the wallpaper. You can launch this activity be starting it with 330 * an {@link android.content.Intent} whose action is MAIN and with an 331 * explicit {@link android.content.ComponentName} 332 * composed of {@link #getPackageName} and the class name returned here. 333 * 334 * <p>A null will be returned if there is no settings activity associated 335 * with the wallpaper. 336 */ 337 public String getSettingsActivity() { 338 return mSettingsActivityName; 339 } 340 341 public void dump(Printer pw, String prefix) { 342 pw.println(prefix + "Service:"); 343 mService.dump(pw, prefix + " "); 344 pw.println(prefix + "mSettingsActivityName=" + mSettingsActivityName); 345 } 346 347 @Override 348 public String toString() { 349 return "WallpaperInfo{" + mService.serviceInfo.name 350 + ", settings: " 351 + mSettingsActivityName + "}"; 352 } 353 354 /** 355 * Used to package this object into a {@link Parcel}. 356 * 357 * @param dest The {@link Parcel} to be written. 358 * @param flags The flags used for parceling. 359 */ 360 public void writeToParcel(Parcel dest, int flags) { 361 dest.writeString(mSettingsActivityName); 362 dest.writeInt(mThumbnailResource); 363 dest.writeInt(mAuthorResource); 364 dest.writeInt(mDescriptionResource); 365 dest.writeInt(mContextUriResource); 366 dest.writeInt(mContextDescriptionResource); 367 dest.writeInt(mShowMetadataInPreview ? 1 : 0); 368 dest.writeInt(mSupportsAmbientMode ? 1 : 0); 369 mService.writeToParcel(dest, flags); 370 } 371 372 /** 373 * Used to make this class parcelable. 374 */ 375 public static final Parcelable.Creator<WallpaperInfo> CREATOR = new Parcelable.Creator<WallpaperInfo>() { 376 public WallpaperInfo createFromParcel(Parcel source) { 377 return new WallpaperInfo(source); 378 } 379 380 public WallpaperInfo[] newArray(int size) { 381 return new WallpaperInfo[size]; 382 } 383 }; 384 385 public int describeContents() { 386 return 0; 387 } 388 } 389