/*
** 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.app.Activity;
import android.app.ActivityManagerNative;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import com.android.internal.view.IDragAndDropPermissions;
/**
* {@link DragAndDropPermissions} controls the access permissions for the content URIs associated
* with a {@link DragEvent}.
* <p>
* Permission are granted when this object is created by {@link
* android.app.Activity#requestDragAndDropPermissions(DragEvent)
* Activity.requestDragAndDropPermissions}.
* Which permissions are granted is defined by the set of flags passed to {@link
* View#startDragAndDrop(android.content.ClipData, View.DragShadowBuilder, Object, int)
* View.startDragAndDrop} by the app that started the drag operation.
* </p>
* <p>
* The life cycle of the permissions is bound to the activity used to call {@link
* android.app.Activity#requestDragAndDropPermissions(DragEvent) requestDragAndDropPermissions}. The
* permissions are revoked when this activity is destroyed, or when {@link #release()} is called,
* whichever occurs first.
* </p>
* <p>
* If you anticipate that your application will receive a large number of drops (e.g. document
* editor), you should try to call {@link #release()} on the obtained permissions as soon as they
* are no longer required. Permissions can be added to your activity's
* {@link Activity#onSaveInstanceState} bundle and later retrieved in order to manually release
* the permissions once they are no longer needed.
* </p>
*/
public final class DragAndDropPermissions implements Parcelable {
private final IDragAndDropPermissions mDragAndDropPermissions;
private IBinder mPermissionOwnerToken;
/**
* Create a new {@link DragAndDropPermissions} object to control the access permissions for
* content URIs associated with {@link DragEvent}.
* @param dragEvent Drag event
* @return {@link DragAndDropPermissions} object or null if there are no content URIs associated
* with the {@link DragEvent}.
* @hide
*/
public static DragAndDropPermissions obtain(DragEvent dragEvent) {
if (dragEvent.getDragAndDropPermissions() == null) {
return null;
}
return new DragAndDropPermissions(dragEvent.getDragAndDropPermissions());
}
/** @hide */
private DragAndDropPermissions(IDragAndDropPermissions dragAndDropPermissions) {
mDragAndDropPermissions = dragAndDropPermissions;
}
/**
* Take the permissions and bind their lifetime to the activity.
* @param activityToken Binder pointing to an Activity instance to bind the lifetime to.
* @return True if permissions are successfully taken.
* @hide
*/
public boolean take(IBinder activityToken) {
try {
mDragAndDropPermissions.take(activityToken);
} catch (RemoteException e) {
return false;
}
return true;
}
/**
* Take the permissions. Must call {@link #release} explicitly.
* @return True if permissions are successfully taken.
* @hide
*/
public boolean takeTransient() {
try {
mPermissionOwnerToken = ActivityManagerNative.getDefault().
newUriPermissionOwner("drop");
mDragAndDropPermissions.takeTransient(mPermissionOwnerToken);
} catch (RemoteException e) {
return false;
}
return true;
}
/**
* Revoke permissions explicitly.
*/
public void release() {
try {
mDragAndDropPermissions.release();
mPermissionOwnerToken = null;
} catch (RemoteException e) {
}
}
public static final Parcelable.Creator<DragAndDropPermissions> CREATOR =
new Parcelable.Creator<DragAndDropPermissions> () {
@Override
public DragAndDropPermissions createFromParcel(Parcel source) {
return new DragAndDropPermissions(source);
}
@Override
public DragAndDropPermissions[] newArray(int size) {
return new DragAndDropPermissions[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel destination, int flags) {
destination.writeStrongInterface(mDragAndDropPermissions);
destination.writeStrongBinder(mPermissionOwnerToken);
}
private DragAndDropPermissions(Parcel in) {
mDragAndDropPermissions = IDragAndDropPermissions.Stub.asInterface(in.readStrongBinder());
mPermissionOwnerToken = in.readStrongBinder();
}
}