diff options
| -rw-r--r-- | Android.mk | 2 | ||||
| -rw-r--r-- | api/current.txt | 10 | ||||
| -rw-r--r-- | api/system-current.txt | 10 | ||||
| -rw-r--r-- | api/test-current.txt | 10 | ||||
| -rw-r--r-- | core/java/android/content/ClipData.java | 22 | ||||
| -rw-r--r-- | core/java/android/view/DragEvent.java | 43 | ||||
| -rw-r--r-- | core/java/android/view/DropPermissionHolder.java | 161 | ||||
| -rw-r--r-- | core/java/android/view/DropPermissions.java | 66 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 8 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/IDropPermissions.aidl (renamed from core/java/com/android/internal/view/IDropPermissionHolder.aidl) | 6 | ||||
| -rw-r--r-- | services/core/java/com/android/server/job/JobStore.java | 21 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/DragState.java | 11 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/DropPermissionsHandler.java | 86 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 8 |
14 files changed, 249 insertions, 215 deletions
diff --git a/Android.mk b/Android.mk index 137ef85dc594..a098379899e1 100644 --- a/Android.mk +++ b/Android.mk @@ -308,7 +308,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/IDropPermissions.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 622a8b7b203b..ec38436deb3d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -39298,11 +39298,11 @@ 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(); method public float getY(); + method public android.view.DropPermissions requestDropPermissions(); method public void writeToParcel(android.os.Parcel, int); field public static final int ACTION_DRAG_ENDED = 4; // 0x4 field public static final int ACTION_DRAG_ENTERED = 5; // 0x5 @@ -39313,12 +39313,8 @@ 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 final class DropPermissions { + method public void release(); } public class FocusFinder { diff --git a/api/system-current.txt b/api/system-current.txt index e51b7d58ac7b..297efc29da0e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -41650,11 +41650,11 @@ 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(); method public float getY(); + method public android.view.DropPermissions requestDropPermissions(); method public void writeToParcel(android.os.Parcel, int); field public static final int ACTION_DRAG_ENDED = 4; // 0x4 field public static final int ACTION_DRAG_ENTERED = 5; // 0x5 @@ -41665,12 +41665,8 @@ 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 final class DropPermissions { + method public void release(); } public class FocusFinder { diff --git a/api/test-current.txt b/api/test-current.txt index 2377a9b87939..7cc7cb6bb370 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -39300,11 +39300,11 @@ 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(); method public float getY(); + method public android.view.DropPermissions requestDropPermissions(); method public void writeToParcel(android.os.Parcel, int); field public static final int ACTION_DRAG_ENDED = 4; // 0x4 field public static final int ACTION_DRAG_ENTERED = 5; // 0x5 @@ -39315,12 +39315,8 @@ 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 final class DropPermissions { + method public void release(); } public class FocusFinder { diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java index c934e8dfec0a..0b80f8a9fc18 100644 --- a/core/java/android/content/ClipData.java +++ b/core/java/android/content/ClipData.java @@ -36,6 +36,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.List; /** * Representation of a clipped data on the clipboard. @@ -914,6 +915,27 @@ public class ClipData implements Parcelable { } } + /** @hide */ + public void collectUris(List<Uri> out) { + for (int i = 0; i < mItems.size(); ++i) { + ClipData.Item item = getItemAt(i); + + if (item.getUri() != null) { + out.add(item.getUri()); + } + + Intent intent = item.getIntent(); + if (intent != null) { + if (intent.getData() != null) { + out.add(intent.getData()); + } + if (intent.getClipData() != null) { + intent.getClipData().collectUris(out); + } + } + } + } + @Override public int describeContents() { return 0; diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java index 34835f4a8070..5903d4a7c444 100644 --- a/core/java/android/view/DragEvent.java +++ b/core/java/android/view/DragEvent.java @@ -21,6 +21,8 @@ import android.content.ClipDescription; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.view.IDropPermissions; + //TODO: Improve Javadoc /** * Represents an event that is sent out by the system at various times during a drag and drop @@ -128,7 +130,7 @@ public class DragEvent implements Parcelable { float mX, mY; ClipDescription mClipDescription; ClipData mClipData; - DropPermissionHolder mDropPermissionHolder; + IDropPermissions mDropPermissions; Object mLocalState; boolean mDragResult; @@ -146,7 +148,7 @@ public class DragEvent implements Parcelable { * Action constant returned by {@link #getAction()}: Signals the start of a * drag and drop operation. The View should return {@code true} from its * {@link View#onDragEvent(DragEvent) onDragEvent()} handler method or - * {@link View.View.OnDragListener#onDrag(View,DragEvent) OnDragListener.onDrag()} listener + * {@link View.OnDragListener#onDrag(View,DragEvent) OnDragListener.onDrag()} listener * if it can accept a drop. The onDragEvent() or onDrag() methods usually inspect the metadata * from {@link #getClipDescription()} to determine if they can accept the data contained in * this drag. For an operation that doesn't represent data transfer, these methods may @@ -190,7 +192,7 @@ public class DragEvent implements Parcelable { * within the View object's bounding box. * <p> * The View should return {@code true} from its {@link View#onDragEvent(DragEvent)} - * handler or {@link View.View.OnDragListener#onDrag(View,DragEvent) OnDragListener.onDrag()} + * handler or {@link View.OnDragListener#onDrag(View,DragEvent) OnDragListener.onDrag()} * listener if it accepted the drop, and {@code false} if it ignored the drop. * </p> * <p> @@ -255,13 +257,13 @@ public class DragEvent implements Parcelable { } private void init(int action, float x, float y, ClipDescription description, ClipData data, - DropPermissionHolder dropPermissionHolder, Object localState, boolean result) { + IDropPermissions dropPermissions, Object localState, boolean result) { mAction = action; mX = x; mY = y; mClipDescription = description; mClipData = data; - mDropPermissionHolder = dropPermissionHolder; + mDropPermissions = dropPermissions; mLocalState = localState; mDragResult = result; } @@ -272,13 +274,13 @@ public class DragEvent implements Parcelable { /** @hide */ public static DragEvent obtain(int action, float x, float y, Object localState, - ClipDescription description, ClipData data, DropPermissionHolder dropPermissionHolder, + ClipDescription description, ClipData data, IDropPermissions dropPermissions, boolean result) { final DragEvent ev; synchronized (gRecyclerLock) { if (gRecyclerTop == null) { ev = new DragEvent(); - ev.init(action, x, y, description, data, dropPermissionHolder, localState, result); + ev.init(action, x, y, description, data, dropPermissions, localState, result); return ev; } ev = gRecyclerTop; @@ -289,7 +291,7 @@ public class DragEvent implements Parcelable { ev.mRecycled = false; ev.mNext = null; - ev.init(action, x, y, description, data, dropPermissionHolder, localState, result); + ev.init(action, x, y, description, data, dropPermissions, localState, result); return ev; } @@ -297,7 +299,7 @@ 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.mDropPermissionHolder, + source.mClipDescription, source.mClipData, source.mDropPermissions, source.mDragResult); } @@ -363,14 +365,19 @@ 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. + * Requests the permissions for the content URIs contained in {@link android.content.ClipData} + * object associated with this event. Which permissions will be granted is defined by the set of + * flags passed to {@link View#startDragAndDrop(ClipData, View.DragShadowBuilder, Object, int)}. + * Returns the {@link DropPermissions} object that can be used by the receiving app to release + * the permissions for the content URIs when they are no longer needed. * This method only returns valid data if the event action is {@link #ACTION_DROP}. - * @return The DropPermissionHolder object used to handle content URI permissions. + * @return The DropPermissions object used to control access to the content URIs. */ - public DropPermissionHolder getDropPermissionHolder() { - return mDropPermissionHolder; + public DropPermissions requestDropPermissions() { + if (mDropPermissions == null) { + return null; + } + return new DropPermissions(mDropPermissions); } /** @@ -493,11 +500,11 @@ public class DragEvent implements Parcelable { dest.writeInt(1); mClipDescription.writeToParcel(dest, flags); } - if (mDropPermissionHolder == null) { + if (mDropPermissions == null) { dest.writeInt(0); } else { dest.writeInt(1); - mDropPermissionHolder.writeToParcel(dest, flags); + dest.writeStrongBinder(mDropPermissions.asBinder()); } } @@ -519,7 +526,7 @@ public class DragEvent implements Parcelable { event.mClipDescription = ClipDescription.CREATOR.createFromParcel(in); } if (in.readInt() != 0) { - event.mDropPermissionHolder = DropPermissionHolder.CREATOR.createFromParcel(in); + event.mDropPermissions = IDropPermissions.Stub.asInterface(in.readStrongBinder());; } return event; } diff --git a/core/java/android/view/DropPermissionHolder.java b/core/java/android/view/DropPermissionHolder.java deleted file mode 100644 index 993e67a2578e..000000000000 --- a/core/java/android/view/DropPermissionHolder.java +++ /dev/null @@ -1,161 +0,0 @@ -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/DropPermissions.java b/core/java/android/view/DropPermissions.java new file mode 100644 index 000000000000..780461fe69a3 --- /dev/null +++ b/core/java/android/view/DropPermissions.java @@ -0,0 +1,66 @@ +/* +** 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 android.view; + +import android.os.RemoteException; +import com.android.internal.view.IDropPermissions; +import dalvik.system.CloseGuard; + + +public final class DropPermissions { + + private final IDropPermissions mDropPermissions; + + private final CloseGuard mCloseGuard = CloseGuard.get(); + + /** + * Create a new DropPermissions object to be passed to the client with a DragEvent. + * + * @hide + */ + DropPermissions(IDropPermissions dropPermissions) { + mDropPermissions = dropPermissions; + try { + mDropPermissions.take(); + } catch (RemoteException e) { + } + mCloseGuard.open("release"); + } + + /** + * Revoke permissions taken by {@link DragEvent#requestDropPermissions()}. + */ + public void release() { + try { + mDropPermissions.release(); + } catch (RemoteException e) { + } + mCloseGuard.close(); + } + + @Override + protected void finalize() throws Throwable { + try { + if (mCloseGuard != null) { + mCloseGuard.warnIfOpen(); + } + release(); + } finally { + super.finalize(); + } + } +} diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 17c803f76cbb..ae360fc36f68 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -5957,6 +5957,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public PointerIcon getPointerIcon(MotionEvent event, float x, float y) { + if (mText instanceof Spannable && mLinksClickable) { + final int offset = getOffsetForPosition(x, y); + final ClickableSpan[] clickables = ((Spannable) mText).getSpans(offset, offset, + ClickableSpan.class); + if (clickables.length > 0) { + return PointerIcon.getSystemIcon(mContext, PointerIcon.STYLE_HAND); + } + } if (isTextSelectable() || isTextEditable()) { return PointerIcon.getSystemIcon(mContext, PointerIcon.STYLE_TEXT); } diff --git a/core/java/com/android/internal/view/IDropPermissionHolder.aidl b/core/java/com/android/internal/view/IDropPermissions.aidl index e60ab0e516e5..86d27e7c6f1f 100644 --- a/core/java/com/android/internal/view/IDropPermissionHolder.aidl +++ b/core/java/com/android/internal/view/IDropPermissions.aidl @@ -20,7 +20,7 @@ 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(); +interface IDropPermissions { + void take(); + void release(); } diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index d9f94d0714ae..472e8f6ff06c 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -46,6 +46,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Set; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -348,9 +349,27 @@ public class JobStore { private void writeBundleToXml(PersistableBundle extras, XmlSerializer out) throws IOException, XmlPullParserException { out.startTag(null, XML_TAG_EXTRAS); - extras.saveToXml(out); + PersistableBundle extrasCopy = deepCopyBundle(extras, 10); + extrasCopy.saveToXml(out); out.endTag(null, XML_TAG_EXTRAS); } + + private PersistableBundle deepCopyBundle(PersistableBundle bundle, int maxDepth) { + if (maxDepth <= 0) { + return null; + } + PersistableBundle copy = (PersistableBundle) bundle.clone(); + Set<String> keySet = bundle.keySet(); + for (String key: keySet) { + PersistableBundle b = copy.getPersistableBundle(key); + if (b != null) { + PersistableBundle bCopy = deepCopyBundle(b, maxDepth-1); + copy.putPersistableBundle(key, bCopy); + } + } + return copy; + } + /** * Write out a tag with data identifying this job's constraints. If the constraint isn't here * it doesn't apply. diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index da894818519a..7b0a8d7c5d0c 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -35,7 +35,6 @@ 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; @@ -54,6 +53,8 @@ import com.android.server.input.InputWindowHandle; import com.android.server.wm.WindowManagerService.DragInputEventReceiver; import com.android.server.wm.WindowManagerService.H; +import com.android.internal.view.IDropPermissions; + import java.util.ArrayList; /** @@ -428,7 +429,7 @@ class DragState { // 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(WindowState touchedWin, DropPermissionHolder dropPermissionHolder, + boolean notifyDropLw(WindowState touchedWin, IDropPermissions dropPermissions, float x, float y) { if (mAnimation != null) { return false; @@ -449,7 +450,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, dropPermissionHolder, false); + null, null, mData, dropPermissions, false); try { touchedWin.mClient.dispatchDragEvent(evt); @@ -516,7 +517,7 @@ class DragState { private static DragEvent obtainDragEvent(WindowState win, int action, float x, float y, Object localState, ClipDescription description, ClipData data, - DropPermissionHolder dropPermissionHolder, + IDropPermissions dropPermissions, boolean result) { float winX = x - win.mFrame.left; float winY = y - win.mFrame.top; @@ -525,7 +526,7 @@ class DragState { winY *= win.mGlobalScale; } return DragEvent.obtain(action, winX, winY, localState, description, data, - dropPermissionHolder, result); + dropPermissions, result); } boolean stepAnimationLocked(long currentTimeMs) { diff --git a/services/core/java/com/android/server/wm/DropPermissionsHandler.java b/services/core/java/com/android/server/wm/DropPermissionsHandler.java new file mode 100644 index 000000000000..2ac1ef4124b5 --- /dev/null +++ b/services/core/java/com/android/server/wm/DropPermissionsHandler.java @@ -0,0 +1,86 @@ +/* +** 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.server.wm; + +import android.app.ActivityManagerNative; +import android.content.ClipData; +import android.net.Uri; +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteException; + +import com.android.internal.view.IDropPermissions; + +import java.util.ArrayList; + +class DropPermissionsHandler extends IDropPermissions.Stub { + + private final int mSourceUid; + private final String mTargetPackage; + private final int mMode; + private final int mSourceUserId; + private final int mTargetUserId; + + private final ArrayList<Uri> mUris = new ArrayList<Uri>(); + + private IBinder mPermissionOwner = null; + + DropPermissionsHandler(ClipData clipData, int sourceUid, String targetPackage, int mode, + int sourceUserId, int targetUserId) { + mSourceUid = sourceUid; + mTargetPackage = targetPackage; + mMode = mode; + mSourceUserId = sourceUserId; + mTargetUserId = targetUserId; + + clipData.collectUris(mUris); + } + + @Override + public void take() throws RemoteException { + if (mPermissionOwner != null) { + return; + } + + mPermissionOwner = ActivityManagerNative.getDefault().newUriPermissionOwner("drop"); + + long origId = Binder.clearCallingIdentity(); + try { + for (int i = 0; i < mUris.size(); i++) { + ActivityManagerNative.getDefault().grantUriPermissionFromOwner( + mPermissionOwner, mSourceUid, mTargetPackage, mUris.get(i), mMode, + mSourceUserId, mTargetUserId); + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void release() throws RemoteException { + if (mPermissionOwner == null) { + return; + } + + for (int i = 0; i < mUris.size(); ++i) { + ActivityManagerNative.getDefault().revokeUriPermissionFromOwner( + mPermissionOwner, mUris.get(i), mMode, mSourceUserId); + } + + mPermissionOwner = null; + } +} diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 456c416be361..4ea0cf55ec27 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -153,7 +153,6 @@ 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.IAppTransitionAnimationSpecsFuture; import android.view.IApplicationToken; @@ -758,13 +757,12 @@ public class WindowManagerService extends IWindowManager.Stub private boolean completeDropLw(float x, float y) { WindowState dropTargetWin = mDragState.getDropTargetWinLw(x, y); - DropPermissionHolder dropPermissionHolder = null; + DropPermissionsHandler dropPermissions = null; if (dropTargetWin != null && (mDragState.mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mDragState.mFlags & DRAG_FLAGS_URI_ACCESS) != 0) { - dropPermissionHolder = new DropPermissionHolder( + dropPermissions = new DropPermissionsHandler( mDragState.mData, - mActivityManager, mDragState.mUid, dropTargetWin.getOwningPackage(), mDragState.mFlags & DRAG_FLAGS_URI_PERMISSIONS, @@ -772,7 +770,7 @@ public class WindowManagerService extends IWindowManager.Stub UserHandle.getUserId(dropTargetWin.getOwningUid())); } - return mDragState.notifyDropLw(dropTargetWin, dropPermissionHolder, x, y); + return mDragState.notifyDropLw(dropTargetWin, dropPermissions, x, y); } /** |