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 static java.lang.Integer.toHexString; 20 21 import android.app.Activity; 22 import android.os.IBinder; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 import android.os.RemoteException; 26 import android.util.Log; 27 28 import com.android.internal.view.IDragAndDropPermissions; 29 30 /** 31 * {@link DragAndDropPermissions} controls the access permissions for the content URIs associated 32 * with a {@link DragEvent}. 33 * <p> 34 * Permission are granted when this object is created by {@link 35 * android.app.Activity#requestDragAndDropPermissions(DragEvent) 36 * Activity.requestDragAndDropPermissions}. 37 * Which permissions are granted is defined by the set of flags passed to {@link 38 * View#startDragAndDrop(android.content.ClipData, View.DragShadowBuilder, Object, int) 39 * View.startDragAndDrop} by the app that started the drag operation. 40 * </p> 41 * <p> 42 * The lifecycle of the permissions is bound to the activity used to call {@link 43 * android.app.Activity#requestDragAndDropPermissions(DragEvent) requestDragAndDropPermissions}. The 44 * permissions are revoked when this activity is destroyed, or when {@link #release()} is called, 45 * whichever occurs first. 46 * </p> 47 * <p> 48 * If you anticipate that your application will receive a large number of drops (e.g. document 49 * editor), you should try to call {@link #release()} on the obtained permissions as soon as they 50 * are no longer required. Permissions can be added to your activity's 51 * {@link Activity#onSaveInstanceState} bundle and later retrieved in order to manually release 52 * the permissions once they are no longer needed. 53 * </p> 54 * <p> 55 * Learn more about <a href="/guide/topics/ui/drag-drop#DragPermissionsMultiWindow">drag permissions 56 * in multi-window mode</a>. 57 * </p> 58 */ 59 public final class DragAndDropPermissions implements Parcelable { 60 61 private static final String TAG = "DragAndDrop"; 62 private static final boolean DEBUG = false; 63 64 private final IDragAndDropPermissions mDragAndDropPermissions; 65 66 /** 67 * Create a new {@link DragAndDropPermissions} object to control the access permissions for 68 * content URIs associated with {@link DragEvent}. 69 * @param dragEvent Drag event 70 * @return {@link DragAndDropPermissions} object or null if there are no content URIs associated 71 * with the {@link DragEvent}. 72 * @hide 73 */ obtain(DragEvent dragEvent)74 public static DragAndDropPermissions obtain(DragEvent dragEvent) { 75 if (dragEvent.getDragAndDropPermissions() == null) { 76 return null; 77 } 78 return new DragAndDropPermissions(dragEvent.getDragAndDropPermissions()); 79 } 80 81 /** @hide */ DragAndDropPermissions(IDragAndDropPermissions dragAndDropPermissions)82 private DragAndDropPermissions(IDragAndDropPermissions dragAndDropPermissions) { 83 mDragAndDropPermissions = dragAndDropPermissions; 84 } 85 86 /** 87 * Take permissions, binding their lifetime to the activity. 88 * 89 * <p>Note: This API is exposed to apps via 90 * {@link Activity#requestDragAndDropPermissions(DragEvent)}. 91 * 92 * @param activityToken Binder pointing to an Activity instance to bind the lifetime to. 93 * @return True if permissions are successfully taken. 94 * 95 * @hide 96 */ take(IBinder activityToken)97 public boolean take(IBinder activityToken) { 98 try { 99 if (DEBUG) { 100 Log.d(TAG, this + ": calling take() with activity-bound token: " 101 + toHexString(activityToken.hashCode())); 102 } 103 mDragAndDropPermissions.take(activityToken); 104 } catch (RemoteException e) { 105 Log.w(TAG, this + ": take() failed with a RemoteException", e); 106 return false; 107 } 108 return true; 109 } 110 111 /** 112 * Take permissions transiently. Permissions will be tied to this object's lifecycle; if not 113 * released explicitly, they will be released automatically when there are no more references 114 * to this object and it's garbage collected. 115 * 116 * <p>Note: This API is not exposed to apps. 117 * 118 * @return True if permissions are successfully taken. 119 * 120 * @hide 121 */ takeTransient()122 public boolean takeTransient() { 123 try { 124 if (DEBUG) { 125 Log.d(TAG, this + ": calling takeTransient()"); 126 } 127 mDragAndDropPermissions.takeTransient(); 128 } catch (RemoteException e) { 129 Log.w(TAG, this + ": takeTransient() failed with a RemoteException", e); 130 return false; 131 } 132 return true; 133 } 134 135 /** 136 * Revoke permissions explicitly. 137 */ release()138 public void release() { 139 try { 140 mDragAndDropPermissions.release(); 141 } catch (RemoteException e) { 142 throw e.rethrowFromSystemServer(); 143 } 144 } 145 146 public static final @android.annotation.NonNull Parcelable.Creator<DragAndDropPermissions> CREATOR = 147 new Parcelable.Creator<DragAndDropPermissions> () { 148 @Override 149 public DragAndDropPermissions createFromParcel(Parcel source) { 150 return new DragAndDropPermissions(source); 151 } 152 153 @Override 154 public DragAndDropPermissions[] newArray(int size) { 155 return new DragAndDropPermissions[size]; 156 } 157 }; 158 159 @Override describeContents()160 public int describeContents() { 161 return 0; 162 } 163 164 @Override writeToParcel(Parcel destination, int flags)165 public void writeToParcel(Parcel destination, int flags) { 166 destination.writeStrongInterface(mDragAndDropPermissions); 167 } 168 DragAndDropPermissions(Parcel in)169 private DragAndDropPermissions(Parcel in) { 170 mDragAndDropPermissions = IDragAndDropPermissions.Stub.asInterface(in.readStrongBinder()); 171 } 172 } 173