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 com.android.server.wm; 18 19 import android.app.ActivityManager; 20 import android.content.ClipData; 21 import android.net.Uri; 22 import android.os.Binder; 23 import android.os.IBinder; 24 import android.os.RemoteException; 25 26 import com.android.internal.view.IDragAndDropPermissions; 27 28 import java.util.ArrayList; 29 30 class DragAndDropPermissionsHandler extends IDragAndDropPermissions.Stub 31 implements IBinder.DeathRecipient { 32 33 private final int mSourceUid; 34 private final String mTargetPackage; 35 private final int mMode; 36 private final int mSourceUserId; 37 private final int mTargetUserId; 38 39 private final ArrayList<Uri> mUris = new ArrayList<Uri>(); 40 41 private IBinder mActivityToken = null; 42 private IBinder mPermissionOwnerToken = null; 43 private IBinder mTransientToken = null; 44 45 DragAndDropPermissionsHandler(ClipData clipData, int sourceUid, String targetPackage, int mode, 46 int sourceUserId, int targetUserId) { 47 mSourceUid = sourceUid; 48 mTargetPackage = targetPackage; 49 mMode = mode; 50 mSourceUserId = sourceUserId; 51 mTargetUserId = targetUserId; 52 53 clipData.collectUris(mUris); 54 } 55 56 @Override 57 public void take(IBinder activityToken) throws RemoteException { 58 if (mActivityToken != null || mPermissionOwnerToken != null) { 59 return; 60 } 61 mActivityToken = activityToken; 62 63 // Will throw if Activity is not found. 64 IBinder permissionOwner = ActivityManager.getService(). 65 getUriPermissionOwnerForActivity(mActivityToken); 66 67 doTake(permissionOwner); 68 } 69 70 private void doTake(IBinder permissionOwner) throws RemoteException { 71 long origId = Binder.clearCallingIdentity(); 72 try { 73 for (int i = 0; i < mUris.size(); i++) { 74 ActivityManager.getService().grantUriPermissionFromOwner( 75 permissionOwner, mSourceUid, mTargetPackage, mUris.get(i), mMode, 76 mSourceUserId, mTargetUserId); 77 } 78 } finally { 79 Binder.restoreCallingIdentity(origId); 80 } 81 } 82 83 @Override 84 public void takeTransient(IBinder transientToken) throws RemoteException { 85 if (mActivityToken != null || mPermissionOwnerToken != null) { 86 return; 87 } 88 mPermissionOwnerToken = ActivityManager.getService().newUriPermissionOwner("drop"); 89 mTransientToken = transientToken; 90 mTransientToken.linkToDeath(this, 0); 91 92 doTake(mPermissionOwnerToken); 93 } 94 95 @Override 96 public void release() throws RemoteException { 97 if (mActivityToken == null && mPermissionOwnerToken == null) { 98 return; 99 } 100 101 IBinder permissionOwner = null; 102 if (mActivityToken != null) { 103 try { 104 permissionOwner = ActivityManager.getService(). 105 getUriPermissionOwnerForActivity(mActivityToken); 106 } catch (Exception e) { 107 // Activity is destroyed, permissions already revoked. 108 return; 109 } finally { 110 mActivityToken = null; 111 } 112 } else { 113 permissionOwner = mPermissionOwnerToken; 114 mPermissionOwnerToken = null; 115 mTransientToken.unlinkToDeath(this, 0); 116 mTransientToken = null; 117 } 118 119 for (int i = 0; i < mUris.size(); ++i) { 120 ActivityManager.getService().revokeUriPermissionFromOwner( 121 permissionOwner, mUris.get(i), mMode, mSourceUserId); 122 } 123 } 124 125 @Override 126 public void binderDied() { 127 try { 128 release(); 129 } catch (RemoteException e) { 130 // Cannot happen, local call. 131 } 132 } 133 } 134