Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6b2d5ca authored by Chad Brubaker's avatar Chad Brubaker
Browse files

Limit clipboard access to the default IME or current focused app.

Test: atest ClipboardManagerTest.java
Bug: 6229949
Change-Id: I450ba3d3c2d0f1c4a6a4c24f50539c68ac844c26
parent 2c1bf635
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -95,6 +95,9 @@ public class ClipboardManager extends android.text.ClipboardManager {
     * Sets the current primary clip on the clipboard.  This is the clip that
     * is involved in normal cut and paste operations.
     *
     * <em>If the application is not the default IME or does not have input focus this will have
     * no effect.</em>
     *
     * @param clip The clipped data item to set.
     * @see #getPrimaryClip()
     * @see #clearPrimaryClip()
@@ -112,6 +115,9 @@ public class ClipboardManager extends android.text.ClipboardManager {
    /**
     * Clears any current primary clip on the clipboard.
     *
     * <em>If the application is not the default IME or does not have input focus this will have
     * no effect.</em>
     *
     * @see #setPrimaryClip(ClipData)
     */
    public void clearPrimaryClip() {
@@ -125,6 +131,9 @@ public class ClipboardManager extends android.text.ClipboardManager {
    /**
     * Returns the current primary clip on the clipboard.
     *
     * <em>If the application is not the default IME or does not have input focus this return
     * {@code null}.</em>
     *
     * @see #setPrimaryClip(ClipData)
     */
    public @Nullable ClipData getPrimaryClip() {
@@ -139,6 +148,9 @@ public class ClipboardManager extends android.text.ClipboardManager {
     * Returns a description of the current primary clip on the clipboard
     * but not a copy of its data.
     *
     * <em>If the application is not the default IME or does not have input focus this return
     * {@code null}.</em>
     *
     * @see #setPrimaryClip(ClipData)
     */
    public @Nullable ClipDescription getPrimaryClipDescription() {
@@ -151,6 +163,9 @@ public class ClipboardManager extends android.text.ClipboardManager {

    /**
     * Returns true if there is currently a primary clip on the clipboard.
     *
     * <em>If the application is not the default IME or the does not have input focus this will
     * return {@code false}.</em>
     */
    public boolean hasPrimaryClip() {
        try {
+17 −12
Original line number Diff line number Diff line
@@ -47,12 +47,14 @@ import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;

import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.WindowManagerInternal;

import java.io.IOException;
import java.io.RandomAccessFile;
@@ -149,6 +151,7 @@ public class ClipboardService extends SystemService {
    private final IActivityManager mAm;
    private final IUriGrantsManager mUgm;
    private final UriGrantsManagerInternal mUgmInternal;
    private final WindowManagerInternal mWm;
    private final IUserManager mUm;
    private final PackageManager mPm;
    private final AppOpsManager mAppOps;
@@ -167,6 +170,7 @@ public class ClipboardService extends SystemService {
        mAm = ActivityManager.getService();
        mUgm = UriGrantsManager.getService();
        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
        mWm = LocalServices.getService(WindowManagerInternal.class);
        mPm = getContext().getPackageManager();
        mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
        mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
@@ -623,18 +627,19 @@ public class ClipboardService extends SystemService {
        if (mAppOps.noteOp(op, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
            return false;
        }
        try {
            // Installed apps can access the clipboard at any time.
            if (!AppGlobals.getPackageManager().isInstantApp(callingPackage,
                        UserHandle.getUserId(callingUid))) {
        // The default IME is always allowed to access the clipboard.
        String defaultIme = Settings.Secure.getStringForUser(getContext().getContentResolver(),
                Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.getUserId(callingUid));
        if (defaultIme != null && defaultIme.equals(callingPackage)) {
            return true;
        }
            // Instant apps can only access the clipboard if they are in the foreground.
            return mAm.isAppForeground(callingUid);
        } catch (RemoteException e) {
            Slog.e("clipboard", "Failed to get Instant App status for package " + callingPackage,
                    e);
            return false;

        // Otherwise only focused applications can access the clipboard.
        boolean uidFocused = mWm.isUidFocused(callingUid);
        if (!uidFocused) {
            Slog.e(TAG, "Denying clipboard access to " + callingPackage
                    + ", application is not in focus.");
        }
        return uidFocused;
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -436,4 +436,9 @@ public abstract class WindowManagerInternal {
     * the window token is not found.
     */
    public abstract int getWindowOwnerUserId(IBinder windowToken);

    /**
     * Returns {@code true} if a Window owned by {@code uid} has focus.
     */
    public abstract boolean isUidFocused(int uid);
}
+7 −0
Original line number Diff line number Diff line
@@ -7422,6 +7422,13 @@ public class WindowManagerService extends IWindowManager.Stub
                return UserHandle.USER_NULL;
            }
        }

        @Override
        public boolean isUidFocused(int uid) {
            synchronized (mWindowMap) {
                return mCurrentFocus != null ? uid == mCurrentFocus.getOwningUid() : false;
            }
        }
    }

    void registerAppFreezeListener(AppFreezeListener listener) {