Merge "RESTRICT AUTOMERGE TextClassifier cross-user vulnerability in direct-reply" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
aced288d66
@@ -60,7 +60,9 @@ public final class ActionsModelParamsSupplier implements
|
|||||||
private boolean mParsed = true;
|
private boolean mParsed = true;
|
||||||
|
|
||||||
public ActionsModelParamsSupplier(Context context, @Nullable Runnable onChangedListener) {
|
public ActionsModelParamsSupplier(Context context, @Nullable Runnable onChangedListener) {
|
||||||
mAppContext = Preconditions.checkNotNull(context).getApplicationContext();
|
final Context appContext = Preconditions.checkNotNull(context).getApplicationContext();
|
||||||
|
// Some contexts don't have an app context.
|
||||||
|
mAppContext = appContext != null ? appContext : context;
|
||||||
mOnChangedListener = onChangedListener == null ? () -> {} : onChangedListener;
|
mOnChangedListener = onChangedListener == null ? () -> {} : onChangedListener;
|
||||||
mSettingsObserver = new SettingsObserver(mAppContext, () -> {
|
mSettingsObserver = new SettingsObserver(mAppContext, () -> {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ import android.annotation.IntRange;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.annotation.StringDef;
|
import android.annotation.StringDef;
|
||||||
|
import android.annotation.UserIdInt;
|
||||||
import android.app.Person;
|
import android.app.Person;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.text.SpannedString;
|
import android.text.SpannedString;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
@@ -316,6 +318,8 @@ public final class ConversationActions implements Parcelable {
|
|||||||
private final List<String> mHints;
|
private final List<String> mHints;
|
||||||
@Nullable
|
@Nullable
|
||||||
private String mCallingPackageName;
|
private String mCallingPackageName;
|
||||||
|
@UserIdInt
|
||||||
|
private int mUserId = UserHandle.USER_NULL;
|
||||||
@NonNull
|
@NonNull
|
||||||
private Bundle mExtras;
|
private Bundle mExtras;
|
||||||
|
|
||||||
@@ -340,6 +344,7 @@ public final class ConversationActions implements Parcelable {
|
|||||||
List<String> hints = new ArrayList<>();
|
List<String> hints = new ArrayList<>();
|
||||||
in.readStringList(hints);
|
in.readStringList(hints);
|
||||||
String callingPackageName = in.readString();
|
String callingPackageName = in.readString();
|
||||||
|
int userId = in.readInt();
|
||||||
Bundle extras = in.readBundle();
|
Bundle extras = in.readBundle();
|
||||||
Request request = new Request(
|
Request request = new Request(
|
||||||
conversation,
|
conversation,
|
||||||
@@ -348,6 +353,7 @@ public final class ConversationActions implements Parcelable {
|
|||||||
hints,
|
hints,
|
||||||
extras);
|
extras);
|
||||||
request.setCallingPackageName(callingPackageName);
|
request.setCallingPackageName(callingPackageName);
|
||||||
|
request.setUserId(userId);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,6 +364,7 @@ public final class ConversationActions implements Parcelable {
|
|||||||
parcel.writeInt(mMaxSuggestions);
|
parcel.writeInt(mMaxSuggestions);
|
||||||
parcel.writeStringList(mHints);
|
parcel.writeStringList(mHints);
|
||||||
parcel.writeString(mCallingPackageName);
|
parcel.writeString(mCallingPackageName);
|
||||||
|
parcel.writeInt(mUserId);
|
||||||
parcel.writeBundle(mExtras);
|
parcel.writeBundle(mExtras);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,6 +434,24 @@ public final class ConversationActions implements Parcelable {
|
|||||||
return mCallingPackageName;
|
return mCallingPackageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id of the user that sent this request.
|
||||||
|
* <p>
|
||||||
|
* Package-private for SystemTextClassifier's use.
|
||||||
|
*/
|
||||||
|
void setUserId(@UserIdInt int userId) {
|
||||||
|
mUserId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id of the user that sent this request.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@UserIdInt
|
||||||
|
public int getUserId() {
|
||||||
|
return mUserId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the extended data related to this request.
|
* Returns the extended data related to this request.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ package android.view.textclassifier;
|
|||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.UserIdInt;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.view.textclassifier.TextClassifier.EntityType;
|
import android.view.textclassifier.TextClassifier.EntityType;
|
||||||
import android.view.textclassifier.TextClassifier.WidgetType;
|
import android.view.textclassifier.TextClassifier.WidgetType;
|
||||||
|
|
||||||
@@ -127,6 +129,7 @@ public final class SelectionEvent implements Parcelable {
|
|||||||
private String mWidgetType = TextClassifier.WIDGET_TYPE_UNKNOWN;
|
private String mWidgetType = TextClassifier.WIDGET_TYPE_UNKNOWN;
|
||||||
private @InvocationMethod int mInvocationMethod;
|
private @InvocationMethod int mInvocationMethod;
|
||||||
@Nullable private String mWidgetVersion;
|
@Nullable private String mWidgetVersion;
|
||||||
|
private @UserIdInt int mUserId = UserHandle.USER_NULL;
|
||||||
@Nullable private String mResultId;
|
@Nullable private String mResultId;
|
||||||
private long mEventTime;
|
private long mEventTime;
|
||||||
private long mDurationSinceSessionStart;
|
private long mDurationSinceSessionStart;
|
||||||
@@ -158,6 +161,7 @@ public final class SelectionEvent implements Parcelable {
|
|||||||
mEntityType = in.readString();
|
mEntityType = in.readString();
|
||||||
mWidgetVersion = in.readInt() > 0 ? in.readString() : null;
|
mWidgetVersion = in.readInt() > 0 ? in.readString() : null;
|
||||||
mPackageName = in.readString();
|
mPackageName = in.readString();
|
||||||
|
mUserId = in.readInt();
|
||||||
mWidgetType = in.readString();
|
mWidgetType = in.readString();
|
||||||
mInvocationMethod = in.readInt();
|
mInvocationMethod = in.readInt();
|
||||||
mResultId = in.readString();
|
mResultId = in.readString();
|
||||||
@@ -184,6 +188,7 @@ public final class SelectionEvent implements Parcelable {
|
|||||||
dest.writeString(mWidgetVersion);
|
dest.writeString(mWidgetVersion);
|
||||||
}
|
}
|
||||||
dest.writeString(mPackageName);
|
dest.writeString(mPackageName);
|
||||||
|
dest.writeInt(mUserId);
|
||||||
dest.writeString(mWidgetType);
|
dest.writeString(mWidgetType);
|
||||||
dest.writeInt(mInvocationMethod);
|
dest.writeInt(mInvocationMethod);
|
||||||
dest.writeString(mResultId);
|
dest.writeString(mResultId);
|
||||||
@@ -400,6 +405,24 @@ public final class SelectionEvent implements Parcelable {
|
|||||||
return mPackageName;
|
return mPackageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id of this event's user.
|
||||||
|
* <p>
|
||||||
|
* Package-private for SystemTextClassifier's use.
|
||||||
|
*/
|
||||||
|
void setUserId(@UserIdInt int userId) {
|
||||||
|
mUserId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id of this event's user.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@UserIdInt
|
||||||
|
public int getUserId() {
|
||||||
|
return mUserId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the type of widget that was involved in triggering this event.
|
* Returns the type of widget that was involved in triggering this event.
|
||||||
*/
|
*/
|
||||||
@@ -426,6 +449,7 @@ public final class SelectionEvent implements Parcelable {
|
|||||||
mPackageName = context.getPackageName();
|
mPackageName = context.getPackageName();
|
||||||
mWidgetType = context.getWidgetType();
|
mWidgetType = context.getWidgetType();
|
||||||
mWidgetVersion = context.getWidgetVersion();
|
mWidgetVersion = context.getWidgetVersion();
|
||||||
|
mUserId = context.getUserId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -612,7 +636,7 @@ public final class SelectionEvent implements Parcelable {
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType,
|
return Objects.hash(mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType,
|
||||||
mWidgetVersion, mPackageName, mWidgetType, mInvocationMethod, mResultId,
|
mWidgetVersion, mPackageName, mUserId, mWidgetType, mInvocationMethod, mResultId,
|
||||||
mEventTime, mDurationSinceSessionStart, mDurationSincePreviousEvent,
|
mEventTime, mDurationSinceSessionStart, mDurationSincePreviousEvent,
|
||||||
mEventIndex, mSessionId, mStart, mEnd, mSmartStart, mSmartEnd);
|
mEventIndex, mSessionId, mStart, mEnd, mSmartStart, mSmartEnd);
|
||||||
}
|
}
|
||||||
@@ -633,6 +657,7 @@ public final class SelectionEvent implements Parcelable {
|
|||||||
&& Objects.equals(mEntityType, other.mEntityType)
|
&& Objects.equals(mEntityType, other.mEntityType)
|
||||||
&& Objects.equals(mWidgetVersion, other.mWidgetVersion)
|
&& Objects.equals(mWidgetVersion, other.mWidgetVersion)
|
||||||
&& Objects.equals(mPackageName, other.mPackageName)
|
&& Objects.equals(mPackageName, other.mPackageName)
|
||||||
|
&& mUserId == other.mUserId
|
||||||
&& Objects.equals(mWidgetType, other.mWidgetType)
|
&& Objects.equals(mWidgetType, other.mWidgetType)
|
||||||
&& mInvocationMethod == other.mInvocationMethod
|
&& mInvocationMethod == other.mInvocationMethod
|
||||||
&& Objects.equals(mResultId, other.mResultId)
|
&& Objects.equals(mResultId, other.mResultId)
|
||||||
@@ -652,12 +677,12 @@ public final class SelectionEvent implements Parcelable {
|
|||||||
return String.format(Locale.US,
|
return String.format(Locale.US,
|
||||||
"SelectionEvent {absoluteStart=%d, absoluteEnd=%d, eventType=%d, entityType=%s, "
|
"SelectionEvent {absoluteStart=%d, absoluteEnd=%d, eventType=%d, entityType=%s, "
|
||||||
+ "widgetVersion=%s, packageName=%s, widgetType=%s, invocationMethod=%s, "
|
+ "widgetVersion=%s, packageName=%s, widgetType=%s, invocationMethod=%s, "
|
||||||
+ "resultId=%s, eventTime=%d, durationSinceSessionStart=%d, "
|
+ "userId=%d, resultId=%s, eventTime=%d, durationSinceSessionStart=%d, "
|
||||||
+ "durationSincePreviousEvent=%d, eventIndex=%d,"
|
+ "durationSincePreviousEvent=%d, eventIndex=%d,"
|
||||||
+ "sessionId=%s, start=%d, end=%d, smartStart=%d, smartEnd=%d}",
|
+ "sessionId=%s, start=%d, end=%d, smartStart=%d, smartEnd=%d}",
|
||||||
mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType,
|
mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType,
|
||||||
mWidgetVersion, mPackageName, mWidgetType, mInvocationMethod,
|
mWidgetVersion, mPackageName, mWidgetType, mInvocationMethod,
|
||||||
mResultId, mEventTime, mDurationSinceSessionStart,
|
mUserId, mResultId, mEventTime, mDurationSinceSessionStart,
|
||||||
mDurationSincePreviousEvent, mEventIndex,
|
mDurationSincePreviousEvent, mEventIndex,
|
||||||
mSessionId, mStart, mEnd, mSmartStart, mSmartEnd);
|
mSessionId, mStart, mEnd, mSmartStart, mSmartEnd);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package android.view.textclassifier;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.UserIdInt;
|
||||||
import android.annotation.WorkerThread;
|
import android.annotation.WorkerThread;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -50,6 +51,10 @@ public final class SystemTextClassifier implements TextClassifier {
|
|||||||
private final TextClassificationConstants mSettings;
|
private final TextClassificationConstants mSettings;
|
||||||
private final TextClassifier mFallback;
|
private final TextClassifier mFallback;
|
||||||
private final String mPackageName;
|
private final String mPackageName;
|
||||||
|
// NOTE: Always set this before sending a request to the manager service otherwise the manager
|
||||||
|
// service will throw a remote exception.
|
||||||
|
@UserIdInt
|
||||||
|
private final int mUserId;
|
||||||
private TextClassificationSessionId mSessionId;
|
private TextClassificationSessionId mSessionId;
|
||||||
|
|
||||||
public SystemTextClassifier(Context context, TextClassificationConstants settings)
|
public SystemTextClassifier(Context context, TextClassificationConstants settings)
|
||||||
@@ -60,6 +65,7 @@ public final class SystemTextClassifier implements TextClassifier {
|
|||||||
mFallback = context.getSystemService(TextClassificationManager.class)
|
mFallback = context.getSystemService(TextClassificationManager.class)
|
||||||
.getTextClassifier(TextClassifier.LOCAL);
|
.getTextClassifier(TextClassifier.LOCAL);
|
||||||
mPackageName = Preconditions.checkNotNull(context.getOpPackageName());
|
mPackageName = Preconditions.checkNotNull(context.getOpPackageName());
|
||||||
|
mUserId = context.getUserId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,6 +78,7 @@ public final class SystemTextClassifier implements TextClassifier {
|
|||||||
Utils.checkMainThread();
|
Utils.checkMainThread();
|
||||||
try {
|
try {
|
||||||
request.setCallingPackageName(mPackageName);
|
request.setCallingPackageName(mPackageName);
|
||||||
|
request.setUserId(mUserId);
|
||||||
final BlockingCallback<TextSelection> callback =
|
final BlockingCallback<TextSelection> callback =
|
||||||
new BlockingCallback<>("textselection");
|
new BlockingCallback<>("textselection");
|
||||||
mManagerService.onSuggestSelection(mSessionId, request, callback);
|
mManagerService.onSuggestSelection(mSessionId, request, callback);
|
||||||
@@ -95,6 +102,7 @@ public final class SystemTextClassifier implements TextClassifier {
|
|||||||
Utils.checkMainThread();
|
Utils.checkMainThread();
|
||||||
try {
|
try {
|
||||||
request.setCallingPackageName(mPackageName);
|
request.setCallingPackageName(mPackageName);
|
||||||
|
request.setUserId(mUserId);
|
||||||
final BlockingCallback<TextClassification> callback =
|
final BlockingCallback<TextClassification> callback =
|
||||||
new BlockingCallback<>("textclassification");
|
new BlockingCallback<>("textclassification");
|
||||||
mManagerService.onClassifyText(mSessionId, request, callback);
|
mManagerService.onClassifyText(mSessionId, request, callback);
|
||||||
@@ -123,6 +131,7 @@ public final class SystemTextClassifier implements TextClassifier {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
request.setCallingPackageName(mPackageName);
|
request.setCallingPackageName(mPackageName);
|
||||||
|
request.setUserId(mUserId);
|
||||||
final BlockingCallback<TextLinks> callback =
|
final BlockingCallback<TextLinks> callback =
|
||||||
new BlockingCallback<>("textlinks");
|
new BlockingCallback<>("textlinks");
|
||||||
mManagerService.onGenerateLinks(mSessionId, request, callback);
|
mManagerService.onGenerateLinks(mSessionId, request, callback);
|
||||||
@@ -142,6 +151,7 @@ public final class SystemTextClassifier implements TextClassifier {
|
|||||||
Utils.checkMainThread();
|
Utils.checkMainThread();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
event.setUserId(mUserId);
|
||||||
mManagerService.onSelectionEvent(mSessionId, event);
|
mManagerService.onSelectionEvent(mSessionId, event);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(LOG_TAG, "Error reporting selection event.", e);
|
Log.e(LOG_TAG, "Error reporting selection event.", e);
|
||||||
@@ -154,6 +164,12 @@ public final class SystemTextClassifier implements TextClassifier {
|
|||||||
Utils.checkMainThread();
|
Utils.checkMainThread();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
final TextClassificationContext tcContext = event.getEventContext() == null
|
||||||
|
? new TextClassificationContext.Builder(mPackageName, WIDGET_TYPE_UNKNOWN)
|
||||||
|
.build()
|
||||||
|
: event.getEventContext();
|
||||||
|
tcContext.setUserId(mUserId);
|
||||||
|
event.setEventContext(tcContext);
|
||||||
mManagerService.onTextClassifierEvent(mSessionId, event);
|
mManagerService.onTextClassifierEvent(mSessionId, event);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(LOG_TAG, "Error reporting textclassifier event.", e);
|
Log.e(LOG_TAG, "Error reporting textclassifier event.", e);
|
||||||
@@ -167,6 +183,7 @@ public final class SystemTextClassifier implements TextClassifier {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
request.setCallingPackageName(mPackageName);
|
request.setCallingPackageName(mPackageName);
|
||||||
|
request.setUserId(mUserId);
|
||||||
final BlockingCallback<TextLanguage> callback =
|
final BlockingCallback<TextLanguage> callback =
|
||||||
new BlockingCallback<>("textlanguage");
|
new BlockingCallback<>("textlanguage");
|
||||||
mManagerService.onDetectLanguage(mSessionId, request, callback);
|
mManagerService.onDetectLanguage(mSessionId, request, callback);
|
||||||
@@ -187,6 +204,7 @@ public final class SystemTextClassifier implements TextClassifier {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
request.setCallingPackageName(mPackageName);
|
request.setCallingPackageName(mPackageName);
|
||||||
|
request.setUserId(mUserId);
|
||||||
final BlockingCallback<ConversationActions> callback =
|
final BlockingCallback<ConversationActions> callback =
|
||||||
new BlockingCallback<>("conversation-actions");
|
new BlockingCallback<>("conversation-actions");
|
||||||
mManagerService.onSuggestConversationActions(mSessionId, request, callback);
|
mManagerService.onSuggestConversationActions(mSessionId, request, callback);
|
||||||
@@ -228,6 +246,7 @@ public final class SystemTextClassifier implements TextClassifier {
|
|||||||
printWriter.printPair("mFallback", mFallback);
|
printWriter.printPair("mFallback", mFallback);
|
||||||
printWriter.printPair("mPackageName", mPackageName);
|
printWriter.printPair("mPackageName", mPackageName);
|
||||||
printWriter.printPair("mSessionId", mSessionId);
|
printWriter.printPair("mSessionId", mSessionId);
|
||||||
|
printWriter.printPair("mUserId", mUserId);
|
||||||
printWriter.decreaseIndent();
|
printWriter.decreaseIndent();
|
||||||
printWriter.println();
|
printWriter.println();
|
||||||
}
|
}
|
||||||
@@ -243,6 +262,7 @@ public final class SystemTextClassifier implements TextClassifier {
|
|||||||
@NonNull TextClassificationSessionId sessionId) {
|
@NonNull TextClassificationSessionId sessionId) {
|
||||||
mSessionId = Preconditions.checkNotNull(sessionId);
|
mSessionId = Preconditions.checkNotNull(sessionId);
|
||||||
try {
|
try {
|
||||||
|
classificationContext.setUserId(mUserId);
|
||||||
mManagerService.onCreateTextClassificationSession(classificationContext, mSessionId);
|
mManagerService.onCreateTextClassificationSession(classificationContext, mSessionId);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(LOG_TAG, "Error starting a new classification session.", e);
|
Log.e(LOG_TAG, "Error starting a new classification session.", e);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import android.annotation.IntDef;
|
|||||||
import android.annotation.IntRange;
|
import android.annotation.IntRange;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.UserIdInt;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.RemoteAction;
|
import android.app.RemoteAction;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -35,6 +36,7 @@ import android.os.Bundle;
|
|||||||
import android.os.LocaleList;
|
import android.os.LocaleList;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.text.SpannedString;
|
import android.text.SpannedString;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
@@ -551,6 +553,8 @@ public final class TextClassification implements Parcelable {
|
|||||||
@Nullable private final ZonedDateTime mReferenceTime;
|
@Nullable private final ZonedDateTime mReferenceTime;
|
||||||
@NonNull private final Bundle mExtras;
|
@NonNull private final Bundle mExtras;
|
||||||
@Nullable private String mCallingPackageName;
|
@Nullable private String mCallingPackageName;
|
||||||
|
@UserIdInt
|
||||||
|
private int mUserId = UserHandle.USER_NULL;
|
||||||
|
|
||||||
private Request(
|
private Request(
|
||||||
CharSequence text,
|
CharSequence text,
|
||||||
@@ -630,6 +634,24 @@ public final class TextClassification implements Parcelable {
|
|||||||
return mCallingPackageName;
|
return mCallingPackageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id of the user that sent this request.
|
||||||
|
* <p>
|
||||||
|
* Package-private for SystemTextClassifier's use.
|
||||||
|
*/
|
||||||
|
void setUserId(@UserIdInt int userId) {
|
||||||
|
mUserId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id of the user that sent this request.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@UserIdInt
|
||||||
|
public int getUserId() {
|
||||||
|
return mUserId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the extended data.
|
* Returns the extended data.
|
||||||
*
|
*
|
||||||
@@ -730,6 +752,7 @@ public final class TextClassification implements Parcelable {
|
|||||||
dest.writeParcelable(mDefaultLocales, flags);
|
dest.writeParcelable(mDefaultLocales, flags);
|
||||||
dest.writeString(mReferenceTime == null ? null : mReferenceTime.toString());
|
dest.writeString(mReferenceTime == null ? null : mReferenceTime.toString());
|
||||||
dest.writeString(mCallingPackageName);
|
dest.writeString(mCallingPackageName);
|
||||||
|
dest.writeInt(mUserId);
|
||||||
dest.writeBundle(mExtras);
|
dest.writeBundle(mExtras);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -742,11 +765,13 @@ public final class TextClassification implements Parcelable {
|
|||||||
final ZonedDateTime referenceTime = referenceTimeString == null
|
final ZonedDateTime referenceTime = referenceTimeString == null
|
||||||
? null : ZonedDateTime.parse(referenceTimeString);
|
? null : ZonedDateTime.parse(referenceTimeString);
|
||||||
final String callingPackageName = in.readString();
|
final String callingPackageName = in.readString();
|
||||||
|
final int userId = in.readInt();
|
||||||
final Bundle extras = in.readBundle();
|
final Bundle extras = in.readBundle();
|
||||||
|
|
||||||
final Request request = new Request(text, startIndex, endIndex,
|
final Request request = new Request(text, startIndex, endIndex,
|
||||||
defaultLocales, referenceTime, extras);
|
defaultLocales, referenceTime, extras);
|
||||||
request.setCallingPackageName(callingPackageName);
|
request.setCallingPackageName(callingPackageName);
|
||||||
|
request.setUserId(userId);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,10 @@ package android.view.textclassifier;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.UserIdInt;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.view.textclassifier.TextClassifier.WidgetType;
|
import android.view.textclassifier.TextClassifier.WidgetType;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
@@ -35,6 +37,8 @@ public final class TextClassificationContext implements Parcelable {
|
|||||||
private final String mPackageName;
|
private final String mPackageName;
|
||||||
private final String mWidgetType;
|
private final String mWidgetType;
|
||||||
@Nullable private final String mWidgetVersion;
|
@Nullable private final String mWidgetVersion;
|
||||||
|
@UserIdInt
|
||||||
|
private int mUserId = UserHandle.USER_NULL;
|
||||||
|
|
||||||
private TextClassificationContext(
|
private TextClassificationContext(
|
||||||
String packageName,
|
String packageName,
|
||||||
@@ -53,6 +57,24 @@ public final class TextClassificationContext implements Parcelable {
|
|||||||
return mPackageName;
|
return mPackageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id of this context's user.
|
||||||
|
* <p>
|
||||||
|
* Package-private for SystemTextClassifier's use.
|
||||||
|
*/
|
||||||
|
void setUserId(@UserIdInt int userId) {
|
||||||
|
mUserId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id of this context's user.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@UserIdInt
|
||||||
|
public int getUserId() {
|
||||||
|
return mUserId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the widget type for this classification context.
|
* Returns the widget type for this classification context.
|
||||||
*/
|
*/
|
||||||
@@ -75,8 +97,8 @@ public final class TextClassificationContext implements Parcelable {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format(Locale.US, "TextClassificationContext{"
|
return String.format(Locale.US, "TextClassificationContext{"
|
||||||
+ "packageName=%s, widgetType=%s, widgetVersion=%s}",
|
+ "packageName=%s, widgetType=%s, widgetVersion=%s, userId=%d}",
|
||||||
mPackageName, mWidgetType, mWidgetVersion);
|
mPackageName, mWidgetType, mWidgetVersion, mUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,12 +155,14 @@ public final class TextClassificationContext implements Parcelable {
|
|||||||
parcel.writeString(mPackageName);
|
parcel.writeString(mPackageName);
|
||||||
parcel.writeString(mWidgetType);
|
parcel.writeString(mWidgetType);
|
||||||
parcel.writeString(mWidgetVersion);
|
parcel.writeString(mWidgetVersion);
|
||||||
|
parcel.writeInt(mUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TextClassificationContext(Parcel in) {
|
private TextClassificationContext(Parcel in) {
|
||||||
mPackageName = in.readString();
|
mPackageName = in.readString();
|
||||||
mWidgetType = in.readString();
|
mWidgetType = in.readString();
|
||||||
mWidgetVersion = in.readString();
|
mWidgetVersion = in.readString();
|
||||||
|
mUserId = in.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final @android.annotation.NonNull Parcelable.Creator<TextClassificationContext> CREATOR =
|
public static final @android.annotation.NonNull Parcelable.Creator<TextClassificationContext> CREATOR =
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ public abstract class TextClassifierEvent implements Parcelable {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private final String[] mEntityTypes;
|
private final String[] mEntityTypes;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final TextClassificationContext mEventContext;
|
private TextClassificationContext mEventContext;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String mResultId;
|
private final String mResultId;
|
||||||
private final int mEventIndex;
|
private final int mEventIndex;
|
||||||
@@ -288,6 +288,15 @@ public abstract class TextClassifierEvent implements Parcelable {
|
|||||||
return mEventContext;
|
return mEventContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the event context.
|
||||||
|
* <p>
|
||||||
|
* Package-private for SystemTextClassifier's use.
|
||||||
|
*/
|
||||||
|
void setEventContext(@Nullable TextClassificationContext eventContext) {
|
||||||
|
mEventContext = eventContext;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the id of the text classifier result related to this event.
|
* Returns the id of the text classifier result related to this event.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ import android.annotation.FloatRange;
|
|||||||
import android.annotation.IntRange;
|
import android.annotation.IntRange;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.UserIdInt;
|
||||||
import android.icu.util.ULocale;
|
import android.icu.util.ULocale;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
@@ -226,6 +228,8 @@ public final class TextLanguage implements Parcelable {
|
|||||||
private final CharSequence mText;
|
private final CharSequence mText;
|
||||||
private final Bundle mExtra;
|
private final Bundle mExtra;
|
||||||
@Nullable private String mCallingPackageName;
|
@Nullable private String mCallingPackageName;
|
||||||
|
@UserIdInt
|
||||||
|
private int mUserId = UserHandle.USER_NULL;
|
||||||
|
|
||||||
private Request(CharSequence text, Bundle bundle) {
|
private Request(CharSequence text, Bundle bundle) {
|
||||||
mText = text;
|
mText = text;
|
||||||
@@ -259,6 +263,24 @@ public final class TextLanguage implements Parcelable {
|
|||||||
return mCallingPackageName;
|
return mCallingPackageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id of the user that sent this request.
|
||||||
|
* <p>
|
||||||
|
* Package-private for SystemTextClassifier's use.
|
||||||
|
*/
|
||||||
|
void setUserId(@UserIdInt int userId) {
|
||||||
|
mUserId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id of the user that sent this request.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@UserIdInt
|
||||||
|
public int getUserId() {
|
||||||
|
return mUserId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a bundle containing non-structured extra information about this request.
|
* Returns a bundle containing non-structured extra information about this request.
|
||||||
*
|
*
|
||||||
@@ -278,16 +300,19 @@ public final class TextLanguage implements Parcelable {
|
|||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeCharSequence(mText);
|
dest.writeCharSequence(mText);
|
||||||
dest.writeString(mCallingPackageName);
|
dest.writeString(mCallingPackageName);
|
||||||
|
dest.writeInt(mUserId);
|
||||||
dest.writeBundle(mExtra);
|
dest.writeBundle(mExtra);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Request readFromParcel(Parcel in) {
|
private static Request readFromParcel(Parcel in) {
|
||||||
final CharSequence text = in.readCharSequence();
|
final CharSequence text = in.readCharSequence();
|
||||||
final String callingPackageName = in.readString();
|
final String callingPackageName = in.readString();
|
||||||
|
final int userId = in.readInt();
|
||||||
final Bundle extra = in.readBundle();
|
final Bundle extra = in.readBundle();
|
||||||
|
|
||||||
final Request request = new Request(text, extra);
|
final Request request = new Request(text, extra);
|
||||||
request.setCallingPackageName(callingPackageName);
|
request.setCallingPackageName(callingPackageName);
|
||||||
|
request.setUserId(userId);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,13 @@ import android.annotation.FloatRange;
|
|||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.UserIdInt;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.LocaleList;
|
import android.os.LocaleList;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.method.MovementMethod;
|
import android.text.method.MovementMethod;
|
||||||
import android.text.style.ClickableSpan;
|
import android.text.style.ClickableSpan;
|
||||||
@@ -339,6 +341,8 @@ public final class TextLinks implements Parcelable {
|
|||||||
private final boolean mLegacyFallback;
|
private final boolean mLegacyFallback;
|
||||||
@Nullable private String mCallingPackageName;
|
@Nullable private String mCallingPackageName;
|
||||||
private final Bundle mExtras;
|
private final Bundle mExtras;
|
||||||
|
@UserIdInt
|
||||||
|
private int mUserId = UserHandle.USER_NULL;
|
||||||
|
|
||||||
private Request(
|
private Request(
|
||||||
CharSequence text,
|
CharSequence text,
|
||||||
@@ -409,6 +413,24 @@ public final class TextLinks implements Parcelable {
|
|||||||
return mCallingPackageName;
|
return mCallingPackageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id of the user that sent this request.
|
||||||
|
* <p>
|
||||||
|
* Package-private for SystemTextClassifier's use.
|
||||||
|
*/
|
||||||
|
void setUserId(@UserIdInt int userId) {
|
||||||
|
mUserId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id of the user that sent this request.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@UserIdInt
|
||||||
|
public int getUserId() {
|
||||||
|
return mUserId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the extended data.
|
* Returns the extended data.
|
||||||
*
|
*
|
||||||
@@ -509,6 +531,7 @@ public final class TextLinks implements Parcelable {
|
|||||||
dest.writeParcelable(mDefaultLocales, flags);
|
dest.writeParcelable(mDefaultLocales, flags);
|
||||||
dest.writeParcelable(mEntityConfig, flags);
|
dest.writeParcelable(mEntityConfig, flags);
|
||||||
dest.writeString(mCallingPackageName);
|
dest.writeString(mCallingPackageName);
|
||||||
|
dest.writeInt(mUserId);
|
||||||
dest.writeBundle(mExtras);
|
dest.writeBundle(mExtras);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,11 +540,13 @@ public final class TextLinks implements Parcelable {
|
|||||||
final LocaleList defaultLocales = in.readParcelable(null);
|
final LocaleList defaultLocales = in.readParcelable(null);
|
||||||
final EntityConfig entityConfig = in.readParcelable(null);
|
final EntityConfig entityConfig = in.readParcelable(null);
|
||||||
final String callingPackageName = in.readString();
|
final String callingPackageName = in.readString();
|
||||||
|
final int userId = in.readInt();
|
||||||
final Bundle extras = in.readBundle();
|
final Bundle extras = in.readBundle();
|
||||||
|
|
||||||
final Request request = new Request(text, defaultLocales, entityConfig,
|
final Request request = new Request(text, defaultLocales, entityConfig,
|
||||||
/* legacyFallback= */ true, extras);
|
/* legacyFallback= */ true, extras);
|
||||||
request.setCallingPackageName(callingPackageName);
|
request.setCallingPackageName(callingPackageName);
|
||||||
|
request.setUserId(userId);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ import android.annotation.FloatRange;
|
|||||||
import android.annotation.IntRange;
|
import android.annotation.IntRange;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.UserIdInt;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.LocaleList;
|
import android.os.LocaleList;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.text.SpannedString;
|
import android.text.SpannedString;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.view.textclassifier.TextClassifier.EntityType;
|
import android.view.textclassifier.TextClassifier.EntityType;
|
||||||
@@ -211,6 +213,8 @@ public final class TextSelection implements Parcelable {
|
|||||||
private final boolean mDarkLaunchAllowed;
|
private final boolean mDarkLaunchAllowed;
|
||||||
private final Bundle mExtras;
|
private final Bundle mExtras;
|
||||||
@Nullable private String mCallingPackageName;
|
@Nullable private String mCallingPackageName;
|
||||||
|
@UserIdInt
|
||||||
|
private int mUserId = UserHandle.USER_NULL;
|
||||||
|
|
||||||
private Request(
|
private Request(
|
||||||
CharSequence text,
|
CharSequence text,
|
||||||
@@ -291,6 +295,24 @@ public final class TextSelection implements Parcelable {
|
|||||||
return mCallingPackageName;
|
return mCallingPackageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id of the user that sent this request.
|
||||||
|
* <p>
|
||||||
|
* Package-private for SystemTextClassifier's use.
|
||||||
|
*/
|
||||||
|
void setUserId(@UserIdInt int userId) {
|
||||||
|
mUserId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id of the user that sent this request.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@UserIdInt
|
||||||
|
public int getUserId() {
|
||||||
|
return mUserId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the extended data.
|
* Returns the extended data.
|
||||||
*
|
*
|
||||||
@@ -394,6 +416,7 @@ public final class TextSelection implements Parcelable {
|
|||||||
dest.writeInt(mEndIndex);
|
dest.writeInt(mEndIndex);
|
||||||
dest.writeParcelable(mDefaultLocales, flags);
|
dest.writeParcelable(mDefaultLocales, flags);
|
||||||
dest.writeString(mCallingPackageName);
|
dest.writeString(mCallingPackageName);
|
||||||
|
dest.writeInt(mUserId);
|
||||||
dest.writeBundle(mExtras);
|
dest.writeBundle(mExtras);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,11 +426,13 @@ public final class TextSelection implements Parcelable {
|
|||||||
final int endIndex = in.readInt();
|
final int endIndex = in.readInt();
|
||||||
final LocaleList defaultLocales = in.readParcelable(null);
|
final LocaleList defaultLocales = in.readParcelable(null);
|
||||||
final String callingPackageName = in.readString();
|
final String callingPackageName = in.readString();
|
||||||
|
final int userId = in.readInt();
|
||||||
final Bundle extras = in.readBundle();
|
final Bundle extras = in.readBundle();
|
||||||
|
|
||||||
final Request request = new Request(text, startIndex, endIndex, defaultLocales,
|
final Request request = new Request(text, startIndex, endIndex, defaultLocales,
|
||||||
/* darkLaunchAllowed= */ false, extras);
|
/* darkLaunchAllowed= */ false, extras);
|
||||||
request.setCallingPackageName(callingPackageName);
|
request.setCallingPackageName(callingPackageName);
|
||||||
|
request.setUserId(userId);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11260,6 +11260,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
return getServiceManagerForUser(getContext().getPackageName(), ClipboardManager.class);
|
return getServiceManagerForUser(getContext().getPackageName(), ClipboardManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
final TextClassificationManager getTextClassificationManagerForUser() {
|
||||||
|
return getServiceManagerForUser(
|
||||||
|
getContext().getPackageName(), TextClassificationManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
final <T> T getServiceManagerForUser(String packageName, Class<T> managerClazz) {
|
final <T> T getServiceManagerForUser(String packageName, Class<T> managerClazz) {
|
||||||
if (mTextOperationUser == null) {
|
if (mTextOperationUser == null) {
|
||||||
@@ -12354,8 +12360,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
@NonNull
|
@NonNull
|
||||||
public TextClassifier getTextClassifier() {
|
public TextClassifier getTextClassifier() {
|
||||||
if (mTextClassifier == null) {
|
if (mTextClassifier == null) {
|
||||||
final TextClassificationManager tcm =
|
final TextClassificationManager tcm = getTextClassificationManagerForUser();
|
||||||
mContext.getSystemService(TextClassificationManager.class);
|
|
||||||
if (tcm != null) {
|
if (tcm != null) {
|
||||||
return tcm.getTextClassifier();
|
return tcm.getTextClassifier();
|
||||||
}
|
}
|
||||||
@@ -12371,8 +12376,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
@NonNull
|
@NonNull
|
||||||
TextClassifier getTextClassificationSession() {
|
TextClassifier getTextClassificationSession() {
|
||||||
if (mTextClassificationSession == null || mTextClassificationSession.isDestroyed()) {
|
if (mTextClassificationSession == null || mTextClassificationSession.isDestroyed()) {
|
||||||
final TextClassificationManager tcm =
|
final TextClassificationManager tcm = getTextClassificationManagerForUser();
|
||||||
mContext.getSystemService(TextClassificationManager.class);
|
|
||||||
if (tcm != null) {
|
if (tcm != null) {
|
||||||
final String widgetType;
|
final String widgetType;
|
||||||
if (isTextEditable()) {
|
if (isTextEditable()) {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import android.os.UserHandle;
|
|||||||
import android.service.textclassifier.ITextClassifierCallback;
|
import android.service.textclassifier.ITextClassifierCallback;
|
||||||
import android.service.textclassifier.ITextClassifierService;
|
import android.service.textclassifier.ITextClassifierService;
|
||||||
import android.service.textclassifier.TextClassifierService;
|
import android.service.textclassifier.TextClassifierService;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.textclassifier.ConversationActions;
|
import android.view.textclassifier.ConversationActions;
|
||||||
@@ -54,6 +55,7 @@ import com.android.server.SystemService;
|
|||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,6 +121,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
private final Object mLock;
|
private final Object mLock;
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
final SparseArray<UserState> mUserStates = new SparseArray<>();
|
final SparseArray<UserState> mUserStates = new SparseArray<>();
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private final Map<TextClassificationSessionId, Integer> mSessionUserIds = new ArrayMap<>();
|
||||||
|
|
||||||
private TextClassificationManagerService(Context context) {
|
private TextClassificationManagerService(Context context) {
|
||||||
mContext = Preconditions.checkNotNull(context);
|
mContext = Preconditions.checkNotNull(context);
|
||||||
@@ -127,15 +131,16 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuggestSelection(
|
public void onSuggestSelection(
|
||||||
TextClassificationSessionId sessionId,
|
@Nullable TextClassificationSessionId sessionId,
|
||||||
TextSelection.Request request, ITextClassifierCallback callback)
|
TextSelection.Request request, ITextClassifierCallback callback)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
Preconditions.checkNotNull(request);
|
Preconditions.checkNotNull(request);
|
||||||
Preconditions.checkNotNull(callback);
|
Preconditions.checkNotNull(callback);
|
||||||
validateInput(mContext, request.getCallingPackageName());
|
final int userId = request.getUserId();
|
||||||
|
validateInput(mContext, request.getCallingPackageName(), userId);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
UserState userState = getCallingUserStateLocked();
|
UserState userState = getUserStateLocked(userId);
|
||||||
if (!userState.bindLocked()) {
|
if (!userState.bindLocked()) {
|
||||||
callback.onFailure();
|
callback.onFailure();
|
||||||
} else if (userState.isBoundLocked()) {
|
} else if (userState.isBoundLocked()) {
|
||||||
@@ -150,15 +155,16 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClassifyText(
|
public void onClassifyText(
|
||||||
TextClassificationSessionId sessionId,
|
@Nullable TextClassificationSessionId sessionId,
|
||||||
TextClassification.Request request, ITextClassifierCallback callback)
|
TextClassification.Request request, ITextClassifierCallback callback)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
Preconditions.checkNotNull(request);
|
Preconditions.checkNotNull(request);
|
||||||
Preconditions.checkNotNull(callback);
|
Preconditions.checkNotNull(callback);
|
||||||
validateInput(mContext, request.getCallingPackageName());
|
final int userId = request.getUserId();
|
||||||
|
validateInput(mContext, request.getCallingPackageName(), userId);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
UserState userState = getCallingUserStateLocked();
|
UserState userState = getUserStateLocked(userId);
|
||||||
if (!userState.bindLocked()) {
|
if (!userState.bindLocked()) {
|
||||||
callback.onFailure();
|
callback.onFailure();
|
||||||
} else if (userState.isBoundLocked()) {
|
} else if (userState.isBoundLocked()) {
|
||||||
@@ -173,15 +179,16 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGenerateLinks(
|
public void onGenerateLinks(
|
||||||
TextClassificationSessionId sessionId,
|
@Nullable TextClassificationSessionId sessionId,
|
||||||
TextLinks.Request request, ITextClassifierCallback callback)
|
TextLinks.Request request, ITextClassifierCallback callback)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
Preconditions.checkNotNull(request);
|
Preconditions.checkNotNull(request);
|
||||||
Preconditions.checkNotNull(callback);
|
Preconditions.checkNotNull(callback);
|
||||||
validateInput(mContext, request.getCallingPackageName());
|
final int userId = request.getUserId();
|
||||||
|
validateInput(mContext, request.getCallingPackageName(), userId);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
UserState userState = getCallingUserStateLocked();
|
UserState userState = getUserStateLocked(userId);
|
||||||
if (!userState.bindLocked()) {
|
if (!userState.bindLocked()) {
|
||||||
callback.onFailure();
|
callback.onFailure();
|
||||||
} else if (userState.isBoundLocked()) {
|
} else if (userState.isBoundLocked()) {
|
||||||
@@ -196,12 +203,14 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSelectionEvent(
|
public void onSelectionEvent(
|
||||||
TextClassificationSessionId sessionId, SelectionEvent event) throws RemoteException {
|
@Nullable TextClassificationSessionId sessionId, SelectionEvent event)
|
||||||
|
throws RemoteException {
|
||||||
Preconditions.checkNotNull(event);
|
Preconditions.checkNotNull(event);
|
||||||
validateInput(mContext, event.getPackageName());
|
final int userId = event.getUserId();
|
||||||
|
validateInput(mContext, event.getPackageName(), userId);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
UserState userState = getCallingUserStateLocked();
|
UserState userState = getUserStateLocked(userId);
|
||||||
if (userState.isBoundLocked()) {
|
if (userState.isBoundLocked()) {
|
||||||
userState.mService.onSelectionEvent(sessionId, event);
|
userState.mService.onSelectionEvent(sessionId, event);
|
||||||
} else {
|
} else {
|
||||||
@@ -213,16 +222,19 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onTextClassifierEvent(
|
public void onTextClassifierEvent(
|
||||||
TextClassificationSessionId sessionId,
|
@Nullable TextClassificationSessionId sessionId,
|
||||||
TextClassifierEvent event) throws RemoteException {
|
TextClassifierEvent event) throws RemoteException {
|
||||||
Preconditions.checkNotNull(event);
|
Preconditions.checkNotNull(event);
|
||||||
final String packageName = event.getEventContext() == null
|
final String packageName = event.getEventContext() == null
|
||||||
? null
|
? null
|
||||||
: event.getEventContext().getPackageName();
|
: event.getEventContext().getPackageName();
|
||||||
validateInput(mContext, packageName);
|
final int userId = event.getEventContext() == null
|
||||||
|
? UserHandle.getCallingUserId()
|
||||||
|
: event.getEventContext().getUserId();
|
||||||
|
validateInput(mContext, packageName, userId);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
UserState userState = getCallingUserStateLocked();
|
UserState userState = getUserStateLocked(userId);
|
||||||
if (userState.isBoundLocked()) {
|
if (userState.isBoundLocked()) {
|
||||||
userState.mService.onTextClassifierEvent(sessionId, event);
|
userState.mService.onTextClassifierEvent(sessionId, event);
|
||||||
} else {
|
} else {
|
||||||
@@ -235,15 +247,16 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDetectLanguage(
|
public void onDetectLanguage(
|
||||||
TextClassificationSessionId sessionId,
|
@Nullable TextClassificationSessionId sessionId,
|
||||||
TextLanguage.Request request,
|
TextLanguage.Request request,
|
||||||
ITextClassifierCallback callback) throws RemoteException {
|
ITextClassifierCallback callback) throws RemoteException {
|
||||||
Preconditions.checkNotNull(request);
|
Preconditions.checkNotNull(request);
|
||||||
Preconditions.checkNotNull(callback);
|
Preconditions.checkNotNull(callback);
|
||||||
validateInput(mContext, request.getCallingPackageName());
|
final int userId = request.getUserId();
|
||||||
|
validateInput(mContext, request.getCallingPackageName(), userId);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
UserState userState = getCallingUserStateLocked();
|
UserState userState = getUserStateLocked(userId);
|
||||||
if (!userState.bindLocked()) {
|
if (!userState.bindLocked()) {
|
||||||
callback.onFailure();
|
callback.onFailure();
|
||||||
} else if (userState.isBoundLocked()) {
|
} else if (userState.isBoundLocked()) {
|
||||||
@@ -258,15 +271,16 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuggestConversationActions(
|
public void onSuggestConversationActions(
|
||||||
TextClassificationSessionId sessionId,
|
@Nullable TextClassificationSessionId sessionId,
|
||||||
ConversationActions.Request request,
|
ConversationActions.Request request,
|
||||||
ITextClassifierCallback callback) throws RemoteException {
|
ITextClassifierCallback callback) throws RemoteException {
|
||||||
Preconditions.checkNotNull(request);
|
Preconditions.checkNotNull(request);
|
||||||
Preconditions.checkNotNull(callback);
|
Preconditions.checkNotNull(callback);
|
||||||
validateInput(mContext, request.getCallingPackageName());
|
final int userId = request.getUserId();
|
||||||
|
validateInput(mContext, request.getCallingPackageName(), userId);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
UserState userState = getCallingUserStateLocked();
|
UserState userState = getUserStateLocked(userId);
|
||||||
if (!userState.bindLocked()) {
|
if (!userState.bindLocked()) {
|
||||||
callback.onFailure();
|
callback.onFailure();
|
||||||
} else if (userState.isBoundLocked()) {
|
} else if (userState.isBoundLocked()) {
|
||||||
@@ -285,13 +299,15 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
Preconditions.checkNotNull(sessionId);
|
Preconditions.checkNotNull(sessionId);
|
||||||
Preconditions.checkNotNull(classificationContext);
|
Preconditions.checkNotNull(classificationContext);
|
||||||
validateInput(mContext, classificationContext.getPackageName());
|
final int userId = classificationContext.getUserId();
|
||||||
|
validateInput(mContext, classificationContext.getPackageName(), userId);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
UserState userState = getCallingUserStateLocked();
|
UserState userState = getUserStateLocked(userId);
|
||||||
if (userState.isBoundLocked()) {
|
if (userState.isBoundLocked()) {
|
||||||
userState.mService.onCreateTextClassificationSession(
|
userState.mService.onCreateTextClassificationSession(
|
||||||
classificationContext, sessionId);
|
classificationContext, sessionId);
|
||||||
|
mSessionUserIds.put(sessionId, userId);
|
||||||
} else {
|
} else {
|
||||||
userState.mPendingRequests.add(new PendingRequest(
|
userState.mPendingRequests.add(new PendingRequest(
|
||||||
() -> onCreateTextClassificationSession(classificationContext, sessionId),
|
() -> onCreateTextClassificationSession(classificationContext, sessionId),
|
||||||
@@ -306,9 +322,15 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
Preconditions.checkNotNull(sessionId);
|
Preconditions.checkNotNull(sessionId);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
UserState userState = getCallingUserStateLocked();
|
final int userId = mSessionUserIds.containsKey(sessionId)
|
||||||
|
? mSessionUserIds.get(sessionId)
|
||||||
|
: UserHandle.getCallingUserId();
|
||||||
|
validateInput(mContext, null /* packageName */, userId);
|
||||||
|
|
||||||
|
UserState userState = getUserStateLocked(userId);
|
||||||
if (userState.isBoundLocked()) {
|
if (userState.isBoundLocked()) {
|
||||||
userState.mService.onDestroyTextClassificationSession(sessionId);
|
userState.mService.onDestroyTextClassificationSession(sessionId);
|
||||||
|
mSessionUserIds.remove(sessionId);
|
||||||
} else {
|
} else {
|
||||||
userState.mPendingRequests.add(new PendingRequest(
|
userState.mPendingRequests.add(new PendingRequest(
|
||||||
() -> onDestroyTextClassificationSession(sessionId),
|
() -> onDestroyTextClassificationSession(sessionId),
|
||||||
@@ -317,11 +339,6 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
|
||||||
private UserState getCallingUserStateLocked() {
|
|
||||||
return getUserStateLocked(UserHandle.getCallingUserId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private UserState getUserStateLocked(int userId) {
|
private UserState getUserStateLocked(int userId) {
|
||||||
UserState result = mUserStates.get(userId);
|
UserState result = mUserStates.get(userId);
|
||||||
@@ -356,6 +373,7 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
pw.decreaseIndent();
|
pw.decreaseIndent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pw.println("Number of active sessions: " + mSessionUserIds.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,20 +438,32 @@ public final class TextClassificationManagerService extends ITextClassifierServi
|
|||||||
e -> Slog.d(LOG_TAG, "Error " + opDesc + ": " + e.getMessage()));
|
e -> Slog.d(LOG_TAG, "Error " + opDesc + ": " + e.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void validateInput(Context context, @Nullable String packageName)
|
private static void validateInput(
|
||||||
|
Context context, @Nullable String packageName, @UserIdInt int userId)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
if (packageName == null) return;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (packageName != null) {
|
||||||
final int packageUid = context.getPackageManager()
|
final int packageUid = context.getPackageManager()
|
||||||
.getPackageUidAsUser(packageName, UserHandle.getCallingUserId());
|
.getPackageUidAsUser(packageName, UserHandle.getCallingUserId());
|
||||||
final int callingUid = Binder.getCallingUid();
|
final int callingUid = Binder.getCallingUid();
|
||||||
Preconditions.checkArgument(callingUid == packageUid
|
Preconditions.checkArgument(callingUid == packageUid
|
||||||
// Trust the system process:
|
// Trust the system process:
|
||||||
|| callingUid == android.os.Process.SYSTEM_UID);
|
|| callingUid == android.os.Process.SYSTEM_UID,
|
||||||
|
"Invalid package name. Package=" + packageName
|
||||||
|
+ ", CallingUid=" + callingUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
Preconditions.checkArgument(userId != UserHandle.USER_NULL, "Null userId");
|
||||||
|
final int callingUserId = UserHandle.getCallingUserId();
|
||||||
|
if (callingUserId != userId) {
|
||||||
|
context.enforceCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
|
||||||
|
"Invalid userId. UserId=" + userId + ", CallingUserId=" + callingUserId);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RemoteException(
|
throw new RemoteException("Invalid request: " + e.getMessage(), e,
|
||||||
String.format("Invalid package: name=%s, error=%s", packageName, e));
|
/* enableSuppression */ true, /* writableStackTrace */ true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user