Skip to content

Commit f5b8671

Browse files
author
Dianne Hackborn
committed
Fix issue #5714517: App shortcuts can result in bad task intents
New API to let you build an Intent whose base configuration is correct, but has an additional "selector" to pick out the specific app that you would like launched. Change-Id: Ide9db6dc60e2844b7696cfe09b28337fe7dd63db
1 parent 003c15d commit f5b8671

File tree

7 files changed

+323
-50
lines changed

7 files changed

+323
-50
lines changed

api/current.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5334,6 +5334,7 @@ package android.content {
53345334
method public java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
53355335
method public T getParcelableExtra(java.lang.String);
53365336
method public java.lang.String getScheme();
5337+
method public android.content.Intent getSelector();
53375338
method public java.io.Serializable getSerializableExtra(java.lang.String);
53385339
method public short[] getShortArrayExtra(java.lang.String);
53395340
method public short getShortExtra(java.lang.String, short);
@@ -5346,6 +5347,7 @@ package android.content {
53465347
method public boolean hasExtra(java.lang.String);
53475348
method public boolean hasFileDescriptors();
53485349
method public static android.content.Intent makeMainActivity(android.content.ComponentName);
5350+
method public static android.content.Intent makeMainSelectorActivity(java.lang.String, java.lang.String);
53495351
method public static android.content.Intent makeRestartActivityTask(android.content.ComponentName);
53505352
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;
53515353
method public static android.content.Intent parseUri(java.lang.String, int) throws java.net.URISyntaxException;
@@ -5399,6 +5401,7 @@ package android.content {
53995401
method public void setExtrasClassLoader(java.lang.ClassLoader);
54005402
method public android.content.Intent setFlags(int);
54015403
method public android.content.Intent setPackage(java.lang.String);
5404+
method public void setSelector(android.content.Intent);
54025405
method public void setSourceBounds(android.graphics.Rect);
54035406
method public android.content.Intent setType(java.lang.String);
54045407
method public deprecated java.lang.String toURI();
@@ -5577,6 +5580,7 @@ package android.content {
55775580
field public static final int FILL_IN_COMPONENT = 8; // 0x8
55785581
field public static final int FILL_IN_DATA = 2; // 0x2
55795582
field public static final int FILL_IN_PACKAGE = 16; // 0x10
5583+
field public static final int FILL_IN_SELECTOR = 64; // 0x40
55805584
field public static final int FILL_IN_SOURCE_BOUNDS = 32; // 0x20
55815585
field public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 4194304; // 0x400000
55825586
field public static final int FLAG_ACTIVITY_CLEAR_TASK = 32768; // 0x8000

cmds/am/src/com/android/commands/am/Am.java

Lines changed: 68 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,18 @@ private void run(String[] args) throws Exception {
131131
runScreenCompat();
132132
} else if (op.equals("display-size")) {
133133
runDisplaySize();
134+
} else if (op.equals("to-uri")) {
135+
runToUri(false);
136+
} else if (op.equals("to-intent-uri")) {
137+
runToUri(true);
134138
} else {
135139
throw new IllegalArgumentException("Unknown command: " + op);
136140
}
137141
}
138142

139143
private Intent makeIntent() throws URISyntaxException {
140144
Intent intent = new Intent();
145+
Intent baseIntent = intent;
141146
boolean hasIntentInfo = false;
142147

143148
mDebugOption = false;
@@ -152,35 +157,39 @@ private Intent makeIntent() throws URISyntaxException {
152157
while ((opt=nextOption()) != null) {
153158
if (opt.equals("-a")) {
154159
intent.setAction(nextArgRequired());
155-
hasIntentInfo = true;
160+
if (intent == baseIntent) {
161+
hasIntentInfo = true;
162+
}
156163
} else if (opt.equals("-d")) {
157164
data = Uri.parse(nextArgRequired());
158-
hasIntentInfo = true;
165+
if (intent == baseIntent) {
166+
hasIntentInfo = true;
167+
}
159168
} else if (opt.equals("-t")) {
160169
type = nextArgRequired();
161-
hasIntentInfo = true;
170+
if (intent == baseIntent) {
171+
hasIntentInfo = true;
172+
}
162173
} else if (opt.equals("-c")) {
163174
intent.addCategory(nextArgRequired());
164-
hasIntentInfo = true;
175+
if (intent == baseIntent) {
176+
hasIntentInfo = true;
177+
}
165178
} else if (opt.equals("-e") || opt.equals("--es")) {
166179
String key = nextArgRequired();
167180
String value = nextArgRequired();
168181
intent.putExtra(key, value);
169-
hasIntentInfo = true;
170182
} else if (opt.equals("--esn")) {
171183
String key = nextArgRequired();
172184
intent.putExtra(key, (String) null);
173-
hasIntentInfo = true;
174185
} else if (opt.equals("--ei")) {
175186
String key = nextArgRequired();
176187
String value = nextArgRequired();
177188
intent.putExtra(key, Integer.valueOf(value));
178-
hasIntentInfo = true;
179189
} else if (opt.equals("--eu")) {
180190
String key = nextArgRequired();
181191
String value = nextArgRequired();
182192
intent.putExtra(key, Uri.parse(value));
183-
hasIntentInfo = true;
184193
} else if (opt.equals("--eia")) {
185194
String key = nextArgRequired();
186195
String value = nextArgRequired();
@@ -190,12 +199,10 @@ private Intent makeIntent() throws URISyntaxException {
190199
list[i] = Integer.valueOf(strings[i]);
191200
}
192201
intent.putExtra(key, list);
193-
hasIntentInfo = true;
194202
} else if (opt.equals("--el")) {
195203
String key = nextArgRequired();
196204
String value = nextArgRequired();
197205
intent.putExtra(key, Long.valueOf(value));
198-
hasIntentInfo = true;
199206
} else if (opt.equals("--ela")) {
200207
String key = nextArgRequired();
201208
String value = nextArgRequired();
@@ -205,18 +212,18 @@ private Intent makeIntent() throws URISyntaxException {
205212
list[i] = Long.valueOf(strings[i]);
206213
}
207214
intent.putExtra(key, list);
208-
hasIntentInfo = true;
209215
} else if (opt.equals("--ez")) {
210216
String key = nextArgRequired();
211217
String value = nextArgRequired();
212218
intent.putExtra(key, Boolean.valueOf(value));
213-
hasIntentInfo = true;
214219
} else if (opt.equals("-n")) {
215220
String str = nextArgRequired();
216221
ComponentName cn = ComponentName.unflattenFromString(str);
217222
if (cn == null) throw new IllegalArgumentException("Bad component name: " + str);
218223
intent.setComponent(cn);
219-
hasIntentInfo = true;
224+
if (intent == baseIntent) {
225+
hasIntentInfo = true;
226+
}
220227
} else if (opt.equals("-f")) {
221228
String str = nextArgRequired();
222229
intent.setFlags(Integer.decode(str).intValue());
@@ -264,6 +271,9 @@ private Intent makeIntent() throws URISyntaxException {
264271
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
265272
} else if (opt.equals("--receiver-replace-pending")) {
266273
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
274+
} else if (opt.equals("--selector")) {
275+
intent.setDataAndType(data, type);
276+
intent = new Intent();
267277
} else if (opt.equals("-D")) {
268278
mDebugOption = true;
269279
} else if (opt.equals("-W")) {
@@ -286,25 +296,42 @@ private Intent makeIntent() throws URISyntaxException {
286296
}
287297
intent.setDataAndType(data, type);
288298

299+
final boolean hasSelector = intent != baseIntent;
300+
if (hasSelector) {
301+
// A selector was specified; fix up.
302+
baseIntent.setSelector(intent);
303+
intent = baseIntent;
304+
}
305+
289306
String arg = nextArg();
290-
if (arg != null) {
291-
Intent baseIntent;
292-
if (arg.indexOf(':') >= 0) {
293-
// The argument is a URI. Fully parse it, and use that result
294-
// to fill in any data not specified so far.
295-
baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME);
296-
} else if (arg.indexOf('/') >= 0) {
297-
// The argument is a component name. Build an Intent to launch
298-
// it.
299-
baseIntent = new Intent(Intent.ACTION_MAIN);
300-
baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
301-
baseIntent.setComponent(ComponentName.unflattenFromString(arg));
302-
} else {
303-
// Assume the argument is a package name.
307+
baseIntent = null;
308+
if (arg == null) {
309+
if (hasSelector) {
310+
// If a selector has been specified, and no arguments
311+
// have been supplied for the main Intent, then we can
312+
// assume it is ACTION_MAIN CATEGORY_LAUNCHER; we don't
313+
// need to have a component name specified yet, the
314+
// selector will take care of that.
304315
baseIntent = new Intent(Intent.ACTION_MAIN);
305316
baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
306-
baseIntent.setPackage(arg);
307317
}
318+
} else if (arg.indexOf(':') >= 0) {
319+
// The argument is a URI. Fully parse it, and use that result
320+
// to fill in any data not specified so far.
321+
baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME);
322+
} else if (arg.indexOf('/') >= 0) {
323+
// The argument is a component name. Build an Intent to launch
324+
// it.
325+
baseIntent = new Intent(Intent.ACTION_MAIN);
326+
baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
327+
baseIntent.setComponent(ComponentName.unflattenFromString(arg));
328+
} else {
329+
// Assume the argument is a package name.
330+
baseIntent = new Intent(Intent.ACTION_MAIN);
331+
baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
332+
baseIntent.setPackage(arg);
333+
}
334+
if (baseIntent != null) {
308335
Bundle extras = intent.getExtras();
309336
intent.replaceExtras((Bundle)null);
310337
Bundle uriExtras = baseIntent.getExtras();
@@ -315,7 +342,7 @@ private Intent makeIntent() throws URISyntaxException {
315342
baseIntent.removeCategory(c);
316343
}
317344
}
318-
intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT);
345+
intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_SELECTOR);
319346
if (extras == null) {
320347
extras = uriExtras;
321348
} else if (uriExtras != null) {
@@ -1064,6 +1091,11 @@ private void runDisplaySize() throws Exception {
10641091
}
10651092
}
10661093

1094+
private void runToUri(boolean intentScheme) throws Exception {
1095+
Intent intent = makeIntent();
1096+
System.out.println(intent.toUri(intentScheme ? Intent.URI_INTENT_SCHEME : 0));
1097+
}
1098+
10671099
private class IntentReceiver extends IIntentReceiver.Stub {
10681100
private boolean mFinished = false;
10691101

@@ -1233,6 +1265,8 @@ private static void showUsage() {
12331265
" am monitor [--gdb <port>]\n" +
12341266
" am screen-compat [on|off] <PACKAGE>\n" +
12351267
" am display-size [reset|MxN]\n" +
1268+
" am to-uri [INTENT]\n" +
1269+
" am to-intent-uri [INTENT]\n" +
12361270
"\n" +
12371271
"am start: start an Activity. Options are:\n" +
12381272
" -D: enable debugging\n" +
@@ -1284,6 +1318,10 @@ private static void showUsage() {
12841318
"\n" +
12851319
"am display-size: override display size.\n" +
12861320
"\n" +
1321+
"am to-uri: print the given Intent specification as a URI.\n" +
1322+
"\n" +
1323+
"am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
1324+
"\n" +
12871325
"<INTENT> specifications include these flags and arguments:\n" +
12881326
" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
12891327
" [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
@@ -1308,6 +1346,7 @@ private static void showUsage() {
13081346
" [--activity-single-top] [--activity-clear-task]\n" +
13091347
" [--activity-task-on-home]\n" +
13101348
" [--receiver-registered-only] [--receiver-replace-pending]\n" +
1349+
" [--selector]\n" +
13111350
" [<URI> | <PACKAGE> | <COMPONENT>]\n"
13121351
);
13131352
}

0 commit comments

Comments
 (0)