blob: e9b01750b3b10af10e28e958464b1b9ba0a22eba [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.slice.Slice;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.service.wallpaper.WallpaperService;
import android.util.AttributeSet;
import android.util.Printer;
import android.util.Xml;
import android.view.SurfaceHolder;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
/**
* This class is used to specify meta information of a wallpaper service.
*/
public final class WallpaperInfo implements Parcelable {
static final String TAG = "WallpaperInfo";
/**
* The Service that implements this wallpaper component.
*/
final ResolveInfo mService;
/**
* The wallpaper setting activity's name, to
* launch the setting activity of this wallpaper.
*/
final String mSettingsActivityName;
/**
* Resource identifier for this wallpaper's thumbnail image.
*/
final int mThumbnailResource;
/**
* Resource identifier for a string indicating the author of the wallpaper.
*/
final int mAuthorResource;
/**
* Resource identifier for a string containing a short description of the wallpaper.
*/
final int mDescriptionResource;
final int mContextUriResource;
final int mContextDescriptionResource;
final boolean mShowMetadataInPreview;
final boolean mSupportsAmbientMode;
final String mSettingsSliceUri;
final boolean mSupportMultipleDisplays;
/**
* Constructor.
*
* @param context The Context in which we are parsing the wallpaper.
* @param service The ResolveInfo returned from the package manager about
* this wallpaper's component.
*/
public WallpaperInfo(Context context, ResolveInfo service)
throws XmlPullParserException, IOException {
mService = service;
ServiceInfo si = service.serviceInfo;
final PackageManager pm = context.getPackageManager();
XmlResourceParser parser = null;
try {
parser = si.loadXmlMetaData(pm, WallpaperService.SERVICE_META_DATA);
if (parser == null) {
throw new XmlPullParserException("No "
+ WallpaperService.SERVICE_META_DATA + " meta-data");
}
Resources res = pm.getResourcesForApplication(si.applicationInfo);
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.START_TAG) {
}
String nodeName = parser.getName();
if (!"wallpaper".equals(nodeName)) {
throw new XmlPullParserException(
"Meta-data does not start with wallpaper tag");
}
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.Wallpaper);
mSettingsActivityName = sa.getString(
com.android.internal.R.styleable.Wallpaper_settingsActivity);
mThumbnailResource = sa.getResourceId(
com.android.internal.R.styleable.Wallpaper_thumbnail,
-1);
mAuthorResource = sa.getResourceId(
com.android.internal.R.styleable.Wallpaper_author,
-1);
mDescriptionResource = sa.getResourceId(
com.android.internal.R.styleable.Wallpaper_description,
-1);
mContextUriResource = sa.getResourceId(
com.android.internal.R.styleable.Wallpaper_contextUri,
-1);
mContextDescriptionResource = sa.getResourceId(
com.android.internal.R.styleable.Wallpaper_contextDescription,
-1);
mShowMetadataInPreview = sa.getBoolean(
com.android.internal.R.styleable.Wallpaper_showMetadataInPreview,
false);
mSupportsAmbientMode = sa.getBoolean(
com.android.internal.R.styleable.Wallpaper_supportsAmbientMode,
false);
mSettingsSliceUri = sa.getString(
com.android.internal.R.styleable.Wallpaper_settingsSliceUri);
mSupportMultipleDisplays = sa.getBoolean(
com.android.internal.R.styleable.Wallpaper_supportsMultipleDisplays,
false);
sa.recycle();
} catch (NameNotFoundException e) {
throw new XmlPullParserException(
"Unable to create context for: " + si.packageName);
} finally {
if (parser != null) parser.close();
}
}
WallpaperInfo(Parcel source) {
mSettingsActivityName = source.readString();
mThumbnailResource = source.readInt();
mAuthorResource = source.readInt();
mDescriptionResource = source.readInt();
mContextUriResource = source.readInt();
mContextDescriptionResource = source.readInt();
mShowMetadataInPreview = source.readInt() != 0;
mSupportsAmbientMode = source.readInt() != 0;
mSettingsSliceUri = source.readString();
mSupportMultipleDisplays = source.readInt() != 0;
mService = ResolveInfo.CREATOR.createFromParcel(source);
}
/**
* Return the .apk package that implements this wallpaper.
*/
public String getPackageName() {
return mService.serviceInfo.packageName;
}
/**
* Return the class name of the service component that implements
* this wallpaper.
*/
public String getServiceName() {
return mService.serviceInfo.name;
}
/**
* Return the raw information about the Service implementing this
* wallpaper. Do not modify the returned object.
*/
public ServiceInfo getServiceInfo() {
return mService.serviceInfo;
}
/**
* Return the component of the service that implements this wallpaper.
*/
public ComponentName getComponent() {
return new ComponentName(mService.serviceInfo.packageName,
mService.serviceInfo.name);
}
/**
* Load the user-displayed label for this wallpaper.
*
* @param pm Supply a PackageManager used to load the wallpaper's
* resources.
*/
public CharSequence loadLabel(PackageManager pm) {
return mService.loadLabel(pm);
}
/**
* Load the user-displayed icon for this wallpaper.
*
* @param pm Supply a PackageManager used to load the wallpaper's
* resources.
*/
public Drawable loadIcon(PackageManager pm) {
return mService.loadIcon(pm);
}
/**
* Load the thumbnail image for this wallpaper.
*
* @param pm Supply a PackageManager used to load the wallpaper's
* resources.
*/
public Drawable loadThumbnail(PackageManager pm) {
if (mThumbnailResource < 0) return null;
return pm.getDrawable(mService.serviceInfo.packageName,
mThumbnailResource,
mService.serviceInfo.applicationInfo);
}
/**
* Return a string indicating the author(s) of this wallpaper.
*/
public CharSequence loadAuthor(PackageManager pm) throws NotFoundException {
if (mAuthorResource <= 0) throw new NotFoundException();
String packageName = mService.resolvePackageName;
ApplicationInfo applicationInfo = null;
if (packageName == null) {
packageName = mService.serviceInfo.packageName;
applicationInfo = mService.serviceInfo.applicationInfo;
}
return pm.getText(packageName, mAuthorResource, applicationInfo);
}
/**
* Return a brief summary of this wallpaper's behavior.
*/
public CharSequence loadDescription(PackageManager pm) throws NotFoundException {
String packageName = mService.resolvePackageName;
ApplicationInfo applicationInfo = null;
if (packageName == null) {
packageName = mService.serviceInfo.packageName;
applicationInfo = mService.serviceInfo.applicationInfo;
}
if (mService.serviceInfo.descriptionRes != 0) {
return pm.getText(packageName, mService.serviceInfo.descriptionRes,
applicationInfo);
}
if (mDescriptionResource <= 0) throw new NotFoundException();
return pm.getText(packageName, mDescriptionResource,
mService.serviceInfo.applicationInfo);
}
/**
* Returns an URI that specifies a link for further context about this wallpaper.
*
* @param pm An instance of {@link PackageManager} to retrieve the URI.
* @return The URI.
*/
public Uri loadContextUri(PackageManager pm) throws NotFoundException {
if (mContextUriResource <= 0) throw new NotFoundException();
String packageName = mService.resolvePackageName;
ApplicationInfo applicationInfo = null;
if (packageName == null) {
packageName = mService.serviceInfo.packageName;
applicationInfo = mService.serviceInfo.applicationInfo;
}
String contextUriString = pm.getText(
packageName, mContextUriResource, applicationInfo).toString();
if (contextUriString == null) {
return null;
}
return Uri.parse(contextUriString);
}
/**
* Retrieves a title of the URI that specifies a link for further context about this wallpaper.
*
* @param pm An instance of {@link PackageManager} to retrieve the title.
* @return The title.
*/
public CharSequence loadContextDescription(PackageManager pm) throws NotFoundException {
if (mContextDescriptionResource <= 0) throw new NotFoundException();
String packageName = mService.resolvePackageName;
ApplicationInfo applicationInfo = null;
if (packageName == null) {
packageName = mService.serviceInfo.packageName;
applicationInfo = mService.serviceInfo.applicationInfo;
}
return pm.getText(packageName, mContextDescriptionResource, applicationInfo).toString();
}
/**
* Queries whether any metadata should be shown when previewing the wallpaper. If this value is
* set to true, any component that shows a preview of this live wallpaper should also show
* accompanying information like {@link #loadLabel},
* {@link #loadDescription}, {@link #loadAuthor} and
* {@link #loadContextDescription(PackageManager)}, so the user gets to know further information
* about this wallpaper.
*
* @return Whether any metadata should be shown when previewing the wallpaper.
*/
public boolean getShowMetadataInPreview() {
return mShowMetadataInPreview;
}
/**
* Returns whether a wallpaper was optimized or not for ambient mode and can be drawn in there.
*
* @see WallpaperService.Engine#onAmbientModeChanged(boolean, boolean)
* @see WallpaperService.Engine#isInAmbientMode()
* @return {@code true} if wallpaper can draw when in ambient mode.
* @hide
*/
@SystemApi
public boolean supportsAmbientMode() {
return mSupportsAmbientMode;
}
/**
* Return the class name of an activity that provides a settings UI for
* the wallpaper. You can launch this activity be starting it with
* an {@link android.content.Intent} whose action is MAIN and with an
* explicit {@link android.content.ComponentName}
* composed of {@link #getPackageName} and the class name returned here.
*
* <p>{@code null} will be returned if there is no settings activity associated
* with the wallpaper.
*/
public String getSettingsActivity() {
return mSettingsActivityName;
}
/**
* Returns an URI that provides a settings {@link Slice} for this wallpaper.
* The wallpaper should implement a SliceProvider associated with this URI.
* The system will display the Slice in the customization section while previewing the live
* wallpaper. Because this URI is accessible to other apps, it is recommended to protect it
* with the android.permission.BIND_WALLPAPER permission.
*
* <p>{@code null} will be returned if there is no settings Slice URI associated
* with the wallpaper.
*
* @return The URI.
*/
@Nullable
public Uri getSettingsSliceUri() {
if (mSettingsSliceUri == null) {
return null;
}
return Uri.parse(mSettingsSliceUri);
}
/**
* Returns whether this wallpaper service can support multiple engines to render on each surface
* independently. An example use case is a multi-display set-up where the wallpaper service can
* render surfaces to each of the connected displays.
* <p>
* This corresponds to the value {@link android.R.styleable#Wallpaper_supportsMultipleDisplays}
* in the XML description of the wallpaper.
* <p>
* The default value is {@code false}.
*
* @see WallpaperService#onCreateEngine()
* @see WallpaperService.Engine#onCreate(SurfaceHolder)
* @return {@code true} if multiple engines can render independently on each surface.
*
* @attr ref android.R.styleable#Wallpaper_supportsMultipleDisplays
*/
public boolean supportsMultipleDisplays() {
return mSupportMultipleDisplays;
}
public void dump(Printer pw, String prefix) {
pw.println(prefix + "Service:");
mService.dump(pw, prefix + " ");
pw.println(prefix + "mSettingsActivityName=" + mSettingsActivityName);
}
@Override
public String toString() {
return "WallpaperInfo{" + mService.serviceInfo.name
+ ", settings: "
+ mSettingsActivityName + "}";
}
/**
* Used to package this object into a {@link Parcel}.
*
* @param dest The {@link Parcel} to be written.
* @param flags The flags used for parceling.
*/
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mSettingsActivityName);
dest.writeInt(mThumbnailResource);
dest.writeInt(mAuthorResource);
dest.writeInt(mDescriptionResource);
dest.writeInt(mContextUriResource);
dest.writeInt(mContextDescriptionResource);
dest.writeInt(mShowMetadataInPreview ? 1 : 0);
dest.writeInt(mSupportsAmbientMode ? 1 : 0);
dest.writeString(mSettingsSliceUri);
dest.writeInt(mSupportMultipleDisplays ? 1 : 0);
mService.writeToParcel(dest, flags);
}
/**
* Used to make this class parcelable.
*/
public static final @android.annotation.NonNull Parcelable.Creator<WallpaperInfo> CREATOR = new Parcelable.Creator<WallpaperInfo>() {
public WallpaperInfo createFromParcel(Parcel source) {
return new WallpaperInfo(source);
}
public WallpaperInfo[] newArray(int size) {
return new WallpaperInfo[size];
}
};
public int describeContents() {
return 0;
}
}