1 /*
2 ** Copyright 2015, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 **     http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16 
17 package android.view;
18 
19 import android.app.Activity;
20 import android.os.Binder;
21 import android.os.IBinder;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.os.RemoteException;
25 
26 import com.android.internal.view.IDragAndDropPermissions;
27 
28 /**
29  * {@link DragAndDropPermissions} controls the access permissions for the content URIs associated
30  * with a {@link DragEvent}.
31  * <p>
32  * Permission are granted when this object is created by {@link
33  * android.app.Activity#requestDragAndDropPermissions(DragEvent)
34  * Activity.requestDragAndDropPermissions}.
35  * Which permissions are granted is defined by the set of flags passed to {@link
36  * View#startDragAndDrop(android.content.ClipData, View.DragShadowBuilder, Object, int)
37  * View.startDragAndDrop} by the app that started the drag operation.
38  * </p>
39  * <p>
40  * The life cycle of the permissions is bound to the activity used to call {@link
41  * android.app.Activity#requestDragAndDropPermissions(DragEvent) requestDragAndDropPermissions}. The
42  * permissions are revoked when this activity is destroyed, or when {@link #release()} is called,
43  * whichever occurs first.
44  * </p>
45  * <p>
46  * If you anticipate that your application will receive a large number of drops (e.g. document
47  * editor), you should try to call {@link #release()} on the obtained permissions as soon as they
48  * are no longer required. Permissions can be added to your activity's
49  * {@link Activity#onSaveInstanceState} bundle and later retrieved in order to manually release
50  * the permissions once they are no longer needed.
51  * </p>
52  */
53 public final class DragAndDropPermissions implements Parcelable {
54 
55     private final IDragAndDropPermissions mDragAndDropPermissions;
56 
57     private IBinder mTransientToken;
58 
59     /**
60      * Create a new {@link DragAndDropPermissions} object to control the access permissions for
61      * content URIs associated with {@link DragEvent}.
62      * @param dragEvent Drag event
63      * @return {@link DragAndDropPermissions} object or null if there are no content URIs associated
64      * with the {@link DragEvent}.
65      * @hide
66      */
obtain(DragEvent dragEvent)67     public static DragAndDropPermissions obtain(DragEvent dragEvent) {
68         if (dragEvent.getDragAndDropPermissions() == null) {
69             return null;
70         }
71         return new DragAndDropPermissions(dragEvent.getDragAndDropPermissions());
72     }
73 
74     /** @hide */
DragAndDropPermissions(IDragAndDropPermissions dragAndDropPermissions)75     private DragAndDropPermissions(IDragAndDropPermissions dragAndDropPermissions) {
76         mDragAndDropPermissions = dragAndDropPermissions;
77     }
78 
79     /**
80      * Take the permissions and bind their lifetime to the activity.
81      * @param activityToken Binder pointing to an Activity instance to bind the lifetime to.
82      * @return True if permissions are successfully taken.
83      * @hide
84      */
take(IBinder activityToken)85     public boolean take(IBinder activityToken) {
86         try {
87             mDragAndDropPermissions.take(activityToken);
88         } catch (RemoteException e) {
89             return false;
90         }
91         return true;
92     }
93 
94     /**
95      * Take the permissions. Must call {@link #release} explicitly.
96      * @return True if permissions are successfully taken.
97      * @hide
98      */
takeTransient()99     public boolean takeTransient() {
100         try {
101             mTransientToken = new Binder();
102             mDragAndDropPermissions.takeTransient(mTransientToken);
103         } catch (RemoteException e) {
104             return false;
105         }
106         return true;
107     }
108 
109     /**
110      * Revoke permissions explicitly.
111      */
release()112     public void release() {
113         try {
114             mDragAndDropPermissions.release();
115             mTransientToken = null;
116         } catch (RemoteException e) {
117         }
118     }
119 
120     public static final @android.annotation.NonNull Parcelable.Creator<DragAndDropPermissions> CREATOR =
121             new Parcelable.Creator<DragAndDropPermissions> () {
122         @Override
123         public DragAndDropPermissions createFromParcel(Parcel source) {
124             return new DragAndDropPermissions(source);
125         }
126 
127         @Override
128         public DragAndDropPermissions[] newArray(int size) {
129             return new DragAndDropPermissions[size];
130         }
131     };
132 
133     @Override
describeContents()134     public int describeContents() {
135         return 0;
136     }
137 
138     @Override
writeToParcel(Parcel destination, int flags)139     public void writeToParcel(Parcel destination, int flags) {
140         destination.writeStrongInterface(mDragAndDropPermissions);
141         destination.writeStrongBinder(mTransientToken);
142     }
143 
DragAndDropPermissions(Parcel in)144     private DragAndDropPermissions(Parcel in) {
145         mDragAndDropPermissions = IDragAndDropPermissions.Stub.asInterface(in.readStrongBinder());
146         mTransientToken = in.readStrongBinder();
147     }
148 }
149