diff options
author | Jason Simmons <jsimmons@google.com> | 2011-12-06 11:05:17 -0800 |
---|---|---|
committer | Jason Simmons <jsimmons@google.com> | 2011-12-06 11:11:13 -0800 |
commit | 3b282fae37c9897514f5bb7a16aa0b80dd65dd1f (patch) | |
tree | 4fd091b21be02cac2efc2fc44159817a2e9c3a8b | |
parent | 7dc935ad17e1cfe1a9840658eb3a0355dd296428 (diff) | |
parent | 0c0120efa2dedaf25ae789bced5a3f9fa33c32bb (diff) | |
download | frameworks_base-3b282fae37c9897514f5bb7a16aa0b80dd65dd1f.zip frameworks_base-3b282fae37c9897514f5bb7a16aa0b80dd65dd1f.tar.gz frameworks_base-3b282fae37c9897514f5bb7a16aa0b80dd65dd1f.tar.bz2 |
resolved conflicts for merge of 0c0120ef to ics-aah
Change-Id: If1f39ff160b4305ef057d50bb1f01d2c45f1579d
7 files changed, 323 insertions, 52 deletions
diff --git a/api/current.txt b/api/current.txt index c62d82b..38cf966 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5334,6 +5334,7 @@ package android.content { method public java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String); method public T getParcelableExtra(java.lang.String); method public java.lang.String getScheme(); + method public android.content.Intent getSelector(); method public java.io.Serializable getSerializableExtra(java.lang.String); method public short[] getShortArrayExtra(java.lang.String); method public short getShortExtra(java.lang.String, short); @@ -5346,6 +5347,7 @@ package android.content { method public boolean hasExtra(java.lang.String); method public boolean hasFileDescriptors(); method public static android.content.Intent makeMainActivity(android.content.ComponentName); + method public static android.content.Intent makeMainSelectorActivity(java.lang.String, java.lang.String); method public static android.content.Intent makeRestartActivityTask(android.content.ComponentName); method public static android.content.Intent parseIntent(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static android.content.Intent parseUri(java.lang.String, int) throws java.net.URISyntaxException; @@ -5399,6 +5401,7 @@ package android.content { method public void setExtrasClassLoader(java.lang.ClassLoader); method public android.content.Intent setFlags(int); method public android.content.Intent setPackage(java.lang.String); + method public void setSelector(android.content.Intent); method public void setSourceBounds(android.graphics.Rect); method public android.content.Intent setType(java.lang.String); method public deprecated java.lang.String toURI(); @@ -5577,6 +5580,7 @@ package android.content { field public static final int FILL_IN_COMPONENT = 8; // 0x8 field public static final int FILL_IN_DATA = 2; // 0x2 field public static final int FILL_IN_PACKAGE = 16; // 0x10 + field public static final int FILL_IN_SELECTOR = 64; // 0x40 field public static final int FILL_IN_SOURCE_BOUNDS = 32; // 0x20 field public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 4194304; // 0x400000 field public static final int FLAG_ACTIVITY_CLEAR_TASK = 32768; // 0x8000 diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 95a8e2c..f4c5359 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -134,6 +134,10 @@ public class Am { runScreenCompat(); } else if (op.equals("display-size")) { runDisplaySize(); + } else if (op.equals("to-uri")) { + runToUri(false); + } else if (op.equals("to-intent-uri")) { + runToUri(true); } else { throw new IllegalArgumentException("Unknown command: " + op); } @@ -141,6 +145,7 @@ public class Am { private Intent makeIntent() throws URISyntaxException { Intent intent = new Intent(); + Intent baseIntent = intent; boolean hasIntentInfo = false; mDebugOption = false; @@ -155,35 +160,39 @@ public class Am { while ((opt=nextOption()) != null) { if (opt.equals("-a")) { intent.setAction(nextArgRequired()); - hasIntentInfo = true; + if (intent == baseIntent) { + hasIntentInfo = true; + } } else if (opt.equals("-d")) { data = Uri.parse(nextArgRequired()); - hasIntentInfo = true; + if (intent == baseIntent) { + hasIntentInfo = true; + } } else if (opt.equals("-t")) { type = nextArgRequired(); - hasIntentInfo = true; + if (intent == baseIntent) { + hasIntentInfo = true; + } } else if (opt.equals("-c")) { intent.addCategory(nextArgRequired()); - hasIntentInfo = true; + if (intent == baseIntent) { + hasIntentInfo = true; + } } else if (opt.equals("-e") || opt.equals("--es")) { String key = nextArgRequired(); String value = nextArgRequired(); intent.putExtra(key, value); - hasIntentInfo = true; } else if (opt.equals("--esn")) { String key = nextArgRequired(); intent.putExtra(key, (String) null); - hasIntentInfo = true; } else if (opt.equals("--ei")) { String key = nextArgRequired(); String value = nextArgRequired(); intent.putExtra(key, Integer.valueOf(value)); - hasIntentInfo = true; } else if (opt.equals("--eu")) { String key = nextArgRequired(); String value = nextArgRequired(); intent.putExtra(key, Uri.parse(value)); - hasIntentInfo = true; } else if (opt.equals("--eia")) { String key = nextArgRequired(); String value = nextArgRequired(); @@ -193,12 +202,10 @@ public class Am { list[i] = Integer.valueOf(strings[i]); } intent.putExtra(key, list); - hasIntentInfo = true; } else if (opt.equals("--el")) { String key = nextArgRequired(); String value = nextArgRequired(); intent.putExtra(key, Long.valueOf(value)); - hasIntentInfo = true; } else if (opt.equals("--ela")) { String key = nextArgRequired(); String value = nextArgRequired(); @@ -208,12 +215,10 @@ public class Am { list[i] = Long.valueOf(strings[i]); } intent.putExtra(key, list); - hasIntentInfo = true; } else if (opt.equals("--ef")) { String key = nextArgRequired(); String value = nextArgRequired(); intent.putExtra(key, Float.valueOf(value)); - hasIntentInfo = true; } else if (opt.equals("--efa")) { String key = nextArgRequired(); String value = nextArgRequired(); @@ -223,18 +228,18 @@ public class Am { list[i] = Float.valueOf(strings[i]); } intent.putExtra(key, list); - hasIntentInfo = true; } else if (opt.equals("--ez")) { String key = nextArgRequired(); String value = nextArgRequired(); intent.putExtra(key, Boolean.valueOf(value)); - hasIntentInfo = true; } else if (opt.equals("-n")) { String str = nextArgRequired(); ComponentName cn = ComponentName.unflattenFromString(str); if (cn == null) throw new IllegalArgumentException("Bad component name: " + str); intent.setComponent(cn); - hasIntentInfo = true; + if (intent == baseIntent) { + hasIntentInfo = true; + } } else if (opt.equals("-f")) { String str = nextArgRequired(); intent.setFlags(Integer.decode(str).intValue()); @@ -282,6 +287,9 @@ public class Am { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } else if (opt.equals("--receiver-replace-pending")) { intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + } else if (opt.equals("--selector")) { + intent.setDataAndType(data, type); + intent = new Intent(); } else if (opt.equals("-D")) { mDebugOption = true; } else if (opt.equals("-W")) { @@ -304,25 +312,42 @@ public class Am { } intent.setDataAndType(data, type); + final boolean hasSelector = intent != baseIntent; + if (hasSelector) { + // A selector was specified; fix up. + baseIntent.setSelector(intent); + intent = baseIntent; + } + String arg = nextArg(); - if (arg != null) { - Intent baseIntent; - if (arg.indexOf(':') >= 0) { - // The argument is a URI. Fully parse it, and use that result - // to fill in any data not specified so far. - baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME); - } else if (arg.indexOf('/') >= 0) { - // The argument is a component name. Build an Intent to launch - // it. - baseIntent = new Intent(Intent.ACTION_MAIN); - baseIntent.addCategory(Intent.CATEGORY_LAUNCHER); - baseIntent.setComponent(ComponentName.unflattenFromString(arg)); - } else { - // Assume the argument is a package name. + baseIntent = null; + if (arg == null) { + if (hasSelector) { + // If a selector has been specified, and no arguments + // have been supplied for the main Intent, then we can + // assume it is ACTION_MAIN CATEGORY_LAUNCHER; we don't + // need to have a component name specified yet, the + // selector will take care of that. baseIntent = new Intent(Intent.ACTION_MAIN); baseIntent.addCategory(Intent.CATEGORY_LAUNCHER); - baseIntent.setPackage(arg); } + } else if (arg.indexOf(':') >= 0) { + // The argument is a URI. Fully parse it, and use that result + // to fill in any data not specified so far. + baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME); + } else if (arg.indexOf('/') >= 0) { + // The argument is a component name. Build an Intent to launch + // it. + baseIntent = new Intent(Intent.ACTION_MAIN); + baseIntent.addCategory(Intent.CATEGORY_LAUNCHER); + baseIntent.setComponent(ComponentName.unflattenFromString(arg)); + } else { + // Assume the argument is a package name. + baseIntent = new Intent(Intent.ACTION_MAIN); + baseIntent.addCategory(Intent.CATEGORY_LAUNCHER); + baseIntent.setPackage(arg); + } + if (baseIntent != null) { Bundle extras = intent.getExtras(); intent.replaceExtras((Bundle)null); Bundle uriExtras = baseIntent.getExtras(); @@ -333,7 +358,7 @@ public class Am { baseIntent.removeCategory(c); } } - intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT); + intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_SELECTOR); if (extras == null) { extras = uriExtras; } else if (uriExtras != null) { @@ -1107,6 +1132,11 @@ public class Am { } } + private void runToUri(boolean intentScheme) throws Exception { + Intent intent = makeIntent(); + System.out.println(intent.toUri(intentScheme ? Intent.URI_INTENT_SCHEME : 0)); + } + private class IntentReceiver extends IIntentReceiver.Stub { private boolean mFinished = false; @@ -1277,6 +1307,8 @@ public class Am { " am monitor [--gdb <port>]\n" + " am screen-compat [on|off] <PACKAGE>\n" + " am display-size [reset|MxN]\n" + + " am to-uri [INTENT]\n" + + " am to-intent-uri [INTENT]\n" + "\n" + "am start: start an Activity. Options are:\n" + " -D: enable debugging\n" + @@ -1330,6 +1362,10 @@ public class Am { "\n" + "am display-size: override display size.\n" + "\n" + + "am to-uri: print the given Intent specification as a URI.\n" + + "\n" + + "am to-intent-uri: print the given Intent specification as an intent: URI.\n" + + "\n" + "<INTENT> specifications include these flags and arguments:\n" + " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" + " [-c <CATEGORY> [-c <CATEGORY>] ...]\n" + @@ -1356,6 +1392,7 @@ public class Am { " [--activity-single-top] [--activity-clear-task]\n" + " [--activity-task-on-home]\n" + " [--receiver-registered-only] [--receiver-replace-pending]\n" + + " [--selector]\n" + " [<URI> | <PACKAGE> | <COMPONENT>]\n" ); } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 9948985..4e5598b 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2315,6 +2315,11 @@ public class Intent implements Parcelable, Cloneable { /** * Used with {@link #ACTION_MAIN} to launch the browser application. * The activity should be able to browse the Internet. + * <p>NOTE: This should not be used as the primary key of an Intent, + * since it will not result in the app launching with the correct + * action and category. Instead, use this with + * {@link #makeMainSelectorActivity(String, String) to generate a main + * Intent with this category in the selector.</p> */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_APP_BROWSER = "android.intent.category.APP_BROWSER"; @@ -2322,6 +2327,11 @@ public class Intent implements Parcelable, Cloneable { /** * Used with {@link #ACTION_MAIN} to launch the calculator application. * The activity should be able to perform standard arithmetic operations. + * <p>NOTE: This should not be used as the primary key of an Intent, + * since it will not result in the app launching with the correct + * action and category. Instead, use this with + * {@link #makeMainSelectorActivity(String, String) to generate a main + * Intent with this category in the selector.</p> */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_APP_CALCULATOR = "android.intent.category.APP_CALCULATOR"; @@ -2329,6 +2339,11 @@ public class Intent implements Parcelable, Cloneable { /** * Used with {@link #ACTION_MAIN} to launch the calendar application. * The activity should be able to view and manipulate calendar entries. + * <p>NOTE: This should not be used as the primary key of an Intent, + * since it will not result in the app launching with the correct + * action and category. Instead, use this with + * {@link #makeMainSelectorActivity(String, String) to generate a main + * Intent with this category in the selector.</p> */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_APP_CALENDAR = "android.intent.category.APP_CALENDAR"; @@ -2336,6 +2351,11 @@ public class Intent implements Parcelable, Cloneable { /** * Used with {@link #ACTION_MAIN} to launch the contacts application. * The activity should be able to view and manipulate address book entries. + * <p>NOTE: This should not be used as the primary key of an Intent, + * since it will not result in the app launching with the correct + * action and category. Instead, use this with + * {@link #makeMainSelectorActivity(String, String) to generate a main + * Intent with this category in the selector.</p> */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_APP_CONTACTS = "android.intent.category.APP_CONTACTS"; @@ -2343,6 +2363,11 @@ public class Intent implements Parcelable, Cloneable { /** * Used with {@link #ACTION_MAIN} to launch the email application. * The activity should be able to send and receive email. + * <p>NOTE: This should not be used as the primary key of an Intent, + * since it will not result in the app launching with the correct + * action and category. Instead, use this with + * {@link #makeMainSelectorActivity(String, String) to generate a main + * Intent with this category in the selector.</p> */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_APP_EMAIL = "android.intent.category.APP_EMAIL"; @@ -2351,6 +2376,11 @@ public class Intent implements Parcelable, Cloneable { * Used with {@link #ACTION_MAIN} to launch the gallery application. * The activity should be able to view and manipulate image and video files * stored on the device. + * <p>NOTE: This should not be used as the primary key of an Intent, + * since it will not result in the app launching with the correct + * action and category. Instead, use this with + * {@link #makeMainSelectorActivity(String, String) to generate a main + * Intent with this category in the selector.</p> */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_APP_GALLERY = "android.intent.category.APP_GALLERY"; @@ -2358,6 +2388,11 @@ public class Intent implements Parcelable, Cloneable { /** * Used with {@link #ACTION_MAIN} to launch the maps application. * The activity should be able to show the user's current location and surroundings. + * <p>NOTE: This should not be used as the primary key of an Intent, + * since it will not result in the app launching with the correct + * action and category. Instead, use this with + * {@link #makeMainSelectorActivity(String, String) to generate a main + * Intent with this category in the selector.</p> */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_APP_MAPS = "android.intent.category.APP_MAPS"; @@ -2365,13 +2400,24 @@ public class Intent implements Parcelable, Cloneable { /** * Used with {@link #ACTION_MAIN} to launch the messaging application. * The activity should be able to send and receive text messages. + * <p>NOTE: This should not be used as the primary key of an Intent, + * since it will not result in the app launching with the correct + * action and category. Instead, use this with + * {@link #makeMainSelectorActivity(String, String) to generate a main + * Intent with this category in the selector.</p> */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_APP_MESSAGING = "android.intent.category.APP_MESSAGING"; /** * Used with {@link #ACTION_MAIN} to launch the music application. - * The activity should be able to play, browse, or manipulate music files stored on the device. + * The activity should be able to play, browse, or manipulate music files + * stored on the device. + * <p>NOTE: This should not be used as the primary key of an Intent, + * since it will not result in the app launching with the correct + * action and category. Instead, use this with + * {@link #makeMainSelectorActivity(String, String) to generate a main + * Intent with this category in the selector.</p> */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_APP_MUSIC = "android.intent.category.APP_MUSIC"; @@ -2963,6 +3009,7 @@ public class Intent implements Parcelable, Cloneable { private HashSet<String> mCategories; private Bundle mExtras; private Rect mSourceBounds; + private Intent mSelector; // --------------------------------------------------------------------- @@ -2991,6 +3038,9 @@ public class Intent implements Parcelable, Cloneable { if (o.mSourceBounds != null) { this.mSourceBounds = new Rect(o.mSourceBounds); } + if (o.mSelector != null) { + this.mSelector = new Intent(o.mSelector); + } } @Override @@ -3131,6 +3181,39 @@ public class Intent implements Parcelable, Cloneable { } /** + * Make an Intent for the main activity of an application, without + * specifying a specific activity to run but giving a selector to find + * the activity. This results in a final Intent that is structured + * the same as when the application is launched from + * Home. For anything else that wants to launch an application in the + * same way, it is important that they use an Intent structured the same + * way, and can use this function to ensure this is the case. + * + * <p>The returned Intent has {@link #ACTION_MAIN} as its action, and includes the + * category {@link #CATEGORY_LAUNCHER}. This does <em>not</em> have + * {@link #FLAG_ACTIVITY_NEW_TASK} set, though typically you will want + * to do that through {@link #addFlags(int)} on the returned Intent. + * + * @param selectorAction The action name of the Intent's selector. + * @param selectorCategory The name of a category to add to the Intent's + * selector. + * @return Returns a newly created Intent that can be used to launch the + * activity as a main application entry. + * + * @see #setSelector(Intent) + */ + public static Intent makeMainSelectorActivity(String selectorAction, + String selectorCategory) { + Intent intent = new Intent(ACTION_MAIN); + intent.addCategory(CATEGORY_LAUNCHER); + Intent selector = new Intent(); + selector.setAction(selectorAction); + selector.addCategory(selectorCategory); + intent.setSelector(selector); + return intent; + } + + /** * Make an Intent that can be used to re-launch an application's task * in its base state. This is like {@link #makeMainActivity(ComponentName)}, * but also sets the flags {@link #FLAG_ACTIVITY_NEW_TASK} and @@ -3205,6 +3288,7 @@ public class Intent implements Parcelable, Cloneable { // new format Intent intent = new Intent(ACTION_VIEW); + Intent baseIntent = intent; // fetch data part, if present String data = i >= 0 ? uri.substring(0, i) : null; @@ -3214,8 +3298,9 @@ public class Intent implements Parcelable, Cloneable { // loop over contents of Intent, all name=value; while (!uri.startsWith("end", i)) { int eq = uri.indexOf('=', i); - int semi = uri.indexOf(';', eq); - String value = Uri.decode(uri.substring(eq + 1, semi)); + if (eq < 0) eq = i-1; + int semi = uri.indexOf(';', i); + String value = eq < semi ? Uri.decode(uri.substring(eq + 1, semi)) : ""; // action if (uri.startsWith("action=", i)) { @@ -3257,6 +3342,11 @@ public class Intent implements Parcelable, Cloneable { intent.mSourceBounds = Rect.unflattenFromString(value); } + // selector + else if (semi == (i+3) && uri.startsWith("SEL", i)) { + intent = new Intent(); + } + // extra else { String key = Uri.decode(uri.substring(i + 2, eq)); @@ -3280,6 +3370,12 @@ public class Intent implements Parcelable, Cloneable { i = semi + 1; } + if (intent != baseIntent) { + // The Intent had a selector; fix it up. + baseIntent.setSelector(intent); + intent = baseIntent; + } + if (data != null) { if (data.startsWith("intent:")) { data = data.substring(7); @@ -3605,7 +3701,7 @@ public class Intent implements Parcelable, Cloneable { * Return the set of all categories in the intent. If there are no categories, * returns NULL. * - * @return Set The set of categories you can examine. Do not modify! + * @return The set of categories you can examine. Do not modify! * * @see #hasCategory * @see #addCategory @@ -3615,6 +3711,16 @@ public class Intent implements Parcelable, Cloneable { } /** + * Return the specific selector associated with this Intent. If there is + * none, returns null. See {@link #setSelector} for more information. + * + * @see #setSelector + */ + public Intent getSelector() { + return mSelector; + } + + /** * Sets the ClassLoader that will be used when unmarshalling * any Parcelable values from the extras of this Intent. * @@ -4433,6 +4539,49 @@ public class Intent implements Parcelable, Cloneable { } /** + * Set a selector for this Intent. This is a modification to the kinds of + * things the Intent will match. If the selector is set, it will be used + * when trying to find entities that can handle the Intent, instead of the + * main contents of the Intent. This allows you build an Intent containing + * a generic protocol while targeting it more specifically. + * + * <p>An example of where this may be used is with things like + * {@link #CATEGORY_APP_BROWSER}. This category allows you to build an + * Intent that will launch the Browser application. However, the correct + * main entry point of an application is actually {@link #ACTION_MAIN} + * {@link #CATEGORY_LAUNCHER} with {@link #setComponent(ComponentName)} + * used to specify the actual Activity to launch. If you launch the browser + * with something different, undesired behavior may happen if the user has + * previously or later launches it the normal way, since they do not match. + * Instead, you can build an Intent with the MAIN action (but no ComponentName + * yet specified) and set a selector with {@link #ACTION_MAIN} and + * {@link #CATEGORY_APP_BROWSER} to point it specifically to the browser activity. + * + * <p>Setting a selector does not impact the behavior of + * {@link #filterEquals(Intent)} and {@link #filterHashCode()}. This is part of the + * desired behavior of a selector -- it does not impact the base meaning + * of the Intent, just what kinds of things will be matched against it + * when determining who can handle it.</p> + * + * <p>You can not use both a selector and {@link #setPackage(String)} on + * the same base Intent.</p> + * + * @param selector The desired selector Intent; set to null to not use + * a special selector. + */ + public void setSelector(Intent selector) { + if (selector == this) { + throw new IllegalArgumentException( + "Intent being set as a selector of itself"); + } + if (selector != null && mPackage != null) { + throw new IllegalArgumentException( + "Can't set selector when package name is already set"); + } + mSelector = selector; + } + + /** * Add extended data to the intent. The name must include a package * prefix, for example the app com.android.contacts would use names * like "com.android.contacts.ShowAll". @@ -5259,6 +5408,10 @@ public class Intent implements Parcelable, Cloneable { * @see #resolveActivity */ public Intent setPackage(String packageName) { + if (packageName != null && mSelector != null) { + throw new IllegalArgumentException( + "Can't set package name when selector is already set"); + } mPackage = packageName; return this; } @@ -5394,12 +5547,18 @@ public class Intent implements Parcelable, Cloneable { public static final int FILL_IN_PACKAGE = 1<<4; /** - * Use with {@link #fillIn} to allow the current package value to be + * Use with {@link #fillIn} to allow the current bounds rectangle to be * overwritten, even if it is already set. */ public static final int FILL_IN_SOURCE_BOUNDS = 1<<5; /** + * Use with {@link #fillIn} to allow the current selector to be + * overwritten, even if it is already set. + */ + public static final int FILL_IN_SELECTOR = 1<<6; + + /** * Copy the contents of <var>other</var> in to this object, but only * where fields are not defined by this object. For purposes of a field * being defined, the following pieces of data in the Intent are @@ -5419,11 +5578,13 @@ public class Intent implements Parcelable, Cloneable { * * <p>In addition, you can use the {@link #FILL_IN_ACTION}, * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE}, - * and {@link #FILL_IN_COMPONENT} to override the restriction where the + * {@link #FILL_IN_COMPONENT}, {@link #FILL_IN_SOURCE_BOUNDS}, and + * {@link #FILL_IN_SELECTOR} to override the restriction where the * corresponding field will not be replaced if it is already set. * * <p>Note: The component field will only be copied if {@link #FILL_IN_COMPONENT} is explicitly - * specified. + * specified. The selector will only be copied if {@link #FILL_IN_SELECTOR} is + * explicitly specified. * * <p>For example, consider Intent A with {data="foo", categories="bar"} * and Intent B with {action="gotit", data-type="some/thing", @@ -5439,7 +5600,8 @@ public class Intent implements Parcelable, Cloneable { * * @return Returns a bit mask of {@link #FILL_IN_ACTION}, * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE}, - * and {@link #FILL_IN_COMPONENT} indicating which fields were changed. + * {@link #FILL_IN_COMPONENT}, {@link #FILL_IN_SOURCE_BOUNDS}, and + * {@link #FILL_IN_SELECTOR} indicating which fields were changed. */ public int fillIn(Intent other, int flags) { int changes = 0; @@ -5464,8 +5626,20 @@ public class Intent implements Parcelable, Cloneable { } if (other.mPackage != null && (mPackage == null || (flags&FILL_IN_PACKAGE) != 0)) { - mPackage = other.mPackage; - changes |= FILL_IN_PACKAGE; + // Only do this if mSelector is not set. + if (mSelector == null) { + mPackage = other.mPackage; + changes |= FILL_IN_PACKAGE; + } + } + // Selector is special: it can only be set if explicitly allowed, + // for the same reason as the component name. + if (other.mSelector != null && (flags&FILL_IN_SELECTOR) != 0) { + if (mPackage == null) { + mSelector = new Intent(other.mSelector); + mPackage = null; + changes |= FILL_IN_SELECTOR; + } } // Component is special: it can -only- be set if explicitly allowed, // since otherwise the sender could force the intent somewhere the @@ -5763,6 +5937,11 @@ public class Intent implements Parcelable, Cloneable { first = false; b.append("(has extras)"); } + if (mSelector != null) { + b.append(" sel={"); + mSelector.toShortString(b, secure, comp, extras); + b.append("}"); + } } /** @@ -5823,6 +6002,21 @@ public class Intent implements Parcelable, Cloneable { uri.append("#Intent;"); + toUriInner(uri, scheme, flags); + if (mSelector != null) { + uri.append("SEL;"); + // Note that for now we are not going to try to handle the + // data part; not clear how to represent this as a URI, and + // not much utility in it. + mSelector.toUriInner(uri, null, flags); + } + + uri.append("end"); + + return uri.toString(); + } + + private void toUriInner(StringBuilder uri, String scheme, int flags) { if (scheme != null) { uri.append("scheme=").append(scheme).append(';'); } @@ -5877,10 +6071,6 @@ public class Intent implements Parcelable, Cloneable { } } } - - uri.append("end"); - - return uri.toString(); } public int describeContents() { @@ -5911,6 +6101,13 @@ public class Intent implements Parcelable, Cloneable { out.writeInt(0); } + if (mSelector != null) { + out.writeInt(1); + mSelector.writeToParcel(out, flags); + } else { + out.writeInt(0); + } + out.writeBundle(mExtras); } @@ -5952,6 +6149,10 @@ public class Intent implements Parcelable, Cloneable { mCategories = null; } + if (in.readInt() != 0) { + mSelector = new Intent(in); + } + mExtras = in.readBundle(); } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index e11d1ae..b1a458b 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -1175,8 +1175,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { intent.setComponent(cn); title = info.loadLabel(packageManager).toString(); } else if (category != null) { - intent = new Intent(Intent.ACTION_MAIN, null); - intent.addCategory(category); + intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category); title = ""; } else { Log.w(TAG, "Unable to add bookmark for shortcut " + shortcutStr diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 7ba7694..4b0dca6 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -1639,8 +1639,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (down && repeatCount == 0) { String category = sApplicationLaunchKeyCategories.get(keyCode); if (category != null) { - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.addCategory(category); + Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { mContext.startActivity(intent); diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java index a860763..de3129b 100644 --- a/services/java/com/android/server/am/TaskRecord.java +++ b/services/java/com/android/server/am/TaskRecord.java @@ -54,8 +54,17 @@ class TaskRecord extends ThumbnailHolder { void setIntent(Intent _intent, ActivityInfo info) { stringName = null; - + if (info.targetActivity == null) { + if (_intent != null) { + // If this Intent has a selector, we want to clear it for the + // recent task since it is not relevant if the user later wants + // to re-launch the app. + if (_intent.getSelector() != null) { + _intent = new Intent(_intent); + _intent.setSelector(null); + } + } intent = _intent; realActivity = _intent != null ? _intent.getComponent() : null; origActivity = null; @@ -65,6 +74,7 @@ class TaskRecord extends ThumbnailHolder { if (_intent != null) { Intent targetIntent = new Intent(_intent); targetIntent.setComponent(targetComponent); + targetIntent.setSelector(null); intent = targetIntent; realActivity = targetComponent; origActivity = _intent.getComponent(); diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 7005541..6b61c47 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -2162,6 +2162,9 @@ public class PackageManagerService extends IPackageManager.Stub { int flags, List<ResolveInfo> query, int priority) { // writer synchronized (mPackages) { + if (intent.getSelector() != null) { + intent = intent.getSelector(); + } if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION); List<PreferredActivity> prefs = mSettings.mPreferredActivities.queryIntent(intent, resolvedType, @@ -2242,7 +2245,13 @@ public class PackageManagerService extends IPackageManager.Stub { public List<ResolveInfo> queryIntentActivities(Intent intent, String resolvedType, int flags) { - final ComponentName comp = intent.getComponent(); + ComponentName comp = intent.getComponent(); + if (comp == null) { + if (intent.getSelector() != null) { + intent = intent.getSelector(); + comp = intent.getComponent(); + } + } if (comp != null) { final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1); final ActivityInfo ai = getActivityInfo(comp, flags); @@ -2440,6 +2449,12 @@ public class PackageManagerService extends IPackageManager.Stub { public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags) { ComponentName comp = intent.getComponent(); + if (comp == null) { + if (intent.getSelector() != null) { + intent = intent.getSelector(); + comp = intent.getComponent(); + } + } if (comp != null) { List<ResolveInfo> list = new ArrayList<ResolveInfo>(1); ActivityInfo ai = getReceiverInfo(comp, flags); @@ -2478,7 +2493,13 @@ public class PackageManagerService extends IPackageManager.Stub { } public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags) { - final ComponentName comp = intent.getComponent(); + ComponentName comp = intent.getComponent(); + if (comp == null) { + if (intent.getSelector() != null) { + intent = intent.getSelector(); + comp = intent.getComponent(); + } + } if (comp != null) { final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1); final ServiceInfo si = getServiceInfo(comp, flags); |