Merge "Rename cts-amwm-util to cts-wm-util" into qt-dev
diff --git a/api/current.txt b/api/current.txt
index 8ec7594..f602c9a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -51509,6 +51509,7 @@
method public android.transition.Transition getSharedElementReturnTransition();
method public boolean getSharedElementsUseOverlay();
method @ColorInt public abstract int getStatusBarColor();
+ method @NonNull public java.util.List<android.graphics.Rect> getSystemGestureExclusionRects();
method public long getTransitionBackgroundFadeDuration();
method public android.transition.TransitionManager getTransitionManager();
method public abstract int getVolumeControlStream();
@@ -51587,6 +51588,7 @@
method public void setSoftInputMode(int);
method public abstract void setStatusBarColor(@ColorInt int);
method public void setSustainedPerformanceMode(boolean);
+ method public void setSystemGestureExclusionRects(@NonNull java.util.List<android.graphics.Rect>);
method public abstract void setTitle(CharSequence);
method @Deprecated public abstract void setTitleColor(@ColorInt int);
method public void setTransitionBackgroundFadeDuration(long);
@@ -53614,29 +53616,23 @@
method @NonNull public android.view.textclassifier.TextClassifier.EntityConfig.Builder setIncludedTypes(@Nullable java.util.Collection<java.lang.String>);
}
- public final class TextClassifierEvent implements android.os.Parcelable {
+ public abstract class TextClassifierEvent implements android.os.Parcelable {
method public int describeContents();
method @NonNull public int[] getActionIndices();
method @NonNull public String[] getEntityTypes();
method public int getEventCategory();
method @Nullable public android.view.textclassifier.TextClassificationContext getEventContext();
method public int getEventIndex();
- method public long getEventTime();
method public int getEventType();
method @NonNull public android.os.Bundle getExtras();
- method @Nullable public String getLanguage();
- method public int getRelativeSuggestedWordEndIndex();
- method public int getRelativeSuggestedWordStartIndex();
- method public int getRelativeWordEndIndex();
- method public int getRelativeWordStartIndex();
+ method @Nullable public String getModelName();
method @Nullable public String getResultId();
- method public float getScore();
+ method @NonNull public float[] getScores();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CATEGORY_CONVERSATION_ACTIONS = 3; // 0x3
field public static final int CATEGORY_LANGUAGE_DETECTION = 4; // 0x4
field public static final int CATEGORY_LINKIFY = 2; // 0x2
field public static final int CATEGORY_SELECTION = 1; // 0x1
- field public static final int CATEGORY_UNDEFINED = 0; // 0x0
field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent> CREATOR;
field public static final int TYPE_ACTIONS_GENERATED = 20; // 0x14
field public static final int TYPE_ACTIONS_SHOWN = 6; // 0x6
@@ -53658,25 +53654,63 @@
field public static final int TYPE_SMART_ACTION = 13; // 0xd
field public static final int TYPE_SMART_SELECTION_MULTI = 4; // 0x4
field public static final int TYPE_SMART_SELECTION_SINGLE = 3; // 0x3
- field public static final int TYPE_UNDEFINED = 0; // 0x0
}
- public static final class TextClassifierEvent.Builder {
- ctor public TextClassifierEvent.Builder(int, int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent build();
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setActionIndices(@NonNull int...);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEntityTypes(@NonNull java.lang.String...);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEventContext(@Nullable android.view.textclassifier.TextClassificationContext);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEventIndex(int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEventTime(long);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setExtras(@NonNull android.os.Bundle);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setLanguage(@Nullable String);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeSuggestedWordEndIndex(int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeSuggestedWordStartIndex(int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeWordEndIndex(int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeWordStartIndex(int);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setResultId(@Nullable String);
- method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setScore(float);
+ public abstract static class TextClassifierEvent.Builder<T extends android.view.textclassifier.TextClassifierEvent.Builder<T>> {
+ method @NonNull public T setActionIndices(@NonNull int...);
+ method @NonNull public T setEntityTypes(@NonNull java.lang.String...);
+ method @NonNull public T setEventContext(@Nullable android.view.textclassifier.TextClassificationContext);
+ method @NonNull public T setEventIndex(int);
+ method @NonNull public T setExtras(@NonNull android.os.Bundle);
+ method @NonNull public T setModelName(@Nullable String);
+ method @NonNull public T setResultId(@Nullable String);
+ method @NonNull public T setScores(@NonNull float...);
+ }
+
+ public static final class TextClassifierEvent.ConversationActionsEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.ConversationActionsEvent> CREATOR;
+ }
+
+ public static final class TextClassifierEvent.ConversationActionsEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.ConversationActionsEvent.Builder> {
+ ctor public TextClassifierEvent.ConversationActionsEvent.Builder(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.ConversationActionsEvent build();
+ }
+
+ public static final class TextClassifierEvent.LanguageDetectionEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+ method @Nullable public android.icu.util.ULocale getLocale();
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent> CREATOR;
+ }
+
+ public static final class TextClassifierEvent.LanguageDetectionEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent.Builder> {
+ ctor public TextClassifierEvent.LanguageDetectionEvent.Builder(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent build();
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent.Builder setLocale(@Nullable android.icu.util.ULocale);
+ }
+
+ public static final class TextClassifierEvent.TextLinkifyEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.TextLinkifyEvent> CREATOR;
+ }
+
+ public static final class TextClassifierEvent.TextLinkifyEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.TextLinkifyEvent.Builder> {
+ ctor public TextClassifierEvent.TextLinkifyEvent.Builder(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextLinkifyEvent build();
+ }
+
+ public static final class TextClassifierEvent.TextSelectionEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+ method public int getRelativeSuggestedWordEndIndex();
+ method public int getRelativeSuggestedWordStartIndex();
+ method public int getRelativeWordEndIndex();
+ method public int getRelativeWordStartIndex();
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.TextSelectionEvent> CREATOR;
+ }
+
+ public static final class TextClassifierEvent.TextSelectionEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder> {
+ ctor public TextClassifierEvent.TextSelectionEvent.Builder(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent build();
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeSuggestedWordEndIndex(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeSuggestedWordStartIndex(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeWordEndIndex(int);
+ method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeWordStartIndex(int);
}
public final class TextLanguage implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index da87689..17894dc 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1130,22 +1130,6 @@
field public static final String SAMPLE_RATE = "android.media.audiotrack.sampleRate";
}
- public final class BufferingParams implements android.os.Parcelable {
- method public int describeContents();
- method public int getInitialMarkMs();
- method public int getResumePlaybackMarkMs();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.BufferingParams> CREATOR;
- }
-
- public static class BufferingParams.Builder {
- ctor public BufferingParams.Builder();
- ctor public BufferingParams.Builder(android.media.BufferingParams);
- method public android.media.BufferingParams build();
- method public android.media.BufferingParams.Builder setInitialMarkMs(int);
- method public android.media.BufferingParams.Builder setResumePlaybackMarkMs(int);
- }
-
public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int, int, @NonNull android.util.Size);
ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint, @NonNull android.util.Size);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 5f972c9..6e935e1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -127,7 +127,6 @@
import android.view.autofill.IAutofillWindowPresenter;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureManager;
-import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
@@ -724,7 +723,7 @@
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback,
- AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
+ AutofillManager.AutofillClient {
private static final String TAG = "Activity";
private static final boolean DEBUG_LIFECYCLE = false;
@@ -1124,12 +1123,6 @@
return this;
}
- /** @hide */
- @Override
- public final ContentCaptureClient getContentCaptureClient() {
- return this;
- }
-
/**
* Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
* lifecycle callbacks for only this Activity.
@@ -6509,12 +6502,6 @@
return getComponentName();
}
- /** @hide */
- @Override
- public final ComponentName contentCaptureClientGetComponentName() {
- return getComponentName();
- }
-
/**
* Retrieve a {@link SharedPreferences} object for accessing preferences
* that are private to this activity. This simply calls the underlying
diff --git a/core/java/android/app/role/RoleControllerManager.java b/core/java/android/app/role/RoleControllerManager.java
index 027e152..394a0d6 100644
--- a/core/java/android/app/role/RoleControllerManager.java
+++ b/core/java/android/app/role/RoleControllerManager.java
@@ -52,7 +52,10 @@
private static final String LOG_TAG = RoleControllerManager.class.getSimpleName();
+ private static volatile ComponentName sRemoteServiceComponentName;
+
private static final Object sRemoteServicesLock = new Object();
+
/**
* Global remote services (per user) used by all {@link RoleControllerManager managers}.
*/
@@ -62,18 +65,36 @@
@NonNull
private final RemoteService mRemoteService;
- public RoleControllerManager(@NonNull Context context, @NonNull Handler handler) {
+ /**
+ * Initialize the remote service component name once so that we can avoid acquiring the
+ * PackageManagerService lock in constructor.
+ *
+ * @see #createWithInitializedRemoteServiceComponentName(Handler, Context)
+ */
+ public static void initializeRemoteServiceComponentName(@NonNull Context context) {
+ sRemoteServiceComponentName = getRemoteServiceComponentName(context);
+ }
+
+ /**
+ * Create a {@link RoleControllerManager} instance with the initialized remote service component
+ * name so that we can avoid acquiring the PackageManagerService lock in constructor.
+ *
+ * @see #initializeRemoteServiceComponentName(Context)
+ */
+ @NonNull
+ public static RoleControllerManager createWithInitializedRemoteServiceComponentName(
+ @NonNull Handler handler, @NonNull Context context) {
+ return new RoleControllerManager(sRemoteServiceComponentName, handler, context);
+ }
+
+ private RoleControllerManager(@NonNull ComponentName remoteServiceComponentName,
+ @NonNull Handler handler, @NonNull Context context) {
synchronized (sRemoteServicesLock) {
int userId = context.getUserId();
RemoteService remoteService = sRemoteServices.get(userId);
if (remoteService == null) {
- Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
- PackageManager packageManager = context.getPackageManager();
- intent.setPackage(packageManager.getPermissionControllerPackageName());
- ResolveInfo resolveInfo = packageManager.resolveService(intent, 0);
-
remoteService = new RemoteService(context.getApplicationContext(),
- resolveInfo.getComponentInfo().getComponentName(), handler, userId);
+ remoteServiceComponentName, handler, userId);
sRemoteServices.put(userId, remoteService);
}
mRemoteService = remoteService;
@@ -81,7 +102,16 @@
}
public RoleControllerManager(@NonNull Context context) {
- this(context, context.getMainThreadHandler());
+ this(getRemoteServiceComponentName(context), context.getMainThreadHandler(), context);
+ }
+
+ @NonNull
+ private static ComponentName getRemoteServiceComponentName(@NonNull Context context) {
+ Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
+ PackageManager packageManager = context.getPackageManager();
+ intent.setPackage(packageManager.getPermissionControllerPackageName());
+ ResolveInfo resolveInfo = packageManager.resolveService(intent, 0);
+ return resolveInfo.getComponentInfo().getComponentName();
}
/**
diff --git a/core/java/android/content/AutofillOptions.java b/core/java/android/content/AutofillOptions.java
index f59bc98..8fb9501 100644
--- a/core/java/android/content/AutofillOptions.java
+++ b/core/java/android/content/AutofillOptions.java
@@ -24,7 +24,7 @@
import android.util.ArraySet;
import android.util.Log;
import android.view.autofill.AutofillManager;
-import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
+import android.view.autofill.AutofillManager.AutofillClient;
import java.io.PrintWriter;
@@ -73,10 +73,10 @@
public boolean isAugmentedAutofillEnabled(@NonNull Context context) {
if (!augmentedAutofillEnabled) return false;
- final ContentCaptureClient contentCaptureClient = context.getContentCaptureClient();
- if (contentCaptureClient == null) return false;
+ final AutofillClient autofillClient = context.getAutofillClient();
+ if (autofillClient == null) return false;
- final ComponentName component = contentCaptureClient.contentCaptureClientGetComponentName();
+ final ComponentName component = autofillClient.autofillClientGetComponentName();
return whitelistedActivitiesForAugmentedAutofill == null
|| whitelistedActivitiesForAugmentedAutofill.contains(component);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5a844aa..0ba457e 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -70,7 +70,6 @@
import android.view.ViewDebug;
import android.view.WindowManager;
import android.view.autofill.AutofillManager.AutofillClient;
-import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
import android.view.textclassifier.TextClassificationManager;
import java.io.File;
@@ -5414,14 +5413,6 @@
/**
* @hide
*/
- @Nullable
- public ContentCaptureClient getContentCaptureClient() {
- return null;
- }
-
- /**
- * @hide
- */
public final boolean isAutofillCompatibilityEnabled() {
final AutofillOptions options = getAutofillOptions();
return options != null && options.compatModeEnabled;
diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java
index b6c4fe2..68826cb 100644
--- a/core/java/android/net/DnsResolver.java
+++ b/core/java/android/net/DnsResolver.java
@@ -197,7 +197,7 @@
final FileDescriptor queryfd;
try {
queryfd = resNetworkSend((network != null
- ? network.netId : NETID_UNSET), query, query.length, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET), query, query.length, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
@@ -238,7 +238,7 @@
final FileDescriptor queryfd;
try {
queryfd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, nsClass, nsType, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET), domain, nsClass, nsType, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
@@ -346,7 +346,8 @@
if (queryIpv6) {
try {
v6fd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_AAAA, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET),
+ domain, CLASS_IN, TYPE_AAAA, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
@@ -365,7 +366,8 @@
if (queryIpv4) {
try {
v4fd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_A, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET),
+ domain, CLASS_IN, TYPE_A, flags);
} catch (ErrnoException e) {
if (queryIpv6) resNetworkCancel(v6fd); // Closes fd, marks it invalid.
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
@@ -423,7 +425,7 @@
final FileDescriptor queryfd;
try {
queryfd = resNetworkQuery((network != null
- ? network.netId : NETID_UNSET), domain, CLASS_IN, nsType, flags);
+ ? network.getNetIdForResolv() : NETID_UNSET), domain, CLASS_IN, nsType, flags);
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index feff9db..f2aaead 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -63,7 +63,6 @@
DEFAULT_FLAGS.put(FORCE_GLOBAL_ACTIONS_GRID_ENABLED, "false");
DEFAULT_FLAGS.put(GLOBAL_ACTIONS_PANEL_ENABLED, "true");
DEFAULT_FLAGS.put(PIXEL_WALLPAPER_CATEGORY_SWITCH, "false");
- DEFAULT_FLAGS.put("settings_wifi_details_saved_screen", "true");
DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
}
diff --git a/core/java/android/view/GestureExclusionTracker.java b/core/java/android/view/GestureExclusionTracker.java
index 8eccc04..6fcdd71 100644
--- a/core/java/android/view/GestureExclusionTracker.java
+++ b/core/java/android/view/GestureExclusionTracker.java
@@ -20,6 +20,8 @@
import android.annotation.Nullable;
import android.graphics.Rect;
+import com.android.internal.util.Preconditions;
+
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
@@ -31,6 +33,8 @@
*/
class GestureExclusionTracker {
private boolean mGestureExclusionViewsChanged = false;
+ private boolean mRootGestureExclusionRectsChanged = false;
+ private List<Rect> mRootGestureExclusionRects = Collections.emptyList();
private List<GestureExclusionViewInfo> mGestureExclusionViewInfos = new ArrayList<>();
private List<Rect> mGestureExclusionRects = Collections.emptyList();
@@ -59,9 +63,9 @@
@Nullable
public List<Rect> computeChangedRects() {
- boolean changed = false;
+ boolean changed = mRootGestureExclusionRectsChanged;
final Iterator<GestureExclusionViewInfo> i = mGestureExclusionViewInfos.iterator();
- final List<Rect> rects = new ArrayList<>();
+ final List<Rect> rects = new ArrayList<>(mRootGestureExclusionRects);
while (i.hasNext()) {
final GestureExclusionViewInfo info = i.next();
switch (info.update()) {
@@ -79,6 +83,7 @@
}
if (changed || mGestureExclusionViewsChanged) {
mGestureExclusionViewsChanged = false;
+ mRootGestureExclusionRectsChanged = false;
if (!mGestureExclusionRects.equals(rects)) {
mGestureExclusionRects = rects;
return rects;
@@ -87,6 +92,17 @@
return null;
}
+ public void setRootSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+ Preconditions.checkNotNull(rects, "rects must not be null");
+ mRootGestureExclusionRects = rects;
+ mRootGestureExclusionRectsChanged = true;
+ }
+
+ @NonNull
+ public List<Rect> getRootSystemGestureExclusionRects() {
+ return mRootGestureExclusionRects;
+ }
+
private static class GestureExclusionViewInfo {
public static final int CHANGED = 0;
public static final int UNCHANGED = 1;
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index 2ba1e01..1c811cb 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -172,6 +172,6 @@
}
private InputMethodManager getImm() {
- return mController.getViewRoot().mDisplayContext.getSystemService(InputMethodManager.class);
+ return mController.getViewRoot().mContext.getSystemService(InputMethodManager.class);
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c3a9465..096c988 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -11648,14 +11648,11 @@
}
/**
- * When screen readers (one type of accessibility tool) decide what should be read to the
- * user, they typically look for input focusable ({@link #isFocusable()}) parents of
- * non-focusable text items, and read those focusable parents and their non-focusable children
- * as a unit. In some situations, this behavior is desirable for views that should not take
- * input focus. Setting an item to be screen reader focusable requests that the view be
- * treated as a unit by screen readers without any effect on input focusability. The default
- * value of {@code false} lets screen readers use other signals, like focusable, to determine
- * how to group items.
+ * Sets whether this View should be a focusable element for screen readers
+ * and include non-focusable Views from its subtree when providing feedback.
+ * <p>
+ * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
+ * but does not impact input focus behavior.
*
* @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
* accessibility tools.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5ca70ba..fd3ecb4 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -283,13 +283,7 @@
@GuardedBy("mWindowCallbacks")
final ArrayList<WindowCallbacks> mWindowCallbacks = new ArrayList<>();
@UnsupportedAppUsage
- final Context mContext;
- /**
- * TODO(b/116349163): Check if we can merge this into {@link #mContext}.
- * @hide
- */
- @NonNull
- public Context mDisplayContext;
+ public final Context mContext;
@UnsupportedAppUsage
final IWindowSession mWindowSession;
@@ -595,7 +589,6 @@
public ViewRootImpl(Context context, Display display) {
mContext = context;
- mDisplayContext = context.createDisplayContext(display);
mWindowSession = WindowManagerGlobal.getWindowSession();
mDisplay = display;
mBasePackageName = context.getBasePackageName();
@@ -1379,7 +1372,7 @@
} else {
mDisplay = preferredDisplay;
}
- mDisplayContext = mContext.createDisplayContext(mDisplay);
+ mContext.updateDisplay(mDisplay.getDisplayId());
}
void pokeDrawLockIfNeeded() {
@@ -2725,7 +2718,7 @@
.mayUseInputMethod(mWindowAttributes.flags);
if (imTarget != mLastWasImTarget) {
mLastWasImTarget = imTarget;
- InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
+ InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
if (imm != null && imTarget) {
imm.onPreWindowFocus(mView, hasWindowFocus);
imm.onPostWindowFocus(mView, mView.findFocus(),
@@ -2855,7 +2848,7 @@
mLastWasImTarget = WindowManager.LayoutParams
.mayUseInputMethod(mWindowAttributes.flags);
- InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
+ InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
imm.onPreWindowFocus(mView, hasWindowFocus);
}
@@ -3829,6 +3822,24 @@
}
/**
+ * Set the root-level system gesture exclusion rects. These are added to those provided by
+ * the root's view hierarchy.
+ */
+ public void setRootSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+ mGestureExclusionTracker.setRootSystemGestureExclusionRects(rects);
+ mHandler.sendEmptyMessage(MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED);
+ }
+
+ /**
+ * Returns the root-level system gesture exclusion rects. These do not include those provided by
+ * the root's view hierarchy.
+ */
+ @NonNull
+ public List<Rect> getRootSystemGestureExclusionRects() {
+ return mGestureExclusionTracker.getRootSystemGestureExclusionRects();
+ }
+
+ /**
* Requests that the root render node is invalidated next time we perform a draw, such that
* {@link WindowCallbacks#onPostDraw} gets called.
*/
@@ -4542,8 +4553,7 @@
enqueueInputEvent(event, null, 0, true);
} break;
case MSG_CHECK_FOCUS: {
- InputMethodManager imm =
- mDisplayContext.getSystemService(InputMethodManager.class);
+ InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
if (imm != null) {
imm.checkFocus();
}
@@ -5088,7 +5098,7 @@
@Override
protected int onProcess(QueuedInputEvent q) {
if (mLastWasImTarget && !isInLocalFocusMode()) {
- InputMethodManager imm = mDisplayContext.getSystemService(InputMethodManager.class);
+ InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
if (imm != null) {
final InputEvent event = q.mEvent;
if (DEBUG_IMF) Log.v(mTag, "Sending input event to IME: " + event);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index fc9d8c2..b0ec621 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -48,6 +48,7 @@
import android.transition.TransitionManager;
import android.view.accessibility.AccessibilityEvent;
+import java.util.Collections;
import java.util.List;
/**
@@ -2397,6 +2398,53 @@
return false;
}
+ /**
+ * Sets a list of areas within this window's coordinate space where the system should not
+ * intercept touch or other pointing device gestures.
+ *
+ * <p>This method should be used by apps that make use of
+ * {@link #takeSurface(SurfaceHolder.Callback2)} and do not have a view hierarchy available.
+ * Apps that do have a view hierarchy should use
+ * {@link View#setSystemGestureExclusionRects(List)} instead. This method does not modify or
+ * replace the gesture exclusion rects populated by individual views in this window's view
+ * hierarchy using {@link View#setSystemGestureExclusionRects(List)}.</p>
+ *
+ * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
+ * input in order to function correctly in the presence of global system gestures that may
+ * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
+ * to provide system-level navigation functionality, a view such as a navigation drawer
+ * container can mark the left (or starting) edge of itself as requiring gesture capture
+ * priority using this API. The system may then choose to relax its own gesture recognition
+ * to allow the app to consume the user's gesture. It is not necessary for an app to register
+ * exclusion rects for broadly spanning regions such as the entirety of a
+ * <code>ScrollView</code> or for simple press and release click targets such as
+ * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
+ * a precision touch gesture in a small area in either the X or Y dimension, such as
+ * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
+ *
+ * <p>Do not modify the provided list after this method is called.</p>
+ *
+ * @param rects A list of precision gesture regions that this window needs to function correctly
+ */
+ @SuppressWarnings("unused")
+ public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+ throw new UnsupportedOperationException("window does not support gesture exclusion rects");
+ }
+
+ /**
+ * Retrieve the list of areas within this window's coordinate space where the system should not
+ * intercept touch or other pointing device gestures. This is the list as set by
+ * {@link #setSystemGestureExclusionRects(List)} or an empty list if
+ * {@link #setSystemGestureExclusionRects(List)} has not been called. It does not include
+ * exclusion rects set by this window's view hierarchy.
+ *
+ * @return a list of system gesture exclusion rects specific to this window
+ */
+ @NonNull
+ public List<Rect> getSystemGestureExclusionRects() {
+ return Collections.emptyList();
+ }
+
/** @hide */
public void setTheme(int resId) {
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 7a6e2ad..26454c0 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -343,15 +343,6 @@
private MainContentCaptureSession mMainSession;
/** @hide */
- public interface ContentCaptureClient {
- /**
- * Gets the component name of the client.
- */
- @NonNull
- ComponentName contentCaptureClientGetComponentName();
- }
-
- /** @hide */
public ContentCaptureManager(@NonNull Context context,
@NonNull IContentCaptureManager service, @NonNull ContentCaptureOptions options) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 5e00425..2cfd622 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -510,7 +510,7 @@
return null;
}
final InputMethodManager fallbackImm =
- viewRootImpl.mDisplayContext.getSystemService(InputMethodManager.class);
+ viewRootImpl.mContext.getSystemService(InputMethodManager.class);
if (fallbackImm == null) {
Log.e(TAG, "b/117267690: Failed to get non-null fallback IMM. view=" + view);
return null;
diff --git a/core/java/android/view/textclassifier/ExtrasUtils.java b/core/java/android/view/textclassifier/ExtrasUtils.java
index 7b23674..11e0e2c 100644
--- a/core/java/android/view/textclassifier/ExtrasUtils.java
+++ b/core/java/android/view/textclassifier/ExtrasUtils.java
@@ -36,6 +36,7 @@
// TODO: Make this a TestApi for CTS testing.
public final class ExtrasUtils {
+ // Keys for response objects.
private static final String SERIALIZED_ENTITIES_DATA = "serialized-entities-data";
private static final String ENTITIES_EXTRAS = "entities-extras";
private static final String ACTION_INTENT = "action-intent";
@@ -48,6 +49,10 @@
private static final String TEXT_LANGUAGES = "text-languages";
private static final String ENTITIES = "entities";
+ // Keys for request objects.
+ private static final String IS_SERIALIZED_ENTITY_DATA_ENABLED =
+ "is-serialized-entity-data-enabled";
+
private ExtrasUtils() {}
/**
@@ -308,7 +313,23 @@
/**
* Returns a list of entities contained in the {@code extra}.
*/
+ @Nullable
public static List<Bundle> getEntities(Bundle container) {
return container.getParcelableArrayList(ENTITIES);
}
+
+ /**
+ * Whether the annotator should populate serialized entity data into the result object.
+ */
+ public static boolean isSerializedEntityDataEnabled(TextLinks.Request request) {
+ return request.getExtras().getBoolean(IS_SERIALIZED_ENTITY_DATA_ENABLED);
+ }
+
+ /**
+ * To indicate whether the annotator should populate serialized entity data in the result
+ * object.
+ */
+ public static void putIsSerializedEntityDataEnabled(Bundle bundle, boolean isEnabled) {
+ bundle.putBoolean(IS_SERIALIZED_ENTITY_DATA_ENABLED, isEnabled);
+ }
}
diff --git a/core/java/android/view/textclassifier/TextClassifierEvent.java b/core/java/android/view/textclassifier/TextClassifierEvent.java
index 236f89b..d3d61a7 100644
--- a/core/java/android/view/textclassifier/TextClassifierEvent.java
+++ b/core/java/android/view/textclassifier/TextClassifierEvent.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.icu.util.ULocale;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,54 +31,65 @@
import java.util.Arrays;
/**
- * A text classifier event.
+ * This class represents events that are sent by components to the {@link TextClassifier} to report
+ * something of note that relates to a feature powered by the TextClassifier. The TextClassifier may
+ * log these events or use them to improve future responses to queries.
+ * <p>
+ * Each categories of the events have their own subclass. Events of each types has an associated
+ * set of related properties. You can find the specification of them in the subclasses.
*/
-// TODO: Comprehensive javadoc.
-public final class TextClassifierEvent implements Parcelable {
+public abstract class TextClassifierEvent implements Parcelable {
- public static final @android.annotation.NonNull Creator<TextClassifierEvent> CREATOR = new Creator<TextClassifierEvent>() {
- @Override
- public TextClassifierEvent createFromParcel(Parcel in) {
- return readFromParcel(in);
- }
-
- @Override
- public TextClassifierEvent[] newArray(int size) {
- return new TextClassifierEvent[size];
- }
- };
+ private static final int PARCEL_TOKEN_TEXT_SELECTION_EVENT = 1;
+ private static final int PARCEL_TOKEN_TEXT_LINKIFY_EVENT = 2;
+ private static final int PARCEL_TOKEN_CONVERSATION_ACTION_EVENT = 3;
+ private static final int PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT = 4;
/** @hide **/
@Retention(RetentionPolicy.SOURCE)
- @IntDef({CATEGORY_UNDEFINED, CATEGORY_SELECTION, CATEGORY_LINKIFY,
+ @IntDef({CATEGORY_SELECTION, CATEGORY_LINKIFY,
CATEGORY_CONVERSATION_ACTIONS, CATEGORY_LANGUAGE_DETECTION})
public @interface Category {
// For custom event categories, use range 1000+.
}
- /** Undefined category */
- public static final int CATEGORY_UNDEFINED = 0;
- /** Smart selection */
+
+ /**
+ * Smart selection
+ *
+ * @see TextSelectionEvent
+ */
public static final int CATEGORY_SELECTION = 1;
- /** Linkify */
+ /**
+ * Linkify
+ *
+ * @see TextLinkifyEvent
+ */
public static final int CATEGORY_LINKIFY = 2;
- /** Conversation actions */
+ /**
+ * Conversation actions
+ *
+ * @see ConversationActionsEvent
+ */
public static final int CATEGORY_CONVERSATION_ACTIONS = 3;
- /** Language detection */
+ /**
+ * Language detection
+ *
+ * @see LanguageDetectionEvent
+ */
public static final int CATEGORY_LANGUAGE_DETECTION = 4;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({TYPE_UNDEFINED, TYPE_SELECTION_STARTED, TYPE_SELECTION_MODIFIED,
- TYPE_SMART_SELECTION_SINGLE, TYPE_SMART_SELECTION_MULTI, TYPE_AUTO_SELECTION,
- TYPE_ACTIONS_SHOWN, TYPE_LINK_CLICKED, TYPE_OVERTYPE, TYPE_COPY_ACTION,
- TYPE_PASTE_ACTION, TYPE_CUT_ACTION, TYPE_SHARE_ACTION, TYPE_SMART_ACTION,
- TYPE_SELECTION_DRAG, TYPE_SELECTION_DESTROYED, TYPE_OTHER_ACTION, TYPE_SELECT_ALL,
- TYPE_SELECTION_RESET, TYPE_MANUAL_REPLY, TYPE_ACTIONS_GENERATED})
+ @IntDef({TYPE_SELECTION_STARTED, TYPE_SELECTION_MODIFIED,
+ TYPE_SMART_SELECTION_SINGLE, TYPE_SMART_SELECTION_MULTI, TYPE_AUTO_SELECTION,
+ TYPE_ACTIONS_SHOWN, TYPE_LINK_CLICKED, TYPE_OVERTYPE, TYPE_COPY_ACTION,
+ TYPE_PASTE_ACTION, TYPE_CUT_ACTION, TYPE_SHARE_ACTION, TYPE_SMART_ACTION,
+ TYPE_SELECTION_DRAG, TYPE_SELECTION_DESTROYED, TYPE_OTHER_ACTION, TYPE_SELECT_ALL,
+ TYPE_SELECTION_RESET, TYPE_MANUAL_REPLY, TYPE_ACTIONS_GENERATED})
public @interface Type {
// For custom event types, use range 1,000,000+.
}
- /** User started a new selection. */
- public static final int TYPE_UNDEFINED = 0;
+
/** User started a new selection. */
public static final int TYPE_SELECTION_STARTED = 1;
/** User modified an existing selection. */
@@ -119,63 +131,49 @@
/** TextClassifier generated some actions */
public static final int TYPE_ACTIONS_GENERATED = 20;
- @Category private final int mEventCategory;
- @Type private final int mEventType;
- @Nullable private final String[] mEntityTypes;
- @Nullable private final TextClassificationContext mEventContext;
- @Nullable private final String mResultId;
+ @Category
+ private final int mEventCategory;
+ @Type
+ private final int mEventType;
+ @Nullable
+ private final String[] mEntityTypes;
+ @Nullable
+ private final TextClassificationContext mEventContext;
+ @Nullable
+ private final String mResultId;
private final int mEventIndex;
- private final long mEventTime;
+ private final float[] mScores;
+ @Nullable
+ private final String mModelName;
+ private final int[] mActionIndices;
private final Bundle mExtras;
- // Smart selection.
- private final int mRelativeWordStartIndex;
- private final int mRelativeWordEndIndex;
- private final int mRelativeSuggestedWordStartIndex;
- private final int mRelativeSuggestedWordEndIndex;
+ private TextClassifierEvent(Builder builder) {
+ mEventCategory = builder.mEventCategory;
+ mEventType = builder.mEventType;
+ mEntityTypes = builder.mEntityTypes;
+ mEventContext = builder.mEventContext;
+ mResultId = builder.mResultId;
+ mEventIndex = builder.mEventIndex;
+ mScores = builder.mScores;
+ mModelName = builder.mModelName;
+ mActionIndices = builder.mActionIndices;
+ mExtras = builder.mExtras == null ? Bundle.EMPTY : builder.mExtras;
+ }
- // Smart action.
- private final int[] mActionIndices;
-
- // Language detection.
- @Nullable private final String mLanguage;
- private final float mScore;
-
- @Nullable private final String mModelName;
-
- private TextClassifierEvent(
- int eventCategory,
- int eventType,
- String[] entityTypes,
- TextClassificationContext eventContext,
- String resultId,
- int eventIndex,
- long eventTime,
- Bundle extras,
- int relativeWordStartIndex,
- int relativeWordEndIndex,
- int relativeSuggestedWordStartIndex,
- int relativeSuggestedWordEndIndex,
- int[] actionIndex,
- String language,
- float score,
- String modelVersion) {
- mEventCategory = eventCategory;
- mEventType = eventType;
- mEntityTypes = entityTypes;
- mEventContext = eventContext;
- mResultId = resultId;
- mEventIndex = eventIndex;
- mEventTime = eventTime;
- mExtras = extras;
- mRelativeWordStartIndex = relativeWordStartIndex;
- mRelativeWordEndIndex = relativeWordEndIndex;
- mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
- mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
- mActionIndices = actionIndex;
- mLanguage = language;
- mScore = score;
- mModelName = modelVersion;
+ private TextClassifierEvent(Parcel in) {
+ mEventCategory = in.readInt();
+ mEventType = in.readInt();
+ mEntityTypes = in.readStringArray();
+ mEventContext = in.readParcelable(null);
+ mResultId = in.readString();
+ mEventIndex = in.readInt();
+ int scoresLength = in.readInt();
+ mScores = new float[scoresLength];
+ in.readFloatArray(mScores);
+ mModelName = in.readString();
+ mActionIndices = in.createIntArray();
+ mExtras = in.readBundle();
}
@Override
@@ -183,44 +181,62 @@
return 0;
}
+ @NonNull
+ public static final Creator<TextClassifierEvent> CREATOR = new Creator<TextClassifierEvent>() {
+ @Override
+ public TextClassifierEvent createFromParcel(Parcel in) {
+ int token = in.readInt();
+ if (token == PARCEL_TOKEN_TEXT_SELECTION_EVENT) {
+ return new TextSelectionEvent(in);
+ }
+ if (token == PARCEL_TOKEN_TEXT_LINKIFY_EVENT) {
+ return new TextLinkifyEvent(in);
+ }
+ if (token == PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT) {
+ return new LanguageDetectionEvent(in);
+ }
+ if (token == PARCEL_TOKEN_CONVERSATION_ACTION_EVENT) {
+ return new ConversationActionsEvent(in);
+ }
+ throw new IllegalStateException("Unexpected input event type token in parcel.");
+ }
+
+ @Override
+ public TextClassifierEvent[] newArray(int size) {
+ return new TextClassifierEvent[size];
+ }
+ };
+
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(getParcelToken());
dest.writeInt(mEventCategory);
dest.writeInt(mEventType);
dest.writeStringArray(mEntityTypes);
dest.writeParcelable(mEventContext, flags);
dest.writeString(mResultId);
dest.writeInt(mEventIndex);
- dest.writeLong(mEventTime);
- dest.writeBundle(mExtras);
- dest.writeInt(mRelativeWordStartIndex);
- dest.writeInt(mRelativeWordEndIndex);
- dest.writeInt(mRelativeSuggestedWordStartIndex);
- dest.writeInt(mRelativeSuggestedWordEndIndex);
- dest.writeIntArray(mActionIndices);
- dest.writeString(mLanguage);
- dest.writeFloat(mScore);
+ dest.writeInt(mScores.length);
+ dest.writeFloatArray(mScores);
dest.writeString(mModelName);
+ dest.writeIntArray(mActionIndices);
+ dest.writeBundle(mExtras);
}
- private static TextClassifierEvent readFromParcel(Parcel in) {
- return new TextClassifierEvent(
- /* eventCategory= */ in.readInt(),
- /* eventType= */ in.readInt(),
- /* entityTypes=*/ in.readStringArray(),
- /* eventContext= */ in.readParcelable(null),
- /* resultId= */ in.readString(),
- /* eventIndex= */ in.readInt(),
- /* eventTime= */ in.readLong(),
- /* extras= */ in.readBundle(),
- /* relativeWordStartIndex= */ in.readInt(),
- /* relativeWordEndIndex= */ in.readInt(),
- /* relativeSuggestedWordStartIndex= */ in.readInt(),
- /* relativeSuggestedWordEndIndex= */ in.readInt(),
- /* actionIndices= */ in.createIntArray(),
- /* language= */ in.readString(),
- /* score= */ in.readFloat(),
- /* modelVersion= */ in.readString());
+ private int getParcelToken() {
+ if (this instanceof TextSelectionEvent) {
+ return PARCEL_TOKEN_TEXT_SELECTION_EVENT;
+ }
+ if (this instanceof TextLinkifyEvent) {
+ return PARCEL_TOKEN_TEXT_LINKIFY_EVENT;
+ }
+ if (this instanceof LanguageDetectionEvent) {
+ return PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT;
+ }
+ if (this instanceof ConversationActionsEvent) {
+ return PARCEL_TOKEN_CONVERSATION_ACTION_EVENT;
+ }
+ throw new IllegalArgumentException("Unexpected type: " + this.getClass().getSimpleName());
}
/**
@@ -241,6 +257,8 @@
/**
* Returns an array of entity types. e.g. {@link TextClassifier#TYPE_ADDRESS}.
+ *
+ * @see Builder#setEntityTypes(String...) for supported types.
*/
@NonNull
public String[] getEntityTypes() {
@@ -270,13 +288,33 @@
return mEventIndex;
}
- // TODO: Remove this API.
/**
- * Returns the time this event occurred. This is the number of milliseconds since
- * January 1, 1970, 00:00:00 GMT. 0 indicates not set.
+ * Returns the scores of the suggestions.
*/
- public long getEventTime() {
- return mEventTime;
+ @NonNull
+ public float[] getScores() {
+ return mScores;
+ }
+
+ /**
+ * Returns the model name.
+ */
+ @Nullable
+ public String getModelName() {
+ return mModelName;
+ }
+
+ /**
+ * Returns the indices of the actions relating to this event.
+ * Actions are usually returned by the text classifier in priority order with the most
+ * preferred action at index 0. This list gives an indication of the position of the actions
+ * that are being reported.
+ *
+ * @see Builder#setActionIndices(int...)
+ */
+ @NonNull
+ public int[] getActionIndices() {
+ return mActionIndices;
}
/**
@@ -289,151 +327,149 @@
return mExtras;
}
- /**
- * For smart selection. Returns the relative word index of the start of the selection.
- */
- public int getRelativeWordStartIndex() {
- return mRelativeWordStartIndex;
- }
-
- /**
- * For smart selection. Returns the relative word (exclusive) index of the end of the selection.
- */
- public int getRelativeWordEndIndex() {
- return mRelativeWordEndIndex;
- }
-
- /**
- * For smart selection. Returns the relative word index of the start of the smart selection.
- */
- public int getRelativeSuggestedWordStartIndex() {
- return mRelativeSuggestedWordStartIndex;
- }
-
- /**
- * For smart selection. Returns the relative word (exclusive) index of the end of the
- * smart selection.
- */
- public int getRelativeSuggestedWordEndIndex() {
- return mRelativeSuggestedWordEndIndex;
- }
-
- /**
- * Returns the indices of the actions relating to this event.
- * Actions are usually returned by the text classifier in priority order with the most
- * preferred action at index 0. This list gives an indication of the position of the actions
- * that are being reported.
- */
- @NonNull
- public int[] getActionIndices() {
- return mActionIndices;
- }
-
- /**
- * For language detection. Returns the language tag for the detected locale.
- * @see java.util.Locale#forLanguageTag(String).
- */
- @Nullable
- public String getLanguage() {
- return mLanguage;
- }
-
- /**
- * Returns the score of the suggestion.
- */
- public float getScore() {
- return mScore;
- }
-
- /**
- * Returns the model name.
- * @hide
- */
- @Nullable
- public String getModelName() {
- return mModelName;
+ @Override
+ public String toString() {
+ StringBuilder out = new StringBuilder(128);
+ out.append(this.getClass().getSimpleName());
+ out.append("{");
+ out.append("mEventCategory=").append(mEventCategory);
+ out.append(", mEventTypes=").append(Arrays.toString(mEntityTypes));
+ out.append(", mEventContext=").append(mEventContext);
+ out.append(", mResultId=").append(mResultId);
+ out.append(", mEventIndex=").append(mEventIndex);
+ out.append(", mExtras=").append(mExtras);
+ out.append(", mScores=").append(Arrays.toString(mScores));
+ out.append(", mModelName=").append(mModelName);
+ out.append(", mActionIndices=").append(Arrays.toString(mActionIndices));
+ out.append("}");
+ return out.toString();
}
/**
* Builder to build a text classifier event.
+ *
+ * @param <T> The subclass to be built.
*/
- public static final class Builder {
+ public abstract static class Builder<T extends Builder<T>> {
private final int mEventCategory;
private final int mEventType;
private String[] mEntityTypes = new String[0];
- @Nullable private TextClassificationContext mEventContext;
- @Nullable private String mResultId;
+ @Nullable
+ private TextClassificationContext mEventContext;
+ @Nullable
+ private String mResultId;
private int mEventIndex;
- private long mEventTime;
- @Nullable private Bundle mExtras;
- private int mRelativeWordStartIndex;
- private int mRelativeWordEndIndex;
- private int mRelativeSuggestedWordStartIndex;
- private int mRelativeSuggestedWordEndIndex;
- private int[] mActionIndices = new int[0];
- @Nullable private String mLanguage;
- private float mScore;
-
+ private float[] mScores = new float[0];
+ @Nullable
private String mModelName;
+ private int[] mActionIndices = new int[0];
+ @Nullable
+ private Bundle mExtras;
/**
* Creates a builder for building {@link TextClassifierEvent}s.
*
* @param eventCategory The event category. e.g. {@link #CATEGORY_SELECTION}
- * @param eventType The event type. e.g. {@link #TYPE_SELECTION_STARTED}
+ * @param eventType The event type. e.g. {@link #TYPE_SELECTION_STARTED}
*/
- public Builder(@Category int eventCategory, @Type int eventType) {
+ private Builder(@Category int eventCategory, @Type int eventType) {
mEventCategory = eventCategory;
mEventType = eventType;
}
/**
* Sets the entity types. e.g. {@link TextClassifier#TYPE_ADDRESS}.
+ * <p>
+ * Supported types:
+ * <p>See {@link TextClassifier.EntityType}
+ * <p>See {@link ConversationAction.ActionType}
+ * <p>See {@link ULocale#toLanguageTag()}
*/
@NonNull
- public Builder setEntityTypes(@NonNull String... entityTypes) {
+ public T setEntityTypes(@NonNull String... entityTypes) {
+ Preconditions.checkNotNull(entityTypes);
mEntityTypes = new String[entityTypes.length];
System.arraycopy(entityTypes, 0, mEntityTypes, 0, entityTypes.length);
- return this;
+ return self();
}
/**
* Sets the event context.
*/
@NonNull
- public Builder setEventContext(@Nullable TextClassificationContext eventContext) {
+ public T setEventContext(@Nullable TextClassificationContext eventContext) {
mEventContext = eventContext;
- return this;
+ return self();
}
/**
* Sets the id of the text classifier result related to this event.
*/
@NonNull
- public Builder setResultId(@Nullable String resultId) {
+ public T setResultId(@Nullable String resultId) {
mResultId = resultId;
- return this;
+ return self();
}
/**
- * Sets the index of this events in the series of events it belongs to.
+ * Sets the index of this event in the series of events it belongs to.
*/
@NonNull
- public Builder setEventIndex(int eventIndex) {
+ public T setEventIndex(int eventIndex) {
mEventIndex = eventIndex;
- return this;
+ return self();
}
- // TODO: Remove this API.
/**
- * Sets the time this event occurred. This is the number of milliseconds since
- * January 1, 1970, 00:00:00 GMT. 0 indicates not set.
+ * Sets the scores of the suggestions.
*/
@NonNull
- public Builder setEventTime(long eventTime) {
- mEventTime = eventTime;
- return this;
+ public T setScores(@NonNull float... scores) {
+ Preconditions.checkNotNull(scores);
+ mScores = new float[scores.length];
+ System.arraycopy(scores, 0, mScores, 0, scores.length);
+ return self();
+ }
+
+ /**
+ * Sets the model name string.
+ */
+ @NonNull
+ public T setModelName(@Nullable String modelVersion) {
+ mModelName = modelVersion;
+ return self();
+ }
+
+ /**
+ * Sets the indices of the actions involved in this event. Actions are usually returned by
+ * the text classifier in priority order with the most preferred action at index 0.
+ * These indices give an indication of the position of the actions that are being reported.
+ * <p>
+ * E.g.
+ * <pre>
+ * // 3 smart actions are shown at index 0, 1, 2 respectively in response to a link click.
+ * new TextClassifierEvent.Builder(CATEGORY_LINKIFY, TYPE_ACTIONS_SHOWN)
+ * .setEventIndex(0, 1, 2)
+ * ...
+ * .build();
+ *
+ * ...
+ *
+ * // Smart action at index 1 is activated.
+ * new TextClassifierEvent.Builder(CATEGORY_LINKIFY, TYPE_SMART_ACTION)
+ * .setEventIndex(1)
+ * ...
+ * .build();
+ * </pre>
+ *
+ * @see TextClassification#getActions()
+ */
+ @NonNull
+ public T setActionIndices(@NonNull int... actionIndices) {
+ mActionIndices = new int[actionIndices.length];
+ System.arraycopy(actionIndices, 0, mActionIndices, 0, actionIndices.length);
+ return self();
}
/**
@@ -445,136 +481,545 @@
* objects in this bundle.
*/
@NonNull
- public Builder setExtras(@NonNull Bundle extras) {
+ public T setExtras(@NonNull Bundle extras) {
mExtras = Preconditions.checkNotNull(extras);
- return this;
+ return self();
}
- /**
- * For smart selection. Sets the relative word index of the start of the selection.
- */
- @NonNull
- public Builder setRelativeWordStartIndex(int relativeWordStartIndex) {
- mRelativeWordStartIndex = relativeWordStartIndex;
- return this;
- }
-
- /**
- * For smart selection. Sets the relative word (exclusive) index of the end of the
- * selection.
- */
- @NonNull
- public Builder setRelativeWordEndIndex(int relativeWordEndIndex) {
- mRelativeWordEndIndex = relativeWordEndIndex;
- return this;
- }
-
- /**
- * For smart selection. Sets the relative word index of the start of the smart selection.
- */
- @NonNull
- public Builder setRelativeSuggestedWordStartIndex(int relativeSuggestedWordStartIndex) {
- mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
- return this;
- }
-
- /**
- * For smart selection. Sets the relative word (exclusive) index of the end of the
- * smart selection.
- */
- @NonNull
- public Builder setRelativeSuggestedWordEndIndex(int relativeSuggestedWordEndIndex) {
- mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
- return this;
- }
-
- /**
- * Sets the indices of the actions involved in this event. Actions are usually returned by
- * the text classifier in priority order with the most preferred action at index 0.
- * This index gives an indication of the position of the action that is being reported.
- */
- @NonNull
- public Builder setActionIndices(@NonNull int... actionIndices) {
- mActionIndices = new int[actionIndices.length];
- System.arraycopy(actionIndices, 0, mActionIndices, 0, actionIndices.length);
- return this;
- }
-
- /**
- * For language detection. Sets the language tag for the detected locale.
- * @see java.util.Locale#forLanguageTag(String).
- */
- @NonNull
- public Builder setLanguage(@Nullable String language) {
- mLanguage = language;
- return this;
- }
-
- /**
- * Sets the score of the suggestion.
- */
- @NonNull
- public Builder setScore(float score) {
- mScore = score;
- return this;
- }
-
- /**
- * Sets the model name string.
- * @hide
- */
- public Builder setModelName(@Nullable String modelVersion) {
- mModelName = modelVersion;
- return this;
- }
-
- /**
- * Builds and returns a text classifier event.
- */
- @NonNull
- public TextClassifierEvent build() {
- mExtras = mExtras == null ? Bundle.EMPTY : mExtras;
- return new TextClassifierEvent(
- mEventCategory,
- mEventType,
- mEntityTypes,
- mEventContext,
- mResultId,
- mEventIndex,
- mEventTime,
- mExtras,
- mRelativeWordStartIndex,
- mRelativeWordEndIndex,
- mRelativeSuggestedWordStartIndex,
- mRelativeSuggestedWordEndIndex,
- mActionIndices,
- mLanguage,
- mScore,
- mModelName);
- }
- // TODO: Add build(boolean validate).
+ abstract T self();
}
- @Override
- public String toString() {
- StringBuilder out = new StringBuilder(128);
- out.append("TextClassifierEvent{");
- out.append("mEventCategory=").append(mEventCategory);
- out.append(", mEventTypes=").append(Arrays.toString(mEntityTypes));
- out.append(", mEventContext=").append(mEventContext);
- out.append(", mResultId=").append(mResultId);
- out.append(", mEventIndex=").append(mEventIndex);
- out.append(", mEventTime=").append(mEventTime);
- out.append(", mExtras=").append(mExtras);
- out.append(", mRelativeWordStartIndex=").append(mRelativeWordStartIndex);
- out.append(", mRelativeWordEndIndex=").append(mRelativeWordEndIndex);
- out.append(", mRelativeSuggestedWordStartIndex=").append(mRelativeSuggestedWordStartIndex);
- out.append(", mRelativeSuggestedWordEndIndex=").append(mRelativeSuggestedWordEndIndex);
- out.append(", mActionIndices=").append(Arrays.toString(mActionIndices));
- out.append(", mLanguage=").append(mLanguage);
- out.append(", mScore=").append(mScore);
- out.append(", mModelName=").append(mModelName);
- out.append("}");
- return out.toString();
+ /**
+ * This class represents events that are related to the smart text selection feature.
+ * <p>
+ * <pre>
+ * // User started a selection. e.g. "York" in text "New York City, NY".
+ * new TextSelectionEvent.Builder(TYPE_SELECTION_STARTED)
+ * .setEventContext(classificationContext)
+ * .setEventIndex(0)
+ * .build();
+ *
+ * // System smart-selects a recognized entity. e.g. "New York City".
+ * new TextSelectionEvent.Builder(TYPE_SMART_SELECTION_MULTI)
+ * .setEventContext(classificationContext)
+ * .setResultId(textSelection.getId())
+ * .setRelativeWordStartIndex(-1) // Goes back one word to "New" from "York".
+ * .setRelativeWordEndIndex(2) // Goes forward 2 words from "York" to start of ",".
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(1)
+ * .build();
+ *
+ * // User resets the selection to the original selection. i.e. "York".
+ * new TextSelectionEvent.Builder(TYPE_SELECTION_RESET)
+ * .setEventContext(classificationContext)
+ * .setResultId(textSelection.getId())
+ * .setRelativeSuggestedWordStartIndex(-1) // Repeated from above.
+ * .setRelativeSuggestedWordEndIndex(2) // Repeated from above.
+ * .setRelativeWordStartIndex(0) // Original selection is always at (0, 1].
+ * .setRelativeWordEndIndex(1)
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(2)
+ * .build();
+ *
+ * // User modified the selection. e.g. "New".
+ * new TextSelectionEvent.Builder(TYPE_SELECTION_MODIFIED)
+ * .setEventContext(classificationContext)
+ * .setResultId(textSelection.getId())
+ * .setRelativeSuggestedWordStartIndex(-1) // Repeated from above.
+ * .setRelativeSuggestedWordEndIndex(2) // Repeated from above.
+ * .setRelativeWordStartIndex(-1) // Goes backward one word from "York" to
+ * "New".
+ * .setRelativeWordEndIndex(0) // Goes backward one word to exclude "York".
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(3)
+ * .build();
+ *
+ * // Smart (contextual) actions (at indices, 0, 1, 2) presented to the user.
+ * // e.g. "Map", "Ride share", "Explore".
+ * new TextSelectionEvent.Builder(TYPE_ACTIONS_SHOWN)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setActionIndices(0, 1, 2)
+ * .setEventIndex(4)
+ * .build();
+ *
+ * // User chooses the "Copy" action.
+ * new TextSelectionEvent.Builder(TYPE_COPY_ACTION)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(5)
+ * .build();
+ *
+ * // User chooses smart action at index 1. i.e. "Ride share".
+ * new TextSelectionEvent.Builder(TYPE_SMART_ACTION)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setActionIndices(1)
+ * .setEventIndex(5)
+ * .build();
+ *
+ * // Selection dismissed.
+ * new TextSelectionEvent.Builder(TYPE_SELECTION_DESTROYED)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(6)
+ * .build();
+ * </pre>
+ * <p>
+ */
+ public static final class TextSelectionEvent extends TextClassifierEvent implements Parcelable {
+
+ @NonNull
+ public static final Creator<TextSelectionEvent> CREATOR =
+ new Creator<TextSelectionEvent>() {
+ @Override
+ public TextSelectionEvent createFromParcel(Parcel in) {
+ in.readInt(); // skip token, we already know this is a TextSelectionEvent
+ return new TextSelectionEvent(in);
+ }
+
+ @Override
+ public TextSelectionEvent[] newArray(int size) {
+ return new TextSelectionEvent[size];
+ }
+ };
+
+ final int mRelativeWordStartIndex;
+ final int mRelativeWordEndIndex;
+ final int mRelativeSuggestedWordStartIndex;
+ final int mRelativeSuggestedWordEndIndex;
+
+ private TextSelectionEvent(TextSelectionEvent.Builder builder) {
+ super(builder);
+ mRelativeWordStartIndex = builder.mRelativeWordStartIndex;
+ mRelativeWordEndIndex = builder.mRelativeWordEndIndex;
+ mRelativeSuggestedWordStartIndex = builder.mRelativeSuggestedWordStartIndex;
+ mRelativeSuggestedWordEndIndex = builder.mRelativeSuggestedWordEndIndex;
+ }
+
+ private TextSelectionEvent(Parcel in) {
+ super(in);
+ mRelativeWordStartIndex = in.readInt();
+ mRelativeWordEndIndex = in.readInt();
+ mRelativeSuggestedWordStartIndex = in.readInt();
+ mRelativeSuggestedWordEndIndex = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mRelativeWordStartIndex);
+ dest.writeInt(mRelativeWordEndIndex);
+ dest.writeInt(mRelativeSuggestedWordStartIndex);
+ dest.writeInt(mRelativeSuggestedWordEndIndex);
+ }
+
+ /**
+ * Returns the relative word index of the start of the selection.
+ */
+ public int getRelativeWordStartIndex() {
+ return mRelativeWordStartIndex;
+ }
+
+ /**
+ * Returns the relative word (exclusive) index of the end of the selection.
+ */
+ public int getRelativeWordEndIndex() {
+ return mRelativeWordEndIndex;
+ }
+
+ /**
+ * Returns the relative word index of the start of the smart selection.
+ */
+ public int getRelativeSuggestedWordStartIndex() {
+ return mRelativeSuggestedWordStartIndex;
+ }
+
+ /**
+ * Returns the relative word (exclusive) index of the end of the
+ * smart selection.
+ */
+ public int getRelativeSuggestedWordEndIndex() {
+ return mRelativeSuggestedWordEndIndex;
+ }
+
+ /**
+ * Builder class for {@link TextSelectionEvent}.
+ */
+ public static final class Builder extends
+ TextClassifierEvent.Builder<TextSelectionEvent.Builder> {
+ int mRelativeWordStartIndex;
+ int mRelativeWordEndIndex;
+ int mRelativeSuggestedWordStartIndex;
+ int mRelativeSuggestedWordEndIndex;
+
+ /**
+ * Creates a builder for building {@link TextSelectionEvent}s.
+ *
+ * @param eventType The event type. e.g. {@link #TYPE_SELECTION_STARTED}
+ */
+ public Builder(@Type int eventType) {
+ super(CATEGORY_SELECTION, eventType);
+ }
+
+ /**
+ * Sets the relative word index of the start of the selection.
+ */
+ @NonNull
+ public Builder setRelativeWordStartIndex(int relativeWordStartIndex) {
+ mRelativeWordStartIndex = relativeWordStartIndex;
+ return this;
+ }
+
+ /**
+ * Sets the relative word (exclusive) index of the end of the
+ * selection.
+ */
+ @NonNull
+ public Builder setRelativeWordEndIndex(int relativeWordEndIndex) {
+ mRelativeWordEndIndex = relativeWordEndIndex;
+ return this;
+ }
+
+ /**
+ * Sets the relative word index of the start of the smart
+ * selection.
+ */
+ @NonNull
+ public Builder setRelativeSuggestedWordStartIndex(int relativeSuggestedWordStartIndex) {
+ mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
+ return this;
+ }
+
+ /**
+ * Sets the relative word (exclusive) index of the end of the
+ * smart selection.
+ */
+ @NonNull
+ public Builder setRelativeSuggestedWordEndIndex(int relativeSuggestedWordEndIndex) {
+ mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
+ return this;
+ }
+
+ @Override
+ TextSelectionEvent.Builder self() {
+ return this;
+ }
+
+ /**
+ * Builds and returns a {@link TextSelectionEvent}.
+ */
+ @NonNull
+ public TextSelectionEvent build() {
+ return new TextSelectionEvent(this);
+ }
+ }
+ }
+
+ /**
+ * This class represents events that are related to the smart linkify feature.
+ * <p>
+ * <pre>
+ * // User clicked on a link.
+ * new TextLinkifyEvent.Builder(TYPE_LINK_CLICKED)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setEventIndex(0)
+ * .build();
+ *
+ * // Smart (contextual) actions presented to the user in response to a link click.
+ * new TextLinkifyEvent.Builder(TYPE_ACTIONS_SHOWN)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setActionIndices(range(textClassification.getActions().size()))
+ * .setEventIndex(1)
+ * .build();
+ *
+ * // User chooses smart action at index 0.
+ * new TextLinkifyEvent.Builder(TYPE_SMART_ACTION)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(textClassification.getEntity(0))
+ * .setScore(textClassification.getConfidenceScore(entityType))
+ * .setActionIndices(0)
+ * .setEventIndex(2)
+ * .build();
+ * </pre>
+ */
+ public static final class TextLinkifyEvent extends TextClassifierEvent implements Parcelable {
+
+ @NonNull
+ public static final Creator<TextLinkifyEvent> CREATOR =
+ new Creator<TextLinkifyEvent>() {
+ @Override
+ public TextLinkifyEvent createFromParcel(Parcel in) {
+ in.readInt(); // skip token, we already know this is a TextLinkifyEvent
+ return new TextLinkifyEvent(in);
+ }
+
+ @Override
+ public TextLinkifyEvent[] newArray(int size) {
+ return new TextLinkifyEvent[size];
+ }
+ };
+
+ private TextLinkifyEvent(Parcel in) {
+ super(in);
+ }
+
+ private TextLinkifyEvent(TextLinkifyEvent.Builder builder) {
+ super(builder);
+ }
+
+ /**
+ * Builder class for {@link TextLinkifyEvent}.
+ */
+ public static final class Builder
+ extends TextClassifierEvent.Builder<TextLinkifyEvent.Builder> {
+ /**
+ * Creates a builder for building {@link TextLinkifyEvent}s.
+ *
+ * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
+ */
+ public Builder(@Type int eventType) {
+ super(TextClassifierEvent.CATEGORY_LINKIFY, eventType);
+ }
+
+ @Override
+ Builder self() {
+ return this;
+ }
+
+ /**
+ * Builds and returns a {@link TextLinkifyEvent}.
+ */
+ @NonNull
+ public TextLinkifyEvent build() {
+ return new TextLinkifyEvent(this);
+ }
+ }
+ }
+
+ /**
+ * This class represents events that are related to the language detection feature.
+ * <p>
+ * <pre>
+ * // Translate action shown for foreign text.
+ * new LanguageDetectionEvent.Builder(TYPE_ACTIONS_SHOWN)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(language)
+ * .setScore(score)
+ * .setActionIndices(textClassification.getActions().indexOf(translateAction))
+ * .setEventIndex(0)
+ * .build();
+ *
+ * // Translate action selected.
+ * new LanguageDetectionEvent.Builder(TYPE_SMART_ACTION)
+ * .setEventContext(classificationContext)
+ * .setResultId(textClassification.getId())
+ * .setEntityTypes(language)
+ * .setScore(score)
+ * .setActionIndices(textClassification.getActions().indexOf(translateAction))
+ * .setEventIndex(1)
+ * .build();
+ */
+ public static final class LanguageDetectionEvent extends TextClassifierEvent
+ implements Parcelable {
+
+ @NonNull
+ public static final Creator<LanguageDetectionEvent> CREATOR =
+ new Creator<LanguageDetectionEvent>() {
+ @Override
+ public LanguageDetectionEvent createFromParcel(Parcel in) {
+ // skip token, we already know this is a LanguageDetectionEvent.
+ in.readInt();
+ return new LanguageDetectionEvent(in);
+ }
+
+ @Override
+ public LanguageDetectionEvent[] newArray(int size) {
+ return new LanguageDetectionEvent[size];
+ }
+ };
+
+ @Nullable
+ private final ULocale mLocale;
+
+ private LanguageDetectionEvent(Parcel in) {
+ super(in);
+ final String languageTag = in.readString();
+ mLocale = languageTag == null ? null : ULocale.forLanguageTag(languageTag);
+ }
+
+ private LanguageDetectionEvent(LanguageDetectionEvent.Builder builder) {
+ super(builder);
+ mLocale = builder.mLocale;
+ }
+
+ /**
+ * Returns the detected locale.
+ */
+ @Nullable
+ public ULocale getLocale() {
+ return mLocale;
+ }
+
+ /**
+ * Builder class for {@link LanguageDetectionEvent}.
+ */
+ public static final class Builder
+ extends TextClassifierEvent.Builder<LanguageDetectionEvent.Builder> {
+ @Nullable
+ private ULocale mLocale;
+
+ /**
+ * Creates a builder for building {@link TextSelectionEvent}s.
+ *
+ * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
+ */
+ public Builder(@Type int eventType) {
+ super(TextClassifierEvent.CATEGORY_LANGUAGE_DETECTION, eventType);
+ }
+
+ /**
+ * Sets the detected locale.
+ */
+ @NonNull
+ public Builder setLocale(@Nullable ULocale locale) {
+ mLocale = locale;
+ return this;
+ }
+
+ @Override
+ Builder self() {
+ return this;
+ }
+
+ /**
+ * Builds and returns a {@link LanguageDetectionEvent}.
+ */
+ @NonNull
+ public LanguageDetectionEvent build() {
+ return new LanguageDetectionEvent(this);
+ }
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeString(mLocale == null ? null : mLocale.toLanguageTag());
+ }
+ }
+
+ /**
+ * This class represents events that are related to the conversation actions feature.
+ * <p>
+ * <pre>
+ * // Conversation (contextual) actions/replies generated.
+ * new ConversationActionsEvent.Builder(TYPE_ACTIONS_GENERATED)
+ * .setEventContext(classificationContext)
+ * .setResultId(conversationActions.getId())
+ * .setEntityTypes(getTypes(conversationActions))
+ * .setActionIndices(range(conversationActions.getActions().size()))
+ * .setEventIndex(0)
+ * .build();
+ *
+ * // Conversation actions/replies presented to user.
+ * new ConversationActionsEvent.Builder(TYPE_ACTIONS_SHOWN)
+ * .setEventContext(classificationContext)
+ * .setResultId(conversationActions.getId())
+ * .setEntityTypes(getTypes(conversationActions))
+ * .setActionIndices(range(conversationActions.getActions().size()))
+ * .setEventIndex(1)
+ * .build();
+ *
+ * // User clicked the "Reply" button to compose their custom reply.
+ * new ConversationActionsEvent.Builder(TYPE_MANUAL_REPLY)
+ * .setEventContext(classificationContext)
+ * .setResultId(conversationActions.getId())
+ * .setEventIndex(2)
+ * .build();
+ *
+ * // User selected a smart (contextual) action/reply.
+ * new ConversationActionsEvent.Builder(TYPE_SMART_ACTION)
+ * .setEventContext(classificationContext)
+ * .setResultId(conversationActions.getId())
+ * .setEntityTypes(conversationActions.get(1).getType())
+ * .setScore(conversationAction.get(1).getConfidenceScore())
+ * .setActionIndices(1)
+ * .setEventIndex(2)
+ * .build();
+ * </pre>
+ */
+ public static final class ConversationActionsEvent extends TextClassifierEvent
+ implements Parcelable {
+
+ @NonNull
+ public static final Creator<ConversationActionsEvent> CREATOR =
+ new Creator<ConversationActionsEvent>() {
+ @Override
+ public ConversationActionsEvent createFromParcel(Parcel in) {
+ // skip token, we already know this is a ConversationActionsEvent.
+ in.readInt();
+ return new ConversationActionsEvent(in);
+ }
+
+ @Override
+ public ConversationActionsEvent[] newArray(int size) {
+ return new ConversationActionsEvent[size];
+ }
+ };
+
+ private ConversationActionsEvent(Parcel in) {
+ super(in);
+ }
+
+ private ConversationActionsEvent(ConversationActionsEvent.Builder builder) {
+ super(builder);
+ }
+
+ /**
+ * Builder class for {@link ConversationActionsEvent}.
+ */
+ public static final class Builder
+ extends TextClassifierEvent.Builder<ConversationActionsEvent.Builder> {
+ /**
+ * Creates a builder for building {@link TextSelectionEvent}s.
+ *
+ * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
+ */
+ public Builder(@Type int eventType) {
+ super(TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS, eventType);
+ }
+
+ @Override
+ Builder self() {
+ return this;
+ }
+
+ /**
+ * Builds and returns a {@link ConversationActionsEvent}.
+ */
+ @NonNull
+ public ConversationActionsEvent build() {
+ return new ConversationActionsEvent(this);
+ }
+ }
}
}
diff --git a/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java b/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
index 6a12250..3e088b8 100644
--- a/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
+++ b/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
@@ -65,9 +65,10 @@
final LogMaker log = new LogMaker(category)
.setSubtype(getLogType(event))
.addTaggedData(FIELD_TEXT_CLASSIFIER_SESSION_ID, event.getResultId())
- .addTaggedData(FIELD_TEXTCLASSIFIER_MODEL, getModelName(event))
- .addTaggedData(FIELD_TEXT_CLASSIFIER_SCORE, event.getScore());
-
+ .addTaggedData(FIELD_TEXTCLASSIFIER_MODEL, getModelName(event));
+ if (event.getScores().length >= 1) {
+ log.addTaggedData(FIELD_TEXT_CLASSIFIER_SCORE, event.getScores()[0]);
+ }
String[] entityTypes = event.getEntityTypes();
// The old logger does not support a field of list type, and thus workaround by store them
// in three separate fields. This is not an issue with the new logger.
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 323bf59..3297523 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -307,6 +307,8 @@
final String detectLanguageTags = detectLanguageTagsFromText(request.getText());
final AnnotatorModel annotatorImpl =
getAnnotatorImpl(request.getDefaultLocales());
+ final boolean isSerializedEntityDataEnabled =
+ ExtrasUtils.isSerializedEntityDataEnabled(request);
final AnnotatorModel.AnnotatedSpan[] annotations =
annotatorImpl.annotate(
textString,
@@ -314,7 +316,10 @@
refTime.toInstant().toEpochMilli(),
refTime.getZone().getId(),
localesString,
- detectLanguageTags));
+ detectLanguageTags,
+ entitiesToIdentify,
+ AnnotatorModel.AnnotationUsecase.SMART.getValue(),
+ isSerializedEntityDataEnabled));
for (AnnotatorModel.AnnotatedSpan span : annotations) {
final AnnotatorModel.ClassificationResult[] results =
span.getClassification();
@@ -326,7 +331,11 @@
for (int i = 0; i < results.length; i++) {
entityScores.put(results[i].getCollection(), results[i].getScore());
}
- builder.addLink(span.getStartIndex(), span.getEndIndex(), entityScores);
+ Bundle extras = new Bundle();
+ if (isSerializedEntityDataEnabled) {
+ ExtrasUtils.putEntities(extras, results);
+ }
+ builder.addLink(span.getStartIndex(), span.getEndIndex(), entityScores, extras);
}
final TextLinks links = builder.build();
final long endTimeMs = System.currentTimeMillis();
@@ -451,10 +460,6 @@
Collection<String> expectedTypes = resolveActionTypesFromRequest(request);
List<ConversationAction> conversationActions = new ArrayList<>();
for (ActionsSuggestionsModel.ActionSuggestion nativeSuggestion : nativeSuggestions) {
- if (request.getMaxSuggestions() >= 0
- && conversationActions.size() == request.getMaxSuggestions()) {
- break;
- }
String actionType = nativeSuggestion.getActionType();
if (!expectedTypes.contains(actionType)) {
continue;
@@ -484,6 +489,10 @@
}
conversationActions =
ActionsSuggestionsHelper.removeActionsWithDuplicates(conversationActions);
+ if (request.getMaxSuggestions() >= 0
+ && conversationActions.size() > request.getMaxSuggestions()) {
+ conversationActions = conversationActions.subList(0, request.getMaxSuggestions());
+ }
String resultId = ActionsSuggestionsHelper.createResultId(
mContext,
request.getConversation(),
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 564cfdd..51ca805 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -933,12 +933,11 @@
final String language = ExtrasUtils.getEntityType(foreignLanguageExtra);
final float score = ExtrasUtils.getScore(foreignLanguageExtra);
final String model = ExtrasUtils.getModelName(foreignLanguageExtra);
- return new TextClassifierEvent.Builder(
- TextClassifierEvent.CATEGORY_LANGUAGE_DETECTION, eventType)
+ return new TextClassifierEvent.LanguageDetectionEvent.Builder(eventType)
.setEventContext(classificationContext)
.setResultId(classification.getId())
.setEntityTypes(language)
- .setScore(score)
+ .setScores(score)
.setActionIndices(classification.getActions().indexOf(translateAction))
.setModelName(model)
.build();
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index fd75f4f..21f8d87 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -45,6 +45,7 @@
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Color;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.session.MediaController;
@@ -115,6 +116,7 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.List;
/**
* Android-specific Window.
@@ -3926,4 +3928,15 @@
public WindowInsetsController getInsetsController() {
return mDecor.getWindowInsetsController();
}
+
+ @Override
+ public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+ getViewRootImpl().setRootSystemGestureExclusionRects(rects);
+ }
+
+ @Override
+ @NonNull
+ public List<Rect> getSystemGestureExclusionRects() {
+ return getViewRootImpl().getRootSystemGestureExclusionRects();
+ }
}
diff --git a/core/jni/android_nio_utils.cpp b/core/jni/android_nio_utils.cpp
index a62dd7c..1e6d49e 100644
--- a/core/jni/android_nio_utils.cpp
+++ b/core/jni/android_nio_utils.cpp
@@ -18,51 +18,29 @@
#include "core_jni_helpers.h"
-namespace {
+namespace android {
-void* getPointer(JNIEnv *_env, jobject buffer, jarray *array, void** elements) {
- assert(array);
- jint position;
- jint limit;
- jint elementSizeShift;
- jlong pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
+AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit)
+ : fEnv(env), fCommit(commit) {
+ jlong pointer = jniGetNioBufferPointer(fEnv, nioBuffer);
if (pointer != 0L) {
- *array = nullptr;
- *elements = nullptr;
- pointer += position << elementSizeShift;
- return reinterpret_cast<void*>(pointer);
+ // Buffer is backed by a direct buffer.
+ fArray = nullptr;
+ fElements = nullptr;
+ fPointer = reinterpret_cast<void*>(pointer);
+ } else {
+ // Buffer is backed by a managed array.
+ jint byteOffset = jniGetNioBufferBaseArrayOffset(fEnv, nioBuffer);
+ fArray = jniGetNioBufferBaseArray(fEnv, nioBuffer);
+ fElements = fEnv->GetPrimitiveArrayCritical(fArray, /* isCopy= */ nullptr);
+ fPointer = reinterpret_cast<void*>(reinterpret_cast<char*>(fElements) + byteOffset);
}
- jint offset = jniGetNioBufferBaseArrayOffset(_env, buffer);
- *array = jniGetNioBufferBaseArray(_env, buffer);
- *elements = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
- return reinterpret_cast<void*>(reinterpret_cast<char*>(*elements) + offset);
}
-void releasePointer(JNIEnv *_env, jarray array, void *elements, jboolean commit) {
- _env->ReleasePrimitiveArrayCritical(array, elements, commit ? 0 : JNI_ABORT);
-}
-
-} // namespace
-
-void* android::nio_getPointer(JNIEnv *_env, jobject buffer, jarray *array) {
- void* elements;
- return getPointer(_env, buffer, array, &elements);
-}
-
-void android::nio_releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) {
- releasePointer(_env, array, data, commit);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-android::AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit) {
- fEnv = env;
- fCommit = commit;
- fPointer = getPointer(env, nioBuffer, &fArray, &fElements);
-}
-
-android::AutoBufferPointer::~AutoBufferPointer() {
+AutoBufferPointer::~AutoBufferPointer() {
if (nullptr != fArray) {
- releasePointer(fEnv, fArray, fElements, fCommit);
+ fEnv->ReleasePrimitiveArrayCritical(fArray, fElements, fCommit ? 0 : JNI_ABORT);
}
}
+
+} // namespace android
diff --git a/core/jni/android_nio_utils.h b/core/jni/android_nio_utils.h
index 7c9acd2..aa75dd0 100644
--- a/core/jni/android_nio_utils.h
+++ b/core/jni/android_nio_utils.h
@@ -22,51 +22,58 @@
namespace android {
/**
- * Given an nio.Buffer, return a pointer to it, beginning at its current
- * position. The returned pointer is only valid for the current JNI stack-frame.
- * For performance, it does not create any global references, so the getPointer
- * (and releasePointer if array is returned non-null) must be done in the
- * same JNI stack-frame.
+ * Class providing scoped access to the memory backing a java.nio.Buffer instance.
*
- * @param env The current JNI env
- * @param buffer The nio.Buffer object
- * @param array REQUIRED. Output. If on return it is set to non-null, then
- * nio_releasePointer must be called with the array
- * and the returned pointer when the caller is through with it.
- * If on return it is set to null, do not call
- * nio_releasePointer.
- * @return The pointer to the memory in the buffer object
- */
-void* nio_getPointer(JNIEnv *env, jobject buffer, jarray *array);
-
-/**
- * Call this if android_nio_getPointer returned non-null in its array parameter.
- * Pass that array and the returned pointer when you are done accessing the
- * pointer. If called (i.e. array is non-null), it must be called in the same
- * JNI stack-frame as getPointer
+ * Instances of this class should only be allocated on the stack as heap allocation is not
+ * supported.
*
- * @param env The current JNI env
- * @param buffer The array returned from android_nio_getPointer (!= null)
- * @param pointer The pointer returned by android_nio_getPointer
- * @param commit JNI_FALSE if the pointer was just read, and JNI_TRUE if
- * the pointer was written to.
+ * Instances of this class do not create any global references for performance reasons.
*/
-void nio_releasePointer(JNIEnv *env, jarray array, void *pointer,
- jboolean commit);
-
-class AutoBufferPointer {
+class AutoBufferPointer final {
public:
+ /** Constructor for an AutoBufferPointer instance.
+ *
+ * @param env The current JNI env
+ * @param nioBuffer Instance of a java.nio.Buffer whose memory will be accessed.
+ * @param commit JNI_TRUE if the underlying memory will be updated and should be
+ * copied back to the managed heap. JNI_FALSE if the data will
+ * not be modified or the modifications may be discarded.
+ *
+ * The commit parameter is only applicable if the buffer is backed by a managed heap
+ * array and the runtime had to provide a copy of the data rather than the original data.
+ */
AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit);
+
+ /** Destructor for an AutoBufferPointer instance.
+ *
+ * Releases critical managed heap array pointer if acquired.
+ */
~AutoBufferPointer();
+ /**
+ * Returns a pointer to the current position of the buffer provided to the constructor. This
+ * pointer is only valid whilst the AutoBufferPointer instance remains in scope.
+ */
void* pointer() const { return fPointer; }
private:
- JNIEnv* fEnv;
- void* fPointer; // pointer to current buffer position.
- void* fElements; // pointer to array element 0 (may be directly in fArray or a copy).
- jarray fArray; // pointer to array on managed heap.
- jboolean fCommit; // commit data to source if required (when fElements is a copy of fArray).
+ JNIEnv* const fEnv;
+ void* fPointer; // Pointer to current buffer position when constructed.
+ void* fElements; // Pointer to array element 0 (null if buffer is direct, may be
+ // within fArray or point to a copy of the array).
+ jarray fArray; // Pointer to array on managed heap.
+ const jboolean fCommit; // Flag to commit data to source (when fElements is a copy of fArray).
+
+ // Unsupported constructors and operators.
+ AutoBufferPointer() = delete;
+ AutoBufferPointer(AutoBufferPointer&) = delete;
+ AutoBufferPointer& operator=(AutoBufferPointer&) = delete;
+ static void* operator new(std::size_t);
+ static void* operator new[](std::size_t);
+ static void* operator new(std::size_t, void*);
+ static void* operator new[](std::size_t, void*);
+ static void operator delete(void*, std::size_t);
+ static void operator delete[](void*, std::size_t);
};
} /* namespace android */
diff --git a/core/tests/coretests/src/android/graphics/BitmapTest.java b/core/tests/coretests/src/android/graphics/BitmapTest.java
index 4bee243..2280cf1 100644
--- a/core/tests/coretests/src/android/graphics/BitmapTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapTest.java
@@ -23,6 +23,8 @@
import junit.framework.TestCase;
import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
public class BitmapTest extends TestCase {
@@ -266,10 +268,11 @@
}
@SmallTest
- public void testCopyWithDirectBuffer() {
+ public void testCopyWithDirectByteBuffer() {
// Initialize Bitmap
final int width = 2;
final int height = 2;
+ final int bytesPerPixel = 2;
Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
@@ -277,7 +280,8 @@
// of bitmap.
final int pad = 1;
final byte padValue = 0x5a;
- final int bufferSize = pad + width * height * 2 + pad;
+ final int bytesPerElement = 1;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
ByteBuffer directBuffer = ByteBuffer.allocateDirect(bufferSize);
// Write padding
@@ -287,7 +291,8 @@
// Copy bitmap
directBuffer.position(pad);
bm1.copyPixelsToBuffer(directBuffer);
- assertEquals(directBuffer.position(), pad + width * height * 2);
+ assertEquals(directBuffer.position(),
+ pad + width * height * bytesPerPixel / bytesPerElement);
// Check padding
assertEquals(directBuffer.get(0), padValue);
@@ -301,10 +306,89 @@
}
@SmallTest
- public void testCopyWithHeapBuffer() {
+ public void testCopyWithDirectShortBuffer() {
// Initialize Bitmap
final int width = 2;
final int height = 2;
+ final int bytesPerPixel = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final short padValue = 0x55aa;
+ final int bytesPerElement = 2;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+ ShortBuffer directBuffer =
+ ByteBuffer.allocateDirect(bufferSize * bytesPerElement).asShortBuffer();
+
+ // Write padding
+ directBuffer.put(0, padValue);
+ directBuffer.put(directBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ directBuffer.position(pad);
+ bm1.copyPixelsToBuffer(directBuffer);
+ assertEquals(directBuffer.position(),
+ pad + width * height * bytesPerPixel / bytesPerElement);
+
+ // Check padding
+ assertEquals(directBuffer.get(0), padValue);
+ assertEquals(directBuffer.get(directBuffer.limit() - 1), padValue);
+
+ // Create bitmap from heap buffer and check match.
+ directBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(directBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
+
+ @SmallTest
+ public void testCopyWithDirectIntBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ final int bytesPerPixel = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final int padValue = 0x55aa5a5a;
+ final int bytesPerElement = 4;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+ IntBuffer directBuffer =
+ ByteBuffer.allocateDirect(bufferSize * bytesPerElement).asIntBuffer();
+
+ // Write padding
+ directBuffer.put(0, padValue);
+ directBuffer.put(directBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ directBuffer.position(pad);
+ bm1.copyPixelsToBuffer(directBuffer);
+ assertEquals(directBuffer.position(),
+ pad + width * height * bytesPerPixel / bytesPerElement);
+
+ // Check padding
+ assertEquals(directBuffer.get(0), padValue);
+ assertEquals(directBuffer.get(directBuffer.limit() - 1), padValue);
+
+ // Create bitmap from heap buffer and check match.
+ directBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(directBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
+
+ @SmallTest
+ public void testCopyWithHeapByteBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ final int bytesPerPixel = 2;
Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
@@ -312,7 +396,8 @@
// of bitmap.
final int pad = 1;
final byte padValue = 0x5a;
- final int bufferSize = pad + width * height * 2 + pad;
+ final int bytesPerElement = 1;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
ByteBuffer heapBuffer = ByteBuffer.allocate(bufferSize);
// Write padding
@@ -322,7 +407,81 @@
// Copy bitmap
heapBuffer.position(pad);
bm1.copyPixelsToBuffer(heapBuffer);
- assertEquals(heapBuffer.position(), pad + width * height * 2);
+ assertEquals(heapBuffer.position(), pad + width * height * bytesPerPixel / bytesPerElement);
+
+ // Check padding
+ assertEquals(heapBuffer.get(0), padValue);
+ assertEquals(heapBuffer.get(heapBuffer.limit() - 1), padValue);
+
+ // Create bitmap from heap buffer and check match.
+ heapBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(heapBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
+
+ @SmallTest
+ public void testCopyWithHeapShortBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ final int bytesPerPixel = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final short padValue = 0x55aa;
+ final int bytesPerElement = 2;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+ ShortBuffer heapBuffer = ShortBuffer.allocate(bufferSize);
+
+ // Write padding
+ heapBuffer.put(0, padValue);
+ heapBuffer.put(heapBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ heapBuffer.position(pad);
+ bm1.copyPixelsToBuffer(heapBuffer);
+ assertEquals(heapBuffer.position(), pad + width * height * bytesPerPixel / bytesPerElement);
+
+ // Check padding
+ assertEquals(heapBuffer.get(0), padValue);
+ assertEquals(heapBuffer.get(heapBuffer.limit() - 1), padValue);
+
+ // Create bitmap from heap buffer and check match.
+ heapBuffer.position(pad);
+ Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm2.copyPixelsFromBuffer(heapBuffer);
+ assertTrue(bm2.sameAs(bm1));
+ }
+
+ @SmallTest
+ public void testCopyWithHeapIntBuffer() {
+ // Initialize Bitmap
+ final int width = 2;
+ final int height = 2;
+ final int bytesPerPixel = 2;
+ Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+ // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+ // of bitmap.
+ final int pad = 1;
+ final int padValue = 0x55aa5a5a;
+ final int bytesPerElement = 4;
+ final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+ IntBuffer heapBuffer = IntBuffer.allocate(bufferSize);
+
+ // Write padding
+ heapBuffer.put(0, padValue);
+ heapBuffer.put(heapBuffer.limit() - 1, padValue);
+
+ // Copy bitmap
+ heapBuffer.position(pad);
+ bm1.copyPixelsToBuffer(heapBuffer);
+ assertEquals(heapBuffer.position(), pad + width * height * bytesPerPixel / bytesPerElement);
// Check padding
assertEquals(heapBuffer.get(0), padValue);
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
index 433991e..aeb8949 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
@@ -362,6 +362,38 @@
}
@Test
+ public void testGenerateLinks_entityData() {
+ if (isTextClassifierDisabled()) return;
+ String text = "The number is +12122537077.";
+ Bundle extras = new Bundle();
+ ExtrasUtils.putIsSerializedEntityDataEnabled(extras, true);
+ TextLinks.Request request = new TextLinks.Request.Builder(text).setExtras(extras).build();
+
+ TextLinks textLinks = mClassifier.generateLinks(request);
+
+ Truth.assertThat(textLinks.getLinks()).hasSize(1);
+ TextLinks.TextLink textLink = textLinks.getLinks().iterator().next();
+ List<Bundle> entities = ExtrasUtils.getEntities(textLink.getExtras());
+ Truth.assertThat(entities).hasSize(1);
+ Bundle entity = entities.get(0);
+ Truth.assertThat(ExtrasUtils.getEntityType(entity)).isEqualTo(TextClassifier.TYPE_PHONE);
+ }
+
+ @Test
+ public void testGenerateLinks_entityData_disabled() {
+ if (isTextClassifierDisabled()) return;
+ String text = "The number is +12122537077.";
+ TextLinks.Request request = new TextLinks.Request.Builder(text).build();
+
+ TextLinks textLinks = mClassifier.generateLinks(request);
+
+ Truth.assertThat(textLinks.getLinks()).hasSize(1);
+ TextLinks.TextLink textLink = textLinks.getLinks().iterator().next();
+ List<Bundle> entities = ExtrasUtils.getEntities(textLink.getExtras());
+ Truth.assertThat(entities).isNull();
+ }
+
+ @Test
public void testDetectLanguage() {
if (isTextClassifierDisabled()) return;
String text = "This is English text";
@@ -380,7 +412,7 @@
}
@Test
- public void testSuggestConversationActions_textReplyOnly_maxThree() {
+ public void testSuggestConversationActions_textReplyOnly_maxOne() {
if (isTextClassifierDisabled()) return;
ConversationActions.Message message =
new ConversationActions.Message.Builder(
@@ -399,12 +431,11 @@
.build();
ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
- assertTrue(conversationActions.getConversationActions().size() > 0);
- for (ConversationAction conversationAction :
- conversationActions.getConversationActions()) {
- assertThat(conversationAction,
- isConversationAction(ConversationAction.TYPE_TEXT_REPLY));
- }
+ Truth.assertThat(conversationActions.getConversationActions()).hasSize(1);
+ ConversationAction conversationAction = conversationActions.getConversationActions().get(0);
+ Truth.assertThat(conversationAction.getType()).isEqualTo(
+ ConversationAction.TYPE_TEXT_REPLY);
+ Truth.assertThat(conversationAction.getTextReply()).isNotNull();
}
@Test
@@ -493,6 +524,24 @@
ExtrasUtils.getSerializedEntityData(conversationAction.getExtras())).isNotEmpty();
}
+ @Test
+ public void testSuggetsConversationActions_deduplicate() {
+ if (isTextClassifierDisabled()) return;
+ ConversationActions.Message message =
+ new ConversationActions.Message.Builder(
+ ConversationActions.Message.PERSON_USER_OTHERS)
+ .setText("a@android.com b@android.com")
+ .build();
+ ConversationActions.Request request =
+ new ConversationActions.Request.Builder(Collections.singletonList(message))
+ .setMaxSuggestions(3)
+ .build();
+
+ ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
+
+ Truth.assertThat(conversationActions.getConversationActions()).isEmpty();
+ }
+
private boolean isTextClassifierDisabled() {
return mClassifier == null || mClassifier == TextClassifier.NO_OP;
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
index 1980a60..2c540e5 100644
--- a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
@@ -49,8 +49,6 @@
public class TextClassifierEventTronLoggerTest {
private static final String WIDGET_TYPE = "notification";
private static final String PACKAGE_NAME = "pkg";
- private static final long EVENT_TIME = System.currentTimeMillis();
-
@Mock
private MetricsLogger mMetricsLogger;
@@ -68,13 +66,11 @@
TextClassificationContext textClassificationContext =
new TextClassificationContext.Builder(PACKAGE_NAME, WIDGET_TYPE)
.build();
- TextClassifierEvent textClassifierEvent =
- new TextClassifierEvent.Builder(
- TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS,
+ TextClassifierEvent.ConversationActionsEvent textClassifierEvent =
+ new TextClassifierEvent.ConversationActionsEvent.Builder(
TextClassifierEvent.TYPE_SMART_ACTION)
.setEntityTypes(ConversationAction.TYPE_CALL_PHONE)
- .setScore(0.5f)
- .setEventTime(EVENT_TIME)
+ .setScores(0.5f)
.setEventContext(textClassificationContext)
.build();
@@ -83,10 +79,8 @@
ArgumentCaptor<LogMaker> captor = ArgumentCaptor.forClass(LogMaker.class);
Mockito.verify(mMetricsLogger).write(captor.capture());
LogMaker logMaker = captor.getValue();
- assertThat(logMaker.getCategory()).isEqualTo(
- CONVERSATION_ACTIONS);
- assertThat(logMaker.getSubtype()).isEqualTo(
- ACTION_TEXT_SELECTION_SMART_SHARE);
+ assertThat(logMaker.getCategory()).isEqualTo(CONVERSATION_ACTIONS);
+ assertThat(logMaker.getSubtype()).isEqualTo(ACTION_TEXT_SELECTION_SMART_SHARE);
assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_FIRST_ENTITY_TYPE))
.isEqualTo(ConversationAction.TYPE_CALL_PHONE);
assertThat((float) logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_SCORE))
@@ -101,9 +95,8 @@
@Test
public void testWriteEvent_unsupportedCategory() {
- TextClassifierEvent textClassifierEvent =
- new TextClassifierEvent.Builder(
- TextClassifierEvent.CATEGORY_SELECTION,
+ TextClassifierEvent.TextSelectionEvent textClassifierEvent =
+ new TextClassifierEvent.TextSelectionEvent.Builder(
TextClassifierEvent.TYPE_SMART_ACTION)
.build();
diff --git a/media/Android.bp b/media/Android.bp
index 5b7b26c..70dacb2 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -20,10 +20,6 @@
],
},
- static_libs: [
- "mediaplayer2-protos",
- ],
-
permitted_packages: [
"android.media",
],
@@ -43,7 +39,6 @@
name: "updatable-media-srcs",
srcs: [
":mediasession2-srcs",
- ":mediaplayer2-srcs",
],
}
@@ -51,7 +46,6 @@
name: "updatable-media-srcs-without-aidls",
srcs : [
":mediasession2-srcs-without-aidls",
- ":mediaplayer2-srcs",
],
}
@@ -109,8 +103,7 @@
"--hide MissingPermission --hide BroadcastBehavior " +
"--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
"--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
- "--hide HiddenTypedefConstant --show-annotation android.annotation.SystemApi " +
- " --show-annotation android.annotation.TestApi "
+ "--hide HiddenTypedefConstant --show-annotation android.annotation.SystemApi "
droidstubs {
name: "updatable-media-stubs",
diff --git a/media/apex/java/android/media/BufferingParams.java b/media/apex/java/android/media/BufferingParams.java
index 83594d4..943f142 100644
--- a/media/apex/java/android/media/BufferingParams.java
+++ b/media/apex/java/android/media/BufferingParams.java
@@ -17,7 +17,6 @@
package android.media;
import android.annotation.IntDef;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -64,7 +63,6 @@
* <p>Users should use {@link Builder} to change {@link BufferingParams}.
* @hide
*/
-@TestApi
public final class BufferingParams implements Parcelable {
private static final int BUFFERING_NO_MARK = -1;
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index fefb0d7..e207721 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -495,15 +495,17 @@
if (mCursor == null || !mCursor.moveToPosition(position)) {
return null;
}
-
- return getUriFromCursor(mCursor);
+
+ return getUriFromCursor(mContext, mCursor);
}
- private static Uri getUriFromCursor(Cursor cursor) {
- return ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)), cursor
- .getLong(ID_COLUMN_INDEX));
+ private static Uri getUriFromCursor(Context context, Cursor cursor) {
+ final Uri uri = ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)),
+ cursor.getLong(ID_COLUMN_INDEX));
+ final Uri canonicalized = context.getContentResolver().canonicalize(uri);
+ return (canonicalized != null) ? canonicalized : uri;
}
-
+
/**
* Gets the position of a {@link Uri} within this {@link RingtoneManager}.
*
@@ -569,7 +571,7 @@
Uri uri = null;
if (cursor.moveToFirst()) {
- uri = getUriFromCursor(cursor);
+ uri = getUriFromCursor(context, cursor);
}
cursor.close();
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index 0d687d4..10360a3 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -338,7 +338,7 @@
createTextClassifierEventBuilder(
TextClassifierEvent.TYPE_SMART_ACTION, session.resultId)
.setEntityTypes(ConversationAction.TYPE_TEXT_REPLY)
- .setScore(session.repliesScores.getOrDefault(reply, 0f))
+ .setScores(session.repliesScores.getOrDefault(reply, 0f))
.build();
mTextClassifier.onTextClassifierEvent(textClassifierEvent);
}
@@ -381,11 +381,9 @@
.build();
}
- private TextClassifierEvent.Builder createTextClassifierEventBuilder(
+ private TextClassifierEvent.ConversationActionsEvent.Builder createTextClassifierEventBuilder(
int eventType, String resultId) {
- return new TextClassifierEvent.Builder(
- TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS, eventType)
- .setEventTime(System.currentTimeMillis())
+ return new TextClassifierEvent.ConversationActionsEvent.Builder(eventType)
.setEventContext(
new TextClassificationContext.Builder(
mContext.getPackageName(), TextClassifier.WIDGET_TYPE_NOTIFICATION)
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
index ebcaee8..dfa1ea0 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
@@ -330,7 +330,9 @@
List<TextClassifierEvent> events = argumentCaptor.getAllValues();
assertTextClassifierEvent(events.get(0), TextClassifierEvent.TYPE_ACTIONS_GENERATED);
assertTextClassifierEvent(events.get(1), TextClassifierEvent.TYPE_SMART_ACTION);
- assertThat(events.get(1).getScore()).isEqualTo(SCORE);
+ float[] scores = events.get(1).getScores();
+ assertThat(scores).hasLength(1);
+ assertThat(scores[0]).isEqualTo(SCORE);
}
@Test
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index b2ac1b8..654c477 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -147,6 +147,8 @@
mLegacyRoleResolver = legacyRoleResolver;
+ RoleControllerManager.initializeRemoteServiceComponentName(context);
+
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
mAppOpsManager = context.getSystemService(AppOpsManager.class);
@@ -231,7 +233,7 @@
// Run grants again
Slog.i(LOG_TAG, "Granting default permissions...");
CompletableFuture<Void> result = new CompletableFuture<>();
- getOrCreateControllerService(userId).grantDefaultRoles(FgThread.getExecutor(),
+ getOrCreateController(userId).grantDefaultRoles(FgThread.getExecutor(),
successful -> {
if (successful) {
userState.setPackagesHash(packagesHash);
@@ -318,7 +320,7 @@
}
@NonNull
- private RoleControllerManager getOrCreateControllerService(@UserIdInt int userId) {
+ private RoleControllerManager getOrCreateController(@UserIdInt int userId) {
synchronized (mLock) {
RoleControllerManager controller = mControllers.get(userId);
if (controller == null) {
@@ -330,7 +332,8 @@
} catch (NameNotFoundException e) {
throw new RuntimeException(e);
}
- controller = new RoleControllerManager(context, FgThread.getHandler());
+ controller = RoleControllerManager.createWithInitializedRemoteServiceComponentName(
+ FgThread.getHandler(), context);
mControllers.put(userId, controller);
}
return controller;
@@ -474,7 +477,7 @@
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
Preconditions.checkNotNull(callback, "callback cannot be null");
- getOrCreateControllerService(userId).onAddRoleHolder(roleName, packageName, flags,
+ getOrCreateController(userId).onAddRoleHolder(roleName, packageName, flags,
callback);
}
@@ -494,7 +497,7 @@
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
Preconditions.checkNotNull(callback, "callback cannot be null");
- getOrCreateControllerService(userId).onRemoveRoleHolder(roleName, packageName, flags,
+ getOrCreateController(userId).onRemoveRoleHolder(roleName, packageName, flags,
callback);
}
@@ -513,7 +516,7 @@
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkNotNull(callback, "callback cannot be null");
- getOrCreateControllerService(userId).onClearRoleHolders(roleName, flags, callback);
+ getOrCreateController(userId).onClearRoleHolders(roleName, flags, callback);
}
@Override
@@ -738,10 +741,10 @@
}
});
if (packageName != null) {
- getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
+ getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
packageName, 0, callback);
} else {
- getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
+ getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
callback);
}
try {
@@ -762,10 +765,10 @@
}
});
if (packageName != null) {
- getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
+ getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
packageName, 0, callback);
} else {
- getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
+ getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
callback);
}
}
@@ -791,10 +794,10 @@
callback.accept(successful);
});
if (packageName != null) {
- getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_HOME,
+ getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_HOME,
packageName, 0, remoteCallback);
} else {
- getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_HOME, 0,
+ getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_HOME, 0,
remoteCallback);
}
}