blob: 70478fe677ed9478be992a7dd78f157212f0c4a9 [file] [log] [blame]
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -08001/*
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
Sudheer Shankadc589ac2016-11-10 15:30:17 -080019import android.app.ActivityManager;
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080020import android.content.ClipData;
21import android.net.Uri;
22import android.os.Binder;
23import android.os.IBinder;
24import android.os.RemoteException;
25
Vladislav Kaznacheev377c3282016-04-20 14:22:23 -070026import com.android.internal.view.IDragAndDropPermissions;
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080027
28import java.util.ArrayList;
29
Vladislav Kaznacheev377c3282016-04-20 14:22:23 -070030class DragAndDropPermissionsHandler extends IDragAndDropPermissions.Stub
31 implements IBinder.DeathRecipient {
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080032
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
Vladislav Kaznacheevb23a7572015-12-18 12:23:43 -080041 private IBinder mActivityToken = null;
Vladislav Kaznacheevc14df8e2016-01-22 11:49:13 -080042 private IBinder mPermissionOwnerToken = null;
Vladislav Kaznacheev87c60d62016-07-21 15:25:12 -070043 private IBinder mTransientToken = null;
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080044
Vladislav Kaznacheev377c3282016-04-20 14:22:23 -070045 DragAndDropPermissionsHandler(ClipData clipData, int sourceUid, String targetPackage, int mode,
46 int sourceUserId, int targetUserId) {
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080047 mSourceUid = sourceUid;
48 mTargetPackage = targetPackage;
49 mMode = mode;
50 mSourceUserId = sourceUserId;
51 mTargetUserId = targetUserId;
52
53 clipData.collectUris(mUris);
54 }
55
56 @Override
Vladislav Kaznacheevb23a7572015-12-18 12:23:43 -080057 public void take(IBinder activityToken) throws RemoteException {
Vladislav Kaznacheevc14df8e2016-01-22 11:49:13 -080058 if (mActivityToken != null || mPermissionOwnerToken != null) {
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080059 return;
60 }
Vladislav Kaznacheevb23a7572015-12-18 12:23:43 -080061 mActivityToken = activityToken;
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080062
Vladislav Kaznacheevb23a7572015-12-18 12:23:43 -080063 // Will throw if Activity is not found.
Sudheer Shankadc589ac2016-11-10 15:30:17 -080064 IBinder permissionOwner = ActivityManager.getService().
Vladislav Kaznacheevb23a7572015-12-18 12:23:43 -080065 getUriPermissionOwnerForActivity(mActivityToken);
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080066
Vladislav Kaznacheevc14df8e2016-01-22 11:49:13 -080067 doTake(permissionOwner);
68 }
69
70 private void doTake(IBinder permissionOwner) throws RemoteException {
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080071 long origId = Binder.clearCallingIdentity();
72 try {
73 for (int i = 0; i < mUris.size(); i++) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -080074 ActivityManager.getService().grantUriPermissionFromOwner(
Vladislav Kaznacheevb23a7572015-12-18 12:23:43 -080075 permissionOwner, mSourceUid, mTargetPackage, mUris.get(i), mMode,
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080076 mSourceUserId, mTargetUserId);
77 }
78 } finally {
79 Binder.restoreCallingIdentity(origId);
80 }
81 }
82
83 @Override
Vladislav Kaznacheev87c60d62016-07-21 15:25:12 -070084 public void takeTransient(IBinder transientToken) throws RemoteException {
Vladislav Kaznacheevc14df8e2016-01-22 11:49:13 -080085 if (mActivityToken != null || mPermissionOwnerToken != null) {
86 return;
87 }
Sudheer Shankadc589ac2016-11-10 15:30:17 -080088 mPermissionOwnerToken = ActivityManager.getService().newUriPermissionOwner("drop");
Vladislav Kaznacheev87c60d62016-07-21 15:25:12 -070089 mTransientToken = transientToken;
90 mTransientToken.linkToDeath(this, 0);
Vladislav Kaznacheevc14df8e2016-01-22 11:49:13 -080091
92 doTake(mPermissionOwnerToken);
93 }
94
95 @Override
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080096 public void release() throws RemoteException {
Vladislav Kaznacheevc14df8e2016-01-22 11:49:13 -080097 if (mActivityToken == null && mPermissionOwnerToken == null) {
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080098 return;
99 }
100
Vladislav Kaznacheevb23a7572015-12-18 12:23:43 -0800101 IBinder permissionOwner = null;
Vladislav Kaznacheevc14df8e2016-01-22 11:49:13 -0800102 if (mActivityToken != null) {
103 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800104 permissionOwner = ActivityManager.getService().
Vladislav Kaznacheevc14df8e2016-01-22 11:49:13 -0800105 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;
Vladislav Kaznacheevc14df8e2016-01-22 11:49:13 -0800114 mPermissionOwnerToken = null;
Vladislav Kaznacheev87c60d62016-07-21 15:25:12 -0700115 mTransientToken.unlinkToDeath(this, 0);
116 mTransientToken = null;
Vladislav Kaznacheevb23a7572015-12-18 12:23:43 -0800117 }
118
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -0800119 for (int i = 0; i < mUris.size(); ++i) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800120 ActivityManager.getService().revokeUriPermissionFromOwner(
Vladislav Kaznacheevb23a7572015-12-18 12:23:43 -0800121 permissionOwner, mUris.get(i), mMode, mSourceUserId);
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -0800122 }
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -0800123 }
Vladislav Kaznacheevc14df8e2016-01-22 11:49:13 -0800124
125 @Override
126 public void binderDied() {
127 try {
128 release();
129 } catch (RemoteException e) {
130 // Cannot happen, local call.
131 }
132 }
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -0800133}