Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ede5f548 authored by Vladislav Kaznacheev's avatar Vladislav Kaznacheev
Browse files

Handle content URI permissions on drop

Change-Id: I846071f01ecd1eff8e3a54a1806e68e1a4b335d2
parent 4dc0c15a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 \
+14 −0
Original line number Diff line number Diff line
@@ -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
+14 −0
Original line number Diff line number Diff line
@@ -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
+31 −6
Original line number Diff line number Diff line
@@ -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);
    }

    /**
@@ -357,6 +362,17 @@ public class DragEvent implements Parcelable {
        return mClipDescription;
    }

    /**
     * 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()}.
@@ -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;
        }

+161 −0
Original line number Diff line number Diff line
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];
        }
    };
}
Loading