diff options
Diffstat (limited to 'core/java/android/content/pm')
33 files changed, 6965 insertions, 0 deletions
diff --git a/core/java/android/content/pm/ActivityInfo.aidl b/core/java/android/content/pm/ActivityInfo.aidl new file mode 100755 index 0000000..dd90302 --- /dev/null +++ b/core/java/android/content/pm/ActivityInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/WindowManager.aidl +** +** Copyright 2007, 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.content.pm; + +parcelable ActivityInfo; diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java new file mode 100644 index 0000000..85d877a --- /dev/null +++ b/core/java/android/content/pm/ActivityInfo.java @@ -0,0 +1,353 @@ +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Printer; + +/** + * Information you can retrieve about a particular application + * activity or receiver. This corresponds to information collected + * from the AndroidManifest.xml's <activity> and + * <receiver> tags. + */ +public class ActivityInfo extends ComponentInfo + implements Parcelable { + /** + * A style resource identifier (in the package's resources) of this + * activity's theme. From the "theme" attribute or, if not set, 0. + */ + public int theme; + + /** + * Constant corresponding to <code>standard</code> in + * the {@link android.R.attr#launchMode} attribute. + */ + public static final int LAUNCH_MULTIPLE = 0; + /** + * Constant corresponding to <code>singleTop</code> in + * the {@link android.R.attr#launchMode} attribute. + */ + public static final int LAUNCH_SINGLE_TOP = 1; + /** + * Constant corresponding to <code>singleTask</code> in + * the {@link android.R.attr#launchMode} attribute. + */ + public static final int LAUNCH_SINGLE_TASK = 2; + /** + * Constant corresponding to <code>singleInstance</code> in + * the {@link android.R.attr#launchMode} attribute. + */ + public static final int LAUNCH_SINGLE_INSTANCE = 3; + /** + * The launch mode style requested by the activity. From the + * {@link android.R.attr#launchMode} attribute, one of + * {@link #LAUNCH_MULTIPLE}, + * {@link #LAUNCH_SINGLE_TOP}, {@link #LAUNCH_SINGLE_TASK}, or + * {@link #LAUNCH_SINGLE_INSTANCE}. + */ + public int launchMode; + + /** + * Optional name of a permission required to be able to access this + * Activity. From the "permission" attribute. + */ + public String permission; + + /** + * The affinity this activity has for another task in the system. The + * string here is the name of the task, often the package name of the + * overall package. If null, the activity has no affinity. Set from the + * {@link android.R.attr#taskAffinity} attribute. + */ + public String taskAffinity; + + /** + * If this is an activity alias, this is the real activity class to run + * for it. Otherwise, this is null. + */ + public String targetActivity; + + /** + * Bit in {@link #flags} indicating whether this activity is able to + * run in multiple processes. If + * true, the system may instantiate it in the some process as the + * process starting it in order to conserve resources. If false, the + * default, it always runs in {@link #processName}. Set from the + * {@link android.R.attr#multiprocess} attribute. + */ + public static final int FLAG_MULTIPROCESS = 0x0001; + /** + * Bit in {@link #flags} indicating that, when the activity's task is + * relaunched from home, this activity should be finished. + * Set from the + * {@link android.R.attr#finishOnTaskLaunch} attribute. + */ + public static final int FLAG_FINISH_ON_TASK_LAUNCH = 0x0002; + /** + * Bit in {@link #flags} indicating that, when the activity is the root + * of a task, that task's stack should be cleared each time the user + * re-launches it from home. As a result, the user will always + * return to the original activity at the top of the task. + * This flag only applies to activities that + * are used to start the root of a new task. Set from the + * {@link android.R.attr#clearTaskOnLaunch} attribute. + */ + public static final int FLAG_CLEAR_TASK_ON_LAUNCH = 0x0004; + /** + * Bit in {@link #flags} indicating that, when the activity is the root + * of a task, that task's stack should never be cleared when it is + * relaunched from home. Set from the + * {@link android.R.attr#alwaysRetainTaskState} attribute. + */ + public static final int FLAG_ALWAYS_RETAIN_TASK_STATE = 0x0008; + /** + * Bit in {@link #flags} indicating that the activity's state + * is not required to be saved, so that if there is a failure the + * activity will not be removed from the activity stack. Set from the + * {@link android.R.attr#stateNotNeeded} attribute. + */ + public static final int FLAG_STATE_NOT_NEEDED = 0x0010; + /** + * Bit in {@link #flags} that indicates that the activity should not + * appear in the list of recently launched activities. Set from the + * {@link android.R.attr#excludeFromRecents} attribute. + */ + public static final int FLAG_EXCLUDE_FROM_RECENTS = 0x0020; + /** + * Bit in {@link #flags} that indicates that the activity can be moved + * between tasks based on its task affinity. Set from the + * {@link android.R.attr#allowTaskReparenting} attribute. + */ + public static final int FLAG_ALLOW_TASK_REPARENTING = 0x0040; + /** + * Bit in {@link #flags} indicating that, when the user navigates away + * from an activity, it should be finished. + * Set from the + * {@link android.R.attr#noHistory} attribute. + */ + public static final int FLAG_NO_HISTORY = 0x0080; + /** + * Options that have been set in the activity declaration in the + * manifest: {@link #FLAG_MULTIPROCESS}, + * {@link #FLAG_FINISH_ON_TASK_LAUNCH}, {@link #FLAG_CLEAR_TASK_ON_LAUNCH}, + * {@link #FLAG_ALWAYS_RETAIN_TASK_STATE}, + * {@link #FLAG_STATE_NOT_NEEDED}, {@link #FLAG_EXCLUDE_FROM_RECENTS}, + * {@link #FLAG_ALLOW_TASK_REPARENTING}, {@link #FLAG_NO_HISTORY}. + */ + public int flags; + + /** + * Constant corresponding to <code>unspecified</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_UNSPECIFIED = -1; + /** + * Constant corresponding to <code>landscape</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_LANDSCAPE = 0; + /** + * Constant corresponding to <code>portrait</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_PORTRAIT = 1; + /** + * Constant corresponding to <code>user</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_USER = 2; + /** + * Constant corresponding to <code>behind</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_BEHIND = 3; + /** + * Constant corresponding to <code>sensor</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_SENSOR = 4; + + /** + * Constant corresponding to <code>sensor</code> in + * the {@link android.R.attr#screenOrientation} attribute. + */ + public static final int SCREEN_ORIENTATION_NOSENSOR = 5; + /** + * The preferred screen orientation this activity would like to run in. + * From the {@link android.R.attr#screenOrientation} attribute, one of + * {@link #SCREEN_ORIENTATION_UNSPECIFIED}, + * {@link #SCREEN_ORIENTATION_LANDSCAPE}, + * {@link #SCREEN_ORIENTATION_PORTRAIT}, + * {@link #SCREEN_ORIENTATION_USER}, + * {@link #SCREEN_ORIENTATION_BEHIND}, + * {@link #SCREEN_ORIENTATION_SENSOR}, + * {@link #SCREEN_ORIENTATION_NOSENSOR}. + */ + public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED; + + /** + * Bit in {@link #configChanges} that indicates that the activity + * can itself handle changes to the IMSI MCC. Set from the + * {@link android.R.attr#configChanges} attribute. + */ + public static final int CONFIG_MCC = 0x0001; + /** + * Bit in {@link #configChanges} that indicates that the activity + * can itself handle changes to the IMSI MNC. Set from the + * {@link android.R.attr#configChanges} attribute. + */ + public static final int CONFIG_MNC = 0x0002; + /** + * Bit in {@link #configChanges} that indicates that the activity + * can itself handle changes to the locale. Set from the + * {@link android.R.attr#configChanges} attribute. + */ + public static final int CONFIG_LOCALE = 0x0004; + /** + * Bit in {@link #configChanges} that indicates that the activity + * can itself handle changes to the touchscreen type. Set from the + * {@link android.R.attr#configChanges} attribute. + */ + public static final int CONFIG_TOUCHSCREEN = 0x0008; + /** + * Bit in {@link #configChanges} that indicates that the activity + * can itself handle changes to the keyboard type. Set from the + * {@link android.R.attr#configChanges} attribute. + */ + public static final int CONFIG_KEYBOARD = 0x0010; + /** + * Bit in {@link #configChanges} that indicates that the activity + * can itself handle changes to the keyboard being hidden/exposed. + * Set from the {@link android.R.attr#configChanges} attribute. + */ + public static final int CONFIG_KEYBOARD_HIDDEN = 0x0020; + /** + * Bit in {@link #configChanges} that indicates that the activity + * can itself handle changes to the navigation type. Set from the + * {@link android.R.attr#configChanges} attribute. + */ + public static final int CONFIG_NAVIGATION = 0x0040; + /** + * Bit in {@link #configChanges} that indicates that the activity + * can itself handle changes to the screen orientation. Set from the + * {@link android.R.attr#configChanges} attribute. + */ + public static final int CONFIG_ORIENTATION = 0x0080; + /** + * Bit in {@link #configChanges} that indicates that the activity + * can itself handle changes to the font scaling factor. Set from the + * {@link android.R.attr#configChanges} attribute. This is + * not a core resource configutation, but a higher-level value, so its + * constant starts at the high bits. + */ + public static final int CONFIG_FONT_SCALE = 0x40000000; + + /** + * Bit mask of kinds of configuration changes that this activity + * can handle itself (without being restarted by the system). + * Contains any combination of {@link #CONFIG_FONT_SCALE}, + * {@link #CONFIG_MCC}, {@link #CONFIG_MNC}, + * {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN}, + * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION}, and + * {@link #CONFIG_ORIENTATION}. Set from the + * {@link android.R.attr#configChanges} attribute. + */ + public int configChanges; + + /** + * The desired soft input mode for this activity's main window. + * Set from the {@link android.R.attr#windowSoftInputMode} attribute + * in the activity's manifest. May be any of the same values allowed + * for {@link android.view.WindowManager.LayoutParams#softInputMode + * WindowManager.LayoutParams.softInputMode}. If 0 (unspecified), + * the mode from the theme will be used. + */ + public int softInputMode; + + public ActivityInfo() { + } + + public ActivityInfo(ActivityInfo orig) { + super(orig); + theme = orig.theme; + launchMode = orig.launchMode; + permission = orig.permission; + taskAffinity = orig.taskAffinity; + targetActivity = orig.targetActivity; + flags = orig.flags; + screenOrientation = orig.screenOrientation; + configChanges = orig.configChanges; + softInputMode = orig.softInputMode; + } + + /** + * Return the theme resource identifier to use for this activity. If + * the activity defines a theme, that is used; else, the application + * theme is used. + * + * @return The theme associated with this activity. + */ + public final int getThemeResource() { + return theme != 0 ? theme : applicationInfo.theme; + } + + public void dump(Printer pw, String prefix) { + super.dumpFront(pw, prefix); + pw.println(prefix + "permission=" + permission); + pw.println(prefix + "taskAffinity=" + taskAffinity + + " targetActivity=" + targetActivity); + pw.println(prefix + "launchMode=" + launchMode + + " flags=0x" + Integer.toHexString(flags) + + " theme=0x" + Integer.toHexString(theme)); + pw.println(prefix + "screenOrientation=" + screenOrientation + + " configChanges=0x" + Integer.toHexString(configChanges) + + " softInputMode=0x" + Integer.toHexString(softInputMode)); + super.dumpBack(pw, prefix); + } + + public String toString() { + return "ActivityInfo{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + name + "}"; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + super.writeToParcel(dest, parcelableFlags); + dest.writeInt(theme); + dest.writeInt(launchMode); + dest.writeString(permission); + dest.writeString(taskAffinity); + dest.writeString(targetActivity); + dest.writeInt(flags); + dest.writeInt(screenOrientation); + dest.writeInt(configChanges); + dest.writeInt(softInputMode); + } + + public static final Parcelable.Creator<ActivityInfo> CREATOR + = new Parcelable.Creator<ActivityInfo>() { + public ActivityInfo createFromParcel(Parcel source) { + return new ActivityInfo(source); + } + public ActivityInfo[] newArray(int size) { + return new ActivityInfo[size]; + } + }; + + private ActivityInfo(Parcel source) { + super(source); + theme = source.readInt(); + launchMode = source.readInt(); + permission = source.readString(); + taskAffinity = source.readString(); + targetActivity = source.readString(); + flags = source.readInt(); + screenOrientation = source.readInt(); + configChanges = source.readInt(); + softInputMode = source.readInt(); + } +} diff --git a/core/java/android/content/pm/ApplicationInfo.aidl b/core/java/android/content/pm/ApplicationInfo.aidl new file mode 100755 index 0000000..006d1bd --- /dev/null +++ b/core/java/android/content/pm/ApplicationInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/WindowManager.aidl +** +** Copyright 2007, 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.content.pm; + +parcelable ApplicationInfo; diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java new file mode 100644 index 0000000..8d727ed --- /dev/null +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -0,0 +1,310 @@ +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Printer; + +import java.text.Collator; +import java.util.Comparator; + +/** + * Information you can retrieve about a particular application. This + * corresponds to information collected from the AndroidManifest.xml's + * <application> tag. + */ +public class ApplicationInfo extends PackageItemInfo implements Parcelable { + + /** + * Default task affinity of all activities in this application. See + * {@link ActivityInfo#taskAffinity} for more information. This comes + * from the "taskAffinity" attribute. + */ + public String taskAffinity; + + /** + * Optional name of a permission required to be able to access this + * application's components. From the "permission" attribute. + */ + public String permission; + + /** + * The name of the process this application should run in. From the + * "process" attribute or, if not set, the same as + * <var>packageName</var>. + */ + public String processName; + + /** + * Class implementing the Application object. From the "class" + * attribute. + */ + public String className; + + /** + * A style resource identifier (in the package's resources) of the + * description of an application. From the "description" attribute + * or, if not set, 0. + */ + public int descriptionRes; + + /** + * A style resource identifier (in the package's resources) of the + * default visual theme of the application. From the "theme" attribute + * or, if not set, 0. + */ + public int theme; + + /** + * Class implementing the Application's manage space + * functionality. From the "manageSpaceActivity" + * attribute. This is an optional attribute and will be null if + * application's dont specify it in their manifest + */ + public String manageSpaceActivityName; + + /** + * Value for {@link #flags}: if set, this application is installed in the + * device's system image. + */ + public static final int FLAG_SYSTEM = 1<<0; + + /** + * Value for {@link #flags}: set to true if this application would like to + * allow debugging of its + * code, even when installed on a non-development system. Comes + * from {@link android.R.styleable#AndroidManifestApplication_debuggable + * android:debuggable} of the <application> tag. + */ + public static final int FLAG_DEBUGGABLE = 1<<1; + + /** + * Value for {@link #flags}: set to true if this application has code + * associated with it. Comes + * from {@link android.R.styleable#AndroidManifestApplication_hasCode + * android:hasCode} of the <application> tag. + */ + public static final int FLAG_HAS_CODE = 1<<2; + + /** + * Value for {@link #flags}: set to true if this application is persistent. + * Comes from {@link android.R.styleable#AndroidManifestApplication_persistent + * android:persistent} of the <application> tag. + */ + public static final int FLAG_PERSISTENT = 1<<3; + + /** + * Value for {@link #flags}: set to true iif this application holds the + * {@link android.Manifest.permission#FACTORY_TEST} permission and the + * device is running in factory test mode. + */ + public static final int FLAG_FACTORY_TEST = 1<<4; + + /** + * Value for {@link #flags}: default value for the corresponding ActivityInfo flag. + * Comes from {@link android.R.styleable#AndroidManifestApplication_allowTaskReparenting + * android:allowTaskReparenting} of the <application> tag. + */ + public static final int FLAG_ALLOW_TASK_REPARENTING = 1<<5; + + /** + * Value for {@link #flags}: default value for the corresponding ActivityInfo flag. + * Comes from {@link android.R.styleable#AndroidManifestApplication_allowClearUserData + * android:allowClearUserData} of the <application> tag. + */ + public static final int FLAG_ALLOW_CLEAR_USER_DATA = 1<<6; + + + /** + * Value for {@link #flags}: default value for the corresponding ActivityInfo flag. + * {@hide} + */ + public static final int FLAG_UPDATED_SYSTEM_APP = 1<<7; + + /** + * Flags associated with the application. Any combination of + * {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE}, + * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and + * {@link #FLAG_ALLOW_TASK_REPARENTING} + * {@link #FLAG_ALLOW_CLEAR_USER_DATA}. + */ + public int flags = 0; + + /** + * Full path to the location of this package. + */ + public String sourceDir; + + /** + * Full path to the location of the publicly available parts of this package (i.e. the resources + * and manifest). For non-forward-locked apps this will be the same as {@link #sourceDir). + */ + public String publicSourceDir; + + /** + * Paths to all shared libraries this application is linked against. This + * field is only set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES + * PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving + * the structure. + */ + public String[] sharedLibraryFiles; + + /** + * Full path to a directory assigned to the package for its persistent + * data. + */ + public String dataDir; + + /** + * The kernel user-ID that has been assigned to this application; + * currently this is not a unique ID (multiple applications can have + * the same uid). + */ + public int uid; + + /** + * When false, indicates that all components within this application are + * considered disabled, regardless of their individually set enabled status. + */ + public boolean enabled = true; + + public void dump(Printer pw, String prefix) { + super.dumpFront(pw, prefix); + pw.println(prefix + "className=" + className); + pw.println(prefix + "permission=" + permission + + " uid=" + uid); + pw.println(prefix + "taskAffinity=" + taskAffinity); + pw.println(prefix + "theme=0x" + Integer.toHexString(theme)); + pw.println(prefix + "flags=0x" + Integer.toHexString(flags) + + " processName=" + processName); + pw.println(prefix + "sourceDir=" + sourceDir); + pw.println(prefix + "publicSourceDir=" + publicSourceDir); + pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles); + pw.println(prefix + "dataDir=" + dataDir); + pw.println(prefix + "enabled=" + enabled); + pw.println(prefix+"manageSpaceActivityName="+manageSpaceActivityName); + pw.println(prefix+"description=0x"+Integer.toHexString(descriptionRes)); + super.dumpBack(pw, prefix); + } + + public static class DisplayNameComparator + implements Comparator<ApplicationInfo> { + public DisplayNameComparator(PackageManager pm) { + mPM = pm; + } + + public final int compare(ApplicationInfo aa, ApplicationInfo ab) { + CharSequence sa = mPM.getApplicationLabel(aa); + if (sa == null) { + sa = aa.packageName; + } + CharSequence sb = mPM.getApplicationLabel(ab); + if (sb == null) { + sb = ab.packageName; + } + + return sCollator.compare(sa.toString(), sb.toString()); + } + + private final Collator sCollator = Collator.getInstance(); + private PackageManager mPM; + } + + public ApplicationInfo() { + } + + public ApplicationInfo(ApplicationInfo orig) { + super(orig); + taskAffinity = orig.taskAffinity; + permission = orig.permission; + processName = orig.processName; + className = orig.className; + theme = orig.theme; + flags = orig.flags; + sourceDir = orig.sourceDir; + publicSourceDir = orig.publicSourceDir; + sharedLibraryFiles = orig.sharedLibraryFiles; + dataDir = orig.dataDir; + uid = orig.uid; + enabled = orig.enabled; + manageSpaceActivityName = orig.manageSpaceActivityName; + descriptionRes = orig.descriptionRes; + } + + + public String toString() { + return "ApplicationInfo{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + packageName + "}"; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + super.writeToParcel(dest, parcelableFlags); + dest.writeString(taskAffinity); + dest.writeString(permission); + dest.writeString(processName); + dest.writeString(className); + dest.writeInt(theme); + dest.writeInt(flags); + dest.writeString(sourceDir); + dest.writeString(publicSourceDir); + dest.writeStringArray(sharedLibraryFiles); + dest.writeString(dataDir); + dest.writeInt(uid); + dest.writeInt(enabled ? 1 : 0); + dest.writeString(manageSpaceActivityName); + dest.writeInt(descriptionRes); + } + + public static final Parcelable.Creator<ApplicationInfo> CREATOR + = new Parcelable.Creator<ApplicationInfo>() { + public ApplicationInfo createFromParcel(Parcel source) { + return new ApplicationInfo(source); + } + public ApplicationInfo[] newArray(int size) { + return new ApplicationInfo[size]; + } + }; + + private ApplicationInfo(Parcel source) { + super(source); + taskAffinity = source.readString(); + permission = source.readString(); + processName = source.readString(); + className = source.readString(); + theme = source.readInt(); + flags = source.readInt(); + sourceDir = source.readString(); + publicSourceDir = source.readString(); + sharedLibraryFiles = source.readStringArray(); + dataDir = source.readString(); + uid = source.readInt(); + enabled = source.readInt() != 0; + manageSpaceActivityName = source.readString(); + descriptionRes = source.readInt(); + } + + /** + * Retrieve the textual description of the application. This + * will call back on the given PackageManager to load the description from + * the application. + * + * @param pm A PackageManager from which the label can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a CharSequence containing the application's description. + * If there is no description, null is returned. + */ + public CharSequence loadDescription(PackageManager pm) { + if (descriptionRes != 0) { + CharSequence label = pm.getText(packageName, descriptionRes, null); + if (label != null) { + return label; + } + } + return null; + } +} diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java new file mode 100644 index 0000000..73c9244 --- /dev/null +++ b/core/java/android/content/pm/ComponentInfo.java @@ -0,0 +1,138 @@ +package android.content.pm; + +import android.graphics.drawable.Drawable; +import android.os.Parcel; +import android.util.Printer; + +/** + * Base class containing information common to all application components + * ({@link ActivityInfo}, {@link ServiceInfo}). This class is not intended + * to be used by itself; it is simply here to share common definitions + * between all application components. As such, it does not itself + * implement Parcelable, but does provide convenience methods to assist + * in the implementation of Parcelable in subclasses. + */ +public class ComponentInfo extends PackageItemInfo { + /** + * Global information about the application/package this component is a + * part of. + */ + public ApplicationInfo applicationInfo; + + /** + * The name of the process this component should run in. + * From the "android:process" attribute or, if not set, the same + * as <var>applicationInfo.processName</var>. + */ + public String processName; + + /** + * Indicates whether or not this component may be instantiated. Note that this value can be + * overriden by the one in its parent {@link ApplicationInfo}. + */ + public boolean enabled = true; + + /** + * Set to true if this component is available for use by other applications. + * Comes from {@link android.R.attr#exported android:exported} of the + * <activity>, <receiver>, <service>, or + * <provider> tag. + */ + public boolean exported = false; + + public ComponentInfo() { + } + + public ComponentInfo(ComponentInfo orig) { + super(orig); + applicationInfo = orig.applicationInfo; + processName = orig.processName; + enabled = orig.enabled; + exported = orig.exported; + } + + @Override public CharSequence loadLabel(PackageManager pm) { + if (nonLocalizedLabel != null) { + return nonLocalizedLabel; + } + ApplicationInfo ai = applicationInfo; + CharSequence label; + if (labelRes != 0) { + label = pm.getText(packageName, labelRes, ai); + if (label != null) { + return label; + } + } + if (ai.nonLocalizedLabel != null) { + return ai.nonLocalizedLabel; + } + if (ai.labelRes != 0) { + label = pm.getText(packageName, ai.labelRes, ai); + if (label != null) { + return label; + } + } + return name; + } + + @Override public Drawable loadIcon(PackageManager pm) { + ApplicationInfo ai = applicationInfo; + Drawable dr; + if (icon != 0) { + dr = pm.getDrawable(packageName, icon, ai); + if (dr != null) { + return dr; + } + } + if (ai.icon != 0) { + dr = pm.getDrawable(packageName, ai.icon, ai); + if (dr != null) { + return dr; + } + } + return pm.getDefaultActivityIcon(); + } + + /** + * Return the icon resource identifier to use for this component. If + * the component defines an icon, that is used; else, the application + * icon is used. + * + * @return The icon associated with this component. + */ + public final int getIconResource() { + return icon != 0 ? icon : applicationInfo.icon; + } + + protected void dumpFront(Printer pw, String prefix) { + super.dumpFront(pw, prefix); + pw.println(prefix + "enabled=" + enabled + " exported=" + exported + + " processName=" + processName); + } + + protected void dumpBack(Printer pw, String prefix) { + if (applicationInfo != null) { + pw.println(prefix + "ApplicationInfo:"); + applicationInfo.dump(pw, prefix + " "); + } else { + pw.println(prefix + "ApplicationInfo: null"); + } + super.dumpBack(pw, prefix); + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + super.writeToParcel(dest, parcelableFlags); + applicationInfo.writeToParcel(dest, parcelableFlags); + dest.writeString(processName); + dest.writeInt(enabled ? 1 : 0); + dest.writeInt(exported ? 1 : 0); + } + + protected ComponentInfo(Parcel source) { + super(source); + applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source); + processName = source.readString(); + enabled = (source.readInt() != 0); + exported = (source.readInt() != 0); + } +} diff --git a/core/java/android/content/pm/ConfigurationInfo.java b/core/java/android/content/pm/ConfigurationInfo.java new file mode 100755 index 0000000..dcc7463 --- /dev/null +++ b/core/java/android/content/pm/ConfigurationInfo.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2008 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.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Information you can retrieve about hardware configuration preferences + * declared by an application. This corresponds to information collected from the + * AndroidManifest.xml's <uses-configuration> tags. + */ +public class ConfigurationInfo implements Parcelable { + /** + * The kind of touch screen attached to the device. + * One of: {@link android.content.res.Configuration#TOUCHSCREEN_NOTOUCH}, + * {@link android.content.res.Configuration#TOUCHSCREEN_STYLUS}, + * {@link android.content.res.Configuration#TOUCHSCREEN_FINGER}. + */ + public int reqTouchScreen; + + /** + * Application's input method preference. + * One of: {@link android.content.res.Configuration#KEYBOARD_UNDEFINED}, + * {@link android.content.res.Configuration#KEYBOARD_NOKEYS}, + * {@link android.content.res.Configuration#KEYBOARD_QWERTY}, + * {@link android.content.res.Configuration#KEYBOARD_12KEY} + */ + public int reqKeyboardType; + + /** + * A flag indicating whether any keyboard is available. + * one of: {@link android.content.res.Configuration#NAVIGATION_UNDEFINED}, + * {@link android.content.res.Configuration#NAVIGATION_DPAD}, + * {@link android.content.res.Configuration#NAVIGATION_TRACKBALL}, + * {@link android.content.res.Configuration#NAVIGATION_WHEEL} + */ + public int reqNavigation; + + /** + * Value for {@link #reqInputFeatures}: if set, indicates that the application + * requires a hard keyboard + */ + public static final int INPUT_FEATURE_HARD_KEYBOARD = 0x00000001; + + /** + * Value for {@link #reqInputFeatures}: if set, indicates that the application + * requires a five way navigation device + */ + public static final int INPUT_FEATURE_FIVE_WAY_NAV = 0x00000002; + + /** + * Flags associated with the input features. Any combination of + * {@link #INPUT_FEATURE_HARD_KEYBOARD}, + * {@link #INPUT_FEATURE_FIVE_WAY_NAV} + */ + public int reqInputFeatures = 0; + + public ConfigurationInfo() { + } + + public ConfigurationInfo(ConfigurationInfo orig) { + reqTouchScreen = orig.reqTouchScreen; + reqKeyboardType = orig.reqKeyboardType; + reqNavigation = orig.reqNavigation; + reqInputFeatures = orig.reqInputFeatures; + } + + public String toString() { + return "ApplicationHardwarePreferences{" + + Integer.toHexString(System.identityHashCode(this)) + + ", touchscreen = " + reqTouchScreen + "}" + + ", inputMethod = " + reqKeyboardType + "}" + + ", navigation = " + reqNavigation + "}" + + ", reqInputFeatures = " + reqInputFeatures + "}"; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + dest.writeInt(reqTouchScreen); + dest.writeInt(reqKeyboardType); + dest.writeInt(reqNavigation); + dest.writeInt(reqInputFeatures); + } + + public static final Creator<ConfigurationInfo> CREATOR = + new Creator<ConfigurationInfo>() { + public ConfigurationInfo createFromParcel(Parcel source) { + return new ConfigurationInfo(source); + } + public ConfigurationInfo[] newArray(int size) { + return new ConfigurationInfo[size]; + } + }; + + private ConfigurationInfo(Parcel source) { + reqTouchScreen = source.readInt(); + reqKeyboardType = source.readInt(); + reqNavigation = source.readInt(); + reqInputFeatures = source.readInt(); + } +} diff --git a/core/java/android/content/pm/IPackageDataObserver.aidl b/core/java/android/content/pm/IPackageDataObserver.aidl new file mode 100755 index 0000000..d010ee4 --- /dev/null +++ b/core/java/android/content/pm/IPackageDataObserver.aidl @@ -0,0 +1,28 @@ +/* +** +** Copyright 2007, 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.content.pm; + +/** + * API for package data change related callbacks from the Package Manager. + * Some usage scenarios include deletion of cache directory, generate + * statistics related to code, data, cache usage(TODO) + * {@hide} + */ +oneway interface IPackageDataObserver { + void onRemoveCompleted(in String packageName, boolean succeeded); +} diff --git a/core/java/android/content/pm/IPackageDeleteObserver.aidl b/core/java/android/content/pm/IPackageDeleteObserver.aidl new file mode 100644 index 0000000..bc16b3e --- /dev/null +++ b/core/java/android/content/pm/IPackageDeleteObserver.aidl @@ -0,0 +1,28 @@ +/* +** +** Copyright 2007, 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.content.pm; + +/** + * API for deletion callbacks from the Package Manager. + * + * {@hide} + */ +oneway interface IPackageDeleteObserver { + void packageDeleted(in boolean succeeded); +} + diff --git a/core/java/android/content/pm/IPackageInstallObserver.aidl b/core/java/android/content/pm/IPackageInstallObserver.aidl new file mode 100644 index 0000000..e83bbc6 --- /dev/null +++ b/core/java/android/content/pm/IPackageInstallObserver.aidl @@ -0,0 +1,27 @@ +/* +** +** Copyright 2007, 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.content.pm; + +/** + * API for installation callbacks from the Package Manager. + * + */ +oneway interface IPackageInstallObserver { + void packageInstalled(in String packageName, int returnCode); +} + diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl new file mode 100644 index 0000000..d3f6f3c --- /dev/null +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -0,0 +1,269 @@ +/* +** +** Copyright 2007, 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.content.pm; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageInstallObserver; +import android.content.pm.IPackageDeleteObserver; +import android.content.pm.IPackageDataObserver; +import android.content.pm.IPackageStatsObserver; +import android.content.pm.InstrumentationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.ProviderInfo; +import android.content.pm.PermissionGroupInfo; +import android.content.pm.PermissionInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.net.Uri; +import android.app.PendingIntent; + +/** + * See {@link PackageManager} for documentation on most of the APIs + * here. + * + * {@hide} + */ +interface IPackageManager { + PackageInfo getPackageInfo(String packageName, int flags); + int getPackageUid(String packageName); + int[] getPackageGids(String packageName); + + PermissionInfo getPermissionInfo(String name, int flags); + + List<PermissionInfo> queryPermissionsByGroup(String group, int flags); + + PermissionGroupInfo getPermissionGroupInfo(String name, int flags); + + List<PermissionGroupInfo> getAllPermissionGroups(int flags); + + ApplicationInfo getApplicationInfo(String packageName, int flags); + + ActivityInfo getActivityInfo(in ComponentName className, int flags); + + ActivityInfo getReceiverInfo(in ComponentName className, int flags); + + ServiceInfo getServiceInfo(in ComponentName className, int flags); + + int checkPermission(String permName, String pkgName); + + int checkUidPermission(String permName, int uid); + + boolean addPermission(in PermissionInfo info); + + void removePermission(String name); + + int checkSignatures(String pkg1, String pkg2); + + String[] getPackagesForUid(int uid); + + String getNameForUid(int uid); + + int getUidForSharedUser(String sharedUserName); + + ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags); + + List<ResolveInfo> queryIntentActivities(in Intent intent, + String resolvedType, int flags); + + List<ResolveInfo> queryIntentActivityOptions( + in ComponentName caller, in Intent[] specifics, + in String[] specificTypes, in Intent intent, + String resolvedType, int flags); + + List<ResolveInfo> queryIntentReceivers(in Intent intent, + String resolvedType, int flags); + + ResolveInfo resolveService(in Intent intent, + String resolvedType, int flags); + + List<ResolveInfo> queryIntentServices(in Intent intent, + String resolvedType, int flags); + + List<PackageInfo> getInstalledPackages(int flags); + + List<ApplicationInfo> getInstalledApplications(int flags); + + /** + * Retrieve all applications that are marked as persistent. + * + * @return A List<applicationInfo> containing one entry for each persistent + * application. + */ + List<ApplicationInfo> getPersistentApplications(int flags); + + ProviderInfo resolveContentProvider(String name, int flags); + + /** + * Retrieve sync information for all content providers. + * + * @param outNames Filled in with a list of the root names of the content + * providers that can sync. + * @param outInfo Filled in with a list of the ProviderInfo for each + * name in 'outNames'. + */ + void querySyncProviders(inout List<String> outNames, + inout List<ProviderInfo> outInfo); + + List<ProviderInfo> queryContentProviders( + String processName, int uid, int flags); + + InstrumentationInfo getInstrumentationInfo( + in ComponentName className, int flags); + + List<InstrumentationInfo> queryInstrumentation( + String targetPackage, int flags); + + /** + * Install a package. + * + * @param packageURI The location of the package file to install. + * @param observer a callback to use to notify when the package installation in finished. + * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE}, + * {@link #REPLACE_EXISITING_PACKAGE} + */ + void installPackage(in Uri packageURI, IPackageInstallObserver observer, int flags); + + /** + * Delete a package. + * + * @param packageName The fully qualified name of the package to delete. + * @param observer a callback to use to notify when the package deletion in finished. + * @param flags - possible values: {@link #DONT_DELETE_DATA} + */ + void deletePackage(in String packageName, IPackageDeleteObserver observer, int flags); + + void addPackageToPreferred(String packageName); + + void removePackageFromPreferred(String packageName); + + List<PackageInfo> getPreferredPackages(int flags); + + void addPreferredActivity(in IntentFilter filter, int match, + in ComponentName[] set, in ComponentName activity); + void clearPackagePreferredActivities(String packageName); + int getPreferredActivities(out List<IntentFilter> outFilters, + out List<ComponentName> outActivities, String packageName); + + /** + * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}. + */ + void setComponentEnabledSetting(in ComponentName componentName, + in int newState, in int flags); + + /** + * As per {@link android.content.pm.PackageManager#getComponentEnabledSetting}. + */ + int getComponentEnabledSetting(in ComponentName componentName); + + /** + * As per {@link android.content.pm.PackageManager#setApplicationEnabledSetting}. + */ + void setApplicationEnabledSetting(in String packageName, in int newState, int flags); + + /** + * As per {@link android.content.pm.PackageManager#getApplicationEnabledSetting}. + */ + int getApplicationEnabledSetting(in String packageName); + + /** + * Free storage by deleting LRU sorted list of cache files across + * all applications. If the currently available free storage + * on the device is greater than or equal to the requested + * free storage, no cache files are cleared. If the currently + * available storage on the device is less than the requested + * free storage, some or all of the cache files across + * all applications are deleted (based on last accessed time) + * to increase the free storage space on the device to + * the requested value. There is no guarantee that clearing all + * the cache files from all applications will clear up + * enough storage to achieve the desired value. + * @param freeStorageSize The number of bytes of storage to be + * freed by the system. Say if freeStorageSize is XX, + * and the current free storage is YY, + * if XX is less than YY, just return. if not free XX-YY number + * of bytes if possible. + * @param observer call back used to notify when + * the operation is completed + */ + void freeStorageAndNotify(in long freeStorageSize, + IPackageDataObserver observer); + + /** + * Free storage by deleting LRU sorted list of cache files across + * all applications. If the currently available free storage + * on the device is greater than or equal to the requested + * free storage, no cache files are cleared. If the currently + * available storage on the device is less than the requested + * free storage, some or all of the cache files across + * all applications are deleted (based on last accessed time) + * to increase the free storage space on the device to + * the requested value. There is no guarantee that clearing all + * the cache files from all applications will clear up + * enough storage to achieve the desired value. + * @param freeStorageSize The number of bytes of storage to be + * freed by the system. Say if freeStorageSize is XX, + * and the current free storage is YY, + * if XX is less than YY, just return. if not free XX-YY number + * of bytes if possible. + * @param opFinishedIntent PendingIntent call back used to + * notify when the operation is completed.May be null + * to indicate that no call back is desired. + */ + void freeStorage(in long freeStorageSize, + in PendingIntent opFinishedIntent); + + /** + * Delete all the cache files in an applications cache directory + * @param packageName The package name of the application whose cache + * files need to be deleted + * @param observer a callback used to notify when the deletion is finished. + */ + void deleteApplicationCacheFiles(in String packageName, IPackageDataObserver observer); + + /** + * Clear the user data directory of an application. + * @param packageName The package name of the application whose cache + * files need to be deleted + * @param observer a callback used to notify when the operation is completed. + */ + void clearApplicationUserData(in String packageName, IPackageDataObserver observer); + + /** + * Get package statistics including the code, data and cache size for + * an already installed package + * @param packageName The package name of the application + * @param observer a callback to use to notify when the asynchronous + * retrieval of information is complete. + */ + void getPackageSizeInfo(in String packageName, IPackageStatsObserver observer); + + /** + * Get a list of shared libraries that are available on the + * system. + */ + String[] getSystemSharedLibraryNames(); + + void enterSafeMode(); + boolean isSafeMode(); + void systemReady(); + boolean hasSystemUidErrors(); +} diff --git a/core/java/android/content/pm/IPackageStatsObserver.aidl b/core/java/android/content/pm/IPackageStatsObserver.aidl new file mode 100755 index 0000000..ede4d1d --- /dev/null +++ b/core/java/android/content/pm/IPackageStatsObserver.aidl @@ -0,0 +1,30 @@ +/* +** +** Copyright 2007, 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.content.pm; + +import android.content.pm.PackageStats; +/** + * API for package data change related callbacks from the Package Manager. + * Some usage scenarios include deletion of cache directory, generate + * statistics related to code, data, cache usage(TODO) + * {@hide} + */ +oneway interface IPackageStatsObserver { + + void onGetStatsCompleted(in PackageStats pStats, boolean succeeded); +} diff --git a/core/java/android/content/pm/InstrumentationInfo.aidl b/core/java/android/content/pm/InstrumentationInfo.aidl new file mode 100755 index 0000000..3d847ae --- /dev/null +++ b/core/java/android/content/pm/InstrumentationInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/WindowManager.aidl +** +** Copyright 2007, 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.content.pm; + +parcelable InstrumentationInfo; diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java new file mode 100644 index 0000000..30ca002 --- /dev/null +++ b/core/java/android/content/pm/InstrumentationInfo.java @@ -0,0 +1,98 @@ +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import java.text.Collator; +import java.util.Comparator; + +/** + * Information you can retrieve about a particular piece of test + * instrumentation. This corresponds to information collected + * from the AndroidManifest.xml's <instrumentation> tag. + */ +public class InstrumentationInfo extends PackageItemInfo implements Parcelable { + /** + * The name of the application package being instrumented. From the + * "package" attribute. + */ + public String targetPackage; + + /** + * Full path to the location of this package. + */ + public String sourceDir; + + /** + * Full path to the location of the publicly available parts of this package (i.e. the resources + * and manifest). For non-forward-locked apps this will be the same as {@link #sourceDir). + */ + public String publicSourceDir; + /** + * Full path to a directory assigned to the package for its persistent + * data. + */ + public String dataDir; + + /** + * Specifies whether or not this instrumentation will handle profiling. + */ + public boolean handleProfiling; + + /** Specifies whether or not to run this instrumentation as a functional test */ + public boolean functionalTest; + + public InstrumentationInfo() { + } + + public InstrumentationInfo(InstrumentationInfo orig) { + super(orig); + targetPackage = orig.targetPackage; + sourceDir = orig.sourceDir; + publicSourceDir = orig.publicSourceDir; + dataDir = orig.dataDir; + handleProfiling = orig.handleProfiling; + functionalTest = orig.functionalTest; + } + + public String toString() { + return "InstrumentationInfo{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + packageName + "}"; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + super.writeToParcel(dest, parcelableFlags); + dest.writeString(targetPackage); + dest.writeString(sourceDir); + dest.writeString(publicSourceDir); + dest.writeString(dataDir); + dest.writeInt((handleProfiling == false) ? 0 : 1); + dest.writeInt((functionalTest == false) ? 0 : 1); + } + + public static final Parcelable.Creator<InstrumentationInfo> CREATOR + = new Parcelable.Creator<InstrumentationInfo>() { + public InstrumentationInfo createFromParcel(Parcel source) { + return new InstrumentationInfo(source); + } + public InstrumentationInfo[] newArray(int size) { + return new InstrumentationInfo[size]; + } + }; + + private InstrumentationInfo(Parcel source) { + super(source); + targetPackage = source.readString(); + sourceDir = source.readString(); + publicSourceDir = source.readString(); + dataDir = source.readString(); + handleProfiling = source.readInt() != 0; + functionalTest = source.readInt() != 0; + } +} diff --git a/core/java/android/content/pm/PackageInfo.aidl b/core/java/android/content/pm/PackageInfo.aidl new file mode 100755 index 0000000..35e2322 --- /dev/null +++ b/core/java/android/content/pm/PackageInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/WindowManager.aidl +** +** Copyright 2007, 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.content.pm; + +parcelable PackageInfo; diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java new file mode 100644 index 0000000..d9326f2 --- /dev/null +++ b/core/java/android/content/pm/PackageInfo.java @@ -0,0 +1,199 @@ +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Overall information about the contents of a package. This corresponds + * to all of the information collected from AndroidManifest.xml. + */ +public class PackageInfo implements Parcelable { + /** + * The name of this package. From the <manifest> tag's "name" + * attribute. + */ + public String packageName; + + /** + * The version number of this package, as specified by the <manifest> + * tag's {@link android.R.styleable#AndroidManifest_versionCode versionCode} + * attribute. + */ + public int versionCode; + + /** + * The version name of this package, as specified by the <manifest> + * tag's {@link android.R.styleable#AndroidManifest_versionName versionName} + * attribute. + */ + public String versionName; + + /** + * The shared user ID name of this package, as specified by the <manifest> + * tag's {@link android.R.styleable#AndroidManifest_sharedUserId sharedUserId} + * attribute. + */ + public String sharedUserId; + + /** + * The shared user ID label of this package, as specified by the <manifest> + * tag's {@link android.R.styleable#AndroidManifest_sharedUserLabel sharedUserLabel} + * attribute. + */ + public int sharedUserLabel; + + /** + * Information collected from the <application> tag, or null if + * there was none. + */ + public ApplicationInfo applicationInfo; + + /** + * All kernel group-IDs that have been assigned to this package. + * This is only filled in if the flag {@link PackageManager#GET_GIDS} was set. + */ + public int[] gids; + + /** + * Array of all {@link android.R.styleable#AndroidManifestActivity + * <activity>} tags included under <application>, + * or null if there were none. This is only filled in if the flag + * {@link PackageManager#GET_ACTIVITIES} was set. + */ + public ActivityInfo[] activities; + + /** + * Array of all {@link android.R.styleable#AndroidManifestReceiver + * <receiver>} tags included under <application>, + * or null if there were none. This is only filled in if the flag + * {@link PackageManager#GET_RECEIVERS} was set. + */ + public ActivityInfo[] receivers; + + /** + * Array of all {@link android.R.styleable#AndroidManifestService + * <service>} tags included under <application>, + * or null if there were none. This is only filled in if the flag + * {@link PackageManager#GET_SERVICES} was set. + */ + public ServiceInfo[] services; + + /** + * Array of all {@link android.R.styleable#AndroidManifestProvider + * <provider>} tags included under <application>, + * or null if there were none. This is only filled in if the flag + * {@link PackageManager#GET_PROVIDERS} was set. + */ + public ProviderInfo[] providers; + + /** + * Array of all {@link android.R.styleable#AndroidManifestInstrumentation + * <instrumentation>} tags included under <manifest>, + * or null if there were none. This is only filled in if the flag + * {@link PackageManager#GET_INSTRUMENTATION} was set. + */ + public InstrumentationInfo[] instrumentation; + + /** + * Array of all {@link android.R.styleable#AndroidManifestPermission + * <permission>} tags included under <manifest>, + * or null if there were none. This is only filled in if the flag + * {@link PackageManager#GET_PERMISSIONS} was set. + */ + public PermissionInfo[] permissions; + + /** + * Array of all {@link android.R.styleable#AndroidManifestUsesPermission + * <uses-permission>} tags included under <manifest>, + * or null if there were none. This is only filled in if the flag + * {@link PackageManager#GET_PERMISSIONS} was set. This list includes + * all permissions requested, even those that were not granted or known + * by the system at install time. + */ + public String[] requestedPermissions; + + /** + * Array of all signatures read from the package file. This is only filled + * in if the flag {@link PackageManager#GET_SIGNATURES} was set. + */ + public Signature[] signatures; + + /** + * Application specified preferred configuration + * {@link android.R.styleable#AndroidManifestUsesConfiguration + * <uses-configuration>} tags included under <manifest>, + * or null if there were none. This is only filled in if the flag + * {@link PackageManager#GET_CONFIGURATIONS} was set. + */ + public ConfigurationInfo[] configPreferences; + + public PackageInfo() { + } + + public String toString() { + return "PackageInfo{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + packageName + "}"; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + dest.writeString(packageName); + dest.writeInt(versionCode); + dest.writeString(versionName); + dest.writeString(sharedUserId); + dest.writeInt(sharedUserLabel); + if (applicationInfo != null) { + dest.writeInt(1); + applicationInfo.writeToParcel(dest, parcelableFlags); + } else { + dest.writeInt(0); + } + dest.writeIntArray(gids); + dest.writeTypedArray(activities, parcelableFlags); + dest.writeTypedArray(receivers, parcelableFlags); + dest.writeTypedArray(services, parcelableFlags); + dest.writeTypedArray(providers, parcelableFlags); + dest.writeTypedArray(instrumentation, parcelableFlags); + dest.writeTypedArray(permissions, parcelableFlags); + dest.writeStringArray(requestedPermissions); + dest.writeTypedArray(signatures, parcelableFlags); + dest.writeTypedArray(configPreferences, parcelableFlags); + } + + public static final Parcelable.Creator<PackageInfo> CREATOR + = new Parcelable.Creator<PackageInfo>() { + public PackageInfo createFromParcel(Parcel source) { + return new PackageInfo(source); + } + + public PackageInfo[] newArray(int size) { + return new PackageInfo[size]; + } + }; + + private PackageInfo(Parcel source) { + packageName = source.readString(); + versionCode = source.readInt(); + versionName = source.readString(); + sharedUserId = source.readString(); + sharedUserLabel = source.readInt(); + int hasApp = source.readInt(); + if (hasApp != 0) { + applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source); + } + gids = source.createIntArray(); + activities = source.createTypedArray(ActivityInfo.CREATOR); + receivers = source.createTypedArray(ActivityInfo.CREATOR); + services = source.createTypedArray(ServiceInfo.CREATOR); + providers = source.createTypedArray(ProviderInfo.CREATOR); + instrumentation = source.createTypedArray(InstrumentationInfo.CREATOR); + permissions = source.createTypedArray(PermissionInfo.CREATOR); + requestedPermissions = source.createStringArray(); + signatures = source.createTypedArray(Signature.CREATOR); + configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR); + } +} diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java new file mode 100644 index 0000000..46e7ca4 --- /dev/null +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -0,0 +1,191 @@ +package android.content.pm; + +import android.content.res.XmlResourceParser; + +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Parcel; +import android.text.TextUtils; +import android.util.Printer; + +import java.text.Collator; +import java.util.Comparator; + +/** + * Base class containing information common to all package items held by + * the package manager. This provides a very common basic set of attributes: + * a label, icon, and meta-data. This class is not intended + * to be used by itself; it is simply here to share common definitions + * between all items returned by the package manager. As such, it does not + * itself implement Parcelable, but does provide convenience methods to assist + * in the implementation of Parcelable in subclasses. + */ +public class PackageItemInfo { + /** + * Public name of this item. From the "android:name" attribute. + */ + public String name; + + /** + * Name of the package that this item is in. + */ + public String packageName; + + /** + * A string resource identifier (in the package's resources) of this + * component's label. From the "label" attribute or, if not set, 0. + */ + public int labelRes; + + /** + * The string provided in the AndroidManifest file, if any. You + * probably don't want to use this. You probably want + * {@link PackageManager#getApplicationLabel} + */ + public CharSequence nonLocalizedLabel; + + /** + * A drawable resource identifier (in the package's resources) of this + * component's icon. From the "icon" attribute or, if not set, 0. + */ + public int icon; + + /** + * Additional meta-data associated with this component. This field + * will only be filled in if you set the + * {@link PackageManager#GET_META_DATA} flag when requesting the info. + */ + public Bundle metaData; + + public PackageItemInfo() { + } + + public PackageItemInfo(PackageItemInfo orig) { + name = orig.name; + packageName = orig.packageName; + labelRes = orig.labelRes; + nonLocalizedLabel = orig.nonLocalizedLabel; + icon = orig.icon; + metaData = orig.metaData; + } + + /** + * Retrieve the current textual label associated with this item. This + * will call back on the given PackageManager to load the label from + * the application. + * + * @param pm A PackageManager from which the label can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a CharSequence containing the item's label. If the + * item does not have a label, its name is returned. + */ + public CharSequence loadLabel(PackageManager pm) { + if (nonLocalizedLabel != null) { + return nonLocalizedLabel; + } + if (labelRes != 0) { + CharSequence label = pm.getText(packageName, labelRes, null); + if (label != null) { + return label; + } + } + if(name != null) { + return name; + } + return packageName; + } + + /** + * Retrieve the current graphical icon associated with this item. This + * will call back on the given PackageManager to load the icon from + * the application. + * + * @param pm A PackageManager from which the icon can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a Drawable containing the item's icon. If the + * item does not have an icon, the default activity icon is returned. + */ + public Drawable loadIcon(PackageManager pm) { + if (icon != 0) { + Drawable dr = pm.getDrawable(packageName, icon, null); + if (dr != null) { + return dr; + } + } + return pm.getDefaultActivityIcon(); + } + + /** + * Load an XML resource attached to the meta-data of this item. This will + * retrieved the name meta-data entry, and if defined call back on the + * given PackageManager to load its XML file from the application. + * + * @param pm A PackageManager from which the XML can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * @param name Name of the meta-date you would like to load. + * + * @return Returns an XmlPullParser you can use to parse the XML file + * assigned as the given meta-data. If the meta-data name is not defined + * or the XML resource could not be found, null is returned. + */ + public XmlResourceParser loadXmlMetaData(PackageManager pm, String name) { + if (metaData != null) { + int resid = metaData.getInt(name); + if (resid != 0) { + return pm.getXml(packageName, resid, null); + } + } + return null; + } + + protected void dumpFront(Printer pw, String prefix) { + pw.println(prefix + "name=" + name); + pw.println(prefix + "packageName=" + packageName); + pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes) + + " nonLocalizedLabel=" + nonLocalizedLabel + + " icon=0x" + Integer.toHexString(icon)); + } + + protected void dumpBack(Printer pw, String prefix) { + // no back here + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + dest.writeString(name); + dest.writeString(packageName); + dest.writeInt(labelRes); + TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags); + dest.writeInt(icon); + dest.writeBundle(metaData); + } + + protected PackageItemInfo(Parcel source) { + name = source.readString(); + packageName = source.readString(); + labelRes = source.readInt(); + nonLocalizedLabel + = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); + icon = source.readInt(); + metaData = source.readBundle(); + } + + public static class DisplayNameComparator + implements Comparator<PackageItemInfo> { + public DisplayNameComparator(PackageManager pm) { + mPM = pm; + } + + public final int compare(PackageItemInfo aa, PackageItemInfo ab) { + CharSequence sa = aa.loadLabel(mPM); + if (sa == null) sa = aa.name; + CharSequence sb = ab.loadLabel(mPM); + if (sb == null) sb = ab.name; + return sCollator.compare(sa.toString(), sb.toString()); + } + + private final Collator sCollator = Collator.getInstance(); + private PackageManager mPM; + } +} diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java new file mode 100644 index 0000000..7287d9c --- /dev/null +++ b/core/java/android/content/pm/PackageManager.java @@ -0,0 +1,1646 @@ +/* + * Copyright (C) 2006 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.content.pm; + + +import android.app.PendingIntent; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.util.AndroidException; +import android.util.DisplayMetrics; + +import java.io.File; +import java.util.List; + +/** + * Class for retrieving various kinds of information related to the application + * packages that are currently installed on the device. + * + * You can find this class through {@link Context#getPackageManager}. + */ +public abstract class PackageManager { + + /** + * This exception is thrown when a given package, application, or component + * name can not be found. + */ + public static class NameNotFoundException extends AndroidException { + public NameNotFoundException() { + } + + public NameNotFoundException(String name) { + super(name); + } + } + + /** + * {@link PackageInfo} flag: return information about + * activities in the package in {@link PackageInfo#activities}. + */ + public static final int GET_ACTIVITIES = 0x00000001; + + /** + * {@link PackageInfo} flag: return information about + * intent receivers in the package in + * {@link PackageInfo#receivers}. + */ + public static final int GET_RECEIVERS = 0x00000002; + + /** + * {@link PackageInfo} flag: return information about + * services in the package in {@link PackageInfo#services}. + */ + public static final int GET_SERVICES = 0x00000004; + + /** + * {@link PackageInfo} flag: return information about + * content providers in the package in + * {@link PackageInfo#providers}. + */ + public static final int GET_PROVIDERS = 0x00000008; + + /** + * {@link PackageInfo} flag: return information about + * instrumentation in the package in + * {@link PackageInfo#instrumentation}. + */ + public static final int GET_INSTRUMENTATION = 0x00000010; + + /** + * {@link PackageInfo} flag: return information about the + * intent filters supported by the activity. + */ + public static final int GET_INTENT_FILTERS = 0x00000020; + + /** + * {@link PackageInfo} flag: return information about the + * signatures included in the package. + */ + public static final int GET_SIGNATURES = 0x00000040; + + /** + * {@link ResolveInfo} flag: return the IntentFilter that + * was matched for a particular ResolveInfo in + * {@link ResolveInfo#filter}. + */ + public static final int GET_RESOLVED_FILTER = 0x00000040; + + /** + * {@link ComponentInfo} flag: return the {@link ComponentInfo#metaData} + * data {@link android.os.Bundle}s that are associated with a component. + * This applies for any API returning a ComponentInfo subclass. + */ + public static final int GET_META_DATA = 0x00000080; + + /** + * {@link PackageInfo} flag: return the + * {@link PackageInfo#gids group ids} that are associated with an + * application. + * This applies for any API returning an PackageInfo class, either + * directly or nested inside of another. + */ + public static final int GET_GIDS = 0x00000100; + + /** + * {@link PackageInfo} flag: include disabled components in the returned info. + */ + public static final int GET_DISABLED_COMPONENTS = 0x00000200; + + /** + * {@link ApplicationInfo} flag: return the + * {@link ApplicationInfo#sharedLibraryFiles paths to the shared libraries} + * that are associated with an application. + * This applies for any API returning an ApplicationInfo class, either + * directly or nested inside of another. + */ + public static final int GET_SHARED_LIBRARY_FILES = 0x00000400; + + /** + * {@link ProviderInfo} flag: return the + * {@link ProviderInfo#uriPermissionPatterns URI permission patterns} + * that are associated with a content provider. + * This applies for any API returning an ProviderInfo class, either + * directly or nested inside of another. + */ + public static final int GET_URI_PERMISSION_PATTERNS = 0x00000800; + /** + * {@link PackageInfo} flag: return information about + * permissions in the package in + * {@link PackageInfo#permissions}. + */ + public static final int GET_PERMISSIONS = 0x00001000; + + /** + * Flag parameter to retrieve all applications(even uninstalled ones) with data directories. + * This state could have resulted if applications have been deleted with flag + * DONT_DELETE_DATA + * with a possibility of being replaced or reinstalled in future + */ + public static final int GET_UNINSTALLED_PACKAGES = 0x00002000; + + /** + * {@link PackageInfo} flag: return information about + * hardware preferences + * {@link PackageInfo#configPreferences} + */ + public static final int GET_CONFIGURATIONS = 0x00004000; + + /** + * Permission check result: this is returned by {@link #checkPermission} + * if the permission has been granted to the given package. + */ + public static final int PERMISSION_GRANTED = 0; + + /** + * Permission check result: this is returned by {@link #checkPermission} + * if the permission has not been granted to the given package. + */ + public static final int PERMISSION_DENIED = -1; + + /** + * Signature check result: this is returned by {@link #checkSignatures} + * if the two packages have a matching signature. + */ + public static final int SIGNATURE_MATCH = 0; + + /** + * Signature check result: this is returned by {@link #checkSignatures} + * if neither of the two packages is signed. + */ + public static final int SIGNATURE_NEITHER_SIGNED = 1; + + /** + * Signature check result: this is returned by {@link #checkSignatures} + * if the first package is not signed, but the second is. + */ + public static final int SIGNATURE_FIRST_NOT_SIGNED = -1; + + /** + * Signature check result: this is returned by {@link #checkSignatures} + * if the second package is not signed, but the first is. + */ + public static final int SIGNATURE_SECOND_NOT_SIGNED = -2; + + /** + * Signature check result: this is returned by {@link #checkSignatures} + * if both packages are signed but there is no matching signature. + */ + public static final int SIGNATURE_NO_MATCH = -3; + + /** + * Signature check result: this is returned by {@link #checkSignatures} + * if either of the given package names are not valid. + */ + public static final int SIGNATURE_UNKNOWN_PACKAGE = -4; + + /** + * Resolution and querying flag: if set, only filters that support the + * {@link android.content.Intent#CATEGORY_DEFAULT} will be considered for + * matching. This is a synonym for including the CATEGORY_DEFAULT in your + * supplied Intent. + */ + public static final int MATCH_DEFAULT_ONLY = 0x00010000; + + public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; + public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; + public static final int COMPONENT_ENABLED_STATE_DISABLED = 2; + + /** + * Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to + * indicate that this package should be installed as forward locked, i.e. only the app itself + * should have access to it's code and non-resource assets. + */ + public static final int FORWARD_LOCK_PACKAGE = 0x00000001; + + /** + * Flag parameter for {@link #installPackage} to indicate that you want to replace an already + * installed package, if one exists + */ + public static final int REPLACE_EXISTING_PACKAGE = 0x00000002; + + /** + * Flag parameter for + * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate + * that you don't want to kill the app containing the component. Be careful when you set this + * since changing component states can make the containing application's behavior unpredictable. + */ + public static final int DONT_KILL_APP = 0x00000001; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} on success. + */ + public static final int INSTALL_SUCCEEDED = 1; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package is + * already installed. + */ + public static final int INSTALL_FAILED_ALREADY_EXISTS = -1; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package archive + * file is invalid. + */ + public static final int INSTALL_FAILED_INVALID_APK = -2; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the URI passed in + * is invalid. + */ + public static final int INSTALL_FAILED_INVALID_URI = -3; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package manager + * service found that the device didn't have enough storage space to install the app + */ + public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if a + * package is already installed with the same name. + */ + public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if + * the requested shared user does not exist. + */ + public static final int INSTALL_FAILED_NO_SHARED_USER = -6; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if + * a previously installed package of the same name has a different signature + * than the new package (and the old package's data was not removed). + */ + public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if + * the new package is requested a shared user which is already installed on the + * device and does not have matching signature. + */ + public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if + * the new package uses a shared library that is not available. + */ + public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if + * the new package uses a shared library that is not available. + */ + public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if + * the new package failed while optimizing and validating its dex files, + * either because there was not enough storage or the validation failed. + */ + public static final int INSTALL_FAILED_DEXOPT = -11; + + /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if + * the new package failed because the current SDK version is older than + * that required by the package. + */ + public static final int INSTALL_FAILED_OLDER_SDK = -12; + + /** + * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the parser was given a path that is not a file, or does not end with the expected + * '.apk' extension. + */ + public static final int INSTALL_PARSE_FAILED_NOT_APK = -100; + + /** + * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the parser was unable to retrieve the AndroidManifest.xml file. + */ + public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101; + + /** + * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the parser encountered an unexpected exception. + */ + public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; + + /** + * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the parser did not find any certificates in the .apk. + */ + public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; + + /** + * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the parser found inconsistent certificates on the files in the .apk. + */ + public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104; + + /** + * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the parser encountered a CertificateEncodingException in one of the + * files in the .apk. + */ + public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105; + + /** + * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the parser encountered a bad or missing package name in the manifest. + */ + public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106; + + /** + * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the parser encountered a bad shared user id name in the manifest. + */ + public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107; + + /** + * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the parser encountered some structural problem in the manifest. + */ + public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108; + + /** + * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the parser did not find any actionable tags (instrumentation or application) + * in the manifest. + */ + public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109; + + /** + * Indicates the state of installation. Used by PackageManager to + * figure out incomplete installations. Say a package is being installed + * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till + * the package installation is successful or unsuccesful lin which case + * the PackageManager will no longer maintain state information associated + * with the package. If some exception(like device freeze or battery being + * pulled out) occurs during installation of a package, the PackageManager + * needs this information to clean up the previously failed installation. + */ + public static final int PKG_INSTALL_INCOMPLETE = 0; + public static final int PKG_INSTALL_COMPLETE = 1; + + /** + * Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the + * package's data directory. + * + * @hide + */ + public static final int DONT_DELETE_DATA = 0x00000001; + + /** + * Retrieve overall information about an application package that is + * installed on the system. + * + * <p>Throws {@link NameNotFoundException} if a package with the given + * name can not be found on the system. + * + * @param packageName The full name (i.e. com.google.apps.contacts) of the + * desired package. + + * @param flags Additional option flags. Use any combination of + * {@link #GET_ACTIVITIES}, + * {@link #GET_GIDS}, + * {@link #GET_CONFIGURATIONS}, + * {@link #GET_INSTRUMENTATION}, + * {@link #GET_PERMISSIONS}, + * {@link #GET_PROVIDERS}, + * {@link #GET_RECEIVERS}, + * {@link #GET_SERVICES}, + * {@link #GET_SIGNATURES}, + * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned. + * + * @return Returns a PackageInfo object containing information about the package. + * If flag GET_UNINSTALLED_PACKAGES is set and if the package is not + * found in the list of installed applications, the package information is + * retrieved from the list of uninstalled applications(which includes + * installed applications as well as applications + * with data directory ie applications which had been + * deleted with DONT_DELTE_DATA flag set). + * + * @see #GET_ACTIVITIES + * @see #GET_GIDS + * @see #GET_CONFIGURATIONS + * @see #GET_INSTRUMENTATION + * @see #GET_PERMISSIONS + * @see #GET_PROVIDERS + * @see #GET_RECEIVERS + * @see #GET_SERVICES + * @see #GET_SIGNATURES + * @see #GET_UNINSTALLED_PACKAGES + * + */ + public abstract PackageInfo getPackageInfo(String packageName, int flags) + throws NameNotFoundException; + + /** + * Return a "good" intent to launch a front-door activity in a package, + * for use for example to implement an "open" button when browsing through + * packages. The current implementation will look first for a main + * activity in the category {@link Intent#CATEGORY_INFO}, next for a + * main activity in the category {@link Intent#CATEGORY_LAUNCHER}, or return + * null if neither are found. + * + * <p>Throws {@link NameNotFoundException} if a package with the given + * name can not be found on the system. + * + * @param packageName The name of the package to inspect. + * + * @return Returns either a fully-qualified Intent that can be used to + * launch the main activity in the package, or null if the package does + * not contain such an activity. + */ + public abstract Intent getLaunchIntentForPackage(String packageName) + throws NameNotFoundException; + + /** + * Return an array of all of the secondary group-ids that have been + * assigned to a package. + * + * <p>Throws {@link NameNotFoundException} if a package with the given + * name can not be found on the system. + * + * @param packageName The full name (i.e. com.google.apps.contacts) of the + * desired package. + * + * @return Returns an int array of the assigned gids, or null if there + * are none. + */ + public abstract int[] getPackageGids(String packageName) + throws NameNotFoundException; + + /** + * Retrieve all of the information we know about a particular permission. + * + * <p>Throws {@link NameNotFoundException} if a permission with the given + * name can not be found on the system. + * + * @param name The fully qualified name (i.e. com.google.permission.LOGIN) + * of the permission you are interested in. + * @param flags Additional option flags. Use {@link #GET_META_DATA} to + * retrieve any meta-data associated with the permission. + * + * @return Returns a {@link PermissionInfo} containing information about the + * permission. + */ + public abstract PermissionInfo getPermissionInfo(String name, int flags) + throws NameNotFoundException; + + /** + * Query for all of the permissions associated with a particular group. + * + * <p>Throws {@link NameNotFoundException} if the given group does not + * exist. + * + * @param group The fully qualified name (i.e. com.google.permission.LOGIN) + * of the permission group you are interested in. Use null to + * find all of the permissions not associated with a group. + * @param flags Additional option flags. Use {@link #GET_META_DATA} to + * retrieve any meta-data associated with the permissions. + * + * @return Returns a list of {@link PermissionInfo} containing information + * about all of the permissions in the given group. + */ + public abstract List<PermissionInfo> queryPermissionsByGroup(String group, + int flags) throws NameNotFoundException; + + /** + * Retrieve all of the information we know about a particular group of + * permissions. + * + * <p>Throws {@link NameNotFoundException} if a permission group with the given + * name can not be found on the system. + * + * @param name The fully qualified name (i.e. com.google.permission_group.APPS) + * of the permission you are interested in. + * @param flags Additional option flags. Use {@link #GET_META_DATA} to + * retrieve any meta-data associated with the permission group. + * + * @return Returns a {@link PermissionGroupInfo} containing information + * about the permission. + */ + public abstract PermissionGroupInfo getPermissionGroupInfo(String name, + int flags) throws NameNotFoundException; + + /** + * Retrieve all of the known permission groups in the system. + * + * @param flags Additional option flags. Use {@link #GET_META_DATA} to + * retrieve any meta-data associated with the permission group. + * + * @return Returns a list of {@link PermissionGroupInfo} containing + * information about all of the known permission groups. + */ + public abstract List<PermissionGroupInfo> getAllPermissionGroups(int flags); + + /** + * Retrieve all of the information we know about a particular + * package/application. + * + * <p>Throws {@link NameNotFoundException} if an application with the given + * package name can not be found on the system. + * + * @param packageName The full name (i.e. com.google.apps.contacts) of an + * application. + * @param flags Additional option flags. Use any combination of + * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, + * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned. + * + * @return {@link ApplicationInfo} Returns ApplicationInfo object containing + * information about the package. + * If flag GET_UNINSTALLED_PACKAGES is set and if the package is not + * found in the list of installed applications, + * the application information is retrieved from the + * list of uninstalled applications(which includes + * installed applications as well as applications + * with data directory ie applications which had been + * deleted with DONT_DELTE_DATA flag set). + * + * @see #GET_META_DATA + * @see #GET_SHARED_LIBRARY_FILES + * @see #GET_UNINSTALLED_PACKAGES + */ + public abstract ApplicationInfo getApplicationInfo(String packageName, + int flags) throws NameNotFoundException; + + /** + * Retrieve all of the information we know about a particular activity + * class. + * + * <p>Throws {@link NameNotFoundException} if an activity with the given + * class name can not be found on the system. + * + * @param className The full name (i.e. + * com.google.apps.contacts.ContactsList) of an Activity + * class. + * @param flags Additional option flags. Use any combination of + * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, + * to modify the data (in ApplicationInfo) returned. + * + * @return {@link ActivityInfo} containing information about the activity. + * + * @see #GET_INTENT_FILTERS + * @see #GET_META_DATA + * @see #GET_SHARED_LIBRARY_FILES + */ + public abstract ActivityInfo getActivityInfo(ComponentName className, + int flags) throws NameNotFoundException; + + /** + * Retrieve all of the information we know about a particular receiver + * class. + * + * <p>Throws {@link NameNotFoundException} if a receiver with the given + * class name can not be found on the system. + * + * @param className The full name (i.e. + * com.google.apps.contacts.CalendarAlarm) of a Receiver + * class. + * @param flags Additional option flags. Use any combination of + * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, + * to modify the data returned. + * + * @return {@link ActivityInfo} containing information about the receiver. + * + * @see #GET_INTENT_FILTERS + * @see #GET_META_DATA + * @see #GET_SHARED_LIBRARY_FILES + */ + public abstract ActivityInfo getReceiverInfo(ComponentName className, + int flags) throws NameNotFoundException; + + /** + * Retrieve all of the information we know about a particular service + * class. + * + * <p>Throws {@link NameNotFoundException} if a service with the given + * class name can not be found on the system. + * + * @param className The full name (i.e. + * com.google.apps.media.BackgroundPlayback) of a Service + * class. + * @param flags Additional option flags. Use any combination of + * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, + * to modify the data returned. + * + * @return ServiceInfo containing information about the service. + * + * @see #GET_META_DATA + * @see #GET_SHARED_LIBRARY_FILES + */ + public abstract ServiceInfo getServiceInfo(ComponentName className, + int flags) throws NameNotFoundException; + + /** + * Return a List of all packages that are installed + * on the device. + * + * @param flags Additional option flags. Use any combination of + * {@link #GET_ACTIVITIES}, + * {@link #GET_GIDS}, + * {@link #GET_CONFIGURATIONS}, + * {@link #GET_INSTRUMENTATION}, + * {@link #GET_PERMISSIONS}, + * {@link #GET_PROVIDERS}, + * {@link #GET_RECEIVERS}, + * {@link #GET_SERVICES}, + * {@link #GET_SIGNATURES}, + * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned. + * + * @return A List of PackageInfo objects, one for each package that is + * installed on the device. In the unlikely case of there being no + * installed packages, an empty list is returned. + * If flag GET_UNINSTALLED_PACKAGES is set, a list of all + * applications including those deleted with DONT_DELETE_DATA + * (partially installed apps with data directory) will be returned. + * + * @see #GET_ACTIVITIES + * @see #GET_GIDS + * @see #GET_CONFIGURATIONS + * @see #GET_INSTRUMENTATION + * @see #GET_PERMISSIONS + * @see #GET_PROVIDERS + * @see #GET_RECEIVERS + * @see #GET_SERVICES + * @see #GET_SIGNATURES + * @see #GET_UNINSTALLED_PACKAGES + * + */ + public abstract List<PackageInfo> getInstalledPackages(int flags); + + /** + * Check whether a particular package has been granted a particular + * permission. + * + * @param permName The name of the permission you are checking for, + * @param pkgName The name of the package you are checking against. + * + * @return If the package has the permission, PERMISSION_GRANTED is + * returned. If it does not have the permission, PERMISSION_DENIED + * is returned. + * + * @see #PERMISSION_GRANTED + * @see #PERMISSION_DENIED + */ + public abstract int checkPermission(String permName, String pkgName); + + /** + * Add a new dynamic permission to the system. For this to work, your + * package must have defined a permission tree through the + * {@link android.R.styleable#AndroidManifestPermissionTree + * <permission-tree>} tag in its manifest. A package can only add + * permissions to trees that were defined by either its own package or + * another with the same user id; a permission is in a tree if it + * matches the name of the permission tree + ".": for example, + * "com.foo.bar" is a member of the permission tree "com.foo". + * + * <p>It is good to make your permission tree name descriptive, because you + * are taking possession of that entire set of permission names. Thus, it + * must be under a domain you control, with a suffix that will not match + * any normal permissions that may be declared in any applications that + * are part of that domain. + * + * <p>New permissions must be added before + * any .apks are installed that use those permissions. Permissions you + * add through this method are remembered across reboots of the device. + * If the given permission already exists, the info you supply here + * will be used to update it. + * + * @param info Description of the permission to be added. + * + * @return Returns true if a new permission was created, false if an + * existing one was updated. + * + * @throws SecurityException if you are not allowed to add the + * given permission name. + * + * @see #removePermission(String) + */ + public abstract boolean addPermission(PermissionInfo info); + + /** + * Removes a permission that was previously added with + * {@link #addPermission(PermissionInfo)}. The same ownership rules apply + * -- you are only allowed to remove permissions that you are allowed + * to add. + * + * @param name The name of the permission to remove. + * + * @throws SecurityException if you are not allowed to remove the + * given permission name. + * + * @see #addPermission(PermissionInfo) + */ + public abstract void removePermission(String name); + + /** + * Compare the signatures of two packages to determine if the same + * signature appears in both of them. If they do contain the same + * signature, then they are allowed special privileges when working + * with each other: they can share the same user-id, run instrumentation + * against each other, etc. + * + * @param pkg1 First package name whose signature will be compared. + * @param pkg2 Second package name whose signature will be compared. + * @return Returns an integer indicating whether there is a matching + * signature: the value is >= 0 if there is a match (or neither package + * is signed), or < 0 if there is not a match. The match result can be + * further distinguished with the success (>= 0) constants + * {@link #SIGNATURE_MATCH}, {@link #SIGNATURE_NEITHER_SIGNED}; or + * failure (< 0) constants {@link #SIGNATURE_FIRST_NOT_SIGNED}, + * {@link #SIGNATURE_SECOND_NOT_SIGNED}, {@link #SIGNATURE_NO_MATCH}, + * or {@link #SIGNATURE_UNKNOWN_PACKAGE}. + * + * @see #SIGNATURE_MATCH + * @see #SIGNATURE_NEITHER_SIGNED + * @see #SIGNATURE_FIRST_NOT_SIGNED + * @see #SIGNATURE_SECOND_NOT_SIGNED + * @see #SIGNATURE_NO_MATCH + * @see #SIGNATURE_UNKNOWN_PACKAGE + */ + public abstract int checkSignatures(String pkg1, String pkg2); + + /** + * Retrieve the names of all packages that are associated with a particular + * user id. In most cases, this will be a single package name, the package + * that has been assigned that user id. Where there are multiple packages + * sharing the same user id through the "sharedUserId" mechanism, all + * packages with that id will be returned. + * + * @param uid The user id for which you would like to retrieve the + * associated packages. + * + * @return Returns an array of one or more packages assigned to the user + * id, or null if there are no known packages with the given id. + */ + public abstract String[] getPackagesForUid(int uid); + + /** + * Retrieve the official name associated with a user id. This name is + * guaranteed to never change, though it is possibly for the underlying + * user id to be changed. That is, if you are storing information about + * user ids in persistent storage, you should use the string returned + * by this function instead of the raw user-id. + * + * @param uid The user id for which you would like to retrieve a name. + * @return Returns a unique name for the given user id, or null if the + * user id is not currently assigned. + */ + public abstract String getNameForUid(int uid); + + /** + * Return the user id associated with a shared user name. Multiple + * applications can specify a shared user name in their manifest and thus + * end up using a common uid. This might be used for new applications + * that use an existing shared user name and need to know the uid of the + * shared user. + * + * @param sharedUserName The shared user name whose uid is to be retrieved. + * @return Returns the uid associated with the shared user, or NameNotFoundException + * if the shared user name is not being used by any installed packages + * @hide + */ + public abstract int getUidForSharedUser(String sharedUserName) + throws NameNotFoundException; + + /** + * Return a List of all application packages that are installed on the + * device. If flag GET_UNINSTALLED_PACKAGES has been set, a list of all + * applications including those deleted with DONT_DELETE_DATA(partially + * installed apps with data directory) will be returned. + * + * @param flags Additional option flags. Use any combination of + * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, + * {link #GET_UNINSTALLED_PACKAGES} to modify the data returned. + * + * @return A List of ApplicationInfo objects, one for each application that + * is installed on the device. In the unlikely case of there being + * no installed applications, an empty list is returned. + * If flag GET_UNINSTALLED_PACKAGES is set, a list of all + * applications including those deleted with DONT_DELETE_DATA + * (partially installed apps with data directory) will be returned. + * + * @see #GET_META_DATA + * @see #GET_SHARED_LIBRARY_FILES + * @see #GET_UNINSTALLED_PACKAGES + */ + public abstract List<ApplicationInfo> getInstalledApplications(int flags); + + /** + * Get a list of shared libraries that are available on the + * system. + * + * @return An array of shared library names that are + * available on the system, or null if none are installed. + * + */ + public abstract String[] getSystemSharedLibraryNames(); + + /** + * Determine the best action to perform for a given Intent. This is how + * {@link Intent#resolveActivity} finds an activity if a class has not + * been explicitly specified. + * + * @param intent An intent containing all of the desired specification + * (action, data, type, category, and/or component). + * @param flags Additional option flags. The most important is + * MATCH_DEFAULT_ONLY, to limit the resolution to only + * those activities that support the CATEGORY_DEFAULT. + * + * @return Returns a ResolveInfo containing the final activity intent that + * was determined to be the best action. Returns null if no + * matching activity was found. + * + * @see #MATCH_DEFAULT_ONLY + * @see #GET_INTENT_FILTERS + * @see #GET_RESOLVED_FILTER + */ + public abstract ResolveInfo resolveActivity(Intent intent, int flags); + + /** + * Retrieve all activities that can be performed for the given intent. + * + * @param intent The desired intent as per resolveActivity(). + * @param flags Additional option flags. The most important is + * MATCH_DEFAULT_ONLY, to limit the resolution to only + * those activities that support the CATEGORY_DEFAULT. + * + * @return A List<ResolveInfo> containing one entry for each matching + * Activity. These are ordered from best to worst match -- that + * is, the first item in the list is what is returned by + * resolveActivity(). If there are no matching activities, an empty + * list is returned. + * + * @see #MATCH_DEFAULT_ONLY + * @see #GET_INTENT_FILTERS + * @see #GET_RESOLVED_FILTER + */ + public abstract List<ResolveInfo> queryIntentActivities(Intent intent, + int flags); + + /** + * Retrieve a set of activities that should be presented to the user as + * similar options. This is like {@link #queryIntentActivities}, except it + * also allows you to supply a list of more explicit Intents that you would + * like to resolve to particular options, and takes care of returning the + * final ResolveInfo list in a reasonable order, with no duplicates, based + * on those inputs. + * + * @param caller The class name of the activity that is making the + * request. This activity will never appear in the output + * list. Can be null. + * @param specifics An array of Intents that should be resolved to the + * first specific results. Can be null. + * @param intent The desired intent as per resolveActivity(). + * @param flags Additional option flags. The most important is + * MATCH_DEFAULT_ONLY, to limit the resolution to only + * those activities that support the CATEGORY_DEFAULT. + * + * @return A List<ResolveInfo> containing one entry for each matching + * Activity. These are ordered first by all of the intents resolved + * in <var>specifics</var> and then any additional activities that + * can handle <var>intent</var> but did not get included by one of + * the <var>specifics</var> intents. If there are no matching + * activities, an empty list is returned. + * + * @see #MATCH_DEFAULT_ONLY + * @see #GET_INTENT_FILTERS + * @see #GET_RESOLVED_FILTER + */ + public abstract List<ResolveInfo> queryIntentActivityOptions( + ComponentName caller, Intent[] specifics, Intent intent, int flags); + + /** + * Retrieve all receivers that can handle a broadcast of the given intent. + * + * @param intent The desired intent as per resolveActivity(). + * @param flags Additional option flags. The most important is + * MATCH_DEFAULT_ONLY, to limit the resolution to only + * those activities that support the CATEGORY_DEFAULT. + * + * @return A List<ResolveInfo> containing one entry for each matching + * Receiver. These are ordered from first to last in priority. If + * there are no matching receivers, an empty list is returned. + * + * @see #MATCH_DEFAULT_ONLY + * @see #GET_INTENT_FILTERS + * @see #GET_RESOLVED_FILTER + */ + public abstract List<ResolveInfo> queryBroadcastReceivers(Intent intent, + int flags); + + /** + * Determine the best service to handle for a given Intent. + * + * @param intent An intent containing all of the desired specification + * (action, data, type, category, and/or component). + * @param flags Additional option flags. + * + * @return Returns a ResolveInfo containing the final service intent that + * was determined to be the best action. Returns null if no + * matching service was found. + * + * @see #GET_INTENT_FILTERS + * @see #GET_RESOLVED_FILTER + */ + public abstract ResolveInfo resolveService(Intent intent, int flags); + + /** + * Retrieve all services that can match the given intent. + * + * @param intent The desired intent as per resolveService(). + * @param flags Additional option flags. + * + * @return A List<ResolveInfo> containing one entry for each matching + * ServiceInfo. These are ordered from best to worst match -- that + * is, the first item in the list is what is returned by + * resolveService(). If there are no matching services, an empty + * list is returned. + * + * @see #GET_INTENT_FILTERS + * @see #GET_RESOLVED_FILTER + */ + public abstract List<ResolveInfo> queryIntentServices(Intent intent, + int flags); + + /** + * Find a single content provider by its base path name. + * + * @param name The name of the provider to find. + * @param flags Additional option flags. Currently should always be 0. + * + * @return ContentProviderInfo Information about the provider, if found, + * else null. + */ + public abstract ProviderInfo resolveContentProvider(String name, + int flags); + + /** + * Retrieve content provider information. + * + * <p><em>Note: unlike most other methods, an empty result set is indicated + * by a null return instead of an empty list.</em> + * + * @param processName If non-null, limits the returned providers to only + * those that are hosted by the given process. If null, + * all content providers are returned. + * @param uid If <var>processName</var> is non-null, this is the required + * uid owning the requested content providers. + * @param flags Additional option flags. Currently should always be 0. + * + * @return A List<ContentProviderInfo> containing one entry for each + * content provider either patching <var>processName</var> or, if + * <var>processName</var> is null, all known content providers. + * <em>If there are no matching providers, null is returned.</em> + */ + public abstract List<ProviderInfo> queryContentProviders( + String processName, int uid, int flags); + + /** + * Retrieve all of the information we know about a particular + * instrumentation class. + * + * <p>Throws {@link NameNotFoundException} if instrumentation with the + * given class name can not be found on the system. + * + * @param className The full name (i.e. + * com.google.apps.contacts.InstrumentList) of an + * Instrumentation class. + * @param flags Additional option flags. Currently should always be 0. + * + * @return InstrumentationInfo containing information about the + * instrumentation. + */ + public abstract InstrumentationInfo getInstrumentationInfo( + ComponentName className, int flags) throws NameNotFoundException; + + /** + * Retrieve information about available instrumentation code. May be used + * to retrieve either all instrumentation code, or only the code targeting + * a particular package. + * + * @param targetPackage If null, all instrumentation is returned; only the + * instrumentation targeting this package name is + * returned. + * @param flags Additional option flags. Currently should always be 0. + * + * @return A List<InstrumentationInfo> containing one entry for each + * matching available Instrumentation. Returns an empty list if + * there is no instrumentation available for the given package. + */ + public abstract List<InstrumentationInfo> queryInstrumentation( + String targetPackage, int flags); + + /** + * Retrieve an image from a package. This is a low-level API used by + * the various package manager info structures (such as + * {@link ComponentInfo} to implement retrieval of their associated + * icon. + * + * @param packageName The name of the package that this icon is coming from. + * Can not be null. + * @param resid The resource identifier of the desired image. Can not be 0. + * @param appInfo Overall information about <var>packageName</var>. This + * may be null, in which case the application information will be retrieved + * for you if needed; if you already have this information around, it can + * be much more efficient to supply it here. + * + * @return Returns a Drawable holding the requested image. Returns null if + * an image could not be found for any reason. + */ + public abstract Drawable getDrawable(String packageName, int resid, + ApplicationInfo appInfo); + + /** + * Retrieve the icon associated with an activity. Given the full name of + * an activity, retrieves the information about it and calls + * {@link ComponentInfo#loadIcon ComponentInfo.loadIcon()} to return its icon. + * If the activity can not be found, NameNotFoundException is thrown. + * + * @param activityName Name of the activity whose icon is to be retrieved. + * + * @return Returns the image of the icon, or the default activity icon if + * it could not be found. Does not return null. + * @throws NameNotFoundException Thrown if the resources for the given + * activity could not be loaded. + * + * @see #getActivityIcon(Intent) + */ + public abstract Drawable getActivityIcon(ComponentName activityName) + throws NameNotFoundException; + + /** + * Retrieve the icon associated with an Intent. If intent.getClassName() is + * set, this simply returns the result of + * getActivityIcon(intent.getClassName()). Otherwise it resolves the intent's + * component and returns the icon associated with the resolved component. + * If intent.getClassName() can not be found or the Intent can not be resolved + * to a component, NameNotFoundException is thrown. + * + * @param intent The intent for which you would like to retrieve an icon. + * + * @return Returns the image of the icon, or the default activity icon if + * it could not be found. Does not return null. + * @throws NameNotFoundException Thrown if the resources for application + * matching the given intent could not be loaded. + * + * @see #getActivityIcon(ComponentName) + */ + public abstract Drawable getActivityIcon(Intent intent) + throws NameNotFoundException; + + /** + * Return the generic icon for an activity that is used when no specific + * icon is defined. + * + * @return Drawable Image of the icon. + */ + public abstract Drawable getDefaultActivityIcon(); + + /** + * Retrieve the icon associated with an application. If it has not defined + * an icon, the default app icon is returned. Does not return null. + * + * @param info Information about application being queried. + * + * @return Returns the image of the icon, or the default application icon + * if it could not be found. + * + * @see #getApplicationIcon(String) + */ + public abstract Drawable getApplicationIcon(ApplicationInfo info); + + /** + * Retrieve the icon associated with an application. Given the name of the + * application's package, retrieves the information about it and calls + * getApplicationIcon() to return its icon. If the application can not be + * found, NameNotFoundException is thrown. + * + * @param packageName Name of the package whose application icon is to be + * retrieved. + * + * @return Returns the image of the icon, or the default application icon + * if it could not be found. Does not return null. + * @throws NameNotFoundException Thrown if the resources for the given + * application could not be loaded. + * + * @see #getApplicationIcon(ApplicationInfo) + */ + public abstract Drawable getApplicationIcon(String packageName) + throws NameNotFoundException; + + /** + * Retrieve text from a package. This is a low-level API used by + * the various package manager info structures (such as + * {@link ComponentInfo} to implement retrieval of their associated + * labels and other text. + * + * @param packageName The name of the package that this text is coming from. + * Can not be null. + * @param resid The resource identifier of the desired text. Can not be 0. + * @param appInfo Overall information about <var>packageName</var>. This + * may be null, in which case the application information will be retrieved + * for you if needed; if you already have this information around, it can + * be much more efficient to supply it here. + * + * @return Returns a CharSequence holding the requested text. Returns null + * if the text could not be found for any reason. + */ + public abstract CharSequence getText(String packageName, int resid, + ApplicationInfo appInfo); + + /** + * Retrieve an XML file from a package. This is a low-level API used to + * retrieve XML meta data. + * + * @param packageName The name of the package that this xml is coming from. + * Can not be null. + * @param resid The resource identifier of the desired xml. Can not be 0. + * @param appInfo Overall information about <var>packageName</var>. This + * may be null, in which case the application information will be retrieved + * for you if needed; if you already have this information around, it can + * be much more efficient to supply it here. + * + * @return Returns an XmlPullParser allowing you to parse out the XML + * data. Returns null if the xml resource could not be found for any + * reason. + */ + public abstract XmlResourceParser getXml(String packageName, int resid, + ApplicationInfo appInfo); + + /** + * Return the label to use for this application. + * + * @return Returns the label associated with this application, or null if + * it could not be found for any reason. + * @param info The application to get the label of + */ + public abstract CharSequence getApplicationLabel(ApplicationInfo info); + + /** + * Retrieve the resources associated with an activity. Given the full + * name of an activity, retrieves the information about it and calls + * getResources() to return its application's resources. If the activity + * can not be found, NameNotFoundException is thrown. + * + * @param activityName Name of the activity whose resources are to be + * retrieved. + * + * @return Returns the application's Resources. + * @throws NameNotFoundException Thrown if the resources for the given + * application could not be loaded. + * + * @see #getResourcesForApplication(ApplicationInfo) + */ + public abstract Resources getResourcesForActivity(ComponentName activityName) + throws NameNotFoundException; + + /** + * Retrieve the resources for an application. Throws NameNotFoundException + * if the package is no longer installed. + * + * @param app Information about the desired application. + * + * @return Returns the application's Resources. + * @throws NameNotFoundException Thrown if the resources for the given + * application could not be loaded (most likely because it was uninstalled). + */ + public abstract Resources getResourcesForApplication(ApplicationInfo app) + throws NameNotFoundException; + + /** + * Retrieve the resources associated with an application. Given the full + * package name of an application, retrieves the information about it and + * calls getResources() to return its application's resources. If the + * appPackageName can not be found, NameNotFoundException is thrown. + * + * @param appPackageName Package name of the application whose resources + * are to be retrieved. + * + * @return Returns the application's Resources. + * @throws NameNotFoundException Thrown if the resources for the given + * application could not be loaded. + * + * @see #getResourcesForApplication(ApplicationInfo) + */ + public abstract Resources getResourcesForApplication(String appPackageName) + throws NameNotFoundException; + + /** + * Retrieve overall information about an application package defined + * in a package archive file + * + * @param archiveFilePath The path to the archive file + * @param flags Additional option flags. Use any combination of + * {@link #GET_ACTIVITIES}, + * {@link #GET_GIDS}, + * {@link #GET_CONFIGURATIONS}, + * {@link #GET_INSTRUMENTATION}, + * {@link #GET_PERMISSIONS}, + * {@link #GET_PROVIDERS}, + * {@link #GET_RECEIVERS}, + * {@link #GET_SERVICES}, + * {@link #GET_SIGNATURES}, to modify the data returned. + * + * @return Returns the information about the package. Returns + * null if the package could not be successfully parsed. + * + * @see #GET_ACTIVITIES + * @see #GET_GIDS + * @see #GET_CONFIGURATIONS + * @see #GET_INSTRUMENTATION + * @see #GET_PERMISSIONS + * @see #GET_PROVIDERS + * @see #GET_RECEIVERS + * @see #GET_SERVICES + * @see #GET_SIGNATURES + * + */ + public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) { + PackageParser packageParser = new PackageParser(archiveFilePath); + DisplayMetrics metrics = new DisplayMetrics(); + metrics.setToDefaults(); + final File sourceFile = new File(archiveFilePath); + PackageParser.Package pkg = packageParser.parsePackage( + sourceFile, archiveFilePath, metrics, 0); + if (pkg == null) { + return null; + } + return PackageParser.generatePackageInfo(pkg, null, flags); + } + + /** + * Install a package. Since this may take a little while, the result will + * be posted back to the given observer. An installation will fail if the calling context + * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the + * package named in the package file's manifest is already installed, or if there's no space + * available on the device. + * + * @param packageURI The location of the package file to install. This can be a 'file:' or a + * 'content:' URI. + * @param observer An observer callback to get notified when the package installation is + * complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be + * called when that happens. observer may be null to indicate that no callback is desired. + * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE}, + * {@link #REPLACE_EXISTING_PACKAGE} + * + * @see #installPackage(android.net.Uri) + */ + public abstract void installPackage( + Uri packageURI, IPackageInstallObserver observer, int flags); + + /** + * Attempts to delete a package. Since this may take a little while, the result will + * be posted back to the given observer. A deletion will fail if the calling context + * lacks the {@link android.Manifest.permission#DELETE_PACKAGES} permission, if the + * named package cannot be found, or if the named package is a "system package". + * (TODO: include pointer to documentation on "system packages") + * + * @param packageName The name of the package to delete + * @param observer An observer callback to get notified when the package deletion is + * complete. {@link android.content.pm.IPackageDeleteObserver#packageDeleted(boolean)} will be + * called when that happens. observer may be null to indicate that no callback is desired. + * @param flags - possible values: {@link #DONT_DELETE_DATA} + * + * @hide + */ + public abstract void deletePackage( + String packageName, IPackageDeleteObserver observer, int flags); + /** + * Attempts to clear the user data directory of an application. + * Since this may take a little while, the result will + * be posted back to the given observer. A deletion will fail if the + * named package cannot be found, or if the named package is a "system package". + * + * @param packageName The name of the package + * @param observer An observer callback to get notified when the operation is finished + * {@link android.content.pm.IPackageDataObserver#onRemoveCompleted(String, boolean)} + * will be called when that happens. observer may be null to indicate that + * no callback is desired. + * + * @hide + */ + public abstract void clearApplicationUserData(String packageName, + IPackageDataObserver observer); + /** + * Attempts to delete the cache files associated with an application. + * Since this may take a little while, the result will + * be posted back to the given observer. A deletion will fail if the calling context + * lacks the {@link android.Manifest.permission#DELETE_CACHE_FILES} permission, if the + * named package cannot be found, or if the named package is a "system package". + * + * @param packageName The name of the package to delete + * @param observer An observer callback to get notified when the cache file deletion + * is complete. + * {@link android.content.pm.IPackageDataObserver#onRemoveCompleted(String, boolean)} + * will be called when that happens. observer may be null to indicate that + * no callback is desired. + * + * @hide + */ + public abstract void deleteApplicationCacheFiles(String packageName, + IPackageDataObserver observer); + + /** + * Free storage by deleting LRU sorted list of cache files across + * all applications. If the currently available free storage + * on the device is greater than or equal to the requested + * free storage, no cache files are cleared. If the currently + * available storage on the device is less than the requested + * free storage, some or all of the cache files across + * all applications are deleted (based on last accessed time) + * to increase the free storage space on the device to + * the requested value. There is no guarantee that clearing all + * the cache files from all applications will clear up + * enough storage to achieve the desired value. + * @param freeStorageSize The number of bytes of storage to be + * freed by the system. Say if freeStorageSize is XX, + * and the current free storage is YY, + * if XX is less than YY, just return. if not free XX-YY number + * of bytes if possible. + * @param observer call back used to notify when + * the operation is completed + * + * @hide + */ + public abstract void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer); + + /** + * Free storage by deleting LRU sorted list of cache files across + * all applications. If the currently available free storage + * on the device is greater than or equal to the requested + * free storage, no cache files are cleared. If the currently + * available storage on the device is less than the requested + * free storage, some or all of the cache files across + * all applications are deleted (based on last accessed time) + * to increase the free storage space on the device to + * the requested value. There is no guarantee that clearing all + * the cache files from all applications will clear up + * enough storage to achieve the desired value. + * @param freeStorageSize The number of bytes of storage to be + * freed by the system. Say if freeStorageSize is XX, + * and the current free storage is YY, + * if XX is less than YY, just return. if not free XX-YY number + * of bytes if possible. + * @param opFinishedIntent PendingIntent call back used to + * notify when the operation is completed.May be null + * to indicate that no call back is desired. + * + * @hide + */ + public abstract void freeStorage(long freeStorageSize, PendingIntent opFinishedIntent); + + /** + * Retrieve the size information for a package. + * Since this may take a little while, the result will + * be posted back to the given observer. The calling context + * should have the {@link android.Manifest.permission#GET_PACKAGE_SIZE} permission. + * + * @param packageName The name of the package whose size information is to be retrieved + * @param observer An observer callback to get notified when the operation + * is complete. + * {@link android.content.pm.IPackageStatsObserver#onGetStatsCompleted(PackageStats, boolean)} + * The observer's callback is invoked with a PackageStats object(containing the + * code, data and cache sizes of the package) and a boolean value representing + * the status of the operation. observer may be null to indicate that + * no callback is desired. + * + * @hide + */ + public abstract void getPackageSizeInfo(String packageName, + IPackageStatsObserver observer); + + /** + * Install a package. + * + * @param packageURI The location of the package file to install + * + * @see #installPackage(android.net.Uri, IPackageInstallObserver, int) + */ + public void installPackage(Uri packageURI) { + installPackage(packageURI, null, 0); + } + + /** + * Add a new package to the list of preferred packages. This new package + * will be added to the front of the list (removed from its current location + * if already listed), meaning it will now be preferred over all other + * packages when resolving conflicts. + * + * @param packageName The package name of the new package to make preferred. + */ + public abstract void addPackageToPreferred(String packageName); + + /** + * Remove a package from the list of preferred packages. If it was on + * the list, it will no longer be preferred over other packages. + * + * @param packageName The package name to remove. + */ + public abstract void removePackageFromPreferred(String packageName); + + /** + * Retrieve the list of all currently configured preferred packages. The + * first package on the list is the most preferred, the last is the + * least preferred. + * + * @param flags Additional option flags. Use any combination of + * {@link #GET_ACTIVITIES}, + * {@link #GET_GIDS}, + * {@link #GET_CONFIGURATIONS}, + * {@link #GET_INSTRUMENTATION}, + * {@link #GET_PERMISSIONS}, + * {@link #GET_PROVIDERS}, + * {@link #GET_RECEIVERS}, + * {@link #GET_SERVICES}, + * {@link #GET_SIGNATURES}, to modify the data returned. + * + * @return Returns a list of PackageInfo objects describing each + * preferred application, in order of preference. + * + * @see #GET_ACTIVITIES + * @see #GET_GIDS + * @see #GET_CONFIGURATIONS + * @see #GET_INSTRUMENTATION + * @see #GET_PERMISSIONS + * @see #GET_PROVIDERS + * @see #GET_RECEIVERS + * @see #GET_SERVICES + * @see #GET_SIGNATURES + */ + public abstract List<PackageInfo> getPreferredPackages(int flags); + + /** + * Add a new preferred activity mapping to the system. This will be used + * to automatically select the given activity component when + * {@link Context#startActivity(Intent) Context.startActivity()} finds + * multiple matching activities and also matches the given filter. + * + * @param filter The set of intents under which this activity will be + * made preferred. + * @param match The IntentFilter match category that this preference + * applies to. + * @param set The set of activities that the user was picking from when + * this preference was made. + * @param activity The component name of the activity that is to be + * preferred. + */ + public abstract void addPreferredActivity(IntentFilter filter, int match, + ComponentName[] set, ComponentName activity); + + /** + * Remove all preferred activity mappings, previously added with + * {@link #addPreferredActivity}, from the + * system whose activities are implemented in the given package name. + * + * @param packageName The name of the package whose preferred activity + * mappings are to be removed. + */ + public abstract void clearPackagePreferredActivities(String packageName); + + /** + * Retrieve all preferred activities, previously added with + * {@link #addPreferredActivity}, that are + * currently registered with the system. + * + * @param outFilters A list in which to place the filters of all of the + * preferred activities, or null for none. + * @param outActivities A list in which to place the component names of + * all of the preferred activities, or null for none. + * @param packageName An option package in which you would like to limit + * the list. If null, all activities will be returned; if non-null, only + * those activities in the given package are returned. + * + * @return Returns the total number of registered preferred activities + * (the number of distinct IntentFilter records, not the number of unique + * activity components) that were found. + */ + public abstract int getPreferredActivities(List<IntentFilter> outFilters, + List<ComponentName> outActivities, String packageName); + + /** + * Set the enabled setting for a package component (activity, receiver, service, provider). + * This setting will override any enabled state which may have been set by the component in its + * manifest. + * + * @param componentName The component to enable + * @param newState The new enabled state for the component. The legal values for this state + * are: + * {@link #COMPONENT_ENABLED_STATE_ENABLED}, + * {@link #COMPONENT_ENABLED_STATE_DISABLED} + * and + * {@link #COMPONENT_ENABLED_STATE_DEFAULT} + * The last one removes the setting, thereby restoring the component's state to + * whatever was set in it's manifest (or enabled, by default). + * @param flags Optional behavior flags: {@link #DONT_KILL_APP} or 0. + */ + public abstract void setComponentEnabledSetting(ComponentName componentName, + int newState, int flags); + + + /** + * Return the the enabled setting for a package component (activity, + * receiver, service, provider). This returns the last value set by + * {@link #setComponentEnabledSetting(ComponentName, int, int)}; in most + * cases this value will be {@link #COMPONENT_ENABLED_STATE_DEFAULT} since + * the value originally specified in the manifest has not been modified. + * + * @param componentName The component to retrieve. + * @return Returns the current enabled state for the component. May + * be one of {@link #COMPONENT_ENABLED_STATE_ENABLED}, + * {@link #COMPONENT_ENABLED_STATE_DISABLED}, or + * {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the + * component's enabled state is based on the original information in + * the manifest as found in {@link ComponentInfo}. + */ + public abstract int getComponentEnabledSetting(ComponentName componentName); + + /** + * Set the enabled setting for an application + * This setting will override any enabled state which may have been set by the application in + * its manifest. It also overrides the enabled state set in the manifest for any of the + * application's components. It does not override any enabled state set by + * {@link #setComponentEnabledSetting} for any of the application's components. + * + * @param packageName The package name of the application to enable + * @param newState The new enabled state for the component. The legal values for this state + * are: + * {@link #COMPONENT_ENABLED_STATE_ENABLED}, + * {@link #COMPONENT_ENABLED_STATE_DISABLED} + * and + * {@link #COMPONENT_ENABLED_STATE_DEFAULT} + * The last one removes the setting, thereby restoring the applications's state to + * whatever was set in its manifest (or enabled, by default). + * @param flags Optional behavior flags: {@link #DONT_KILL_APP} or 0. + */ + public abstract void setApplicationEnabledSetting(String packageName, + int newState, int flags); + + /** + * Return the the enabled setting for an application. This returns + * the last value set by + * {@link #setApplicationEnabledSetting(String, int, int)}; in most + * cases this value will be {@link #COMPONENT_ENABLED_STATE_DEFAULT} since + * the value originally specified in the manifest has not been modified. + * + * @param packageName The component to retrieve. + * @return Returns the current enabled state for the component. May + * be one of {@link #COMPONENT_ENABLED_STATE_ENABLED}, + * {@link #COMPONENT_ENABLED_STATE_DISABLED}, or + * {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the + * application's enabled state is based on the original information in + * the manifest as found in {@link ComponentInfo}. + */ + public abstract int getApplicationEnabledSetting(String packageName); + + /** + * Return whether the device has been booted into safe mode. + */ + public abstract boolean isSafeMode(); +} diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java new file mode 100644 index 0000000..4ae8b08 --- /dev/null +++ b/core/java/android/content/pm/PackageParser.java @@ -0,0 +1,2352 @@ +/* + * Copyright (C) 2007 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.content.pm; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.AssetManager; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.os.Bundle; +import android.os.PatternMatcher; +import android.util.AttributeSet; +import android.util.Config; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.TypedValue; +import com.android.internal.util.XmlUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.WeakReference; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * Package archive parsing + * + * {@hide} + */ +public class PackageParser { + + private String mArchiveSourcePath; + private String[] mSeparateProcesses; + private int mSdkVersion; + + private int mParseError = PackageManager.INSTALL_SUCCEEDED; + + private static final Object mSync = new Object(); + private static WeakReference<byte[]> mReadBuffer; + + /** If set to true, we will only allow package files that exactly match + * the DTD. Otherwise, we try to get as much from the package as we + * can without failing. This should normally be set to false, to + * support extensions to the DTD in future versions. */ + private static final boolean RIGID_PARSER = false; + + private static final String TAG = "PackageParser"; + + public PackageParser(String archiveSourcePath) { + mArchiveSourcePath = archiveSourcePath; + } + + public void setSeparateProcesses(String[] procs) { + mSeparateProcesses = procs; + } + + public void setSdkVersion(int sdkVersion) { + mSdkVersion = sdkVersion; + } + + private static final boolean isPackageFilename(String name) { + return name.endsWith(".apk"); + } + + /** + * Generate and return the {@link PackageInfo} for a parsed package. + * + * @param p the parsed package. + * @param flags indicating which optional information is included. + */ + public static PackageInfo generatePackageInfo(PackageParser.Package p, + int gids[], int flags) { + + PackageInfo pi = new PackageInfo(); + pi.packageName = p.packageName; + pi.versionCode = p.mVersionCode; + pi.versionName = p.mVersionName; + pi.sharedUserId = p.mSharedUserId; + pi.sharedUserLabel = p.mSharedUserLabel; + pi.applicationInfo = p.applicationInfo; + if ((flags&PackageManager.GET_GIDS) != 0) { + pi.gids = gids; + } + if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) { + int N = p.configPreferences.size(); + if (N > 0) { + pi.configPreferences = new ConfigurationInfo[N]; + for (int i=0; i<N; i++) { + pi.configPreferences[i] = p.configPreferences.get(i); + } + } + } + if ((flags&PackageManager.GET_ACTIVITIES) != 0) { + int N = p.activities.size(); + if (N > 0) { + pi.activities = new ActivityInfo[N]; + for (int i=0; i<N; i++) { + final Activity activity = p.activities.get(i); + if (activity.info.enabled + || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { + pi.activities[i] = generateActivityInfo(p.activities.get(i), flags); + } + } + } + } + if ((flags&PackageManager.GET_RECEIVERS) != 0) { + int N = p.receivers.size(); + if (N > 0) { + pi.receivers = new ActivityInfo[N]; + for (int i=0; i<N; i++) { + final Activity activity = p.receivers.get(i); + if (activity.info.enabled + || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { + pi.receivers[i] = generateActivityInfo(p.receivers.get(i), flags); + } + } + } + } + if ((flags&PackageManager.GET_SERVICES) != 0) { + int N = p.services.size(); + if (N > 0) { + pi.services = new ServiceInfo[N]; + for (int i=0; i<N; i++) { + final Service service = p.services.get(i); + if (service.info.enabled + || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { + pi.services[i] = generateServiceInfo(p.services.get(i), flags); + } + } + } + } + if ((flags&PackageManager.GET_PROVIDERS) != 0) { + int N = p.providers.size(); + if (N > 0) { + pi.providers = new ProviderInfo[N]; + for (int i=0; i<N; i++) { + final Provider provider = p.providers.get(i); + if (provider.info.enabled + || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { + pi.providers[i] = generateProviderInfo(p.providers.get(i), flags); + } + } + } + } + if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) { + int N = p.instrumentation.size(); + if (N > 0) { + pi.instrumentation = new InstrumentationInfo[N]; + for (int i=0; i<N; i++) { + pi.instrumentation[i] = generateInstrumentationInfo( + p.instrumentation.get(i), flags); + } + } + } + if ((flags&PackageManager.GET_PERMISSIONS) != 0) { + int N = p.permissions.size(); + if (N > 0) { + pi.permissions = new PermissionInfo[N]; + for (int i=0; i<N; i++) { + pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags); + } + } + N = p.requestedPermissions.size(); + if (N > 0) { + pi.requestedPermissions = new String[N]; + for (int i=0; i<N; i++) { + pi.requestedPermissions[i] = p.requestedPermissions.get(i); + } + } + } + if ((flags&PackageManager.GET_SIGNATURES) != 0) { + int N = p.mSignatures.length; + if (N > 0) { + pi.signatures = new Signature[N]; + System.arraycopy(p.mSignatures, 0, pi.signatures, 0, N); + } + } + return pi; + } + + private Certificate[] loadCertificates(JarFile jarFile, JarEntry je, + byte[] readBuffer) { + try { + // We must read the stream for the JarEntry to retrieve + // its certificates. + InputStream is = jarFile.getInputStream(je); + while (is.read(readBuffer, 0, readBuffer.length) != -1) { + // not using + } + is.close(); + return je != null ? je.getCertificates() : null; + } catch (IOException e) { + Log.w(TAG, "Exception reading " + je.getName() + " in " + + jarFile.getName(), e); + } + return null; + } + + public final static int PARSE_IS_SYSTEM = 0x0001; + public final static int PARSE_CHATTY = 0x0002; + public final static int PARSE_MUST_BE_APK = 0x0004; + public final static int PARSE_IGNORE_PROCESSES = 0x0008; + + public int getParseError() { + return mParseError; + } + + public Package parsePackage(File sourceFile, String destFileName, + DisplayMetrics metrics, int flags) { + mParseError = PackageManager.INSTALL_SUCCEEDED; + + mArchiveSourcePath = sourceFile.getPath(); + if (!sourceFile.isFile()) { + Log.w(TAG, "Skipping dir: " + mArchiveSourcePath); + mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK; + return null; + } + if (!isPackageFilename(sourceFile.getName()) + && (flags&PARSE_MUST_BE_APK) != 0) { + if ((flags&PARSE_IS_SYSTEM) == 0) { + // We expect to have non-.apk files in the system dir, + // so don't warn about them. + Log.w(TAG, "Skipping non-package file: " + mArchiveSourcePath); + } + mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK; + return null; + } + + if ((flags&PARSE_CHATTY) != 0 && Config.LOGD) Log.d( + TAG, "Scanning package: " + mArchiveSourcePath); + + XmlResourceParser parser = null; + AssetManager assmgr = null; + boolean assetError = true; + try { + assmgr = new AssetManager(); + if(assmgr.addAssetPath(mArchiveSourcePath) != 0) { + parser = assmgr.openXmlResourceParser("AndroidManifest.xml"); + assetError = false; + } else { + Log.w(TAG, "Failed adding asset path:"+mArchiveSourcePath); + } + } catch (Exception e) { + Log.w(TAG, "Unable to read AndroidManifest.xml of " + + mArchiveSourcePath, e); + } + if(assetError) { + if (assmgr != null) assmgr.close(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; + return null; + } + String[] errorText = new String[1]; + Package pkg = null; + Exception errorException = null; + try { + // XXXX todo: need to figure out correct configuration. + Resources res = new Resources(assmgr, metrics, null); + pkg = parsePackage(res, parser, flags, errorText); + } catch (Exception e) { + errorException = e; + mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; + } + + + if (pkg == null) { + if (errorException != null) { + Log.w(TAG, mArchiveSourcePath, errorException); + } else { + Log.w(TAG, mArchiveSourcePath + " (at " + + parser.getPositionDescription() + + "): " + errorText[0]); + } + parser.close(); + assmgr.close(); + if (mParseError == PackageManager.INSTALL_SUCCEEDED) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + } + return null; + } + + parser.close(); + assmgr.close(); + + pkg.applicationInfo.sourceDir = destFileName; + pkg.applicationInfo.publicSourceDir = destFileName; + pkg.mSignatures = null; + + return pkg; + } + + public boolean collectCertificates(Package pkg, int flags) { + pkg.mSignatures = null; + + WeakReference<byte[]> readBufferRef; + byte[] readBuffer = null; + synchronized (mSync) { + readBufferRef = mReadBuffer; + if (readBufferRef != null) { + mReadBuffer = null; + readBuffer = readBufferRef.get(); + } + if (readBuffer == null) { + readBuffer = new byte[8192]; + readBufferRef = new WeakReference<byte[]>(readBuffer); + } + } + + try { + JarFile jarFile = new JarFile(mArchiveSourcePath); + + Certificate[] certs = null; + + if ((flags&PARSE_IS_SYSTEM) != 0) { + // If this package comes from the system image, then we + // can trust it... we'll just use the AndroidManifest.xml + // to retrieve its signatures, not validating all of the + // files. + JarEntry jarEntry = jarFile.getJarEntry("AndroidManifest.xml"); + certs = loadCertificates(jarFile, jarEntry, readBuffer); + if (certs == null) { + Log.e(TAG, "Package " + pkg.packageName + + " has no certificates at entry " + + jarEntry.getName() + "; ignoring!"); + jarFile.close(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; + return false; + } + if (false) { + Log.i(TAG, "File " + mArchiveSourcePath + ": entry=" + jarEntry + + " certs=" + (certs != null ? certs.length : 0)); + if (certs != null) { + final int N = certs.length; + for (int i=0; i<N; i++) { + Log.i(TAG, " Public key: " + + certs[i].getPublicKey().getEncoded() + + " " + certs[i].getPublicKey()); + } + } + } + + } else { + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry je = (JarEntry)entries.nextElement(); + if (je.isDirectory()) continue; + if (je.getName().startsWith("META-INF/")) continue; + Certificate[] localCerts = loadCertificates(jarFile, je, + readBuffer); + if (false) { + Log.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName() + + ": certs=" + certs + " (" + + (certs != null ? certs.length : 0) + ")"); + } + if (localCerts == null) { + Log.e(TAG, "Package " + pkg.packageName + + " has no certificates at entry " + + je.getName() + "; ignoring!"); + jarFile.close(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; + return false; + } else if (certs == null) { + certs = localCerts; + } else { + // Ensure all certificates match. + for (int i=0; i<certs.length; i++) { + boolean found = false; + for (int j=0; j<localCerts.length; j++) { + if (certs[i] != null && + certs[i].equals(localCerts[j])) { + found = true; + break; + } + } + if (!found || certs.length != localCerts.length) { + Log.e(TAG, "Package " + pkg.packageName + + " has mismatched certificates at entry " + + je.getName() + "; ignoring!"); + jarFile.close(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; + return false; + } + } + } + } + } + jarFile.close(); + + synchronized (mSync) { + mReadBuffer = readBufferRef; + } + + if (certs != null && certs.length > 0) { + final int N = certs.length; + pkg.mSignatures = new Signature[certs.length]; + for (int i=0; i<N; i++) { + pkg.mSignatures[i] = new Signature( + certs[i].getEncoded()); + } + } else { + Log.e(TAG, "Package " + pkg.packageName + + " has no certificates; ignoring!"); + mParseError = PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; + return false; + } + } catch (CertificateEncodingException e) { + Log.w(TAG, "Exception reading " + mArchiveSourcePath, e); + mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; + return false; + } catch (IOException e) { + Log.w(TAG, "Exception reading " + mArchiveSourcePath, e); + mParseError = PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; + return false; + } catch (RuntimeException e) { + Log.w(TAG, "Exception reading " + mArchiveSourcePath, e); + mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; + return false; + } + + return true; + } + + public static String parsePackageName(String packageFilePath, int flags) { + XmlResourceParser parser = null; + AssetManager assmgr = null; + try { + assmgr = new AssetManager(); + int cookie = assmgr.addAssetPath(packageFilePath); + parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml"); + } catch (Exception e) { + if (assmgr != null) assmgr.close(); + Log.w(TAG, "Unable to read AndroidManifest.xml of " + + packageFilePath, e); + return null; + } + AttributeSet attrs = parser; + String errors[] = new String[1]; + String packageName = null; + try { + packageName = parsePackageName(parser, attrs, flags, errors); + } catch (IOException e) { + Log.w(TAG, packageFilePath, e); + } catch (XmlPullParserException e) { + Log.w(TAG, packageFilePath, e); + } finally { + if (parser != null) parser.close(); + if (assmgr != null) assmgr.close(); + } + if (packageName == null) { + Log.e(TAG, "parsePackageName error: " + errors[0]); + return null; + } + return packageName; + } + + private static String validateName(String name, boolean requiresSeparator) { + final int N = name.length(); + boolean hasSep = false; + boolean front = true; + for (int i=0; i<N; i++) { + final char c = name.charAt(i); + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + front = false; + continue; + } + if (!front) { + if ((c >= '0' && c <= '9') || c == '_') { + continue; + } + } + if (c == '.') { + hasSep = true; + front = true; + continue; + } + return "bad character '" + c + "'"; + } + return hasSep || !requiresSeparator + ? null : "must have at least one '.' separator"; + } + + private static String parsePackageName(XmlPullParser parser, + AttributeSet attrs, int flags, String[] outError) + throws IOException, XmlPullParserException { + + int type; + while ((type=parser.next()) != parser.START_TAG + && type != parser.END_DOCUMENT) { + ; + } + + if (type != parser.START_TAG) { + outError[0] = "No start tag found"; + return null; + } + if ((flags&PARSE_CHATTY) != 0 && Config.LOGV) Log.v( + TAG, "Root element name: '" + parser.getName() + "'"); + if (!parser.getName().equals("manifest")) { + outError[0] = "No <manifest> tag"; + return null; + } + String pkgName = attrs.getAttributeValue(null, "package"); + if (pkgName == null || pkgName.length() == 0) { + outError[0] = "<manifest> does not specify package"; + return null; + } + String nameError = validateName(pkgName, true); + if (nameError != null && !"android".equals(pkgName)) { + outError[0] = "<manifest> specifies bad package name \"" + + pkgName + "\": " + nameError; + return null; + } + + return pkgName.intern(); + } + + /** + * Temporary. + */ + static public Signature stringToSignature(String str) { + final int N = str.length(); + byte[] sig = new byte[N]; + for (int i=0; i<N; i++) { + sig[i] = (byte)str.charAt(i); + } + return new Signature(sig); + } + + private Package parsePackage( + Resources res, XmlResourceParser parser, int flags, String[] outError) + throws XmlPullParserException, IOException { + AttributeSet attrs = parser; + + String pkgName = parsePackageName(parser, attrs, flags, outError); + if (pkgName == null) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; + return null; + } + int type; + + final Package pkg = new Package(pkgName); + pkg.mSystem = (flags&PARSE_IS_SYSTEM) != 0; + boolean foundApp = false; + + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifest); + pkg.mVersionCode = sa.getInteger( + com.android.internal.R.styleable.AndroidManifest_versionCode, 0); + pkg.mVersionName = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifest_versionName); + if (pkg.mVersionName != null) { + pkg.mVersionName = pkg.mVersionName.intern(); + } + String str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifest_sharedUserId); + if (str != null) { + String nameError = validateName(str, true); + if (nameError != null && !"android".equals(pkgName)) { + outError[0] = "<manifest> specifies bad sharedUserId name \"" + + str + "\": " + nameError; + mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID; + return null; + } + pkg.mSharedUserId = str.intern(); + pkg.mSharedUserLabel = sa.getResourceId( + com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0); + } + sa.recycle(); + + final int innerDepth = parser.getDepth(); + + int outerDepth = parser.getDepth(); + while ((type=parser.next()) != parser.END_DOCUMENT + && (type != parser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == parser.END_TAG || type == parser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("application")) { + if (foundApp) { + if (RIGID_PARSER) { + outError[0] = "<manifest> has more than one <application>"; + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } else { + Log.w(TAG, "<manifest> has more than one <application>"); + XmlUtils.skipCurrentTag(parser); + continue; + } + } + + foundApp = true; + if (!parseApplication(pkg, res, parser, attrs, flags, outError)) { + return null; + } + } else if (tagName.equals("permission-group")) { + if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) { + return null; + } + } else if (tagName.equals("permission")) { + if (parsePermission(pkg, res, parser, attrs, outError) == null) { + return null; + } + } else if (tagName.equals("permission-tree")) { + if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) { + return null; + } + } else if (tagName.equals("uses-permission")) { + sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestUsesPermission); + + String name = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestUsesPermission_name); + + sa.recycle(); + + if (name != null && !pkg.requestedPermissions.contains(name)) { + pkg.requestedPermissions.add(name); + } + + XmlUtils.skipCurrentTag(parser); + + } else if (tagName.equals("uses-configuration")) { + ConfigurationInfo cPref = new ConfigurationInfo(); + sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestUsesConfiguration); + cPref.reqTouchScreen = sa.getInt( + com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen, + Configuration.TOUCHSCREEN_UNDEFINED); + cPref.reqKeyboardType = sa.getInt( + com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType, + Configuration.KEYBOARD_UNDEFINED); + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard, + false)) { + cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD; + } + cPref.reqNavigation = sa.getInt( + com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation, + Configuration.NAVIGATION_UNDEFINED); + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav, + false)) { + cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV; + } + sa.recycle(); + pkg.configPreferences.add(cPref); + + XmlUtils.skipCurrentTag(parser); + + } else if (tagName.equals("uses-sdk")) { + if (mSdkVersion > 0) { + sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestUsesSdk); + + int vers = sa.getInt( + com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion, 0); + + sa.recycle(); + + if (vers > mSdkVersion) { + outError[0] = "Requires newer sdk version #" + vers + + " (current version is #" + mSdkVersion + ")"; + mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; + return null; + } + } + + XmlUtils.skipCurrentTag(parser); + + } else if (tagName.equals("instrumentation")) { + if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) { + return null; + } + } else if (tagName.equals("eat-comment")) { + // Just skip this tag + XmlUtils.skipCurrentTag(parser); + continue; + } else if (RIGID_PARSER) { + outError[0] = "Bad element under <manifest>: " + + parser.getName(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } else { + Log.w(TAG, "Bad element under <manifest>: " + + parser.getName()); + XmlUtils.skipCurrentTag(parser); + continue; + } + } + + if (!foundApp && pkg.instrumentation.size() == 0) { + outError[0] = "<manifest> does not contain an <application> or <instrumentation>"; + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY; + } + + if (pkg.usesLibraries.size() > 0) { + pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()]; + pkg.usesLibraries.toArray(pkg.usesLibraryFiles); + } + + return pkg; + } + + private static String buildClassName(String pkg, CharSequence clsSeq, + String[] outError) { + if (clsSeq == null || clsSeq.length() <= 0) { + outError[0] = "Empty class name in package " + pkg; + return null; + } + String cls = clsSeq.toString(); + char c = cls.charAt(0); + if (c == '.') { + return (pkg + cls).intern(); + } + if (cls.indexOf('.') < 0) { + StringBuilder b = new StringBuilder(pkg); + b.append('.'); + b.append(cls); + return b.toString().intern(); + } + if (c >= 'a' && c <= 'z') { + return cls.intern(); + } + outError[0] = "Bad class name " + cls + " in package " + pkg; + return null; + } + + private static String buildCompoundName(String pkg, + CharSequence procSeq, String type, String[] outError) { + String proc = procSeq.toString(); + char c = proc.charAt(0); + if (pkg != null && c == ':') { + if (proc.length() < 2) { + outError[0] = "Bad " + type + " name " + proc + " in package " + pkg + + ": must be at least two characters"; + return null; + } + String subName = proc.substring(1); + String nameError = validateName(subName, false); + if (nameError != null) { + outError[0] = "Invalid " + type + " name " + proc + " in package " + + pkg + ": " + nameError; + return null; + } + return (pkg + proc).intern(); + } + String nameError = validateName(proc, true); + if (nameError != null && !"system".equals(proc)) { + outError[0] = "Invalid " + type + " name " + proc + " in package " + + pkg + ": " + nameError; + return null; + } + return proc.intern(); + } + + private static String buildProcessName(String pkg, String defProc, + CharSequence procSeq, int flags, String[] separateProcesses, + String[] outError) { + if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) { + return defProc != null ? defProc : pkg; + } + if (separateProcesses != null) { + for (int i=separateProcesses.length-1; i>=0; i--) { + String sp = separateProcesses[i]; + if (sp.equals(pkg) || sp.equals(defProc) || sp.equals(procSeq)) { + return pkg; + } + } + } + if (procSeq == null || procSeq.length() <= 0) { + return defProc; + } + return buildCompoundName(pkg, procSeq, "package", outError); + } + + private static String buildTaskAffinityName(String pkg, String defProc, + CharSequence procSeq, String[] outError) { + if (procSeq == null) { + return defProc; + } + if (procSeq.length() <= 0) { + return null; + } + return buildCompoundName(pkg, procSeq, "taskAffinity", outError); + } + + private PermissionGroup parsePermissionGroup(Package owner, Resources res, + XmlPullParser parser, AttributeSet attrs, String[] outError) + throws XmlPullParserException, IOException { + PermissionGroup perm = new PermissionGroup(owner); + + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestPermissionGroup); + + if (!parsePackageItemInfo(owner, perm.info, outError, + "<permission-group>", sa, + com.android.internal.R.styleable.AndroidManifestPermissionGroup_name, + com.android.internal.R.styleable.AndroidManifestPermissionGroup_label, + com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon)) { + sa.recycle(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + + perm.info.descriptionRes = sa.getResourceId( + com.android.internal.R.styleable.AndroidManifestPermissionGroup_description, + 0); + + sa.recycle(); + + if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm, + outError)) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + + owner.permissionGroups.add(perm); + + return perm; + } + + private Permission parsePermission(Package owner, Resources res, + XmlPullParser parser, AttributeSet attrs, String[] outError) + throws XmlPullParserException, IOException { + Permission perm = new Permission(owner); + + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestPermission); + + if (!parsePackageItemInfo(owner, perm.info, outError, + "<permission>", sa, + com.android.internal.R.styleable.AndroidManifestPermission_name, + com.android.internal.R.styleable.AndroidManifestPermission_label, + com.android.internal.R.styleable.AndroidManifestPermission_icon)) { + sa.recycle(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + + perm.info.group = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPermission_permissionGroup); + if (perm.info.group != null) { + perm.info.group = perm.info.group.intern(); + } + + perm.info.descriptionRes = sa.getResourceId( + com.android.internal.R.styleable.AndroidManifestPermission_description, + 0); + + perm.info.protectionLevel = sa.getInt( + com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel, + PermissionInfo.PROTECTION_NORMAL); + + sa.recycle(); + + if (perm.info.protectionLevel == -1) { + outError[0] = "<permission> does not specify protectionLevel"; + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + + if (!parseAllMetaData(res, parser, attrs, "<permission>", perm, + outError)) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + + owner.permissions.add(perm); + + return perm; + } + + private Permission parsePermissionTree(Package owner, Resources res, + XmlPullParser parser, AttributeSet attrs, String[] outError) + throws XmlPullParserException, IOException { + Permission perm = new Permission(owner); + + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestPermissionTree); + + if (!parsePackageItemInfo(owner, perm.info, outError, + "<permission-tree>", sa, + com.android.internal.R.styleable.AndroidManifestPermissionTree_name, + com.android.internal.R.styleable.AndroidManifestPermissionTree_label, + com.android.internal.R.styleable.AndroidManifestPermissionTree_icon)) { + sa.recycle(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + + sa.recycle(); + + int index = perm.info.name.indexOf('.'); + if (index > 0) { + index = perm.info.name.indexOf('.', index+1); + } + if (index < 0) { + outError[0] = "<permission-tree> name has less than three segments: " + + perm.info.name; + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + + perm.info.descriptionRes = 0; + perm.info.protectionLevel = PermissionInfo.PROTECTION_NORMAL; + perm.tree = true; + + if (!parseAllMetaData(res, parser, attrs, "<permission-tree>", perm, + outError)) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + + owner.permissions.add(perm); + + return perm; + } + + private Instrumentation parseInstrumentation(Package owner, Resources res, + XmlPullParser parser, AttributeSet attrs, String[] outError) + throws XmlPullParserException, IOException { + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestInstrumentation); + + Instrumentation a = new Instrumentation(owner); + + if (!parsePackageItemInfo(owner, a.info, outError, "<instrumentation>", sa, + com.android.internal.R.styleable.AndroidManifestInstrumentation_name, + com.android.internal.R.styleable.AndroidManifestInstrumentation_label, + com.android.internal.R.styleable.AndroidManifestInstrumentation_icon)) { + sa.recycle(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + + a.component = new ComponentName(owner.applicationInfo.packageName, + a.info.name); + + String str; + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage); + a.info.targetPackage = str != null ? str.intern() : null; + + a.info.handleProfiling = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestInstrumentation_handleProfiling, + false); + + a.info.functionalTest = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestInstrumentation_functionalTest, + false); + + sa.recycle(); + + if (a.info.targetPackage == null) { + outError[0] = "<instrumentation> does not specify targetPackage"; + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + + if (!parseAllMetaData(res, parser, attrs, "<instrumentation>", a, + outError)) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + + owner.instrumentation.add(a); + + return a; + } + + private boolean parseApplication(Package owner, Resources res, + XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) + throws XmlPullParserException, IOException { + final ApplicationInfo ai = owner.applicationInfo; + final String pkgName = owner.applicationInfo.packageName; + + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestApplication); + + String name = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestApplication_name); + if (name != null) { + ai.className = buildClassName(pkgName, name, outError); + if (ai.className == null) { + sa.recycle(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return false; + } + } + + String manageSpaceActivity = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity); + if (manageSpaceActivity != null) { + ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity, + outError); + } + + TypedValue v = sa.peekValue( + com.android.internal.R.styleable.AndroidManifestApplication_label); + if (v != null && (ai.labelRes=v.resourceId) == 0) { + ai.nonLocalizedLabel = v.coerceToString(); + } + + ai.icon = sa.getResourceId( + com.android.internal.R.styleable.AndroidManifestApplication_icon, 0); + ai.theme = sa.getResourceId( + com.android.internal.R.styleable.AndroidManifestApplication_theme, 0); + ai.descriptionRes = sa.getResourceId( + com.android.internal.R.styleable.AndroidManifestApplication_description, 0); + + if ((flags&PARSE_IS_SYSTEM) != 0) { + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_persistent, + false)) { + ai.flags |= ApplicationInfo.FLAG_PERSISTENT; + } + } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_debuggable, + false)) { + ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE; + } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_hasCode, + true)) { + ai.flags |= ApplicationInfo.FLAG_HAS_CODE; + } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting, + false)) { + ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING; + } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData, + true)) { + ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA; + } + + String str; + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestApplication_permission); + ai.permission = (str != null && str.length() > 0) ? str.intern() : null; + + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity); + ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName, + str, outError); + + if (outError[0] == null) { + ai.processName = buildProcessName(ai.packageName, null, sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestApplication_process), + flags, mSeparateProcesses, outError); + + ai.enabled = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_enabled, true); + } + + sa.recycle(); + + if (outError[0] != null) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return false; + } + + final int innerDepth = parser.getDepth(); + + int type; + while ((type=parser.next()) != parser.END_DOCUMENT + && (type != parser.END_TAG || parser.getDepth() > innerDepth)) { + if (type == parser.END_TAG || type == parser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("activity")) { + Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false); + if (a == null) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return false; + } + + owner.activities.add(a); + + } else if (tagName.equals("receiver")) { + Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true); + if (a == null) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return false; + } + + owner.receivers.add(a); + + } else if (tagName.equals("service")) { + Service s = parseService(owner, res, parser, attrs, flags, outError); + if (s == null) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return false; + } + + owner.services.add(s); + + } else if (tagName.equals("provider")) { + Provider p = parseProvider(owner, res, parser, attrs, flags, outError); + if (p == null) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return false; + } + + owner.providers.add(p); + + } else if (tagName.equals("activity-alias")) { + Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError, false); + if (a == null) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return false; + } + + owner.activities.add(a); + + } else if (parser.getName().equals("meta-data")) { + // note: application meta-data is stored off to the side, so it can + // remain null in the primary copy (we like to avoid extra copies because + // it can be large) + if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData, + outError)) == null) { + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return false; + } + + } else if (tagName.equals("uses-library")) { + sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestUsesLibrary); + + String lname = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestUsesLibrary_name); + + sa.recycle(); + + if (lname != null && !owner.usesLibraries.contains(lname)) { + owner.usesLibraries.add(lname); + } + + XmlUtils.skipCurrentTag(parser); + + } else { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "Unknown element under <application>: " + tagName); + XmlUtils.skipCurrentTag(parser); + continue; + } else { + outError[0] = "Bad element under <application>: " + tagName; + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return false; + } + } + } + + return true; + } + + private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo, + String[] outError, String tag, TypedArray sa, + int nameRes, int labelRes, int iconRes) { + String name = sa.getNonResourceString(nameRes); + if (name == null) { + outError[0] = tag + " does not specify android:name"; + return false; + } + + outInfo.name + = buildClassName(owner.applicationInfo.packageName, name, outError); + if (outInfo.name == null) { + return false; + } + + int iconVal = sa.getResourceId(iconRes, 0); + if (iconVal != 0) { + outInfo.icon = iconVal; + outInfo.nonLocalizedLabel = null; + } + + TypedValue v = sa.peekValue(labelRes); + if (v != null && (outInfo.labelRes=v.resourceId) == 0) { + outInfo.nonLocalizedLabel = v.coerceToString(); + } + + outInfo.packageName = owner.packageName; + + return true; + } + + private boolean parseComponentInfo(Package owner, int flags, + ComponentInfo outInfo, String[] outError, String tag, TypedArray sa, + int nameRes, int labelRes, int iconRes, int processRes, + int enabledRes) { + if (!parsePackageItemInfo(owner, outInfo, outError, tag, sa, + nameRes, labelRes, iconRes)) { + return false; + } + + if (processRes != 0) { + outInfo.processName = buildProcessName(owner.applicationInfo.packageName, + owner.applicationInfo.processName, sa.getNonResourceString(processRes), + flags, mSeparateProcesses, outError); + } + outInfo.enabled = sa.getBoolean(enabledRes, true); + + return outError[0] == null; + } + + private Activity parseActivity(Package owner, Resources res, + XmlPullParser parser, AttributeSet attrs, int flags, String[] outError, + boolean receiver) throws XmlPullParserException, IOException { + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestActivity); + + Activity a = new Activity(owner); + + if (!parseComponentInfo(owner, flags, a.info, outError, + receiver ? "<receiver>" : "<activity>", sa, + com.android.internal.R.styleable.AndroidManifestActivity_name, + com.android.internal.R.styleable.AndroidManifestActivity_label, + com.android.internal.R.styleable.AndroidManifestActivity_icon, + com.android.internal.R.styleable.AndroidManifestActivity_process, + com.android.internal.R.styleable.AndroidManifestActivity_enabled)) { + sa.recycle(); + return null; + } + + final boolean setExported = sa.hasValue( + com.android.internal.R.styleable.AndroidManifestActivity_exported); + if (setExported) { + a.info.exported = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_exported, false); + } + + a.component = new ComponentName(owner.applicationInfo.packageName, + a.info.name); + + a.info.theme = sa.getResourceId( + com.android.internal.R.styleable.AndroidManifestActivity_theme, 0); + + String str; + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestActivity_permission); + if (str == null) { + a.info.permission = owner.applicationInfo.permission; + } else { + a.info.permission = str.length() > 0 ? str.toString().intern() : null; + } + + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity); + a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName, + owner.applicationInfo.taskAffinity, str, outError); + + a.info.flags = 0; + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_multiprocess, + false)) { + a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS; + } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_finishOnTaskLaunch, + false)) { + a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH; + } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_clearTaskOnLaunch, + false)) { + a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH; + } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_noHistory, + false)) { + a.info.flags |= ActivityInfo.FLAG_NO_HISTORY; + } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_alwaysRetainTaskState, + false)) { + a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE; + } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_stateNotNeeded, + false)) { + a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED; + } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_excludeFromRecents, + false)) { + a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; + } + + if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_allowTaskReparenting, + (owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) { + a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING; + } + + if (!receiver) { + a.info.launchMode = sa.getInt( + com.android.internal.R.styleable.AndroidManifestActivity_launchMode, + ActivityInfo.LAUNCH_MULTIPLE); + a.info.screenOrientation = sa.getInt( + com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation, + ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); + a.info.configChanges = sa.getInt( + com.android.internal.R.styleable.AndroidManifestActivity_configChanges, + 0); + a.info.softInputMode = sa.getInt( + com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode, + 0); + } else { + a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE; + a.info.configChanges = 0; + } + + sa.recycle(); + + if (outError[0] != null) { + return null; + } + + int outerDepth = parser.getDepth(); + int type; + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + if (parser.getName().equals("intent-filter")) { + ActivityIntentInfo intent = new ActivityIntentInfo(a); + if (!parseIntent(res, parser, attrs, flags, intent, outError, !receiver)) { + return null; + } + if (intent.countActions() == 0) { + Log.w(TAG, "Intent filter for activity " + intent + + " defines no actions"); + } else { + a.intents.add(intent); + } + } else if (parser.getName().equals("meta-data")) { + if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData, + outError)) == null) { + return null; + } + } else { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + if (receiver) { + Log.w(TAG, "Unknown element under <receiver>: " + parser.getName()); + } else { + Log.w(TAG, "Unknown element under <activity>: " + parser.getName()); + } + XmlUtils.skipCurrentTag(parser); + continue; + } + if (receiver) { + outError[0] = "Bad element under <receiver>: " + parser.getName(); + } else { + outError[0] = "Bad element under <activity>: " + parser.getName(); + } + return null; + } + } + + if (!setExported) { + a.info.exported = a.intents.size() > 0; + } + + return a; + } + + private Activity parseActivityAlias(Package owner, Resources res, + XmlPullParser parser, AttributeSet attrs, int flags, String[] outError, + boolean receiver) throws XmlPullParserException, IOException { + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestActivityAlias); + + String targetActivity = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestActivityAlias_targetActivity); + if (targetActivity == null) { + outError[0] = "<activity-alias> does not specify android:targetActivity"; + sa.recycle(); + return null; + } + + targetActivity = buildClassName(owner.applicationInfo.packageName, + targetActivity, outError); + if (targetActivity == null) { + sa.recycle(); + return null; + } + + Activity a = new Activity(owner); + Activity target = null; + + final int NA = owner.activities.size(); + for (int i=0; i<NA; i++) { + Activity t = owner.activities.get(i); + if (targetActivity.equals(t.info.name)) { + target = t; + break; + } + } + + if (target == null) { + outError[0] = "<activity-alias> target activity " + targetActivity + + " not found in manifest"; + sa.recycle(); + return null; + } + + a.info.targetActivity = targetActivity; + + a.info.configChanges = target.info.configChanges; + a.info.flags = target.info.flags; + a.info.icon = target.info.icon; + a.info.labelRes = target.info.labelRes; + a.info.launchMode = target.info.launchMode; + a.info.nonLocalizedLabel = target.info.nonLocalizedLabel; + a.info.processName = target.info.processName; + a.info.screenOrientation = target.info.screenOrientation; + a.info.taskAffinity = target.info.taskAffinity; + a.info.theme = target.info.theme; + + if (!parseComponentInfo(owner, flags, a.info, outError, + receiver ? "<receiver>" : "<activity>", sa, + com.android.internal.R.styleable.AndroidManifestActivityAlias_name, + com.android.internal.R.styleable.AndroidManifestActivityAlias_label, + com.android.internal.R.styleable.AndroidManifestActivityAlias_icon, + 0, + com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled)) { + sa.recycle(); + return null; + } + + final boolean setExported = sa.hasValue( + com.android.internal.R.styleable.AndroidManifestActivityAlias_exported); + if (setExported) { + a.info.exported = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false); + } + + a.component = new ComponentName(owner.applicationInfo.packageName, + a.info.name); + + String str; + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestActivityAlias_permission); + if (str != null) { + a.info.permission = str.length() > 0 ? str.toString().intern() : null; + } + + sa.recycle(); + + if (outError[0] != null) { + return null; + } + + int outerDepth = parser.getDepth(); + int type; + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + if (parser.getName().equals("intent-filter")) { + ActivityIntentInfo intent = new ActivityIntentInfo(a); + if (!parseIntent(res, parser, attrs, flags, intent, outError, true)) { + return null; + } + if (intent.countActions() == 0) { + Log.w(TAG, "Intent filter for activity alias " + intent + + " defines no actions"); + } else { + a.intents.add(intent); + } + } else if (parser.getName().equals("meta-data")) { + if ((a.metaData=parseMetaData(res, parser, attrs, a.metaData, + outError)) == null) { + return null; + } + } else { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "Unknown element under <activity-alias>: " + parser.getName()); + XmlUtils.skipCurrentTag(parser); + continue; + } + outError[0] = "Bad element under <activity-alias>: " + parser.getName(); + return null; + } + } + + if (!setExported) { + a.info.exported = a.intents.size() > 0; + } + + return a; + } + + private Provider parseProvider(Package owner, Resources res, + XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) + throws XmlPullParserException, IOException { + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestProvider); + + Provider p = new Provider(owner); + + if (!parseComponentInfo(owner, flags, p.info, outError, "<provider>", sa, + com.android.internal.R.styleable.AndroidManifestProvider_name, + com.android.internal.R.styleable.AndroidManifestProvider_label, + com.android.internal.R.styleable.AndroidManifestProvider_icon, + com.android.internal.R.styleable.AndroidManifestProvider_process, + com.android.internal.R.styleable.AndroidManifestProvider_enabled)) { + sa.recycle(); + return null; + } + + p.info.exported = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestProvider_exported, true); + + p.component = new ComponentName(owner.applicationInfo.packageName, + p.info.name); + + String cpname = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestProvider_authorities); + + p.info.isSyncable = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestProvider_syncable, + false); + + String permission = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestProvider_permission); + String str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestProvider_readPermission); + if (str == null) { + str = permission; + } + if (str == null) { + p.info.readPermission = owner.applicationInfo.permission; + } else { + p.info.readPermission = + str.length() > 0 ? str.toString().intern() : null; + } + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestProvider_writePermission); + if (str == null) { + str = permission; + } + if (str == null) { + p.info.writePermission = owner.applicationInfo.permission; + } else { + p.info.writePermission = + str.length() > 0 ? str.toString().intern() : null; + } + + p.info.grantUriPermissions = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions, + false); + + p.info.multiprocess = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestProvider_multiprocess, + false); + + p.info.initOrder = sa.getInt( + com.android.internal.R.styleable.AndroidManifestProvider_initOrder, + 0); + + sa.recycle(); + + if (cpname == null) { + outError[0] = "<provider> does not incude authorities attribute"; + return null; + } + p.info.authority = cpname.intern(); + + if (!parseProviderTags(res, parser, attrs, p, outError)) { + return null; + } + + return p; + } + + private boolean parseProviderTags(Resources res, + XmlPullParser parser, AttributeSet attrs, + Provider outInfo, String[] outError) + throws XmlPullParserException, IOException { + int outerDepth = parser.getDepth(); + int type; + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + if (parser.getName().equals("meta-data")) { + if ((outInfo.metaData=parseMetaData(res, parser, attrs, + outInfo.metaData, outError)) == null) { + return false; + } + } else if (parser.getName().equals("grant-uri-permission")) { + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestGrantUriPermission); + + PatternMatcher pa = null; + + String str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestGrantUriPermission_path); + if (str != null) { + pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL); + } + + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPrefix); + if (str != null) { + pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX); + } + + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestGrantUriPermission_pathPattern); + if (str != null) { + pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB); + } + + sa.recycle(); + + if (pa != null) { + if (outInfo.info.uriPermissionPatterns == null) { + outInfo.info.uriPermissionPatterns = new PatternMatcher[1]; + outInfo.info.uriPermissionPatterns[0] = pa; + } else { + final int N = outInfo.info.uriPermissionPatterns.length; + PatternMatcher[] newp = new PatternMatcher[N+1]; + System.arraycopy(outInfo.info.uriPermissionPatterns, 0, newp, 0, N); + newp[N] = pa; + outInfo.info.uriPermissionPatterns = newp; + } + outInfo.info.grantUriPermissions = true; + } + XmlUtils.skipCurrentTag(parser); + + } else { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "Unknown element under <provider>: " + + parser.getName()); + XmlUtils.skipCurrentTag(parser); + continue; + } + outError[0] = "Bad element under <provider>: " + + parser.getName(); + return false; + } + } + return true; + } + + private Service parseService(Package owner, Resources res, + XmlPullParser parser, AttributeSet attrs, int flags, String[] outError) + throws XmlPullParserException, IOException { + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestService); + + Service s = new Service(owner); + + if (!parseComponentInfo(owner, flags, s.info, outError, "<service>", sa, + com.android.internal.R.styleable.AndroidManifestService_name, + com.android.internal.R.styleable.AndroidManifestService_label, + com.android.internal.R.styleable.AndroidManifestService_icon, + com.android.internal.R.styleable.AndroidManifestService_process, + com.android.internal.R.styleable.AndroidManifestService_enabled)) { + sa.recycle(); + return null; + } + + final boolean setExported = sa.hasValue( + com.android.internal.R.styleable.AndroidManifestService_exported); + if (setExported) { + s.info.exported = sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestService_exported, false); + } + + s.component = new ComponentName(owner.applicationInfo.packageName, + s.info.name); + + String str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestService_permission); + if (str == null) { + s.info.permission = owner.applicationInfo.permission; + } else { + s.info.permission = str.length() > 0 ? str.toString().intern() : null; + } + + sa.recycle(); + + int outerDepth = parser.getDepth(); + int type; + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + if (parser.getName().equals("intent-filter")) { + ServiceIntentInfo intent = new ServiceIntentInfo(s); + if (!parseIntent(res, parser, attrs, flags, intent, outError, false)) { + return null; + } + + s.intents.add(intent); + } else if (parser.getName().equals("meta-data")) { + if ((s.metaData=parseMetaData(res, parser, attrs, s.metaData, + outError)) == null) { + return null; + } + } else { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "Unknown element under <service>: " + + parser.getName()); + XmlUtils.skipCurrentTag(parser); + continue; + } + outError[0] = "Bad element under <service>: " + + parser.getName(); + return null; + } + } + + if (!setExported) { + s.info.exported = s.intents.size() > 0; + } + + return s; + } + + private boolean parseAllMetaData(Resources res, + XmlPullParser parser, AttributeSet attrs, String tag, + Component outInfo, String[] outError) + throws XmlPullParserException, IOException { + int outerDepth = parser.getDepth(); + int type; + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + if (parser.getName().equals("meta-data")) { + if ((outInfo.metaData=parseMetaData(res, parser, attrs, + outInfo.metaData, outError)) == null) { + return false; + } + } else { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "Unknown element under " + tag + ": " + + parser.getName()); + XmlUtils.skipCurrentTag(parser); + continue; + } + outError[0] = "Bad element under " + tag + ": " + + parser.getName(); + return false; + } + } + return true; + } + + private Bundle parseMetaData(Resources res, + XmlPullParser parser, AttributeSet attrs, + Bundle data, String[] outError) + throws XmlPullParserException, IOException { + + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestMetaData); + + if (data == null) { + data = new Bundle(); + } + + String name = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestMetaData_name); + if (name == null) { + outError[0] = "<meta-data> requires an android:name attribute"; + sa.recycle(); + return null; + } + + boolean success = true; + + TypedValue v = sa.peekValue( + com.android.internal.R.styleable.AndroidManifestMetaData_resource); + if (v != null && v.resourceId != 0) { + //Log.i(TAG, "Meta data ref " + name + ": " + v); + data.putInt(name, v.resourceId); + } else { + v = sa.peekValue( + com.android.internal.R.styleable.AndroidManifestMetaData_value); + //Log.i(TAG, "Meta data " + name + ": " + v); + if (v != null) { + if (v.type == TypedValue.TYPE_STRING) { + CharSequence cs = v.coerceToString(); + data.putString(name, cs != null ? cs.toString() : null); + } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) { + data.putBoolean(name, v.data != 0); + } else if (v.type >= TypedValue.TYPE_FIRST_INT + && v.type <= TypedValue.TYPE_LAST_INT) { + data.putInt(name, v.data); + } else if (v.type == TypedValue.TYPE_FLOAT) { + data.putFloat(name, v.getFloat()); + } else { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "<meta-data> only supports string, integer, float, color, boolean, and resource reference types"); + } else { + outError[0] = "<meta-data> only supports string, integer, float, color, boolean, and resource reference types"; + data = null; + } + } + } else { + outError[0] = "<meta-data> requires an android:value or android:resource attribute"; + data = null; + } + } + + sa.recycle(); + + XmlUtils.skipCurrentTag(parser); + + return data; + } + + private static final String ANDROID_RESOURCES + = "http://schemas.android.com/apk/res/android"; + + private boolean parseIntent(Resources res, + XmlPullParser parser, AttributeSet attrs, int flags, + IntentInfo outInfo, String[] outError, boolean isActivity) + throws XmlPullParserException, IOException { + + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestIntentFilter); + + int priority = sa.getInt( + com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0); + if (priority > 0 && isActivity && (flags&PARSE_IS_SYSTEM) == 0) { + Log.w(TAG, "Activity with priority > 0, forcing to 0 at " + + parser.getPositionDescription()); + priority = 0; + } + outInfo.setPriority(priority); + + TypedValue v = sa.peekValue( + com.android.internal.R.styleable.AndroidManifestIntentFilter_label); + if (v != null && (outInfo.labelRes=v.resourceId) == 0) { + outInfo.nonLocalizedLabel = v.coerceToString(); + } + + outInfo.icon = sa.getResourceId( + com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0); + + sa.recycle(); + + int outerDepth = parser.getDepth(); + int type; + while ((type=parser.next()) != parser.END_DOCUMENT + && (type != parser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == parser.END_TAG || type == parser.TEXT) { + continue; + } + + String nodeName = parser.getName(); + if (nodeName.equals("action")) { + String value = attrs.getAttributeValue( + ANDROID_RESOURCES, "name"); + if (value == null || value == "") { + outError[0] = "No value supplied for <android:name>"; + return false; + } + XmlUtils.skipCurrentTag(parser); + + outInfo.addAction(value); + } else if (nodeName.equals("category")) { + String value = attrs.getAttributeValue( + ANDROID_RESOURCES, "name"); + if (value == null || value == "") { + outError[0] = "No value supplied for <android:name>"; + return false; + } + XmlUtils.skipCurrentTag(parser); + + outInfo.addCategory(value); + + } else if (nodeName.equals("data")) { + sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestData); + + String str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestData_mimeType); + if (str != null) { + try { + outInfo.addDataType(str); + } catch (IntentFilter.MalformedMimeTypeException e) { + outError[0] = e.toString(); + sa.recycle(); + return false; + } + } + + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestData_scheme); + if (str != null) { + outInfo.addDataScheme(str); + } + + String host = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestData_host); + String port = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestData_port); + if (host != null) { + outInfo.addDataAuthority(host, port); + } + + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestData_path); + if (str != null) { + outInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL); + } + + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestData_pathPrefix); + if (str != null) { + outInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX); + } + + str = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestData_pathPattern); + if (str != null) { + outInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB); + } + + sa.recycle(); + XmlUtils.skipCurrentTag(parser); + } else if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "Unknown element under <intent-filter>: " + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } else { + outError[0] = "Bad element under <intent-filter>: " + parser.getName(); + return false; + } + } + + outInfo.hasDefault = outInfo.hasCategory(Intent.CATEGORY_DEFAULT); + if (false) { + String cats = ""; + Iterator<String> it = outInfo.categoriesIterator(); + while (it != null && it.hasNext()) { + cats += " " + it.next(); + } + System.out.println("Intent d=" + + outInfo.hasDefault + ", cat=" + cats); + } + + return true; + } + + public final static class Package { + public final String packageName; + + // For now we only support one application per package. + public final ApplicationInfo applicationInfo = new ApplicationInfo(); + + public final ArrayList<Permission> permissions = new ArrayList<Permission>(0); + public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0); + public final ArrayList<Activity> activities = new ArrayList<Activity>(0); + public final ArrayList<Activity> receivers = new ArrayList<Activity>(0); + public final ArrayList<Provider> providers = new ArrayList<Provider>(0); + public final ArrayList<Service> services = new ArrayList<Service>(0); + public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0); + + public final ArrayList<String> requestedPermissions = new ArrayList<String>(); + + public final ArrayList<String> usesLibraries = new ArrayList<String>(); + public String[] usesLibraryFiles = null; + + // We store the application meta-data independently to avoid multiple unwanted references + public Bundle mAppMetaData = null; + + // If this is a 3rd party app, this is the path of the zip file. + public String mPath; + + // True if this package is part of the system image. + public boolean mSystem; + + // The version code declared for this package. + public int mVersionCode; + + // The version name declared for this package. + public String mVersionName; + + // The shared user id that this package wants to use. + public String mSharedUserId; + + // The shared user label that this package wants to use. + public int mSharedUserLabel; + + // Signatures that were read from the package. + public Signature mSignatures[]; + + // For use by package manager service for quick lookup of + // preferred up order. + public int mPreferredOrder = 0; + + // Additional data supplied by callers. + public Object mExtras; + + /* + * Applications hardware preferences + */ + public final ArrayList<ConfigurationInfo> configPreferences = + new ArrayList<ConfigurationInfo>(); + + public Package(String _name) { + packageName = _name; + applicationInfo.packageName = _name; + applicationInfo.uid = -1; + } + + public String toString() { + return "Package{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + packageName + "}"; + } + } + + public static class Component<II extends IntentInfo> { + public final Package owner; + public final ArrayList<II> intents = new ArrayList<II>(0); + public ComponentName component; + public Bundle metaData; + + public Component(Package _owner) { + owner = _owner; + } + + public Component(Component<II> clone) { + owner = clone.owner; + metaData = clone.metaData; + } + } + + public final static class Permission extends Component<IntentInfo> { + public final PermissionInfo info; + public boolean tree; + public PermissionGroup group; + + public Permission(Package _owner) { + super(_owner); + info = new PermissionInfo(); + } + + public Permission(Package _owner, PermissionInfo _info) { + super(_owner); + info = _info; + } + + public String toString() { + return "Permission{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + info.name + "}"; + } + } + + public final static class PermissionGroup extends Component<IntentInfo> { + public final PermissionGroupInfo info; + + public PermissionGroup(Package _owner) { + super(_owner); + info = new PermissionGroupInfo(); + } + + public PermissionGroup(Package _owner, PermissionGroupInfo _info) { + super(_owner); + info = _info; + } + + public String toString() { + return "PermissionGroup{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + info.name + "}"; + } + } + + private static boolean copyNeeded(int flags, Package p, Bundle metaData) { + if ((flags & PackageManager.GET_META_DATA) != 0 + && (metaData != null || p.mAppMetaData != null)) { + return true; + } + if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0 + && p.usesLibraryFiles != null) { + return true; + } + return false; + } + + public static ApplicationInfo generateApplicationInfo(Package p, int flags) { + if (p == null) return null; + if (!copyNeeded(flags, p, null)) { + return p.applicationInfo; + } + + // Make shallow copy so we can store the metadata/libraries safely + ApplicationInfo ai = new ApplicationInfo(p.applicationInfo); + if ((flags & PackageManager.GET_META_DATA) != 0) { + ai.metaData = p.mAppMetaData; + } + if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) { + ai.sharedLibraryFiles = p.usesLibraryFiles; + } + return ai; + } + + public static final PermissionInfo generatePermissionInfo( + Permission p, int flags) { + if (p == null) return null; + if ((flags&PackageManager.GET_META_DATA) == 0) { + return p.info; + } + PermissionInfo pi = new PermissionInfo(p.info); + pi.metaData = p.metaData; + return pi; + } + + public static final PermissionGroupInfo generatePermissionGroupInfo( + PermissionGroup pg, int flags) { + if (pg == null) return null; + if ((flags&PackageManager.GET_META_DATA) == 0) { + return pg.info; + } + PermissionGroupInfo pgi = new PermissionGroupInfo(pg.info); + pgi.metaData = pg.metaData; + return pgi; + } + + public final static class Activity extends Component<ActivityIntentInfo> { + public final ActivityInfo info = + new ActivityInfo(); + + public Activity(Package _owner) { + super(_owner); + info.applicationInfo = owner.applicationInfo; + } + + public String toString() { + return "Activity{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + component.flattenToString() + "}"; + } + } + + public static final ActivityInfo generateActivityInfo(Activity a, + int flags) { + if (a == null) return null; + if (!copyNeeded(flags, a.owner, a.metaData)) { + return a.info; + } + // Make shallow copies so we can store the metadata safely + ActivityInfo ai = new ActivityInfo(a.info); + ai.metaData = a.metaData; + ai.applicationInfo = generateApplicationInfo(a.owner, flags); + return ai; + } + + public final static class Service extends Component<ServiceIntentInfo> { + public final ServiceInfo info = + new ServiceInfo(); + + public Service(Package _owner) { + super(_owner); + info.applicationInfo = owner.applicationInfo; + } + + public String toString() { + return "Service{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + component.flattenToString() + "}"; + } + } + + public static final ServiceInfo generateServiceInfo(Service s, int flags) { + if (s == null) return null; + if (!copyNeeded(flags, s.owner, s.metaData)) { + return s.info; + } + // Make shallow copies so we can store the metadata safely + ServiceInfo si = new ServiceInfo(s.info); + si.metaData = s.metaData; + si.applicationInfo = generateApplicationInfo(s.owner, flags); + return si; + } + + public final static class Provider extends Component { + public final ProviderInfo info; + public boolean syncable; + + public Provider(Package _owner) { + super(_owner); + info = new ProviderInfo(); + info.applicationInfo = owner.applicationInfo; + syncable = false; + } + + public Provider(Provider existingProvider) { + super(existingProvider); + this.info = existingProvider.info; + this.syncable = existingProvider.syncable; + } + + public String toString() { + return "Provider{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + info.name + "}"; + } + } + + public static final ProviderInfo generateProviderInfo(Provider p, + int flags) { + if (p == null) return null; + if (!copyNeeded(flags, p.owner, p.metaData) + && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0 + || p.info.uriPermissionPatterns == null)) { + return p.info; + } + // Make shallow copies so we can store the metadata safely + ProviderInfo pi = new ProviderInfo(p.info); + pi.metaData = p.metaData; + if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) { + pi.uriPermissionPatterns = null; + } + pi.applicationInfo = generateApplicationInfo(p.owner, flags); + return pi; + } + + public final static class Instrumentation extends Component { + public final InstrumentationInfo info = + new InstrumentationInfo(); + + public Instrumentation(Package _owner) { + super(_owner); + } + + public String toString() { + return "Instrumentation{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + component.flattenToString() + "}"; + } + } + + public static final InstrumentationInfo generateInstrumentationInfo( + Instrumentation i, int flags) { + if (i == null) return null; + if ((flags&PackageManager.GET_META_DATA) == 0) { + return i.info; + } + InstrumentationInfo ii = new InstrumentationInfo(i.info); + ii.metaData = i.metaData; + return ii; + } + + public static class IntentInfo extends IntentFilter { + public boolean hasDefault; + public int labelRes; + public CharSequence nonLocalizedLabel; + public int icon; + } + + public final static class ActivityIntentInfo extends IntentInfo { + public final Activity activity; + + public ActivityIntentInfo(Activity _activity) { + activity = _activity; + } + + public String toString() { + return "ActivityIntentInfo{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + activity.info.name + "}"; + } + } + + public final static class ServiceIntentInfo extends IntentInfo { + public final Service service; + + public ServiceIntentInfo(Service _service) { + service = _service; + } + + public String toString() { + return "ServiceIntentInfo{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + service.info.name + "}"; + } + } +} diff --git a/core/java/android/content/pm/PackageStats.aidl b/core/java/android/content/pm/PackageStats.aidl new file mode 100755 index 0000000..8c9786f --- /dev/null +++ b/core/java/android/content/pm/PackageStats.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/WindowManager.aidl +** +** Copyright 2007, 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.content.pm; + +parcelable PackageStats; diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java new file mode 100755 index 0000000..66c6efd --- /dev/null +++ b/core/java/android/content/pm/PackageStats.java @@ -0,0 +1,63 @@ +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Arrays; + +/** + * implementation of PackageStats associated with a + * application package. + */ +public class PackageStats implements Parcelable { + public String packageName; + public long codeSize; + public long dataSize; + public long cacheSize; + + public static final Parcelable.Creator<PackageStats> CREATOR + = new Parcelable.Creator<PackageStats>() { + public PackageStats createFromParcel(Parcel in) { + return new PackageStats(in); + } + + public PackageStats[] newArray(int size) { + return new PackageStats[size]; + } + }; + + public String toString() { + return "PackageStats{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + packageName + "}"; + } + + public PackageStats(String pkgName) { + packageName = pkgName; + } + + public PackageStats(Parcel source) { + packageName = source.readString(); + codeSize = source.readLong(); + dataSize = source.readLong(); + cacheSize = source.readLong(); + } + + public PackageStats(PackageStats pStats) { + packageName = pStats.packageName; + codeSize = pStats.codeSize; + dataSize = pStats.dataSize; + cacheSize = pStats.cacheSize; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int parcelableFlags){ + dest.writeString(packageName); + dest.writeLong(codeSize); + dest.writeLong(dataSize); + dest.writeLong(cacheSize); + } +} diff --git a/core/java/android/content/pm/PermissionGroupInfo.aidl b/core/java/android/content/pm/PermissionGroupInfo.aidl new file mode 100755 index 0000000..9f215f1 --- /dev/null +++ b/core/java/android/content/pm/PermissionGroupInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/WindowManager.aidl +** +** Copyright 2008, 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.content.pm; + +parcelable PermissionGroupInfo; diff --git a/core/java/android/content/pm/PermissionGroupInfo.java b/core/java/android/content/pm/PermissionGroupInfo.java new file mode 100644 index 0000000..02eb816 --- /dev/null +++ b/core/java/android/content/pm/PermissionGroupInfo.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2008 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.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +/** + * Information you can retrieve about a particular security permission + * group known to the system. This corresponds to information collected from the + * AndroidManifest.xml's <permission-group> tags. + */ +public class PermissionGroupInfo extends PackageItemInfo implements Parcelable { + /** + * A string resource identifier (in the package's resources) of this + * permission's description. From the "description" attribute or, + * if not set, 0. + */ + public int descriptionRes; + + /** + * The description string provided in the AndroidManifest file, if any. You + * probably don't want to use this, since it will be null if the description + * is in a resource. You probably want + * {@link PermissionInfo#loadDescription} instead. + */ + public CharSequence nonLocalizedDescription; + + public PermissionGroupInfo() { + } + + public PermissionGroupInfo(PermissionGroupInfo orig) { + super(orig); + descriptionRes = orig.descriptionRes; + nonLocalizedDescription = orig.nonLocalizedDescription; + } + + /** + * Retrieve the textual description of this permission. This + * will call back on the given PackageManager to load the description from + * the application. + * + * @param pm A PackageManager from which the label can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a CharSequence containing the permission's description. + * If there is no description, null is returned. + */ + public CharSequence loadDescription(PackageManager pm) { + if (nonLocalizedDescription != null) { + return nonLocalizedDescription; + } + if (descriptionRes != 0) { + CharSequence label = pm.getText(packageName, descriptionRes, null); + if (label != null) { + return label; + } + } + return null; + } + + public String toString() { + return "PermissionGroupInfo{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + name + "}"; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + super.writeToParcel(dest, parcelableFlags); + dest.writeInt(descriptionRes); + TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags); + } + + public static final Creator<PermissionGroupInfo> CREATOR = + new Creator<PermissionGroupInfo>() { + public PermissionGroupInfo createFromParcel(Parcel source) { + return new PermissionGroupInfo(source); + } + public PermissionGroupInfo[] newArray(int size) { + return new PermissionGroupInfo[size]; + } + }; + + private PermissionGroupInfo(Parcel source) { + super(source); + descriptionRes = source.readInt(); + nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); + } +} diff --git a/core/java/android/content/pm/PermissionInfo.aidl b/core/java/android/content/pm/PermissionInfo.aidl new file mode 100755 index 0000000..5a7d4f4 --- /dev/null +++ b/core/java/android/content/pm/PermissionInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/WindowManager.aidl +** +** Copyright 2007, 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.content.pm; + +parcelable PermissionInfo; diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java new file mode 100644 index 0000000..3cc884b --- /dev/null +++ b/core/java/android/content/pm/PermissionInfo.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2008 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.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +/** + * Information you can retrieve about a particular security permission + * known to the system. This corresponds to information collected from the + * AndroidManifest.xml's <permission> tags. + */ +public class PermissionInfo extends PackageItemInfo implements Parcelable { + /** + * A normal application value for {@link #protectionLevel}, corresponding + * to the <code>normal</code> value of + * {@link android.R.attr#protectionLevel}. + */ + public static final int PROTECTION_NORMAL = 0; + + /** + * Dangerous value for {@link #protectionLevel}, corresponding + * to the <code>dangerous</code> value of + * {@link android.R.attr#protectionLevel}. + */ + public static final int PROTECTION_DANGEROUS = 1; + + /** + * System-level value for {@link #protectionLevel}, corresponding + * to the <code>signature</code> value of + * {@link android.R.attr#protectionLevel}. + */ + public static final int PROTECTION_SIGNATURE = 2; + + /** + * System-level value for {@link #protectionLevel}, corresponding + * to the <code>signatureOrSystem</code> value of + * {@link android.R.attr#protectionLevel}. + */ + public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; + + /** + * The group this permission is a part of, as per + * {@link android.R.attr#permissionGroup}. + */ + public String group; + + /** + * A string resource identifier (in the package's resources) of this + * permission's description. From the "description" attribute or, + * if not set, 0. + */ + public int descriptionRes; + + /** + * The description string provided in the AndroidManifest file, if any. You + * probably don't want to use this, since it will be null if the description + * is in a resource. You probably want + * {@link PermissionInfo#loadDescription} instead. + */ + public CharSequence nonLocalizedDescription; + + /** + * The level of access this permission is protecting, as per + * {@link android.R.attr#protectionLevel}. Values may be + * {@link #PROTECTION_NORMAL}, {@link #PROTECTION_DANGEROUS}, or + * {@link #PROTECTION_SIGNATURE}. + */ + public int protectionLevel; + + public PermissionInfo() { + } + + public PermissionInfo(PermissionInfo orig) { + super(orig); + group = orig.group; + descriptionRes = orig.descriptionRes; + protectionLevel = orig.protectionLevel; + nonLocalizedDescription = orig.nonLocalizedDescription; + } + + /** + * Retrieve the textual description of this permission. This + * will call back on the given PackageManager to load the description from + * the application. + * + * @param pm A PackageManager from which the label can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a CharSequence containing the permission's description. + * If there is no description, null is returned. + */ + public CharSequence loadDescription(PackageManager pm) { + if (nonLocalizedDescription != null) { + return nonLocalizedDescription; + } + if (descriptionRes != 0) { + CharSequence label = pm.getText(packageName, descriptionRes, null); + if (label != null) { + return label; + } + } + return null; + } + + public String toString() { + return "PermissionInfo{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + name + "}"; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + super.writeToParcel(dest, parcelableFlags); + dest.writeString(group); + dest.writeInt(descriptionRes); + dest.writeInt(protectionLevel); + TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags); + } + + public static final Creator<PermissionInfo> CREATOR = + new Creator<PermissionInfo>() { + public PermissionInfo createFromParcel(Parcel source) { + return new PermissionInfo(source); + } + public PermissionInfo[] newArray(int size) { + return new PermissionInfo[size]; + } + }; + + private PermissionInfo(Parcel source) { + super(source); + group = source.readString(); + descriptionRes = source.readInt(); + protectionLevel = source.readInt(); + nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); + } +} diff --git a/core/java/android/content/pm/ProviderInfo.aidl b/core/java/android/content/pm/ProviderInfo.aidl new file mode 100755 index 0000000..18fbc8a --- /dev/null +++ b/core/java/android/content/pm/ProviderInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/WindowManager.aidl +** +** Copyright 2007, 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.content.pm; + +parcelable ProviderInfo; diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java new file mode 100644 index 0000000..b67ddf6 --- /dev/null +++ b/core/java/android/content/pm/ProviderInfo.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2006 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.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PatternMatcher; + +/** + * Holds information about a specific + * {@link android.content.ContentProvider content provider}. This is returned by + * {@link android.content.pm.PackageManager#resolveContentProvider(java.lang.String, int) + * PackageManager.resolveContentProvider()}. + */ +public final class ProviderInfo extends ComponentInfo + implements Parcelable { + /** The name provider is published under content:// */ + public String authority = null; + + /** Optional permission required for read-only access this content + * provider. */ + public String readPermission = null; + + /** Optional permission required for read/write access this content + * provider. */ + public String writePermission = null; + + /** If true, additional permissions to specific Uris in this content + * provider can be granted, as per the + * {@link android.R.styleable#AndroidManifestProvider_grantUriPermissions + * grantUriPermissions} attribute. + */ + public boolean grantUriPermissions = false; + + /** + * If non-null, these are the patterns that are allowed for granting URI + * permissions. Any URI that does not match one of these patterns will not + * allowed to be granted. If null, all URIs are allowed. The + * {@link PackageManager#GET_URI_PERMISSION_PATTERNS + * PackageManager.GET_URI_PERMISSION_PATTERNS} flag must be specified for + * this field to be filled in. + */ + public PatternMatcher[] uriPermissionPatterns = null; + + /** If true, this content provider allows multiple instances of itself + * to run in different process. If false, a single instances is always + * run in {@link #processName}. */ + public boolean multiprocess = false; + + /** Used to control initialization order of single-process providers + * running in the same process. Higher goes first. */ + public int initOrder = 0; + + /** Whether or not this provider is syncable. */ + public boolean isSyncable = false; + + public ProviderInfo() { + } + + public ProviderInfo(ProviderInfo orig) { + super(orig); + authority = orig.authority; + readPermission = orig.readPermission; + writePermission = orig.writePermission; + grantUriPermissions = orig.grantUriPermissions; + uriPermissionPatterns = orig.uriPermissionPatterns; + multiprocess = orig.multiprocess; + initOrder = orig.initOrder; + isSyncable = orig.isSyncable; + } + + public int describeContents() { + return 0; + } + + @Override public void writeToParcel(Parcel out, int parcelableFlags) { + super.writeToParcel(out, parcelableFlags); + out.writeString(authority); + out.writeString(readPermission); + out.writeString(writePermission); + out.writeInt(grantUriPermissions ? 1 : 0); + out.writeTypedArray(uriPermissionPatterns, parcelableFlags); + out.writeInt(multiprocess ? 1 : 0); + out.writeInt(initOrder); + out.writeInt(isSyncable ? 1 : 0); + } + + public static final Parcelable.Creator<ProviderInfo> CREATOR + = new Parcelable.Creator<ProviderInfo>() { + public ProviderInfo createFromParcel(Parcel in) { + return new ProviderInfo(in); + } + + public ProviderInfo[] newArray(int size) { + return new ProviderInfo[size]; + } + }; + + public String toString() { + return "ContentProviderInfo{name=" + authority + " className=" + name + + " isSyncable=" + (isSyncable ? "true" : "false") + "}"; + } + + private ProviderInfo(Parcel in) { + super(in); + authority = in.readString(); + readPermission = in.readString(); + writePermission = in.readString(); + grantUriPermissions = in.readInt() != 0; + uriPermissionPatterns = in.createTypedArray(PatternMatcher.CREATOR); + multiprocess = in.readInt() != 0; + initOrder = in.readInt(); + isSyncable = in.readInt() != 0; + } +} diff --git a/core/java/android/content/pm/ResolveInfo.aidl b/core/java/android/content/pm/ResolveInfo.aidl new file mode 100755 index 0000000..b4e7f8b --- /dev/null +++ b/core/java/android/content/pm/ResolveInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/WindowManager.aidl +** +** Copyright 2007, 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.content.pm; + +parcelable ResolveInfo; diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java new file mode 100644 index 0000000..ee49c02 --- /dev/null +++ b/core/java/android/content/pm/ResolveInfo.java @@ -0,0 +1,280 @@ +package android.content.pm; + +import android.content.IntentFilter; +import android.graphics.drawable.Drawable; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; +import android.util.Printer; + +import java.text.Collator; +import java.util.Comparator; + +/** + * Information that is returned from resolving an intent + * against an IntentFilter. This partially corresponds to + * information collected from the AndroidManifest.xml's + * <intent> tags. + */ +public class ResolveInfo implements Parcelable { + /** + * The activity that corresponds to this resolution match, if this + * resolution is for an activity. One and only one of this and + * serviceInfo must be non-null. + */ + public ActivityInfo activityInfo; + + /** + * The service that corresponds to this resolution match, if this + * resolution is for a service. One and only one of this and + * activityInfo must be non-null. + */ + public ServiceInfo serviceInfo; + + /** + * The IntentFilter that was matched for this ResolveInfo. + */ + public IntentFilter filter; + + /** + * The declared priority of this match. Comes from the "priority" + * attribute or, if not set, defaults to 0. Higher values are a higher + * priority. + */ + public int priority; + + /** + * Order of result according to the user's preference. If the user + * has not set a preference for this result, the value is 0; higher + * values are a higher priority. + */ + public int preferredOrder; + + /** + * The system's evaluation of how well the activity matches the + * IntentFilter. This is a match constant, a combination of + * {@link IntentFilter#MATCH_CATEGORY_MASK IntentFilter.MATCH_CATEGORY_MASK} + * and {@link IntentFilter#MATCH_ADJUSTMENT_MASK IntentFiler.MATCH_ADJUSTMENT_MASK}. + */ + public int match; + + /** + * Only set when returned by + * {@link PackageManager#queryIntentActivityOptions}, this tells you + * which of the given specific intents this result came from. 0 is the + * first in the list, < 0 means it came from the generic Intent query. + */ + public int specificIndex = -1; + + /** + * This filter has specified the Intent.CATEGORY_DEFAULT, meaning it + * would like to be considered a default action that the user can + * perform on this data. + */ + public boolean isDefault; + + /** + * A string resource identifier (in the package's resources) of this + * match's label. From the "label" attribute or, if not set, 0. + */ + public int labelRes; + + /** + * The actual string retrieve from <var>labelRes</var> or null if none + * was provided. + */ + public CharSequence nonLocalizedLabel; + + /** + * A drawable resource identifier (in the package's resources) of this + * match's icon. From the "icon" attribute or, if not set, 0. + */ + public int icon; + + /** + * Retrieve the current textual label associated with this resolution. This + * will call back on the given PackageManager to load the label from + * the application. + * + * @param pm A PackageManager from which the label can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a CharSequence containing the resolutions's label. If the + * item does not have a label, its name is returned. + */ + public CharSequence loadLabel(PackageManager pm) { + if (nonLocalizedLabel != null) { + return nonLocalizedLabel; + } + ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; + ApplicationInfo ai = ci.applicationInfo; + CharSequence label; + if (labelRes != 0) { + label = pm.getText(ci.packageName, labelRes, ai); + if (label != null) { + return label; + } + } + return ci.loadLabel(pm); + } + + /** + * Retrieve the current graphical icon associated with this resolution. This + * will call back on the given PackageManager to load the icon from + * the application. + * + * @param pm A PackageManager from which the icon can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a Drawable containing the resolution's icon. If the + * item does not have an icon, the default activity icon is returned. + */ + public Drawable loadIcon(PackageManager pm) { + ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; + ApplicationInfo ai = ci.applicationInfo; + Drawable dr; + if (icon != 0) { + dr = pm.getDrawable(ci.packageName, icon, ai); + if (dr != null) { + return dr; + } + } + return ci.loadIcon(pm); + } + + /** + * Return the icon resource identifier to use for this match. If the + * match defines an icon, that is used; else if the activity defines + * an icon, that is used; else, the application icon is used. + * + * @return The icon associated with this match. + */ + public final int getIconResource() { + if (icon != 0) return icon; + if (activityInfo != null) return activityInfo.getIconResource(); + if (serviceInfo != null) return serviceInfo.getIconResource(); + return 0; + } + + public void dump(Printer pw, String prefix) { + if (filter != null) { + pw.println(prefix + "Filter:"); + filter.dump(pw, prefix + " "); + } else { + pw.println(prefix + "Filter: null"); + } + pw.println(prefix + "priority=" + priority + + " preferredOrder=" + preferredOrder + + " match=0x" + Integer.toHexString(match) + + " specificIndex=" + specificIndex + + " isDefault=" + isDefault); + pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes) + + " nonLocalizedLabel=" + nonLocalizedLabel + + " icon=0x" + Integer.toHexString(icon)); + if (activityInfo != null) { + pw.println(prefix + "ActivityInfo:"); + activityInfo.dump(pw, prefix + " "); + } else if (serviceInfo != null) { + pw.println(prefix + "ServiceInfo:"); + // TODO + //serviceInfo.dump(pw, prefix + " "); + } + } + + public ResolveInfo() { + } + + public String toString() { + ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; + return "ResolveInfo{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + ci.name + " p=" + priority + " o=" + + preferredOrder + " m=0x" + Integer.toHexString(match) + "}"; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + if (activityInfo != null) { + dest.writeInt(1); + activityInfo.writeToParcel(dest, parcelableFlags); + } else if (serviceInfo != null) { + dest.writeInt(2); + serviceInfo.writeToParcel(dest, parcelableFlags); + } else { + dest.writeInt(0); + } + if (filter != null) { + dest.writeInt(1); + filter.writeToParcel(dest, parcelableFlags); + } else { + dest.writeInt(0); + } + dest.writeInt(priority); + dest.writeInt(preferredOrder); + dest.writeInt(match); + dest.writeInt(specificIndex); + dest.writeInt(labelRes); + TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags); + dest.writeInt(icon); + } + + public static final Creator<ResolveInfo> CREATOR + = new Creator<ResolveInfo>() { + public ResolveInfo createFromParcel(Parcel source) { + return new ResolveInfo(source); + } + public ResolveInfo[] newArray(int size) { + return new ResolveInfo[size]; + } + }; + + private ResolveInfo(Parcel source) { + switch (source.readInt()) { + case 1: + activityInfo = ActivityInfo.CREATOR.createFromParcel(source); + serviceInfo = null; + break; + case 2: + serviceInfo = ServiceInfo.CREATOR.createFromParcel(source); + activityInfo = null; + break; + default: + activityInfo = null; + serviceInfo = null; + break; + } + if (source.readInt() != 0) { + filter = IntentFilter.CREATOR.createFromParcel(source); + } + priority = source.readInt(); + preferredOrder = source.readInt(); + match = source.readInt(); + specificIndex = source.readInt(); + labelRes = source.readInt(); + nonLocalizedLabel + = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); + icon = source.readInt(); + } + + public static class DisplayNameComparator + implements Comparator<ResolveInfo> { + public DisplayNameComparator(PackageManager pm) { + mPM = pm; + } + + public final int compare(ResolveInfo a, ResolveInfo b) { + CharSequence sa = a.loadLabel(mPM); + if (sa == null) sa = a.activityInfo.name; + CharSequence sb = b.loadLabel(mPM); + if (sb == null) sb = b.activityInfo.name; + + return sCollator.compare(sa.toString(), sb.toString()); + } + + private final Collator sCollator = Collator.getInstance(); + private PackageManager mPM; + } +} diff --git a/core/java/android/content/pm/ServiceInfo.aidl b/core/java/android/content/pm/ServiceInfo.aidl new file mode 100755 index 0000000..5ddae1a --- /dev/null +++ b/core/java/android/content/pm/ServiceInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/WindowManager.aidl +** +** Copyright 2007, 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.content.pm; + +parcelable ServiceInfo; diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java new file mode 100644 index 0000000..b60650c --- /dev/null +++ b/core/java/android/content/pm/ServiceInfo.java @@ -0,0 +1,56 @@ +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Information you can retrieve about a particular application + * service. This corresponds to information collected from the + * AndroidManifest.xml's <service> tags. + */ +public class ServiceInfo extends ComponentInfo + implements Parcelable { + /** + * Optional name of a permission required to be able to access this + * Service. From the "permission" attribute. + */ + public String permission; + + public ServiceInfo() { + } + + public ServiceInfo(ServiceInfo orig) { + super(orig); + permission = orig.permission; + } + + public String toString() { + return "ServiceInfo{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + name + "}"; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + super.writeToParcel(dest, parcelableFlags); + dest.writeString(permission); + } + + public static final Creator<ServiceInfo> CREATOR = + new Creator<ServiceInfo>() { + public ServiceInfo createFromParcel(Parcel source) { + return new ServiceInfo(source); + } + public ServiceInfo[] newArray(int size) { + return new ServiceInfo[size]; + } + }; + + private ServiceInfo(Parcel source) { + super(source); + permission = source.readString(); + } +} diff --git a/core/java/android/content/pm/Signature.aidl b/core/java/android/content/pm/Signature.aidl new file mode 100755 index 0000000..3a0d775 --- /dev/null +++ b/core/java/android/content/pm/Signature.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/WindowManager.aidl +** +** Copyright 2007, 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.content.pm; + +parcelable Signature; diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java new file mode 100644 index 0000000..1bb3857 --- /dev/null +++ b/core/java/android/content/pm/Signature.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2008 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.content.pm; + +import android.content.ComponentName; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Arrays; + +/** + * Opaque, immutable representation of a signature associated with an + * application package. + */ +public class Signature implements Parcelable { + private final byte[] mSignature; + private int mHashCode; + private boolean mHaveHashCode; + private String mString; + + /** + * Create Signature from an existing raw byte array. + */ + public Signature(byte[] signature) { + mSignature = signature.clone(); + } + + /** + * Create Signature from a text representation previously returned by + * {@link #toChars} or {@link #toCharsString()}. + */ + public Signature(String text) { + final int N = text.length()/2; + byte[] sig = new byte[N]; + for (int i=0; i<N; i++) { + char c = text.charAt(i*2); + byte b = (byte)( + (c >= 'a' ? (c - 'a' + 10) : (c - '0'))<<4); + c = text.charAt(i*2 + 1); + b |= (byte)(c >= 'a' ? (c - 'a' + 10) : (c - '0')); + sig[i] = b; + } + mSignature = sig; + } + + /** + * Encode the Signature as ASCII text. + */ + public char[] toChars() { + return toChars(null, null); + } + + /** + * Encode the Signature as ASCII text in to an existing array. + * + * @param existingArray Existing char array or null. + * @param outLen Output parameter for the number of characters written in + * to the array. + * @return Returns either <var>existingArray</var> if it was large enough + * to hold the ASCII representation, or a newly created char[] array if + * needed. + */ + public char[] toChars(char[] existingArray, int[] outLen) { + byte[] sig = mSignature; + final int N = sig.length; + final int N2 = N*2; + char[] text = existingArray == null || N2 > existingArray.length + ? new char[N2] : existingArray; + for (int j=0; j<N; j++) { + byte v = sig[j]; + int d = (v>>4)&0xf; + text[j*2] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d)); + d = v&0xf; + text[j*2+1] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d)); + } + if (outLen != null) outLen[0] = N; + return text; + } + + /** + * Return the result of {@link #toChars()} as a String. This result is + * cached so future calls will return the same String. + */ + public String toCharsString() { + if (mString != null) return mString; + String str = new String(toChars()); + mString = str; + return mString; + } + + /** + * @return the contents of this signature as a byte array. + */ + public byte[] toByteArray() { + byte[] bytes = new byte[mSignature.length]; + System.arraycopy(mSignature, 0, bytes, 0, mSignature.length); + return bytes; + } + + @Override + public boolean equals(Object obj) { + try { + if (obj != null) { + Signature other = (Signature)obj; + return Arrays.equals(mSignature, other.mSignature); + } + } catch (ClassCastException e) { + } + return false; + } + + @Override + public int hashCode() { + if (mHaveHashCode) { + return mHashCode; + } + mHashCode = Arrays.hashCode(mSignature); + mHaveHashCode = true; + return mHashCode; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int parcelableFlags) { + dest.writeByteArray(mSignature); + } + + public static final Parcelable.Creator<Signature> CREATOR + = new Parcelable.Creator<Signature>() { + public Signature createFromParcel(Parcel source) { + return new Signature(source); + } + + public Signature[] newArray(int size) { + return new Signature[size]; + } + }; + + private Signature(Parcel source) { + mSignature = source.createByteArray(); + } +} diff --git a/core/java/android/content/pm/package.html b/core/java/android/content/pm/package.html new file mode 100644 index 0000000..766b7dd --- /dev/null +++ b/core/java/android/content/pm/package.html @@ -0,0 +1,7 @@ +<HTML> +<BODY> +Contains classes for accessing information about an +application package, including information about its activities, +permissions, services, signatures, and providers. +</BODY> +</HTML>
\ No newline at end of file |