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

Commit cbf7f26b authored by Felipe Leme's avatar Felipe Leme
Browse files

Fixed content capture whitelist for specific activities.

Test: manual verification (it cannot be fully verified using the current CTS setup)
Test: atest CtsContentCaptureServiceTestCases:android.contentcaptureservice.cts.WhitelistTest
Test: atest FrameworksCoreTests:android.content.ContentCaptureOptionsTest
Test: atest CtsContentCaptureServiceTestCases # sanity check
Test: m update-api

Fixes: 130573023
Merged-In: I2c76a01bd98c4154c4c59099f1368232d2dba80d
Change-Id: I2c76a01bd98c4154c4c59099f1368232d2dba80d
parent d4cced9a
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ import android.view.autofill.AutofillPopupWindow;
import android.view.autofill.IAutofillWindowPresenter;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
@@ -723,7 +724,7 @@ public class Activity extends ContextThemeWrapper
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback,
        AutofillManager.AutofillClient {
        AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
    private static final String TAG = "Activity";
    private static final boolean DEBUG_LIFECYCLE = false;

@@ -1125,6 +1126,12 @@ public class Activity extends ContextThemeWrapper
        return this;
    }

    /** @hide */
    @Override
    public final ContentCaptureClient getContentCaptureClient() {
        return this;
    }

    /**
     * Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
     * lifecycle callbacks for only this Activity.
@@ -6511,6 +6518,12 @@ public class Activity extends ContextThemeWrapper
        return getComponentName();
    }

    /** @hide */
    @Override
    public final ComponentName contentCaptureClientGetComponentName() {
        return getComponentName();
    }

    /**
     * Retrieve a {@link SharedPreferences} object for accessing preferences
     * that are private to this activity.  This simply calls the underlying
+1 −1
Original line number Diff line number Diff line
@@ -1143,7 +1143,7 @@ final class SystemServiceRegistry {
                Context outerContext = ctx.getOuterContext();
                ContentCaptureOptions options = outerContext.getContentCaptureOptions();
                // Options is null when the service didn't whitelist the activity or package
                if (options != null) {
                if (options != null && (options.lite || options.isWhitelisted(outerContext))) {
                    IBinder b = ServiceManager
                            .getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
                    IContentCaptureManager service = IContentCaptureManager.Stub.asInterface(b);
+35 −11
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@ import android.os.Parcelable;
import android.util.ArraySet;
import android.util.Log;
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;

import com.android.internal.annotations.VisibleForTesting;

import java.io.PrintWriter;

@@ -78,12 +81,19 @@ public final class ContentCaptureOptions implements Parcelable {
     */
    public final boolean lite;

    /**
     * Constructor for "lite" objects that are just used to enable a {@link ContentCaptureManager}
     * for contexts belonging to the content capture service app.
     */
    public ContentCaptureOptions(int loggingLevel) {
        this(/* lite= */ true, loggingLevel, /* maxBufferSize= */ 0,
                /* idleFlushingFrequencyMs= */ 0, /* textChangeFlushingFrequencyMs= */ 0,
                /* logHistorySize= */ 0, /* whitelistedComponents= */ null);
    }

    /**
     * Default constructor.
     */
    public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
            int textChangeFlushingFrequencyMs, int logHistorySize,
            @Nullable ArraySet<ComponentName> whitelistedComponents) {
@@ -91,6 +101,16 @@ public final class ContentCaptureOptions implements Parcelable {
                textChangeFlushingFrequencyMs, logHistorySize, whitelistedComponents);
    }

    /** @hide */
    @VisibleForTesting
    public ContentCaptureOptions(@Nullable ArraySet<ComponentName> whitelistedComponents) {
        this(ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
                ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
                ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
                ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
                ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE, whitelistedComponents);
    }

    private ContentCaptureOptions(boolean lite, int loggingLevel, int maxBufferSize,
            int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
            @Nullable ArraySet<ComponentName> whitelistedComponents) {
@@ -103,10 +123,6 @@ public final class ContentCaptureOptions implements Parcelable {
        this.whitelistedComponents = whitelistedComponents;
    }

    /**
     * @hide
     */
    @TestApi
    public static ContentCaptureOptions forWhitelistingItself() {
        final ActivityThread at = ActivityThread.currentActivityThread();
        if (at == null) {
@@ -120,19 +136,27 @@ public final class ContentCaptureOptions implements Parcelable {
            throw new SecurityException("Thou shall not pass!");
        }

        final ContentCaptureOptions options = new ContentCaptureOptions(
                ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
                ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
                ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
                ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
                ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE,
                /* whitelistedComponents= */ null);
        final ContentCaptureOptions options =
                new ContentCaptureOptions(/* whitelistedComponents= */ null);
        // Always log, as it's used by test only
        Log.i(TAG, "forWhitelistingItself(" + packageName + "): " + options);

        return options;
    }

    /** @hide */
    @VisibleForTesting
    public boolean isWhitelisted(@NonNull Context context) {
        if (whitelistedComponents == null) return true; // whole package is whitelisted
        final ContentCaptureClient client = context.getContentCaptureClient();
        if (client == null) {
            // Shouldn't happen, but it doesn't hurt to check...
            Log.w(TAG, "isWhitelisted(): no ContentCaptureClient on " + context);
            return false;
        }
        return whitelistedComponents.contains(client.contentCaptureClientGetComponentName());
    }

    @Override
    public String toString() {
        if (lite) {
+9 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ import android.view.View;
import android.view.ViewDebug;
import android.view.WindowManager;
import android.view.autofill.AutofillManager.AutofillClient;
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
import android.view.textclassifier.TextClassificationManager;

import java.io.File;
@@ -5411,6 +5412,14 @@ public abstract class Context {
    public void setAutofillClient(@SuppressWarnings("unused") AutofillClient client) {
    }

    /**
     * @hide
     */
    @Nullable
    public ContentCaptureClient getContentCaptureClient() {
        return null;
    }

    /**
     * @hide
     */
+9 −0
Original line number Diff line number Diff line
@@ -342,6 +342,15 @@ public final class ContentCaptureManager {
    @GuardedBy("mLock")
    private MainContentCaptureSession mMainSession;

    /** @hide */
    public interface ContentCaptureClient {
        /**
         * Gets the component name of the client.
         */
        @NonNull
        ComponentName contentCaptureClientGetComponentName();
    }

    /** @hide */
    public ContentCaptureManager(@NonNull Context context,
            @NonNull IContentCaptureManager service, @NonNull ContentCaptureOptions options) {
Loading