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
This commit is contained in:
Felipe Leme
2018-11-05 16:29:29 -08:00
parent 7a53408d19
commit a7bdb1486e
6 changed files with 136 additions and 122 deletions

View File

@@ -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;
/** @hide */
public InteractionSessionId(int globalId, int localId) {
mGlobalId = globalId;
mLocalId = localId;
/**
* Creates a new instance.
*
* @hide
*/
public InteractionSessionId() {
this(UUID.randomUUID().toString());
}
/** @hide */
public int getGlobalId() {
return mGlobalId;
/**
* Creates a new instance.
*
* @param value The internal value.
*
* @hide
*/
public InteractionSessionId(@NonNull String value) {
mValue = value;
}
/**
* @hide
*/
public String getValue() {
return mValue;
}
@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 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 String toString() {
return "SessionId[globalId=" + mGlobalId + ", localId=" + mLocalId + "]";
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

View File

@@ -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);
}

View File

@@ -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
@Nullable
@GuardedBy("mLock")
private int mLocalSessionId = NO_SESSION;
@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: