Merge "Fix issue #5714517: App shortcuts can result in bad task intents" into ics-mr1

This commit is contained in:
Dianne Hackborn
2011-12-05 19:16:54 -08:00
committed by Android (Google) Code Review
7 changed files with 323 additions and 50 deletions

View File

@ -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

View File

@ -131,6 +131,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);
}
@ -138,6 +142,7 @@ public class Am {
private Intent makeIntent() throws URISyntaxException {
Intent intent = new Intent();
Intent baseIntent = intent;
boolean hasIntentInfo = false;
mDebugOption = false;
@ -152,35 +157,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();
@ -190,12 +199,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();
@ -205,18 +212,18 @@ public class Am {
list[i] = Long.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());
@ -264,6 +271,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")) {
@ -286,25 +296,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 = 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.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);
}
} 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();
@ -315,7 +342,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) {
@ -1064,6 +1091,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;
@ -1233,6 +1265,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" +
@ -1284,6 +1318,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" +
@ -1308,6 +1346,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"
);
}

View File

@ -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
@ -3130,6 +3180,39 @@ public class Intent implements Parcelable, Cloneable {
return intent;
}
/**
* 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)},
@ -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
@ -3614,6 +3710,16 @@ public class Intent implements Parcelable, Cloneable {
return mCategories;
}
/**
* 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.
@ -4432,6 +4538,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
@ -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,11 +5547,17 @@ 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
@ -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();
}

View File

@ -1151,8 +1151,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

View File

@ -1638,8 +1638,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);

View File

@ -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();

View File

@ -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);