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 17package com.android.server.wm; 18 19import android.app.ActivityManagerNative; 20import android.content.ClipData; 21import android.net.Uri; 22import android.os.Binder; 23import android.os.IBinder; 24import android.os.RemoteException; 25 26import com.android.internal.view.IDragAndDropPermissions; 27 28import java.util.ArrayList; 29 30class 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