All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.android.server.wm.DragAndDropPermissionsHandler Maven / Gradle / Ivy

/*
** Copyright 2015, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

package com.android.server.wm;

import static java.lang.Integer.toHexString;

import android.app.UriGrantsManager;
import android.content.ClipData;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.view.IDragAndDropPermissions;
import com.android.server.LocalServices;
import com.android.server.uri.UriGrantsManagerInternal;

import java.util.ArrayList;

class DragAndDropPermissionsHandler extends IDragAndDropPermissions.Stub {

    private static final String TAG = "DragAndDrop";
    private static final boolean DEBUG = false;

    private final WindowManagerGlobalLock mGlobalLock;
    private final int mSourceUid;
    private final String mTargetPackage;
    private final int mMode;
    private final int mSourceUserId;
    private final int mTargetUserId;

    private final ArrayList mUris = new ArrayList();

    private IBinder mActivityToken = null;
    private IBinder mPermissionOwnerToken = null;

    DragAndDropPermissionsHandler(WindowManagerGlobalLock lock, ClipData clipData, int sourceUid,
            String targetPackage, int mode, int sourceUserId, int targetUserId) {
        mGlobalLock = lock;
        mSourceUid = sourceUid;
        mTargetPackage = targetPackage;
        mMode = mode;
        mSourceUserId = sourceUserId;
        mTargetUserId = targetUserId;

        clipData.collectUris(mUris);
    }

    @Override
    public void take(IBinder activityToken) throws RemoteException {
        if (mActivityToken != null || mPermissionOwnerToken != null) {
            return;
        }
        if (DEBUG) {
            Log.d(TAG, this + ": taking permissions bound to activity: "
                    + toHexString(activityToken.hashCode()));
        }
        mActivityToken = activityToken;

        // Will throw if Activity is not found.
        IBinder permissionOwner = getUriPermissionOwnerForActivity(mActivityToken);

        doTake(permissionOwner);
    }

    private void doTake(IBinder permissionOwner) throws RemoteException {
        final long origId = Binder.clearCallingIdentity();
        try {
            for (int i = 0; i < mUris.size(); i++) {
                UriGrantsManager.getService().grantUriPermissionFromOwner(
                        permissionOwner, mSourceUid, mTargetPackage, mUris.get(i), mMode,
                        mSourceUserId, mTargetUserId);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

    @Override
    public void takeTransient() throws RemoteException {
        if (mActivityToken != null || mPermissionOwnerToken != null) {
            return;
        }
        if (DEBUG) {
            Log.d(TAG, this + ": taking transient permissions");
        }
        mPermissionOwnerToken = LocalServices.getService(UriGrantsManagerInternal.class)
                .newUriPermissionOwner("drop");

        doTake(mPermissionOwnerToken);
    }

    @Override
    public void release() throws RemoteException {
        if (mActivityToken == null && mPermissionOwnerToken == null) {
            return;
        }

        IBinder permissionOwner = null;
        if (mActivityToken != null) {
            try {
                permissionOwner = getUriPermissionOwnerForActivity(mActivityToken);
            } catch (Exception e) {
                // Activity is destroyed, permissions already revoked.
                return;
            } finally {
                mActivityToken = null;
            }
            if (DEBUG) {
                Log.d(TAG, this + ": releasing activity-bound permissions");
            }
        } else {
            permissionOwner = mPermissionOwnerToken;
            mPermissionOwnerToken = null;
            if (DEBUG) {
                Log.d(TAG, this + ": releasing transient permissions");
            }
        }

        UriGrantsManagerInternal ugm = LocalServices.getService(UriGrantsManagerInternal.class);
        for (int i = 0; i < mUris.size(); ++i) {
            ugm.revokeUriPermissionFromOwner(permissionOwner, mUris.get(i), mMode, mSourceUserId);
        }
    }

    private IBinder getUriPermissionOwnerForActivity(IBinder activityToken) {
        ActivityTaskManagerService.enforceNotIsolatedCaller("getUriPermissionOwnerForActivity");
        synchronized (mGlobalLock) {
            ActivityRecord r = ActivityRecord.isInRootTaskLocked(activityToken);
            if (r == null) {
                throw new IllegalArgumentException("Activity does not exist; token="
                        + activityToken);
            }
            return r.getUriPermissionsLocked().getExternalToken();
        }
    }

    /**
     * If permissions are not tied to an activity, release whenever there are no more references
     * to this object (if not already released).
     */
    @Override
    protected void finalize() throws Throwable {
        if (DEBUG) {
            Log.d(TAG, this + ": running finalizer");
        }
        if (mActivityToken != null || mPermissionOwnerToken == null) {
            return;
        }
        release();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy