summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt14
-rw-r--r--api/system-current.txt14
-rw-r--r--core/java/android/view/DragEvent.java37
-rw-r--r--core/java/android/view/DropPermissionHolder.java161
-rw-r--r--core/java/android/view/View.java39
-rw-r--r--core/java/com/android/internal/view/IDropPermissionHolder.aidl26
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java3
-rw-r--r--services/core/java/com/android/server/wm/DragState.java29
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java31
10 files changed, 335 insertions, 20 deletions
diff --git a/Android.mk b/Android.mk
index d48887d17e3b..f1e16b841585 100644
--- a/Android.mk
+++ b/Android.mk
@@ -303,6 +303,7 @@ LOCAL_SRC_FILES += \
core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl \
core/java/com/android/internal/textservice/ITextServicesManager.aidl \
core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl \
+ core/java/com/android/internal/view/IDropPermissionHolder.aidl \
core/java/com/android/internal/view/IInputContext.aidl \
core/java/com/android/internal/view/IInputContextCallback.aidl \
core/java/com/android/internal/view/IInputMethod.aidl \
diff --git a/api/current.txt b/api/current.txt
index 7e6f445e6ff4..2a3b5e1207d3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -34802,6 +34802,7 @@ package android.view {
method public int getAction();
method public android.content.ClipData getClipData();
method public android.content.ClipDescription getClipDescription();
+ method public android.view.DropPermissionHolder getDropPermissionHolder();
method public java.lang.Object getLocalState();
method public boolean getResult();
method public float getX();
@@ -34816,6 +34817,14 @@ package android.view {
field public static final android.os.Parcelable.Creator<android.view.DragEvent> CREATOR;
}
+ public class DropPermissionHolder implements android.os.Parcelable {
+ method public int describeContents();
+ method public void grant();
+ method public void revoke();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.DropPermissionHolder> CREATOR;
+ }
+
public class FocusFinder {
method public android.view.View findNearestTouchable(android.view.ViewGroup, int, int, int, int[]);
method public final android.view.View findNextFocus(android.view.ViewGroup, android.view.View, int);
@@ -36519,6 +36528,11 @@ package android.view {
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+ field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
+ field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
+ field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
+ field public static final int DRAG_FLAG_GLOBAL_URI_READ = 1; // 0x1
+ field public static final int DRAG_FLAG_GLOBAL_URI_WRITE = 2; // 0x2
field public static final int DRAG_FLAG_OPAQUE = 512; // 0x200
field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
diff --git a/api/system-current.txt b/api/system-current.txt
index 0a2a5212532f..7c4ced000c14 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -37096,6 +37096,7 @@ package android.view {
method public int getAction();
method public android.content.ClipData getClipData();
method public android.content.ClipDescription getClipDescription();
+ method public android.view.DropPermissionHolder getDropPermissionHolder();
method public java.lang.Object getLocalState();
method public boolean getResult();
method public float getX();
@@ -37110,6 +37111,14 @@ package android.view {
field public static final android.os.Parcelable.Creator<android.view.DragEvent> CREATOR;
}
+ public class DropPermissionHolder implements android.os.Parcelable {
+ method public int describeContents();
+ method public void grant();
+ method public void revoke();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.DropPermissionHolder> CREATOR;
+ }
+
public class FocusFinder {
method public android.view.View findNearestTouchable(android.view.ViewGroup, int, int, int, int[]);
method public final android.view.View findNextFocus(android.view.ViewGroup, android.view.View, int);
@@ -38813,6 +38822,11 @@ package android.view {
field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
+ field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
+ field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
+ field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
+ field public static final int DRAG_FLAG_GLOBAL_URI_READ = 1; // 0x1
+ field public static final int DRAG_FLAG_GLOBAL_URI_WRITE = 2; // 0x2
field public static final int DRAG_FLAG_OPAQUE = 512; // 0x200
field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index f559e21f661e..34835f4a8070 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -128,6 +128,8 @@ public class DragEvent implements Parcelable {
float mX, mY;
ClipDescription mClipDescription;
ClipData mClipData;
+ DropPermissionHolder mDropPermissionHolder;
+
Object mLocalState;
boolean mDragResult;
@@ -253,28 +255,30 @@ public class DragEvent implements Parcelable {
}
private void init(int action, float x, float y, ClipDescription description, ClipData data,
- Object localState, boolean result) {
+ DropPermissionHolder dropPermissionHolder, Object localState, boolean result) {
mAction = action;
mX = x;
mY = y;
mClipDescription = description;
mClipData = data;
+ mDropPermissionHolder = dropPermissionHolder;
mLocalState = localState;
mDragResult = result;
}
static DragEvent obtain() {
- return DragEvent.obtain(0, 0f, 0f, null, null, null, false);
+ return DragEvent.obtain(0, 0f, 0f, null, null, null, null, false);
}
/** @hide */
public static DragEvent obtain(int action, float x, float y, Object localState,
- ClipDescription description, ClipData data, boolean result) {
+ ClipDescription description, ClipData data, DropPermissionHolder dropPermissionHolder,
+ boolean result) {
final DragEvent ev;
synchronized (gRecyclerLock) {
if (gRecyclerTop == null) {
ev = new DragEvent();
- ev.init(action, x, y, description, data, localState, result);
+ ev.init(action, x, y, description, data, dropPermissionHolder, localState, result);
return ev;
}
ev = gRecyclerTop;
@@ -285,7 +289,7 @@ public class DragEvent implements Parcelable {
ev.mRecycled = false;
ev.mNext = null;
- ev.init(action, x, y, description, data, localState, result);
+ ev.init(action, x, y, description, data, dropPermissionHolder, localState, result);
return ev;
}
@@ -293,7 +297,8 @@ public class DragEvent implements Parcelable {
/** @hide */
public static DragEvent obtain(DragEvent source) {
return obtain(source.mAction, source.mX, source.mY, source.mLocalState,
- source.mClipDescription, source.mClipData, source.mDragResult);
+ source.mClipDescription, source.mClipData, source.mDropPermissionHolder,
+ source.mDragResult);
}
/**
@@ -358,6 +363,17 @@ public class DragEvent implements Parcelable {
}
/**
+ * Returns the {@link android.view.DropPermissionHolder} object that can be used by the drag
+ * listener to request and release the permissions for the content URIs contained in the
+ * {@link android.content.ClipData} object associated with this event.
+ * This method only returns valid data if the event action is {@link #ACTION_DROP}.
+ * @return The DropPermissionHolder object used to handle content URI permissions.
+ */
+ public DropPermissionHolder getDropPermissionHolder() {
+ return mDropPermissionHolder;
+ }
+
+ /**
* Returns the local state object sent to the system as part of the call to
* {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
* The object is intended to provide local information about the drag and drop operation. For
@@ -477,6 +493,12 @@ public class DragEvent implements Parcelable {
dest.writeInt(1);
mClipDescription.writeToParcel(dest, flags);
}
+ if (mDropPermissionHolder == null) {
+ dest.writeInt(0);
+ } else {
+ dest.writeInt(1);
+ mDropPermissionHolder.writeToParcel(dest, flags);
+ }
}
/**
@@ -496,6 +518,9 @@ public class DragEvent implements Parcelable {
if (in.readInt() != 0) {
event.mClipDescription = ClipDescription.CREATOR.createFromParcel(in);
}
+ if (in.readInt() != 0) {
+ event.mDropPermissionHolder = DropPermissionHolder.CREATOR.createFromParcel(in);
+ }
return event;
}
diff --git a/core/java/android/view/DropPermissionHolder.java b/core/java/android/view/DropPermissionHolder.java
new file mode 100644
index 000000000000..993e67a2578e
--- /dev/null
+++ b/core/java/android/view/DropPermissionHolder.java
@@ -0,0 +1,161 @@
+package android.view;
+
+import android.app.IActivityManager;
+import android.content.ClipData;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import com.android.internal.view.IDropPermissionHolder;
+
+import java.util.ArrayList;
+
+public class DropPermissionHolder implements Parcelable {
+
+ IDropPermissionHolder mDropPermissionHolder;
+
+ /**
+ * Create a new DropPermissionHolder to be passed to the client with a DragEvent.
+ *
+ * @hide
+ */
+ public DropPermissionHolder(ClipData clipData, IActivityManager activityManager,
+ int sourceUid, String targetPackage, int mode, int sourceUserId, int targetUserId) {
+ mDropPermissionHolder = new LocalDropPermissionHolder(clipData, activityManager,
+ sourceUid, targetPackage, mode, sourceUserId, targetUserId);
+ }
+
+ private class LocalDropPermissionHolder extends IDropPermissionHolder.Stub {
+
+ private final IActivityManager mActivityManager;
+ private final int mSourceUid;
+ private final String mTargetPackage;
+ private final int mMode;
+ private final int mSourceUserId;
+ private final int mTargetUserId;
+
+ IBinder mPermissionOwner = null;
+
+ final private ArrayList<Uri> mUris = new ArrayList<Uri>();
+
+ LocalDropPermissionHolder(ClipData clipData, IActivityManager activityManager,
+ int sourceUid, String targetPackage, int mode, int sourceUserId, int targetUserId) {
+ mActivityManager = activityManager;
+ mSourceUid = sourceUid;
+ mTargetPackage = targetPackage;
+ mMode = mode;
+ mSourceUserId = sourceUserId;
+ mTargetUserId = targetUserId;
+
+ int N = clipData.getItemCount();
+ for (int i = 0; i != N; ++i) {
+ ClipData.Item item = clipData.getItemAt(i);
+
+ if (item.getUri() != null) {
+ mUris.add(item.getUri());
+ }
+
+ Intent intent = item.getIntent();
+ if (intent != null && intent.getData() != null) {
+ mUris.add(intent.getData());
+ }
+ }
+ }
+
+ @Override
+ public void grant() throws RemoteException {
+ if (mPermissionOwner != null) {
+ return;
+ }
+
+ mPermissionOwner = mActivityManager.newUriPermissionOwner("drop");
+
+ long origId = Binder.clearCallingIdentity();
+ try {
+ for (Uri mUri : mUris) {
+ mActivityManager.grantUriPermissionFromOwner(
+ mPermissionOwner, mSourceUid, mTargetPackage, mUri, mMode,
+ mSourceUserId, mTargetUserId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+
+ }
+
+ @Override
+ public void revoke() throws RemoteException {
+ if (mPermissionOwner == null) {
+ return;
+ }
+
+ for (Uri mUri : mUris) {
+ mActivityManager.revokeUriPermissionFromOwner(
+ mPermissionOwner, mUri, mMode, mSourceUserId);
+ }
+
+ mPermissionOwner = null;
+ }
+ }
+
+ /**
+ * Request permissions granted by the activity which started the drag.
+ */
+ public void grant() {
+ try {
+ mDropPermissionHolder.grant();
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Revoke permissions granted by the {@link #grant()} call.
+ */
+ public void revoke() {
+ try {
+ mDropPermissionHolder.revoke();
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Returns information about the {@link android.os.Parcel} representation of this
+ * DropPermissionHolder object.
+ * @return Information about the {@link android.os.Parcel} representation.
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Creates a {@link android.os.Parcel} object from this DropPermissionHolder object.
+ * @param dest A {@link android.os.Parcel} object in which to put the DropPermissionHolder
+ * object.
+ * @param flags Flags to store in the Parcel.
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeStrongBinder(mDropPermissionHolder.asBinder());
+ }
+
+ DropPermissionHolder(Parcel in) {
+ mDropPermissionHolder = IDropPermissionHolder.Stub.asInterface(in.readStrongBinder());
+ }
+
+ /**
+ * A container for creating a DropPermissionHolder from a Parcel.
+ */
+ public static final Parcelable.Creator<DropPermissionHolder> CREATOR
+ = new Parcelable.Creator<DropPermissionHolder>() {
+ public DropPermissionHolder createFromParcel(Parcel in) {
+ return new DropPermissionHolder(in);
+ }
+ public DropPermissionHolder[] newArray(int size) {
+ return new DropPermissionHolder[size];
+ }
+ };
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index eb591c1bfa86..b5d76c5ba0ba 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3641,9 +3641,44 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* with this flag set, all visible applications will be able to participate
* in the drag operation and receive the dragged content.
*
- * @hide
+ * If this is the only flag set, then the drag recipient will only have access to text data
+ * and intents contained in the {@link ClipData} object. Access to URIs contained in the
+ * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags.
+ */
+ public static final int DRAG_FLAG_GLOBAL = 1 << 8; // 256
+
+ /**
+ * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
+ * request read access to the content URI(s) contained in the {@link ClipData} object.
+ * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
+ */
+ public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
+
+ /**
+ * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
+ * request write access to the content URI(s) contained in the {@link ClipData} object.
+ * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ */
+ public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+
+ /**
+ * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
+ * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
+ * reboots until explicitly revoked with
+ * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
+ * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ */
+ public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
+ Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
+
+ /**
+ * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
+ * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
+ * match against the original granted URI.
+ * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
*/
- public static final int DRAG_FLAG_GLOBAL = 1;
+ public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
+ Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
/**
* Flag indicating that the drag shadow will be opaque. When
diff --git a/core/java/com/android/internal/view/IDropPermissionHolder.aidl b/core/java/com/android/internal/view/IDropPermissionHolder.aidl
new file mode 100644
index 000000000000..e60ab0e516e5
--- /dev/null
+++ b/core/java/com/android/internal/view/IDropPermissionHolder.aidl
@@ -0,0 +1,26 @@
+/*
+** Copyright 2015, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package com.android.internal.view;
+
+/**
+ * Interface to allow a drop receiver to request permissions for URIs passed along with ClipData
+ * contained in DragEvent.
+ */
+interface IDropPermissionHolder {
+ void grant();
+ void revoke();
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 046f3df3b5d4..3202876569e0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -1519,7 +1519,8 @@ public class DirectoryFragment extends Fragment {
getClipDataFromDocuments(docs),
new DrawableShadowBuilder(getDragShadowIcon(docs)),
null,
- View.DRAG_FLAG_GLOBAL
+ View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ |
+ View.DRAG_FLAG_GLOBAL_URI_WRITE
);
return true;
}
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 8f77176feb73..ddcf2a711d8b 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -27,6 +27,7 @@ import android.content.ClipDescription;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
+import android.os.Binder;
import android.os.IBinder;
import android.os.Message;
import android.os.Process;
@@ -34,6 +35,7 @@ import android.os.RemoteException;
import android.util.Slog;
import android.view.Display;
import android.view.DragEvent;
+import android.view.DropPermissionHolder;
import android.view.InputChannel;
import android.view.SurfaceControl;
import android.view.View;
@@ -50,6 +52,7 @@ class DragState {
SurfaceControl mSurfaceControl;
int mFlags;
IBinder mLocalWin;
+ int mUid;
ClipData mData;
ClipDescription mDataDescription;
boolean mDragResult;
@@ -74,6 +77,7 @@ class DragState {
mSurfaceControl = surface;
mFlags = flags;
mLocalWin = localWin;
+ mUid = Binder.getCallingUid();
mNotifiedWindows = new ArrayList<WindowState>();
}
@@ -225,7 +229,7 @@ class DragState {
if (mDragInProgress && newWin.isPotentialDragTarget()) {
DragEvent event = obtainDragEvent(newWin, DragEvent.ACTION_DRAG_STARTED,
- touchX, touchY, null, desc, null, false);
+ touchX, touchY, null, desc, null, null, false);
try {
newWin.mClient.dispatchDragEvent(event);
// track each window that we've notified that the drag is starting
@@ -265,7 +269,7 @@ class DragState {
Slog.d(WindowManagerService.TAG, "broadcasting DRAG_ENDED");
}
DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
- 0, 0, null, null, null, mDragResult);
+ 0, 0, null, null, null, null, mDragResult);
for (WindowState ws: mNotifiedWindows) {
try {
ws.mClient.dispatchDragEvent(evt);
@@ -331,7 +335,7 @@ class DragState {
}
// force DRAG_EXITED_EVENT if appropriate
DragEvent evt = obtainDragEvent(mTargetWindow, DragEvent.ACTION_DRAG_EXITED,
- x, y, null, null, null, false);
+ x, y, null, null, null, null, false);
mTargetWindow.mClient.dispatchDragEvent(evt);
if (myPid != mTargetWindow.mSession.mPid) {
evt.recycle();
@@ -342,7 +346,7 @@ class DragState {
Slog.d(WindowManagerService.TAG, "sending DRAG_LOCATION to " + touchedWin);
}
DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DRAG_LOCATION,
- x, y, null, null, null, false);
+ x, y, null, null, null, null, false);
touchedWin.mClient.dispatchDragEvent(evt);
if (myPid != touchedWin.mSession.mPid) {
evt.recycle();
@@ -354,11 +358,15 @@ class DragState {
mTargetWindow = touchedWin;
}
+ WindowState getDropTargetWinLw(float x, float y) {
+ return getTouchedWinAtPointLw(x, y);
+ }
+
// Tell the drop target about the data. Returns 'true' if we can immediately
// dispatch the global drag-ended message, 'false' if we need to wait for a
// result from the recipient.
- boolean notifyDropLw(float x, float y) {
- WindowState touchedWin = getTouchedWinAtPointLw(x, y);
+ boolean notifyDropLw(WindowState touchedWin, DropPermissionHolder dropPermissionHolder,
+ float x, float y) {
if (touchedWin == null) {
// "drop" outside a valid window -- no recipient to apply a
// timeout to, and we can send the drag-ended message immediately.
@@ -372,7 +380,7 @@ class DragState {
final int myPid = Process.myPid();
final IBinder token = touchedWin.mClient.asBinder();
DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DROP, x, y,
- null, null, mData, false);
+ null, null, mData, dropPermissionHolder, false);
try {
touchedWin.mClient.dispatchDragEvent(evt);
@@ -438,13 +446,16 @@ class DragState {
private static DragEvent obtainDragEvent(WindowState win, int action,
float x, float y, Object localState,
- ClipDescription description, ClipData data, boolean result) {
+ ClipDescription description, ClipData data,
+ DropPermissionHolder dropPermissionHolder,
+ boolean result) {
float winX = x - win.mFrame.left;
float winY = y - win.mFrame.top;
if (win.mEnforceSizeCompat) {
winX *= win.mGlobalScale;
winY *= win.mGlobalScale;
}
- return DragEvent.obtain(action, winX, winY, localState, description, data, result);
+ return DragEvent.obtain(action, winX, winY, localState, description, data,
+ dropPermissionHolder, result);
}
} \ No newline at end of file
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 554587d212f5..943e9ec0a32c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -107,6 +107,7 @@ import android.view.AppTransitionAnimationSpec;
import android.view.Choreographer;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.DropPermissionHolder;
import android.view.Gravity;
import android.view.IApplicationToken;
import android.view.IInputFilter;
@@ -626,6 +627,13 @@ public class WindowManagerService extends IWindowManager.Stub
private WindowContentFrameStats mTempWindowRenderStats;
+ private static final int DRAG_FLAGS_URI_ACCESS = View.DRAG_FLAG_GLOBAL_URI_READ |
+ View.DRAG_FLAG_GLOBAL_URI_WRITE;
+
+ private static final int DRAG_FLAGS_URI_PERMISSIONS = DRAG_FLAGS_URI_ACCESS |
+ View.DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION |
+ View.DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION;
+
final class DragInputEventReceiver extends InputEventReceiver {
// Set, if stylus button was down at the start of the drag.
private boolean mStylusButtonDownAtStart;
@@ -671,7 +679,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_DRAG) Slog.d(TAG, "Button no longer pressed; dropping at "
+ newX + "," + newY);
synchronized (mWindowMap) {
- endDrag = mDragState.notifyDropLw(newX, newY);
+ endDrag = completeDrop(newX, newY);
}
} else {
synchronized (mWindowMap) {
@@ -685,7 +693,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at "
+ newX + "," + newY);
synchronized (mWindowMap) {
- endDrag = mDragState.notifyDropLw(newX, newY);
+ endDrag = completeDrop(newX, newY);
}
} break;
@@ -715,6 +723,25 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ private boolean completeDrop(float x, float y) {
+ WindowState dropTargetWin = mDragState.getDropTargetWinLw(x, y);
+
+ DropPermissionHolder dropPermissionHolder = null;
+ if ((mDragState.mFlags & View.DRAG_FLAG_GLOBAL) != 0 &&
+ (mDragState.mFlags & DRAG_FLAGS_URI_ACCESS) != 0) {
+ dropPermissionHolder = new DropPermissionHolder(
+ mDragState.mData,
+ mActivityManager,
+ mDragState.mUid,
+ dropTargetWin.getOwningPackage(),
+ mDragState.mFlags & DRAG_FLAGS_URI_PERMISSIONS,
+ UserHandle.getUserId(mDragState.mUid),
+ UserHandle.getUserId(dropTargetWin.getOwningUid()));
+ }
+
+ return mDragState.notifyDropLw(dropTargetWin, dropPermissionHolder, x, y);
+ }
+
/**
* Whether the UI is currently running in touch mode (not showing
* navigational focus because the user is directly pressing the screen).