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

Commit f8bbe8c6 authored by Jing Ji's avatar Jing Ji
Browse files

Log the clipboard retrieval event into statsd

Including the source/destination package of the clipdata,
as well as the time between the set and get (copy & paste).

Bug: 402542624
Test: statsd_testdrive 1048
Flag: com.android.server.clipboard.clipboard_get_event_logging
Change-Id: I8c4f007e7e4aac3dd3a721d45a9a2c69b97718c0
parent a17f38cd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -263,6 +263,7 @@ java_library_static {
        "profiling_flags_lib",
        "android.adpf.sessionmanager_aidl-java",
        "uprobestats_flags_java_lib",
        "clipboard_flags_lib",
    ],
    javac_shard_size: 50,
    javacflags: [
+18 −0
Original line number Diff line number Diff line
aconfig_declarations {
    name: "clipboard_flags",
    package: "com.android.server.clipboard",
    container: "system",
    srcs: ["*.aconfig"],
}

java_aconfig_library {
    name: "clipboard_flags_lib",
    aconfig_declarations: "clipboard_flags",
}

java_aconfig_library {
    name: "clipboard_flags_host_lib",
    host_supported: true,
    libs: ["fake_device_config"],
    aconfig_declarations: "clipboard_flags",
}
+87 −0
Original line number Diff line number Diff line
@@ -19,9 +19,27 @@ package com.android.server.clipboard;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CLIPBOARD;
import static android.content.ClipDescription.MIMETYPE_UNKNOWN;
import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN;
import static android.content.ClipDescription.MIMETYPE_TEXT_HTML;
import static android.content.ClipDescription.MIMETYPE_TEXT_URILIST;
import static android.content.ClipDescription.MIMETYPE_TEXT_INTENT;
import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY;
import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT;
import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK;
import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.content.Context.DEVICE_ID_INVALID;

import static com.android.internal.util.FrameworkStatsLog.CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_TEXT_PLAIN;
import static com.android.internal.util.FrameworkStatsLog.CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_TEXT_HTML;
import static com.android.internal.util.FrameworkStatsLog.CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_TEXT_URILIST;
import static com.android.internal.util.FrameworkStatsLog.CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_TEXT_INTENT;
import static com.android.internal.util.FrameworkStatsLog.CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_APPLICATION_ACTIVITY;
import static com.android.internal.util.FrameworkStatsLog.CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_APPLICATION_SHORTCUT;
import static com.android.internal.util.FrameworkStatsLog.CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_APPLICATION_TASK;
import static com.android.server.clipboard.Flags.clipboardGetEventLogging;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -70,6 +88,7 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.Pair;
import android.util.SafetyProtectionUtils;
import android.util.Slog;
@@ -98,6 +117,7 @@ import com.android.server.wm.WindowManagerInternal;

import java.util.HashSet;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
@@ -132,6 +152,10 @@ public class ClipboardService extends SystemService {
    private static final String PROPERTY_MAX_CLASSIFICATION_LENGTH = "max_classification_length";
    private static final int DEFAULT_MAX_CLASSIFICATION_LENGTH = 400;

    private static final int[] CLIP_DATA_TYPES_UNKNOWN = {
            CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_UNKNOWN
    };

    private final ActivityManagerInternal mAmInternal;
    private final IUriGrantsManager mUgm;
    private final UriGrantsManagerInternal mUgmInternal;
@@ -657,6 +681,8 @@ public class ClipboardService extends SystemService {
                        pkg, intendingUid, intendingUserId, clipboard, deviceId);
                notifyTextClassifierLocked(clipboard, pkg, intendingUid);
                if (clipboard.primaryClip != null) {
                    scheduleWriteClipDataStats(clipboard.primaryClip,
                            clipboard.primaryClipUid, intendingUid);
                    scheduleAutoClear(userId, intendingUid, intendingDeviceId);
                }
                return clipboard.primaryClip;
@@ -1600,4 +1626,65 @@ public class ClipboardService extends SystemService {
        Context context = getContext().createContextAsUser(UserHandle.of(userId), /* flags= */ 0);
        return context.getSystemService(TextClassificationManager.class);
    }

    private static int mimeTypeToClipDataType(@NonNull String mimeType) {
        switch (mimeType) {
            case MIMETYPE_TEXT_PLAIN:
                return CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_TEXT_PLAIN;
            case MIMETYPE_TEXT_HTML:
                return CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_TEXT_HTML;
            case MIMETYPE_TEXT_URILIST:
                return CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_TEXT_URILIST;
            case MIMETYPE_TEXT_INTENT:
                return CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_TEXT_INTENT;
            case MIMETYPE_APPLICATION_ACTIVITY:
                return CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_APPLICATION_ACTIVITY;
            case MIMETYPE_APPLICATION_SHORTCUT:
                return CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_APPLICATION_SHORTCUT;
            case MIMETYPE_APPLICATION_TASK:
                return CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_APPLICATION_TASK;
            case MIMETYPE_UNKNOWN:
                // fallthrough
            default:
                return CLIPBOARD_GET_EVENT_REPORTED__CLIP_DATA_TYPE__MIMETYPE_UNKNOWN;
        }
    }

    private void scheduleWriteClipDataStats(@NonNull ClipData clipData,
            int sourceUid, int intendingUid) {
        if (!clipboardGetEventLogging()) {
            return;
        }
        final ClipDescription description = clipData.getDescription();
        if (description != null) {
            final IntArray mimeTypes = new IntArray();
            final int secondsSinceSet = (int) TimeUnit.MILLISECONDS.toSeconds(
                    System.currentTimeMillis() - description.getTimestamp());
            for (int i = description.getMimeTypeCount() - 1; i >= 0; i--) {
                final String mimeType = description.getMimeType(i);
                if (mimeType != null) {
                    final int clipDataType = mimeTypeToClipDataType(mimeType);
                    if (!mimeTypes.contains(clipDataType)) {
                        mimeTypes.add(clipDataType);
                    }
                }
            }
            // The getUidProcessState() will hit AMS lock which might be slow, while getting the
            // clip data might be on the critical UI path. So post to the work thread.
            // There could be race conditions where the UID state might have been changed
            // between now and the work thread execution time, but this should be acceptable.
            mWorkerHandler.post(() -> FrameworkStatsLog.write(
                    FrameworkStatsLog.CLIPBOARD_GET_EVENT_REPORTED,
                    sourceUid, intendingUid,
                    mAmInternal.getUidProcessState(intendingUid),
                    mimeTypes.toArray(),
                    secondsSinceSet));
        } else {
            mWorkerHandler.post(() -> FrameworkStatsLog.write(
                    FrameworkStatsLog.CLIPBOARD_GET_EVENT_REPORTED,
                    sourceUid, intendingUid,
                    mAmInternal.getUidProcessState(intendingUid),
                    CLIP_DATA_TYPES_UNKNOWN, 0));
        }
    }
}
+9 −0
Original line number Diff line number Diff line
package: "com.android.server.clipboard"
container: "system"

flag {
    name: "clipboard_get_event_logging"
    namespace: "backstage_power"
    description: "Log the clipboard retrieval event in statsd"
    bug: "402542624"
}