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

Commit 01b8749b authored by Felipe Leme's avatar Felipe Leme
Browse files

Improved ContentCaptureManagerSession state.

Test: atest CtsContentCaptureServiceTestCases
Bug: 111276913

Change-Id: I8b1f36174582d89913d5d170abb65789a16818ec
parent 6079d151
Loading
Loading
Loading
Loading
+12 −11
Original line number Diff line number Diff line
@@ -323,20 +323,21 @@ public abstract class ContentCaptureService extends Service {
        mSessionUids.put(sessionId, uid);
        onCreateContentCaptureSession(context, new ContentCaptureSessionId(sessionId));

        final int flags = context.getFlags();
        if ((flags & ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE) != 0) {
            setClientState(clientReceiver, ContentCaptureSession.STATE_DISABLED_BY_FLAG_SECURE,
                    mClientInterface.asBinder());
            return;
        final int clientFlags = context.getFlags();
        int stateFlags = 0;
        if ((clientFlags & ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE) != 0) {
            stateFlags |= ContentCaptureSession.STATE_FLAG_SECURE;
        }
        if ((flags & ContentCaptureContext.FLAG_DISABLED_BY_APP) != 0) {
            setClientState(clientReceiver, ContentCaptureSession.STATE_DISABLED_BY_APP,
                    mClientInterface.asBinder());
            return;
        if ((clientFlags & ContentCaptureContext.FLAG_DISABLED_BY_APP) != 0) {
            stateFlags |= ContentCaptureSession.STATE_BY_APP;
        }
        if (stateFlags == 0) {
            stateFlags = ContentCaptureSession.STATE_ACTIVE;
        } else {
            stateFlags |= ContentCaptureSession.STATE_DISABLED;

        setClientState(clientReceiver, ContentCaptureSession.STATE_ACTIVE,
                mClientInterface.asBinder());
        }
        setClientState(clientReceiver, stateFlags, mClientInterface.asBinder());
    }

    private void handleSendEvents(int uid,
+1 −2
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.SyncResultReceiver;

import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicBoolean;

/*
 * NOTE: all methods in this class should return right away, or do the real work in a handler
@@ -125,7 +124,7 @@ public final class ContentCaptureManager {
        synchronized (mLock) {
            if (mMainSession == null) {
                mMainSession = new MainContentCaptureSession(mContext, mHandler, mService,
                        new AtomicBoolean(mDisabled));
                        mDisabled);
                if (VERBOSE) {
                    Log.v(TAG, "getDefaultContentCaptureSession(): created " + mMainSession);
                }
+20 −26
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.view.contentcapture.ContentCaptureManager.VERBOSE;
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.DebugUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewStructure;
@@ -56,49 +57,58 @@ public abstract class ContentCaptureSession implements AutoCloseable {
     *
     * @hide
     */
    public static final int STATE_UNKNOWN = 0;
    // NOTE: not prefixed by STATE_ so it's not printed on getStateAsString()
    public static final int UNKNWON_STATE = 0x0;

    /**
     * Service's startSession() was called, but server didn't confirm it was created yet.
     *
     * @hide
     */
    public static final int STATE_WAITING_FOR_SERVER = 1;
    public static final int STATE_WAITING_FOR_SERVER = 0x1;

    /**
     * Session is active.
     *
     * @hide
     */
    public static final int STATE_ACTIVE = 2;
    public static final int STATE_ACTIVE = 0x2;

    /**
     * Session is disabled because there is no service for this user.
     *
     * @hide
     */
    public static final int STATE_DISABLED_NO_SERVICE = 3;
    public static final int STATE_DISABLED = 0x4;

    /**
     * Session is disabled because its id already existed on server.
     *
     * @hide
     */
    public static final int STATE_DISABLED_DUPLICATED_ID = 4;
    public static final int STATE_DUPLICATED_ID = 0x8;

    /**
     * Session is disabled because service is not set for user.
     *
     * @hide
     */
    public static final int STATE_NO_SERVICE = 0x10;

    /**
     * Session is disabled by FLAG_SECURE
     *
     * @hide
     */
    public static final int STATE_DISABLED_BY_FLAG_SECURE = 5;
    public static final int STATE_FLAG_SECURE = 0x20;

    /**
     * Session is disabled manually by the specific app.
     *
     * @hide
     */
    public static final int STATE_DISABLED_BY_APP = 6;
    public static final int STATE_BY_APP = 0x40;


    private static final int INITIAL_CHILDREN_CAPACITY = 5;

@@ -117,7 +127,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
    @Nullable
    protected final String mId;

    private int mState = STATE_UNKNOWN;
    private int mState = UNKNWON_STATE;

    // Lazily created on demand.
    private ContentCaptureSessionId mContentCaptureSessionId;
@@ -389,23 +399,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
     */
    @NonNull
    protected static String getStateAsString(int state) {
        switch (state) {
            case STATE_UNKNOWN:
                return "UNKNOWN";
            case STATE_WAITING_FOR_SERVER:
                return "WAITING_FOR_SERVER";
            case STATE_ACTIVE:
                return "ACTIVE";
            case STATE_DISABLED_NO_SERVICE:
                return "DISABLED_NO_SERVICE";
            case STATE_DISABLED_DUPLICATED_ID:
                return "DISABLED_DUPLICATED_ID";
            case STATE_DISABLED_BY_FLAG_SECURE:
                return "DISABLED_FLAG_SECURE";
            case STATE_DISABLED_BY_APP:
                return "DISABLED_BY_APP";
            default:
                return "INVALID:" + state;
        }
        return state + " (" + (state == UNKNWON_STATE ? "UNKNOWN"
                : DebugUtils.flagsToString(ContentCaptureSession.class, "STATE_", state)) + ")";
    }
}
+9 −13
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
     */
    public static final String EXTRA_BINDER = "binder";

    // TODO(b/111276913): make sure disabled state is in sync with manager's disabled
    @NonNull
    private final AtomicBoolean mDisabled;

@@ -113,7 +114,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
    @Nullable
    private DeathRecipient mDirectServiceVulture;

    private int mState = STATE_UNKNOWN;
    private int mState = UNKNWON_STATE;

    @Nullable
    private IBinder mApplicationToken;
@@ -133,11 +134,11 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
    /** @hide */
    protected MainContentCaptureSession(@NonNull Context context, @NonNull Handler handler,
            @Nullable IContentCaptureManager systemServerInterface,
            @NonNull AtomicBoolean disabled) {
            @NonNull boolean disabled) {
        mContext = context;
        mHandler = handler;
        mSystemServerInterface = systemServerInterface;
        mDisabled = disabled;
        mDisabled = new AtomicBoolean(disabled);
    }

    @Override
@@ -184,7 +185,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {

    private void handleStartSession(@NonNull IBinder token, @NonNull ComponentName componentName,
            int flags) {
        if (mState != STATE_UNKNOWN) {
        if (mState != UNKNWON_STATE) {
            // TODO(b/111276913): revisit this scenario
            Log.w(TAG, "ignoring handleStartSession(" + token + ") while on state "
                    + getStateAsString(mState));
@@ -247,18 +248,14 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
            }
        }

        // TODO(b/111276913): change the resultCode to use flags so there's just one flag for
        // disabled stuff
        if (resultCode == STATE_DISABLED_NO_SERVICE || resultCode == STATE_DISABLED_DUPLICATED_ID
                || resultCode == STATE_DISABLED_BY_FLAG_SECURE
                || resultCode == STATE_DISABLED_BY_APP) {
        if ((mState & STATE_DISABLED) != 0) {
            mDisabled.set(true);
            handleResetSession(/* resetState= */ false);
        } else {
            mDisabled.set(false);
        }
        if (VERBOSE) {
            Log.v(TAG, "handleSessionStarted() result: code=" + resultCode + ", id=" + mId
            Log.v(TAG, "handleSessionStarted() result: id=" + mId
                    + ", state=" + getStateAsString(mState) + ", disabled=" + mDisabled.get()
                    + ", binder=" + binder + ", events=" + (mEvents == null ? 0 : mEvents.size()));
        }
@@ -408,7 +405,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
    // clearings out.
    private void handleResetSession(boolean resetState) {
        if (resetState) {
            mState = STATE_UNKNOWN;
            mState = UNKNWON_STATE;
        }

        // TODO(b/122454205): must reset children (which currently is owned by superclass)
@@ -497,8 +494,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
        }
        pw.print(prefix); pw.print("mDisabled: "); pw.println(mDisabled.get());
        pw.print(prefix); pw.print("isEnabled(): "); pw.println(isContentCaptureEnabled());
        pw.print(prefix); pw.print("state: "); pw.print(mState); pw.print(" (");
        pw.print(getStateAsString(mState)); pw.println(")");
        pw.print(prefix); pw.print("state: "); pw.println(getStateAsString(mState));
        if (mApplicationToken != null) {
            pw.print(prefix); pw.print("app token: "); pw.println(mApplicationToken);
        }
+6 −5
Original line number Diff line number Diff line
@@ -17,6 +17,9 @@
package com.android.server.contentcapture;

import static android.service.contentcapture.ContentCaptureService.setClientState;
import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED;
import static android.view.contentcapture.ContentCaptureSession.STATE_DUPLICATED_ID;
import static android.view.contentcapture.ContentCaptureSession.STATE_NO_SERVICE;

import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
@@ -39,7 +42,6 @@ import android.service.contentcapture.ContentCaptureService;
import android.service.contentcapture.SnapshotData;
import android.util.ArrayMap;
import android.util.Slog;
import android.view.contentcapture.ContentCaptureSession;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
@@ -165,7 +167,7 @@ final class ContentCapturePerUserService
        if (!isEnabledLocked()) {
            // TODO: it would be better to split in differet reasons, like
            // STATE_DISABLED_NO_SERVICE and STATE_DISABLED_BY_DEVICE_POLICY
            setClientState(clientReceiver, ContentCaptureSession.STATE_DISABLED_NO_SERVICE,
            setClientState(clientReceiver, STATE_DISABLED | STATE_NO_SERVICE,
                    /* binder= */ null);
            return;
        }
@@ -184,7 +186,7 @@ final class ContentCapturePerUserService
        if (existingSession != null) {
            Slog.w(TAG, "startSession(id=" + existingSession + ", token=" + activityToken
                    + ": ignoring because it already exists for " + existingSession.mActivityToken);
            setClientState(clientReceiver, ContentCaptureSession.STATE_DISABLED_DUPLICATED_ID,
            setClientState(clientReceiver, STATE_DISABLED | STATE_DUPLICATED_ID,
                    /* binder=*/ null);
            return;
        }
@@ -197,8 +199,7 @@ final class ContentCapturePerUserService
            // TODO(b/119613670): log metrics
            Slog.w(TAG, "startSession(id=" + existingSession + ", token=" + activityToken
                    + ": ignoring because service is not set");
            // TODO(b/111276913): use a new disabled state?
            setClientState(clientReceiver, ContentCaptureSession.STATE_DISABLED_NO_SERVICE,
            setClientState(clientReceiver, STATE_DISABLED | STATE_NO_SERVICE,
                    /* binder= */ null);
            return;
        }