Home | History | Annotate | Download | only in wm
      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