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

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

Refactored InteractionSessionId.

Rather than use a local and global id, just use a local, unique id.

Such change not only simplifies the code, but makes it consistent with
TextClassificationSessionId.

Test: mmm -j packages/experimental/FillService && \
      adb install -r ${OUT}/data/app/FillService/FillService.apk && \
      adb shell settings put secure intel_service foo.bar.fill/.AiaiService
Bug: 111276913

Change-Id: I0e610f825aab1d2b32bbafa1bd3d3c7897d889d6
parent 7a53408d
Loading
Loading
Loading
Loading
+60 −21
Original line number Diff line number Diff line
@@ -16,43 +16,85 @@

package android.service.intelligence;

import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;

import java.io.PrintWriter;
import java.util.UUID;

// TODO(b/111276913): add javadocs / implement equals/hashcode/string
/** @hide */
@SystemApi
public final class InteractionSessionId implements Parcelable {

    private final int mGlobalId;
    private final @NonNull String mValue;

    // TODO(b/111276913): remove if not needed
    private final int mLocalId;
    /**
     * Creates a new instance.
     *
     * @hide
     */
    public InteractionSessionId() {
        this(UUID.randomUUID().toString());
    }

    /** @hide */
    public InteractionSessionId(int globalId, int localId) {
        mGlobalId = globalId;
        mLocalId = localId;
    /**
     * Creates a new instance.
     *
     * @param value The internal value.
     *
     * @hide
     */
    public InteractionSessionId(@NonNull String value) {
        mValue = value;
    }

    /** @hide */
    public int getGlobalId() {
        return mGlobalId;
    /**
     * @hide
     */
    public String getValue() {
        return mValue;
    }

    /** @hide */
    // TODO(b/111276913): dump to proto as well
    public void dump(PrintWriter pw) {
        pw.print("globalId="); pw.print(mGlobalId);
        pw.print("localId="); pw.print(mLocalId);
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((mValue == null) ? 0 : mValue.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        final InteractionSessionId other = (InteractionSessionId) obj;
        if (mValue == null) {
            if (other.mValue != null) return false;
        } else if (!mValue.equals(other.mValue)) {
            return false;
        }
        return true;
    }

    /**
     * @inheritdoc
     *
     * <p><b>NOTE: </b>this method is only useful for debugging purposes and is not guaranteed to
     * be stable, hence it should not be used to identify the session.
     */
    @Override
    public String toString() {
        return "SessionId[globalId=" + mGlobalId + ", localId=" + mLocalId + "]";
        return mValue;
    }

    /** @hide */
    // TODO(b/111276913): dump to proto as well
    public void dump(PrintWriter pw) {
        pw.print(mValue);
    }

    @Override
@@ -62,8 +104,7 @@ public final class InteractionSessionId implements Parcelable {

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeInt(mGlobalId);
        parcel.writeInt(mLocalId);
        parcel.writeString(mValue);
    }

    public static final Parcelable.Creator<InteractionSessionId> CREATOR =
@@ -71,9 +112,7 @@ public final class InteractionSessionId implements Parcelable {

        @Override
        public InteractionSessionId createFromParcel(Parcel parcel) {
            final int globalId = parcel.readInt();
            final int localId = parcel.readInt();
            return new InteractionSessionId(globalId, localId);
            return new InteractionSessionId(parcel.readString());
        }

        @Override
+5 −9
Original line number Diff line number Diff line
@@ -17,9 +17,8 @@
package android.view.intelligence;

import android.content.ComponentName;

import android.os.IBinder;

import android.service.intelligence.InteractionSessionId;
import android.view.intelligence.ContentCaptureEvent;

import com.android.internal.os.IResultReceiver;
@@ -34,19 +33,16 @@ oneway interface IIntelligenceManager {
      * Starts a session, sending the "remote" sessionId to the receiver.
      */
    void startSession(int userId, IBinder activityToken, in ComponentName componentName,
                      int localSessionId, int flags, in IResultReceiver result);
                      in InteractionSessionId sessionId, int flags, in IResultReceiver result);

    /**
      * Finishes a session.
      */
    // TODO(b/111276913): pass just (global) session id
    void finishSession(int userId, IBinder activityToken, in ComponentName componentName,
                       int localSessionId, int globalSessionId);
    void finishSession(int userId, in InteractionSessionId sessionId);

    /**
      * Sends a batch of events
      */
    // TODO(b/111276913): pass just (global) session id
    void sendEvents(int userId, IBinder activityToken, in ComponentName componentName,
                    int localSessionId, int globalSessionId, in List<ContentCaptureEvent> events);
    void sendEvents(int userId, in InteractionSessionId sessionId,
                    in List<ContentCaptureEvent> events);
}
+20 −35
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.intelligence.InteractionSessionId;
import android.util.Log;
import android.view.intelligence.ContentCaptureEvent.EventType;

@@ -55,9 +56,6 @@ public final class IntelligenceManager {
    public static final int FLAG_USER_INPUT = 0x1;


    /** @hide */
    public static final int NO_SESSION = 0;

    /**
     * Initial state, when there is no session.
     *
@@ -66,11 +64,11 @@ public final class IntelligenceManager {
    public static final int STATE_UNKNOWN = 0;

    /**
     * Service's startSession() was called, but remote session id was not returned yet.
     * Service's startSession() was called, but server didn't confirm it was created yet.
     *
     * @hide
     */
    public static final int STATE_WAITING_FOR_SESSION_ID = 1;
    public static final int STATE_WAITING_FOR_SERVER = 1;

    /**
     * Session is active.
@@ -79,8 +77,6 @@ public final class IntelligenceManager {
     */
    public static final int STATE_ACTIVE = 2;

    private static int sNextSessionId;

    private final Context mContext;

    @Nullable
@@ -88,14 +84,9 @@ public final class IntelligenceManager {

    private final Object mLock = new Object();

    // TODO(b/111276913): localSessionId might be an overkill, perhaps just the global id is enough.
    // Let's keep both for now, and revisit once we decide whether the session id will be persisted
    // when the activity's process is killed
    @GuardedBy("mLock")
    private int mLocalSessionId = NO_SESSION;

    @Nullable
    @GuardedBy("mLock")
    private int mRemoteSessionId = NO_SESSION;
    private InteractionSessionId mId;

    @GuardedBy("mLock")
    private int mState = STATE_UNKNOWN;
@@ -124,27 +115,25 @@ public final class IntelligenceManager {
                        + getStateAsStringLocked());
                return;
            }
            mState = STATE_WAITING_FOR_SESSION_ID;
            mLocalSessionId = ++sNextSessionId;
            mRemoteSessionId = NO_SESSION;
            mState = STATE_WAITING_FOR_SERVER;
            mId = new InteractionSessionId();
            mApplicationToken = token;
            mComponentName = componentName;

            if (VERBOSE) {
                Log.v(TAG, "onActivityStarted(): token=" + token + ", act=" + componentName
                        + ", localSessionId=" + mLocalSessionId);
                        + ", id=" + mId);
            }
            final int flags = 0; // TODO(b/111276913): get proper flags

            try {
                mService.startSession(mContext.getUserId(), mApplicationToken, componentName,
                        mLocalSessionId, flags, new IResultReceiver.Stub() {
                        mId, flags, new IResultReceiver.Stub() {
                            @Override
                            public void send(int resultCode, Bundle resultData)
                                    throws RemoteException {
                                synchronized (mLock) {
                                    if (resultCode > 0) {
                                        mRemoteSessionId = resultCode;
                                        mState = STATE_ACTIVE;
                                    } else {
                                        // TODO(b/111276913): handle other cases like disabled by
@@ -153,7 +142,7 @@ public final class IntelligenceManager {
                                    }
                                    if (VERBOSE) {
                                        Log.v(TAG, "onActivityStarted() result: code=" + resultCode
                                                + ", remoteSession=" + mRemoteSessionId
                                                + ", id=" + mId
                                                + ", state=" + getStateAsStringLocked());
                                    }
                                }
@@ -189,8 +178,7 @@ public final class IntelligenceManager {
            }

            try {
                mService.sendEvents(mContext.getUserId(), mApplicationToken, mComponentName,
                        mLocalSessionId, mRemoteSessionId, events);
                mService.sendEvents(mContext.getUserId(), mId, events);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
@@ -207,15 +195,13 @@ public final class IntelligenceManager {

            if (VERBOSE) {
                Log.v(TAG, "onActivityDestroyed(): state=" + getStateAsStringLocked()
                        + ", localSessionId=" + mLocalSessionId
                        + ", mRemoteSessionId=" + mRemoteSessionId);
                        + ", mId=" + mId);
            }

            try {
                mService.finishSession(mContext.getUserId(), mApplicationToken, mComponentName,
                        mLocalSessionId, mRemoteSessionId);
                mService.finishSession(mContext.getUserId(), mId);
                mState = STATE_UNKNOWN;
                mLocalSessionId = mRemoteSessionId = NO_SESSION;
                mId = null;
                mApplicationToken = null;
                mComponentName = null;
            } catch (RemoteException e) {
@@ -334,12 +320,11 @@ public final class IntelligenceManager {
            pw.print(prefix2); pw.print("mService: "); pw.println(mService);
            pw.print(prefix2); pw.print("user: "); pw.println(mContext.getUserId());
            pw.print(prefix2); pw.print("enabled: "); pw.println(isContentCaptureEnabled());
            pw.print(prefix2); pw.print("mLocalSessionId: "); pw.println(mLocalSessionId);
            pw.print(prefix2); pw.print("mRemoteSessionId: "); pw.println(mRemoteSessionId);
            pw.print(prefix2); pw.print("mState: "); pw.print(mState); pw.print(" (");
            pw.print(prefix2); pw.print("id: "); pw.println(mId);
            pw.print(prefix2); pw.print("state: "); pw.print(mState); pw.print(" (");
            pw.print(getStateAsStringLocked()); pw.println(")");
            pw.print(prefix2); pw.print("mAppToken: "); pw.println(mApplicationToken);
            pw.print(prefix2); pw.print("mComponentName: "); pw.println(mComponentName);
            pw.print(prefix2); pw.print("appToken: "); pw.println(mApplicationToken);
            pw.print(prefix2); pw.print("componentName: "); pw.println(mComponentName);
        }
    }

@@ -353,8 +338,8 @@ public final class IntelligenceManager {
        switch (state) {
            case STATE_UNKNOWN:
                return "UNKNOWN";
            case STATE_WAITING_FOR_SESSION_ID:
                return "WAITING_FOR_SESSION_ID";
            case STATE_WAITING_FOR_SERVER:
                return "WAITING_FOR_SERVER";
            case STATE_ACTIVE:
                return "ACTIVE";
            default:
+9 −10
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.util.Slog;
import android.view.intelligence.ContentCaptureEvent;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.server.AbstractRemoteService;
import com.android.server.intelligence.RemoteIntelligenceService.RemoteIntelligenceServiceCallbacks;

@@ -47,15 +48,15 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks
    ContentCaptureSession(@NonNull Context context, int userId, @NonNull Object lock,
            @NonNull IBinder activityToken, @NonNull IntelligencePerUserService service,
            @NonNull ComponentName serviceComponentName, @NonNull ComponentName appComponentName,
            int taskId, int displayId, int localSessionId, int globalSessionId, int flags,
            int taskId, int displayId, @NonNull InteractionSessionId sessionId, int flags,
            boolean bindInstantServiceAllowed, boolean verbose) {
        mLock = lock;
        mActivityToken = activityToken;
        mService = service;
        mId = Preconditions.checkNotNull(sessionId);
        mRemoteService = new RemoteIntelligenceService(context,
                IntelligenceService.SERVICE_INTERFACE, serviceComponentName, userId, this,
                bindInstantServiceAllowed, verbose);
        mId = new InteractionSessionId(globalSessionId, localSessionId);
        mInterationContext = new InteractionContext(appComponentName, taskId, displayId, flags);
    }

@@ -88,7 +89,7 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks
                mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
            }
        } finally {
            mService.removeSessionLocked(mInterationContext.getActivityComponent());
            mService.removeSessionLocked(mId);
        }
    }

@@ -114,17 +115,15 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks
        }
    }

    /**
     * Gets global id, unique per {@link IntelligencePerUserService}.
     */
    public int getGlobalSessionId() {
        return mId.getGlobalId();
    }

    @GuardedBy("mLock")
    public void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
        pw.print(prefix); pw.print("id: ");  mId.dump(pw); pw.println();
        pw.print(prefix); pw.print("context: ");  mInterationContext.dump(pw); pw.println();
        pw.print(prefix); pw.print("activity token: "); pw.println(mActivityToken);
    }

    @Override
    public String toString() {
        return "ContentCaptureSession[id=" + mId.getValue() + ", act=" + mActivityToken + "]";
    }
}
+13 −12
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.os.IBinder;
import android.os.UserManager;
import android.service.intelligence.InteractionSessionId;
import android.view.intelligence.ContentCaptureEvent;
import android.view.intelligence.IIntelligenceManager;

@@ -87,9 +88,11 @@ public final class IntelligenceManagerService

        @Override
        public void startSession(int userId, @NonNull IBinder activityToken,
                @NonNull ComponentName componentName, int localSessionId, int flags,
                @NonNull IResultReceiver result) {
                @NonNull ComponentName componentName, @NonNull InteractionSessionId sessionId,
                int flags, @NonNull IResultReceiver result) {
            Preconditions.checkNotNull(activityToken);
            Preconditions.checkNotNull(componentName);
            Preconditions.checkNotNull(sessionId);

            // TODO(b/111276913): refactor getTaskIdForActivity() to also return ComponentName,
            // so we don't pass it on startSession (same for Autofill)
@@ -101,31 +104,29 @@ public final class IntelligenceManagerService
            synchronized (mLock) {
                final IntelligencePerUserService service = getServiceForUserLocked(userId);
                service.startSessionLocked(activityToken, componentName, taskId, displayId,
                        localSessionId, flags, result);
                        sessionId, flags, result);
            }
        }

        @Override
        public void sendEvents(int userId, @NonNull IBinder activityToken,
                @NonNull ComponentName componentName, int localSessionId, int globalSessionId,
                List<ContentCaptureEvent> events) {
        public void sendEvents(int userId, @NonNull InteractionSessionId sessionId,
                @NonNull List<ContentCaptureEvent> events) {
            Preconditions.checkNotNull(sessionId);
            Preconditions.checkNotNull(events);

            synchronized (mLock) {
                final IntelligencePerUserService service = getServiceForUserLocked(userId);
                service.sendEventsLocked(componentName, events);
                service.sendEventsLocked(sessionId, events);
            }
        }

        @Override
        public void finishSession(int userId, @NonNull IBinder activityToken,
                @NonNull ComponentName componentName, int localSessionId, int globalSessionId) {
            Preconditions.checkNotNull(activityToken);
        public void finishSession(int userId, @NonNull InteractionSessionId sessionId) {
            Preconditions.checkNotNull(sessionId);

            synchronized (mLock) {
                final IntelligencePerUserService service = getServiceForUserLocked(userId);
                service.finishSessionLocked(activityToken, componentName, localSessionId,
                        globalSessionId);
                service.finishSessionLocked(sessionId);
            }
        }

Loading