Fix issue #15828903: Intent.parseUri allows call to FLAG_GRANT_*_URI_PERMISSION

You now need to set a flag if you want this unsafe behavior.

Change-Id: I185e9a04e005e42a887c3d58a2818616790b060a
diff --git a/api/current.txt b/api/current.txt
index fb26daf..553a30c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7819,6 +7819,7 @@
     field public static final int FLAG_RECEIVER_REGISTERED_ONLY = 1073741824; // 0x40000000
     field public static final int FLAG_RECEIVER_REPLACE_PENDING = 536870912; // 0x20000000
     field public static final java.lang.String METADATA_DOCK_HOME = "android.dock_home";
+    field public static final int URI_ALLOW_UNSAFE = 4; // 0x4
     field public static final int URI_ANDROID_APP_SCHEME = 2; // 0x2
     field public static final int URI_INTENT_SCHEME = 1; // 0x1
   }
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 0cad17d..475d540 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -55,12 +55,9 @@
 import android.util.AndroidException;
 import android.util.ArrayMap;
 import android.view.IWindowManager;
-import android.view.View;
 
 import com.android.internal.os.BaseCommand;
 
-import dalvik.system.VMRuntime;
-
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -619,7 +616,7 @@
             // 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
-                    | Intent.URI_ANDROID_APP_SCHEME);
+                    | Intent.URI_ANDROID_APP_SCHEME | Intent.URI_ALLOW_UNSAFE);
         } else if (arg.indexOf('/') >= 0) {
             // The argument is a component name.  Build an Intent to launch
             // it.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a13a2ea..de7fbab 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4010,6 +4010,20 @@
      */
     public static final int URI_ANDROID_APP_SCHEME = 1<<1;
 
+    /**
+     * Flag for use with {@link #toUri} and {@link #parseUri}: allow parsing
+     * of unsafe information.  In particular, the flags {@link #FLAG_GRANT_READ_URI_PERMISSION},
+     * {@link #FLAG_GRANT_WRITE_URI_PERMISSION}, {@link #FLAG_GRANT_PERSISTABLE_URI_PERMISSION},
+     * and {@link #FLAG_GRANT_PREFIX_URI_PERMISSION} flags can not be set, so that the
+     * generated Intent can not cause unexpected data access to happen.
+     *
+     * <p>If you do not trust the source of the URI being parsed, you should still do further
+     * processing to protect yourself from it.  In particular, when using it to start an
+     * activity you should usually add in {@link #CATEGORY_BROWSABLE} to limit the activities
+     * that can handle it.</p>
+     */
+    public static final int URI_ALLOW_UNSAFE = 1<<2;
+
     // ---------------------------------------------------------------------
 
     private String mAction;
@@ -4309,7 +4323,7 @@
             // old format Intent URI
             } else if (!uri.startsWith("#Intent;", i)) {
                 if (!androidApp) {
-                    return getIntentOld(uri);
+                    return getIntentOld(uri, flags);
                 } else {
                     i = -1;
                 }
@@ -4359,6 +4373,9 @@
                 // launch flags
                 else if (uri.startsWith("launchFlags=", i)) {
                     intent.mFlags = Integer.decode(value).intValue();
+                    if ((flags& URI_ALLOW_UNSAFE) == 0) {
+                        intent.mFlags &= ~IMMUTABLE_FLAGS;
+                    }
                 }
 
                 // package
@@ -4488,6 +4505,10 @@
     }
 
     public static Intent getIntentOld(String uri) throws URISyntaxException {
+        return getIntentOld(uri, 0);
+    }
+
+    private static Intent getIntentOld(String uri, int flags) throws URISyntaxException {
         Intent intent;
 
         int i = uri.lastIndexOf('#');
@@ -4536,6 +4557,9 @@
                 i += 12;
                 int j = uri.indexOf(')', i);
                 intent.mFlags = Integer.decode(uri.substring(i, j)).intValue();
+                if ((flags& URI_ALLOW_UNSAFE) == 0) {
+                    intent.mFlags &= ~IMMUTABLE_FLAGS;
+                }
                 i = j + 1;
             }