diff options
| author | 2018-11-05 16:29:29 -0800 | |
|---|---|---|
| committer | 2018-11-06 13:09:03 -0800 | |
| commit | a7bdb1486e9dd99d044cc79d640e31d02c21d452 (patch) | |
| tree | 9de4391111ad49657b99867003b4f4a002e71b1e | |
| parent | 7a53408d196d6a288d9a6745d98db697cb2a411f (diff) | |
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
6 files changed, 134 insertions, 120 deletions
diff --git a/core/java/android/service/intelligence/InteractionSessionId.java b/core/java/android/service/intelligence/InteractionSessionId.java index ca68f8efdbd3..a2971ae3c594 100644 --- a/core/java/android/service/intelligence/InteractionSessionId.java +++ b/core/java/android/service/intelligence/InteractionSessionId.java @@ -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 diff --git a/core/java/android/view/intelligence/IIntelligenceManager.aidl b/core/java/android/view/intelligence/IIntelligenceManager.aidl index 7bbe99a9ad48..2f128de1f53d 100644 --- a/core/java/android/view/intelligence/IIntelligenceManager.aidl +++ b/core/java/android/view/intelligence/IIntelligenceManager.aidl @@ -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); } diff --git a/core/java/android/view/intelligence/IntelligenceManager.java b/core/java/android/view/intelligence/IntelligenceManager.java index a30d77e4d446..9bf6c2ce6184 100644 --- a/core/java/android/view/intelligence/IntelligenceManager.java +++ b/core/java/android/view/intelligence/IntelligenceManager.java @@ -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: diff --git a/services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java b/services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java index 14b28d32d22a..9cab1ed15b9e 100644 --- a/services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java +++ b/services/autofill/java/com/android/server/intelligence/ContentCaptureSession.java @@ -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 + "]"; + } } diff --git a/services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java index d67c15b01f0c..43d4a4476c11 100644 --- a/services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java +++ b/services/autofill/java/com/android/server/intelligence/IntelligenceManagerService.java @@ -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); } } diff --git a/services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java index 1d988192125c..584b872c64d0 100644 --- a/services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java +++ b/services/autofill/java/com/android/server/intelligence/IntelligencePerUserService.java @@ -25,9 +25,11 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ServiceInfo; import android.os.IBinder; import android.os.RemoteException; +import android.service.intelligence.InteractionSessionId; import android.util.ArrayMap; import android.util.Slog; import android.view.intelligence.ContentCaptureEvent; +import android.view.intelligence.IntelligenceManager; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.IResultReceiver; @@ -44,11 +46,9 @@ final class IntelligencePerUserService private static final String TAG = "IntelligencePerUserService"; - private static int sNextSessionId; - - // TODO(b/111276913): should key by componentName + taskId or ActivityToken @GuardedBy("mLock") - private final ArrayMap<ComponentName, ContentCaptureSession> mSessions = new ArrayMap<>(); + private final ArrayMap<InteractionSessionId, ContentCaptureSession> mSessions = + new ArrayMap<>(); // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's @@ -85,8 +85,9 @@ final class IntelligencePerUserService // TODO(b/111276913): log metrics @GuardedBy("mLock") public void startSessionLocked(@NonNull IBinder activityToken, - @NonNull ComponentName componentName, int taskId, int displayId, int localSessionId, - int flags, @NonNull IResultReceiver resultReceiver) { + @NonNull ComponentName componentName, int taskId, int displayId, + @NonNull InteractionSessionId sessionId, int flags, + @NonNull IResultReceiver resultReceiver) { final ComponentName serviceComponentName = getServiceComponentName(); if (serviceComponentName == null) { // TODO(b/111276913): this happens when the system service is starting, we should @@ -96,16 +97,16 @@ final class IntelligencePerUserService return; } - ContentCaptureSession session = mSessions.get(componentName); + ContentCaptureSession session = mSessions.get(sessionId); if (session != null) { if (mMaster.debug) { - Slog.d(TAG, "startSession(): reusing session " + session.getGlobalSessionId() - + " for " + componentName); + Slog.d(TAG, "startSession(): reusing session " + sessionId + " for " + + componentName); } // TODO(b/111276913): check if local ids match and decide what to do if they don't // TODO(b/111276913): should we call session.notifySessionStartedLocked() again?? // if not, move notifySessionStartedLocked() into session constructor - sendToClient(resultReceiver, session.getGlobalSessionId()); + sendToClient(resultReceiver, IntelligenceManager.STATE_ACTIVE); return; } @@ -113,59 +114,53 @@ final class IntelligencePerUserService final boolean bindInstantServiceAllowed = false; session = new ContentCaptureSession(getContext(), mUserId, mLock, activityToken, - this, serviceComponentName, componentName, taskId, displayId, localSessionId, - ++sNextSessionId, flags, bindInstantServiceAllowed, mMaster.verbose); + this, serviceComponentName, componentName, taskId, displayId, sessionId, flags, + bindInstantServiceAllowed, mMaster.verbose); if (mMaster.verbose) { - Slog.v(TAG, "startSession(): new session for " + componentName + "; globalId =" - + session.getGlobalSessionId()); + Slog.v(TAG, "startSession(): new session for " + componentName + " and id " + + sessionId); } - mSessions.put(componentName, session); + mSessions.put(sessionId, session); session.notifySessionStartedLocked(); - sendToClient(resultReceiver, session.getGlobalSessionId()); + sendToClient(resultReceiver, IntelligenceManager.STATE_ACTIVE); } // TODO(b/111276913): log metrics @GuardedBy("mLock") - public void finishSessionLocked(@NonNull IBinder activityToken, - @NonNull ComponentName componentName, int localSessionId, int globalSessionId) { - final ContentCaptureSession session = mSessions.get(componentName); + public void finishSessionLocked(@NonNull InteractionSessionId sessionId) { + final ContentCaptureSession session = mSessions.get(sessionId); if (session == null) { - Slog.w(TAG, "finishSession(): no session for " + componentName); + Slog.w(TAG, "finishSession(): no session with id" + sessionId); return; } if (mMaster.verbose) { - Slog.v(TAG, "finishSession(): comp=" + componentName + "; globalId =" - + session.getGlobalSessionId()); + Slog.v(TAG, "finishSession(): " + session); } - // TODO(b/111276913): check if all arguments match existing session and throw exception if - // not. Or just use componentName if we change AIDL to pass just ApplicationToken and - // retrieve componentName from AMInternal session.removeSelfLocked(true); } @GuardedBy("mLock") - public void sendEventsLocked(@NonNull ComponentName componentName, + public void sendEventsLocked(@NonNull InteractionSessionId sessionId, @NonNull List<ContentCaptureEvent> events) { - final ContentCaptureSession session = mSessions.get(componentName); + final ContentCaptureSession session = mSessions.get(sessionId); if (session == null) { - Slog.w(TAG, "sendEventsLocked(): no session for " + componentName); + Slog.w(TAG, "sendEvents(): no session for " + sessionId); return; } if (mMaster.verbose) { - Slog.v(TAG, "sendEventsLocked(): comp=" + componentName + "; events =" + events.size()); + Slog.v(TAG, "sendEvents(): id=" + sessionId + "; events =" + events.size()); } session.sendEventsLocked(events); } @GuardedBy("mLock") - public void removeSessionLocked(@NonNull ComponentName key) { - mSessions.remove(key); + public void removeSessionLocked(@NonNull InteractionSessionId sessionId) { + mSessions.remove(sessionId); } @Override protected void dumpLocked(String prefix, PrintWriter pw) { super.dumpLocked(prefix, pw); - pw.print(prefix); pw.print("next id: "); pw.println(sNextSessionId); if (mSessions.isEmpty()) { pw.print(prefix); pw.println("no sessions"); } else { @@ -187,5 +182,4 @@ final class IntelligencePerUserService Slog.w(TAG, "Error async reporting result to client: " + e); } } - } |