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.ActivityManagerNative; 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 44 DragAndDropPermissionsHandler(ClipData clipData, int sourceUid, String targetPackage, int mode, 45 int sourceUserId, int targetUserId) { 46 mSourceUid = sourceUid; 47 mTargetPackage = targetPackage; 48 mMode = mode; 49 mSourceUserId = sourceUserId; 50 mTargetUserId = targetUserId; 51 52 clipData.collectUris(mUris); 53 } 54 55 @Override 56 public void take(IBinder activityToken) throws RemoteException { 57 if (mActivityToken != null || mPermissionOwnerToken != null) { 58 return; 59 } 60 mActivityToken = activityToken; 61 62 // Will throw if Activity is not found. 63 IBinder permissionOwner = ActivityManagerNative.getDefault(). 64 getUriPermissionOwnerForActivity(mActivityToken); 65 66 doTake(permissionOwner); 67 } 68 69 private void doTake(IBinder permissionOwner) throws RemoteException { 70 long origId = Binder.clearCallingIdentity(); 71 try { 72 for (int i = 0; i < mUris.size(); i++) { 73 ActivityManagerNative.getDefault().grantUriPermissionFromOwner( 74 permissionOwner, mSourceUid, mTargetPackage, mUris.get(i), mMode, 75 mSourceUserId, mTargetUserId); 76 } 77 } finally { 78 Binder.restoreCallingIdentity(origId); 79 } 80 } 81 82 @Override 83 public void takeTransient(IBinder permissionOwnerToken) throws RemoteException { 84 if (mActivityToken != null || mPermissionOwnerToken != null) { 85 return; 86 } 87 mPermissionOwnerToken = permissionOwnerToken; 88 mPermissionOwnerToken.linkToDeath(this, 0); 89 90 doTake(mPermissionOwnerToken); 91 } 92 93 @Override 94 public void release() throws RemoteException { 95 if (mActivityToken == null && mPermissionOwnerToken == null) { 96 return; 97 } 98 99 IBinder permissionOwner = null; 100 if (mActivityToken != null) { 101 try { 102 permissionOwner = ActivityManagerNative.getDefault(). 103 getUriPermissionOwnerForActivity(mActivityToken); 104 } catch (Exception e) { 105 // Activity is destroyed, permissions already revoked. 106 return; 107 } finally { 108 mActivityToken = null; 109 } 110 } else { 111 permissionOwner = mPermissionOwnerToken; 112 mPermissionOwnerToken.unlinkToDeath(this, 0); 113 mPermissionOwnerToken = null; 114 } 115 116 for (int i = 0; i < mUris.size(); ++i) { 117 ActivityManagerNative.getDefault().revokeUriPermissionFromOwner( 118 permissionOwner, mUris.get(i), mMode, mSourceUserId); 119 } 120 } 121 122 @Override 123 public void binderDied() { 124 try { 125 release(); 126 } catch (RemoteException e) { 127 // Cannot happen, local call. 128 } 129 } 130 } 131