diff options
| -rw-r--r-- | api/current.txt | 4 | ||||
| -rw-r--r-- | core/java/android/app/Activity.java | 24 | ||||
| -rw-r--r-- | core/java/android/app/Service.java | 14 | ||||
| -rw-r--r-- | core/java/android/content/ClipData.java | 84 | ||||
| -rw-r--r-- | core/java/android/content/ClipDescription.java | 33 | ||||
| -rw-r--r-- | core/java/android/content/Intent.java | 133 | ||||
| -rw-r--r-- | services/java/com/android/server/AlarmManagerService.java | 3 | ||||
| -rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 128 | ||||
| -rw-r--r-- | services/java/com/android/server/am/ActivityRecord.java | 33 | ||||
| -rw-r--r-- | services/java/com/android/server/am/ActivityStack.java | 4 | ||||
| -rw-r--r-- | services/java/com/android/server/am/IntentBindRecord.java | 4 | ||||
| -rw-r--r-- | services/java/com/android/server/am/PendingIntentRecord.java | 4 | ||||
| -rw-r--r-- | services/java/com/android/server/am/ServiceRecord.java | 14 | ||||
| -rw-r--r-- | services/java/com/android/server/am/TaskRecord.java | 4 |
14 files changed, 397 insertions, 89 deletions
diff --git a/api/current.txt b/api/current.txt index dbe57d1e31a5..f79df94158b0 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4761,6 +4761,7 @@ package android.content { public class ClipData implements android.os.Parcelable { ctor public ClipData(java.lang.CharSequence, java.lang.String[], android.content.ClipData.Item); ctor public ClipData(android.content.ClipDescription, android.content.ClipData.Item); + ctor public ClipData(android.content.ClipData); method public void addItem(android.content.ClipData.Item); method public int describeContents(); method public android.content.ClipDescription getDescription(); @@ -5378,6 +5379,7 @@ package android.content { method public java.lang.CharSequence[] getCharSequenceArrayExtra(java.lang.String); method public java.util.ArrayList<java.lang.CharSequence> getCharSequenceArrayListExtra(java.lang.String); method public java.lang.CharSequence getCharSequenceExtra(java.lang.String); + method public android.content.ClipData getClipData(); method public android.content.ComponentName getComponent(); method public android.net.Uri getData(); method public java.lang.String getDataString(); @@ -5461,6 +5463,7 @@ package android.content { method public android.content.Intent setClass(android.content.Context, java.lang.Class<?>); method public android.content.Intent setClassName(android.content.Context, java.lang.String); method public android.content.Intent setClassName(java.lang.String, java.lang.String); + method public void setClipData(android.content.ClipData); method public android.content.Intent setComponent(android.content.ComponentName); method public android.content.Intent setData(android.net.Uri); method public android.content.Intent setDataAndNormalize(android.net.Uri); @@ -5646,6 +5649,7 @@ package android.content { field public static final java.lang.String EXTRA_UID = "android.intent.extra.UID"; field public static final int FILL_IN_ACTION = 1; // 0x1 field public static final int FILL_IN_CATEGORIES = 4; // 0x4 + field public static final int FILL_IN_CLIP_DATA = 128; // 0x80 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 diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 8e8d37d645c9..f8954315630b 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -570,7 +570,18 @@ import java.util.HashMap; * tag. By doing so, other applications will need to declare a corresponding * {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>} * element in their own manifest to be able to start that activity. - * + * + * <p>When starting an Activity you can set {@link Intent#FLAG_GRANT_READ_URI_PERMISSION + * Intent.FLAG_GRANT_READ_URI_PERMISSION} and/or {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION + * Intent.FLAG_GRANT_WRITE_URI_PERMISSION} on the Intent. This will grant the + * Activity access to the specific URIs in the Intent. Access will remain + * until the Activity has finished (it will remain across the hosting + * process being killed and other temporary destruction). As of + * {@link android.os.Build.VERSION_CODES#GINGERBREAD}, if the Activity + * was already created and a new Intent is being delivered to + * {@link #onNewIntent(Intent)}, any newly granted URI permissions will be added + * to the existing ones it holds. + * * <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> * document for more information on permissions and security in general. * @@ -3549,7 +3560,16 @@ public class Activity extends ContextThemeWrapper /** * Call this to set the result that your activity will return to its * caller. - * + * + * <p>As of {@link android.os.Build.VERSION_CODES#GINGERBREAD}, the Intent + * you supply here can have {@link Intent#FLAG_GRANT_READ_URI_PERMISSION + * Intent.FLAG_GRANT_READ_URI_PERMISSION} and/or {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION + * Intent.FLAG_GRANT_WRITE_URI_PERMISSION} set. This will grant the + * Activity receiving the result access to the specific URIs in the Intent. + * Access will remain until the Activity has finished (it will remain across the hosting + * process being killed and other temporary destruction) and will be added + * to any existing set of URI permissions it already holds. + * * @param resultCode The result code to propagate back to the originating * activity, often RESULT_CANCELED or RESULT_OK * @param data The data to propagate back to the originating activity. diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index 35bd8c08a713..be4b8af6fb49 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -163,7 +163,19 @@ import java.io.PrintWriter; * {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>} * element in their own manifest to be able to start, stop, or bind to * the service. - * + * + * <p>As of {@link android.os.Build.VERSION_CODES#GINGERBREAD}, when using + * {@link Context#startService(Intent) Context.startService(Intent)}, you can + * also set {@link Intent#FLAG_GRANT_READ_URI_PERMISSION + * Intent.FLAG_GRANT_READ_URI_PERMISSION} and/or {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION + * Intent.FLAG_GRANT_WRITE_URI_PERMISSION} on the Intent. This will grant the + * Service temporary access to the specific URIs in the Intent. Access will + * remain until the Service has called {@link #stopSelf(int)} for that start + * command or a later one, or until the Service has been completely stopped. + * This works for granting access to the other apps that have not requested + * the permission protecting the Service, or even when the Service is not + * exported at all. + * * <p>In addition, a service can protect individual IPC calls into it with * permissions, by calling the * {@link #checkCallingPermission} diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java index a8b1bf47d624..a655dd424aa9 100644 --- a/core/java/android/content/ClipData.java +++ b/core/java/android/content/ClipData.java @@ -153,7 +153,7 @@ public class ClipData implements Parcelable { final Bitmap mIcon; - final ArrayList<Item> mItems = new ArrayList<Item>(); + final ArrayList<Item> mItems; /** * Description of a single item in a ClippedData. @@ -321,6 +321,33 @@ public class ClipData implements Parcelable { return ""; } //END_INCLUDE(coerceToText) + + @Override + public String toString() { + StringBuilder b = new StringBuilder(128); + + b.append("ClipData.Item { "); + toShortString(b); + b.append(" }"); + + return b.toString(); + } + + /** @hide */ + public void toShortString(StringBuilder b) { + if (mText != null) { + b.append("T:"); + b.append(mText); + } else if (mUri != null) { + b.append("U:"); + b.append(mUri); + } else if (mIntent != null) { + b.append("I:"); + mIntent.toShortString(b, true, true, true, true); + } else { + b.append("NULL"); + } + } } /** @@ -336,6 +363,7 @@ public class ClipData implements Parcelable { throw new NullPointerException("item is null"); } mIcon = null; + mItems = new ArrayList<Item>(); mItems.add(item); } @@ -351,10 +379,23 @@ public class ClipData implements Parcelable { throw new NullPointerException("item is null"); } mIcon = null; + mItems = new ArrayList<Item>(); mItems.add(item); } /** + * Create a new clip that is a copy of another clip. This does a deep-copy + * of all items in the clip. + * + * @param other The existing ClipData that is to be copied. + */ + public ClipData(ClipData other) { + mClipDescription = other.mClipDescription; + mIcon = other.mIcon; + mItems = new ArrayList<Item>(other.mItems); + } + + /** * Create a new ClipData holding data of the type * {@link ClipDescription#MIMETYPE_TEXT_PLAIN}. * @@ -475,6 +516,46 @@ public class ClipData implements Parcelable { } @Override + public String toString() { + StringBuilder b = new StringBuilder(128); + + b.append("ClipData { "); + toShortString(b); + b.append(" }"); + + return b.toString(); + } + + /** @hide */ + public void toShortString(StringBuilder b) { + boolean first; + if (mClipDescription != null) { + first = !mClipDescription.toShortString(b); + } else { + first = true; + } + if (mIcon != null) { + if (!first) { + b.append(' '); + } + first = false; + b.append("I:"); + b.append(mIcon.getWidth()); + b.append('x'); + b.append(mIcon.getHeight()); + } + for (int i=0; i<mItems.size(); i++) { + if (!first) { + b.append(' '); + } + first = false; + b.append('{'); + mItems.get(i).toShortString(b); + b.append('}'); + } + } + + @Override public int describeContents() { return 0; } @@ -515,6 +596,7 @@ public class ClipData implements Parcelable { } else { mIcon = null; } + mItems = new ArrayList<Item>(); final int N = in.readInt(); for (int i=0; i<N; i++) { CharSequence text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); diff --git a/core/java/android/content/ClipDescription.java b/core/java/android/content/ClipDescription.java index b5fa20cda7ff..c6b51efbc362 100644 --- a/core/java/android/content/ClipDescription.java +++ b/core/java/android/content/ClipDescription.java @@ -184,6 +184,39 @@ public class ClipDescription implements Parcelable { } @Override + public String toString() { + StringBuilder b = new StringBuilder(128); + + b.append("ClipDescription { "); + toShortString(b); + b.append(" }"); + + return b.toString(); + } + + /** @hide */ + public boolean toShortString(StringBuilder b) { + boolean first = true; + for (int i=0; i<mMimeTypes.length; i++) { + if (!first) { + b.append(' '); + } + first = false; + b.append(mMimeTypes[i]); + } + if (mLabel != null) { + if (!first) { + b.append(' '); + } + first = false; + b.append('"'); + b.append(mLabel); + b.append('"'); + } + return !first; + } + + @Override public int describeContents() { return 0; } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index b1b09d56c363..57391199a31a 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2688,12 +2688,20 @@ public class Intent implements Parcelable, Cloneable { /** * If set, the recipient of this Intent will be granted permission to - * perform read operations on the Uri in the Intent's data. + * perform read operations on the Uri in the Intent's data and any URIs + * specified in its ClipData. When applying to an Intent's ClipData, + * all URIs as well as recursive traversals through data or other ClipData + * in Intent items will be granted; only the grant flags of the top-level + * Intent are used. */ public static final int FLAG_GRANT_READ_URI_PERMISSION = 0x00000001; /** * If set, the recipient of this Intent will be granted permission to - * perform write operations on the Uri in the Intent's data. + * perform write operations on the Uri in the Intent's data and any URIs + * specified in its ClipData. When applying to an Intent's ClipData, + * all URIs as well as recursive traversals through data or other ClipData + * in Intent items will be granted; only the grant flags of the top-level + * Intent are used. */ public static final int FLAG_GRANT_WRITE_URI_PERMISSION = 0x00000002; /** @@ -3018,6 +3026,7 @@ public class Intent implements Parcelable, Cloneable { private Bundle mExtras; private Rect mSourceBounds; private Intent mSelector; + private ClipData mClipData; // --------------------------------------------------------------------- @@ -3049,6 +3058,9 @@ public class Intent implements Parcelable, Cloneable { if (o.mSelector != null) { this.mSelector = new Intent(o.mSelector); } + if (o.mClipData != null) { + this.mClipData = new ClipData(o.mClipData); + } } @Override @@ -3729,6 +3741,16 @@ public class Intent implements Parcelable, Cloneable { } /** + * Return the {@link ClipData} associated with this Intent. If there is + * none, returns null. See {@link #setClipData} for more information. + * + * @see #setClipData; + */ + public ClipData getClipData() { + return mClipData; + } + + /** * Sets the ClassLoader that will be used when unmarshalling * any Parcelable values from the extras of this Intent. * @@ -4683,6 +4705,37 @@ public class Intent implements Parcelable, Cloneable { } /** + * Set a {@link ClipData} associated with this Intent. This replaces any + * previously set ClipData. + * + * <p>The ClipData in an intent is not used for Intent matching or other + * such operations. Semantically it is like extras, used to transmit + * additional data with the Intent. The main feature of using this over + * the extras for data is that {@link #FLAG_GRANT_READ_URI_PERMISSION} + * and {@link #FLAG_GRANT_WRITE_URI_PERMISSION} will operate on any URI + * items included in the clip data. This is useful, in particular, if + * you want to transmit an Intent containing multiple <code>content:</code> + * URIs for which the recipient may not have global permission to access the + * content provider. + * + * <p>If the ClipData contains items that are themselves Intents, any + * grant flags in those Intents will be ignored. Only the top-level flags + * of the main Intent are respected, and will be applied to all Uri or + * Intent items in the clip (or sub-items of the clip). + * + * <p>The MIME type, label, and icon in the ClipData object are not + * directly used by Intent. Applications should generally rely on the + * MIME type of the Intent itself, not what it may find in the ClipData. + * A common practice is to construct a ClipData for use with an Intent + * with a MIME type of "*\/*". + * + * @param clip The new clip to set. May be null to clear the current clip. + */ + public void setClipData(ClipData clip) { + mClipData = clip; + } + + /** * 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". @@ -5660,6 +5713,12 @@ public class Intent implements Parcelable, Cloneable { public static final int FILL_IN_SELECTOR = 1<<6; /** + * Use with {@link #fillIn} to allow the current ClipData to be + * overwritten, even if it is already set. + */ + public static final int FILL_IN_CLIP_DATA = 1<<7; + + /** * 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 @@ -5673,19 +5732,22 @@ public class Intent implements Parcelable, Cloneable { * <li> package, as set by {@link #setPackage}. * <li> component, as set by {@link #setComponent(ComponentName)} or * related methods. - * <li> source bounds, as set by {@link #setSourceBounds} + * <li> source bounds, as set by {@link #setSourceBounds}. + * <li> selector, as set by {@link #setSelector(Intent)}. + * <li> clip data, as set by {@link #setClipData(ClipData)}. * <li> each top-level name in the associated extras. * </ul> * * <p>In addition, you can use the {@link #FILL_IN_ACTION}, * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE}, - * {@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. + * {@link #FILL_IN_COMPONENT}, {@link #FILL_IN_SOURCE_BOUNDS}, + * {@link #FILL_IN_SELECTOR}, and {@link #FILL_IN_CLIP_DATA} 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. The selector will only be copied if {@link #FILL_IN_SELECTOR} is - * explicitly specified. + * <p>Note: The component field will only be copied if {@link #FILL_IN_COMPONENT} + * is explicitly 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", @@ -5742,6 +5804,11 @@ public class Intent implements Parcelable, Cloneable { changes |= FILL_IN_SELECTOR; } } + if (other.mClipData != null + && (mClipData == null || (flags&FILL_IN_CLIP_DATA) != 0)) { + mClipData = other.mClipData; + changes |= FILL_IN_CLIP_DATA; + } // Component is special: it can -only- be set if explicitly allowed, // since otherwise the sender could force the intent somewhere the // originator didn't intend. @@ -5938,7 +6005,7 @@ public class Intent implements Parcelable, Cloneable { StringBuilder b = new StringBuilder(128); b.append("Intent { "); - toShortString(b, true, true, true); + toShortString(b, true, true, true, false); b.append(" }"); return b.toString(); @@ -5949,21 +6016,33 @@ public class Intent implements Parcelable, Cloneable { StringBuilder b = new StringBuilder(128); b.append("Intent { "); - toShortString(b, false, true, true); + toShortString(b, false, true, true, false); + b.append(" }"); + + return b.toString(); + } + + /** @hide */ + public String toInsecureStringWithClip() { + StringBuilder b = new StringBuilder(128); + + b.append("Intent { "); + toShortString(b, false, true, true, true); b.append(" }"); return b.toString(); } /** @hide */ - public String toShortString(boolean secure, boolean comp, boolean extras) { + public String toShortString(boolean secure, boolean comp, boolean extras, boolean clip) { StringBuilder b = new StringBuilder(128); - toShortString(b, secure, comp, extras); + toShortString(b, secure, comp, extras, clip); return b.toString(); } /** @hide */ - public void toShortString(StringBuilder b, boolean secure, boolean comp, boolean extras) { + public void toShortString(StringBuilder b, boolean secure, boolean comp, boolean extras, + boolean clip) { boolean first = true; if (mAction != null) { b.append("act=").append(mAction); @@ -6031,6 +6110,19 @@ public class Intent implements Parcelable, Cloneable { first = false; b.append("bnds=").append(mSourceBounds.toShortString()); } + if (mClipData != null) { + if (!first) { + b.append(' '); + } + first = false; + if (clip) { + b.append("clip={"); + mClipData.toShortString(b); + b.append('}'); + } else { + b.append("(has clip)"); + } + } if (extras && mExtras != null) { if (!first) { b.append(' '); @@ -6040,7 +6132,7 @@ public class Intent implements Parcelable, Cloneable { } if (mSelector != null) { b.append(" sel={"); - mSelector.toShortString(b, secure, comp, extras); + mSelector.toShortString(b, secure, comp, extras, clip); b.append("}"); } } @@ -6209,6 +6301,13 @@ public class Intent implements Parcelable, Cloneable { out.writeInt(0); } + if (mClipData != null) { + out.writeInt(1); + mClipData.writeToParcel(out, flags); + } else { + out.writeInt(0); + } + out.writeBundle(mExtras); } @@ -6254,6 +6353,10 @@ public class Intent implements Parcelable, Cloneable { mSelector = new Intent(in); } + if (in.readInt() != 0) { + mClipData = new ClipData(in); + } + mExtras = in.readBundle(); } diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java index b8c44d9cf99a..057440572384 100644 --- a/services/java/com/android/server/AlarmManagerService.java +++ b/services/java/com/android/server/AlarmManagerService.java @@ -477,7 +477,8 @@ class AlarmManagerService extends IAlarmManager.Stub { : bs.filterStats.entrySet()) { pw.print(" "); pw.print(fe.getValue().count); pw.print(" alarms: "); - pw.println(fe.getKey().getIntent().toShortString(false, true, false)); + pw.println(fe.getKey().getIntent().toShortString( + false, true, false, true)); } } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 4ea2f041c74d..ce597adf5c5b 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -49,10 +49,10 @@ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; -import android.app.WallpaperManager; import android.app.backup.IBackupManager; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; +import android.content.ClipData; import android.content.ComponentCallbacks2; import android.content.ComponentName; import android.content.ContentResolver; @@ -4657,9 +4657,11 @@ public final class ActivityManagerService extends ActivityManagerNative * if callingUid is not allowed to do this. Returns the uid of the target * if the URI permission grant should be performed; returns -1 if it is not * needed (for example targetPkg already has permission to access the URI). + * If you already know the uid of the target, you can supply it in + * lastTargetUid else set that to -1. */ int checkGrantUriPermissionLocked(int callingUid, String targetPkg, - Uri uri, int modeFlags) { + Uri uri, int modeFlags, int lastTargetUid) { modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); if (modeFlags == 0) { @@ -4698,8 +4700,8 @@ public final class ActivityManagerService extends ActivityManagerNative return -1; } - int targetUid; - if (targetPkg != null) { + int targetUid = lastTargetUid; + if (targetUid < 0 && targetPkg != null) { try { targetUid = pm.getPackageUid(targetPkg); if (targetUid < 0) { @@ -4710,8 +4712,6 @@ public final class ActivityManagerService extends ActivityManagerNative } catch (RemoteException ex) { return -1; } - } else { - targetUid = -1; } if (targetUid >= 0) { @@ -4783,7 +4783,7 @@ public final class ActivityManagerService extends ActivityManagerNative Uri uri, int modeFlags) { enforceNotIsolatedCaller("checkGrantUriPermission"); synchronized(this) { - return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags); + return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags, -1); } } @@ -4830,13 +4830,13 @@ public final class ActivityManagerService extends ActivityManagerNative } } - void grantUriPermissionLocked(int callingUid, - String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) { + void grantUriPermissionLocked(int callingUid, String targetPkg, Uri uri, + int modeFlags, UriPermissionOwner owner) { if (targetPkg == null) { throw new NullPointerException("targetPkg"); } - int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags); + int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags, -1); if (targetUid < 0) { return; } @@ -4844,13 +4844,26 @@ public final class ActivityManagerService extends ActivityManagerNative grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner); } + static class NeededUriGrants extends ArrayList<Uri> { + final String targetPkg; + final int targetUid; + final int flags; + + NeededUriGrants(String _targetPkg, int _targetUid, int _flags) { + targetPkg = _targetPkg; + targetUid = _targetUid; + flags = _flags; + } + } + /** * Like checkGrantUriPermissionLocked, but takes an Intent. */ - int checkGrantUriPermissionFromIntentLocked(int callingUid, - String targetPkg, Intent intent) { + NeededUriGrants checkGrantUriPermissionFromIntentLocked(int callingUid, + String targetPkg, Intent intent, int mode, NeededUriGrants needed) { if (DEBUG_URI_PERMISSION) Slog.v(TAG, - "Checking URI perm to " + (intent != null ? intent.getData() : null) + "Checking URI perm to data=" + (intent != null ? intent.getData() : null) + + " clip=" + (intent != null ? intent.getClipData() : null) + " from " + intent + "; flags=0x" + Integer.toHexString(intent != null ? intent.getFlags() : 0)); @@ -4859,33 +4872,74 @@ public final class ActivityManagerService extends ActivityManagerNative } if (intent == null) { - return -1; + return null; } Uri data = intent.getData(); - if (data == null) { - return -1; + ClipData clip = intent.getClipData(); + if (data == null && clip == null) { + return null; + } + if (data != null) { + int target = checkGrantUriPermissionLocked(callingUid, targetPkg, data, + mode, needed != null ? needed.targetUid : -1); + if (target > 0) { + if (needed == null) { + needed = new NeededUriGrants(targetPkg, target, mode); + } + needed.add(data); + } + } + if (clip != null) { + for (int i=0; i<clip.getItemCount(); i++) { + Uri uri = clip.getItemAt(i).getUri(); + if (uri != null) { + int target = -1; + target = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, + mode, needed != null ? needed.targetUid : -1); + if (target > 0) { + if (needed == null) { + needed = new NeededUriGrants(targetPkg, target, mode); + } + needed.add(uri); + } + } else { + Intent clipIntent = clip.getItemAt(i).getIntent(); + if (clipIntent != null) { + NeededUriGrants newNeeded = checkGrantUriPermissionFromIntentLocked( + callingUid, targetPkg, clipIntent, mode, needed); + if (newNeeded != null) { + needed = newNeeded; + } + } + } + } } - return checkGrantUriPermissionLocked(callingUid, targetPkg, data, - intent.getFlags()); + + return needed; } /** * Like grantUriPermissionUncheckedLocked, but takes an Intent. */ - void grantUriPermissionUncheckedFromIntentLocked(int targetUid, - String targetPkg, Intent intent, UriPermissionOwner owner) { - grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(), - intent.getFlags(), owner); + void grantUriPermissionUncheckedFromIntentLocked(NeededUriGrants needed, + UriPermissionOwner owner) { + if (needed != null) { + for (int i=0; i<needed.size(); i++) { + grantUriPermissionUncheckedLocked(needed.targetUid, needed.targetPkg, + needed.get(i), needed.flags, owner); + } + } } void grantUriPermissionFromIntentLocked(int callingUid, String targetPkg, Intent intent, UriPermissionOwner owner) { - int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent); - if (targetUid < 0) { + NeededUriGrants needed = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, + intent, intent.getFlags(), null); + if (needed == null) { return; } - grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner); + grantUriPermissionUncheckedFromIntentLocked(needed, owner); } public void grantUriPermission(IApplicationThread caller, String targetPkg, @@ -5406,7 +5460,7 @@ public final class ActivityManagerService extends ActivityManagerNative stopServiceLocked(sr); } else { sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true, - sr.makeNextStartId(), baseIntent, -1)); + sr.makeNextStartId(), baseIntent, null)); if (sr.app != null && sr.app.thread != null) { sendServiceArgsLocked(sr, false); } @@ -9044,7 +9098,7 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=0; i<N; i++) { sb.setLength(0); sb.append(" Intent: "); - intents.get(i).toShortString(sb, false, true, false); + intents.get(i).toShortString(sb, false, true, false, false); pw.println(sb.toString()); Bundle bundle = intents.get(i).getExtras(); if (bundle != null) { @@ -9129,7 +9183,7 @@ public final class ActivityManagerService extends ActivityManagerNative ConnectionRecord conn = clist.get(i); pw.print(" "); pw.print(conn.binding.intent.intent.getIntent() - .toShortString(false, false, false)); + .toShortString(false, false, false, false)); pw.print(" -> "); ProcessRecord proc = conn.binding.client; pw.println(proc != null ? proc.toShortString() : "null"); @@ -9380,7 +9434,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Complete + brief == give a summary. Isn't that obvious?!? if (lastTask.intent != null) { pw.print(prefix); pw.print(" "); - pw.println(lastTask.intent.toInsecureString()); + pw.println(lastTask.intent.toInsecureStringWithClip()); } } } @@ -10692,9 +10746,9 @@ public final class ActivityManagerService extends ActivityManagerNative si.deliveredTime = SystemClock.uptimeMillis(); r.deliveredStarts.add(si); si.deliveryCount++; - if (si.targetPermissionUid >= 0 && si.intent != null) { - grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid, - r.packageName, si.intent, si.getUriPermissionsLocked()); + if (si.neededGrants != null) { + grantUriPermissionUncheckedFromIntentLocked(si.neededGrants, + si.getUriPermissionsLocked()); } bumpServiceExecutingLocked(r, "start"); if (!oomAdjusted) { @@ -10772,7 +10826,7 @@ public final class ActivityManagerService extends ActivityManagerNative boolean created = false; try { mStringBuilder.setLength(0); - r.intent.getIntent().toShortString(mStringBuilder, true, false, true); + r.intent.getIntent().toShortString(mStringBuilder, true, false, true, false); EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE, System.identityHashCode(r), r.shortName, mStringBuilder.toString(), r.app.pid); @@ -10798,7 +10852,7 @@ public final class ActivityManagerService extends ActivityManagerNative // be called. if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) { r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), - null, -1)); + null, null)); } sendServiceArgsLocked(r, true); @@ -11170,15 +11224,15 @@ public final class ActivityManagerService extends ActivityManagerNative ? res.permission : "private to package"); } ServiceRecord r = res.record; - int targetPermissionUid = checkGrantUriPermissionFromIntentLocked( - callingUid, r.packageName, service); + NeededUriGrants neededGrants = checkGrantUriPermissionFromIntentLocked( + callingUid, r.packageName, service, service.getFlags(), null); if (unscheduleServiceRestartLocked(r)) { if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r); } r.startRequested = true; r.callStart = false; r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), - service, targetPermissionUid)); + service, neededGrants)); r.lastActivity = SystemClock.uptimeMillis(); synchronized (r.stats.getBatteryStats()) { r.stats.startRunningLocked(); diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index cdab6c6f67b3..a337b400288a 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -127,26 +127,27 @@ final class ActivityRecord { pw.print(prefix); pw.print("packageName="); pw.print(packageName); pw.print(" processName="); pw.println(processName); pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid); - pw.print(prefix); pw.print("userId="); pw.print(userId); - pw.print(" app="); pw.println(app); - pw.print(prefix); pw.println(intent.toInsecureString()); + pw.print(" userId="); pw.println(userId); + pw.print(prefix); pw.print("app="); pw.println(app); + pw.print(prefix); pw.println(intent.toInsecureStringWithClip()); pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask); pw.print(" task="); pw.println(task); pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity); pw.print(prefix); pw.print("realActivity="); pw.println(realActivity.flattenToShortString()); - pw.print(prefix); pw.print("base="); pw.print(baseDir); - if (!resDir.equals(baseDir)) pw.print(" res="); pw.print(resDir); - pw.print(" data="); pw.println(dataDir); - pw.print(prefix); pw.print("labelRes=0x"); - pw.print(Integer.toHexString(labelRes)); - pw.print(" icon=0x"); pw.print(Integer.toHexString(icon)); - pw.print(" theme=0x"); pw.println(Integer.toHexString(theme)); + pw.print(prefix); pw.print("baseDir="); pw.println(baseDir); + if (!resDir.equals(baseDir)) { + pw.print(prefix); pw.print("resDir="); pw.println(resDir); + } + pw.print(prefix); pw.print("dataDir="); pw.println(dataDir); pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded); pw.print(" componentSpecified="); pw.print(componentSpecified); pw.print(" isHomeActivity="); pw.println(isHomeActivity); + pw.print(prefix); pw.print("compat="); pw.print(compat); + pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes)); + pw.print(" icon=0x"); pw.print(Integer.toHexString(icon)); + pw.print(" theme=0x"); pw.println(Integer.toHexString(theme)); pw.print(prefix); pw.print("config="); pw.println(configuration); - pw.print(prefix); pw.print("compat="); pw.println(compat); if (resultTo != null || resultWho != null) { pw.print(prefix); pw.print("resultTo="); pw.print(resultTo); pw.print(" resultWho="); pw.print(resultWho); @@ -193,13 +194,11 @@ final class ActivityRecord { TimeUtils.formatDuration(launchTime, pw); pw.print(" startTime="); TimeUtils.formatDuration(startTime, pw); pw.println(""); } - if (lastVisibleTime != 0) { - pw.print(prefix); pw.print("lastVisibleTime="); - TimeUtils.formatDuration(lastVisibleTime, pw); pw.println(""); - } - if (waitingVisible || nowVisible) { + if (lastVisibleTime != 0 || waitingVisible || nowVisible) { pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible); - pw.print(" nowVisible="); pw.println(nowVisible); + pw.print(" nowVisible="); pw.print(nowVisible); + pw.print("lastVisibleTime="); + TimeUtils.formatDuration(lastVisibleTime, pw); pw.println(""); } if (configDestroy || configChangeFlags != 0) { pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy); diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index f9641eb564f4..19fe1bfba801 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -2290,8 +2290,8 @@ final class ActivityStack { } if (err == START_SUCCESS) { - Slog.i(TAG, "START {" + intent.toShortString(true, true, true) + "} from pid " - + (callerApp != null ? callerApp.pid : callingPid)); + Slog.i(TAG, "START {" + intent.toShortString(true, true, true, false) + + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)); } ActivityRecord sourceRecord = null; diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java index 2618c77e2b2d..c94f714fdbaa 100644 --- a/services/java/com/android/server/am/IntentBindRecord.java +++ b/services/java/com/android/server/am/IntentBindRecord.java @@ -54,7 +54,7 @@ class IntentBindRecord { void dumpInService(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("intent={"); - pw.print(intent.getIntent().toShortString(false, true, false)); + pw.print(intent.getIntent().toShortString(false, true, false, false)); pw.println('}'); pw.print(prefix); pw.print("binder="); pw.println(binder); pw.print(prefix); pw.print("requested="); pw.print(requested); @@ -89,7 +89,7 @@ class IntentBindRecord { sb.append(service.shortName); sb.append(':'); if (intent != null) { - intent.getIntent().toShortString(sb, false, false, false); + intent.getIntent().toShortString(sb, false, false, false, false); } sb.append('}'); return stringName = sb.toString(); diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java index 3b6a97c41ecc..0043874e18e6 100644 --- a/services/java/com/android/server/am/PendingIntentRecord.java +++ b/services/java/com/android/server/am/PendingIntentRecord.java @@ -152,7 +152,7 @@ class PendingIntentRecord extends IIntentSender.Stub { return "Key{" + typeName() + " pkg=" + packageName + " intent=" + (requestIntent != null - ? requestIntent.toShortString(false, true, false) : "<null>") + ? requestIntent.toShortString(false, true, false, false) : "<null>") + " flags=0x" + Integer.toHexString(flags) + "}"; } @@ -320,7 +320,7 @@ class PendingIntentRecord extends IIntentSender.Stub { } if (key.requestIntent != null) { pw.print(prefix); pw.print("requestIntent="); - pw.println(key.requestIntent.toShortString(false, true, true)); + pw.println(key.requestIntent.toShortString(false, true, true, true)); } if (sent || canceled) { pw.print(prefix); pw.print("sent="); pw.print(sent); diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java index daa3653d0bc2..828eef767f44 100644 --- a/services/java/com/android/server/am/ServiceRecord.java +++ b/services/java/com/android/server/am/ServiceRecord.java @@ -106,7 +106,7 @@ class ServiceRecord extends Binder { final boolean taskRemoved; final int id; final Intent intent; - final int targetPermissionUid; + final ActivityManagerService.NeededUriGrants neededGrants; long deliveredTime; int deliveryCount; int doneExecutingCount; @@ -115,12 +115,12 @@ class ServiceRecord extends Binder { String stringName; // caching of toString StartItem(ServiceRecord _sr, boolean _taskRemoved, int _id, Intent _intent, - int _targetPermissionUid) { + ActivityManagerService.NeededUriGrants _neededGrants) { sr = _sr; taskRemoved = _taskRemoved; id = _id; intent = _intent; - targetPermissionUid = _targetPermissionUid; + neededGrants = _neededGrants; } UriPermissionOwner getUriPermissionsLocked() { @@ -177,9 +177,9 @@ class ServiceRecord extends Binder { pw.print(prefix); pw.print(" intent="); if (si.intent != null) pw.println(si.intent.toString()); else pw.println("null"); - if (si.targetPermissionUid >= 0) { - pw.print(prefix); pw.print(" targetPermissionUid="); - pw.println(si.targetPermissionUid); + if (si.neededGrants != null) { + pw.print(prefix); pw.print(" neededGrants="); + pw.println(si.neededGrants); } if (si.uriPermissions != null) { if (si.uriPermissions.readUriPermissions != null) { @@ -196,7 +196,7 @@ class ServiceRecord extends Binder { void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("intent={"); - pw.print(intent.getIntent().toShortString(false, true, false)); + pw.print(intent.getIntent().toShortString(false, true, false, true)); pw.println('}'); pw.print(prefix); pw.print("packageName="); pw.println(packageName); pw.print(prefix); pw.print("processName="); pw.println(processName); diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java index 47ec21805638..67873ccefdcb 100644 --- a/services/java/com/android/server/am/TaskRecord.java +++ b/services/java/com/android/server/am/TaskRecord.java @@ -111,14 +111,14 @@ class TaskRecord extends ThumbnailHolder { if (intent != null) { StringBuilder sb = new StringBuilder(128); sb.append(prefix); sb.append("intent={"); - intent.toShortString(sb, false, true, false); + intent.toShortString(sb, false, true, false, true); sb.append('}'); pw.println(sb.toString()); } if (affinityIntent != null) { StringBuilder sb = new StringBuilder(128); sb.append(prefix); sb.append("affinityIntent={"); - affinityIntent.toShortString(sb, false, true, false); + affinityIntent.toShortString(sb, false, true, false, true); sb.append('}'); pw.println(sb.toString()); } |