Merge "Move netd related file group to the end for avoiding conflict"
diff --git a/Android.bp b/Android.bp
index 34162d1..2ae7d6c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -268,6 +268,8 @@
"core/java/android/rolecontrollerservice/IRoleControllerService.aidl",
":keystore_aidl",
"core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
+ "core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl",
+ "core/java/android/service/autofill/augmented/IFillCallback.aidl",
"core/java/android/service/autofill/IAutoFillService.aidl",
"core/java/android/service/autofill/IAutofillFieldClassificationService.aidl",
"core/java/android/service/autofill/IFillCallback.aidl",
@@ -290,7 +292,7 @@
"core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl",
"core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl",
"core/java/android/service/gatekeeper/IGateKeeperService.aidl",
- "core/java/android/service/intelligence/IIntelligenceService.aidl",
+ "core/java/android/service/contentcapture/IContentCaptureService.aidl",
"core/java/android/service/notification/INotificationListener.aidl",
"core/java/android/service/notification/IStatusBarNotificationHolder.aidl",
"core/java/android/service/notification/IConditionListener.aidl",
@@ -351,7 +353,7 @@
"core/java/android/view/autofill/IAutoFillManagerClient.aidl",
"core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl",
"core/java/android/view/autofill/IAutofillWindowPresenter.aidl",
- "core/java/android/view/intelligence/IIntelligenceManager.aidl",
+ "core/java/android/view/contentcapture/IContentCaptureManager.aidl",
"core/java/android/view/IApplicationToken.aidl",
"core/java/android/view/IAppTransitionAnimationSpecsFuture.aidl",
"core/java/android/view/IDockedStackListener.aidl",
diff --git a/api/current.txt b/api/current.txt
index 88330fd..7a53327 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -34660,6 +34660,7 @@
field public static final java.lang.String DISALLOW_CONFIG_TETHERING = "no_config_tethering";
field public static final java.lang.String DISALLOW_CONFIG_VPN = "no_config_vpn";
field public static final java.lang.String DISALLOW_CONFIG_WIFI = "no_config_wifi";
+ field public static final java.lang.String DISALLOW_CONTENT_CAPTURE = "no_content_capture";
field public static final java.lang.String DISALLOW_CREATE_WINDOWS = "no_create_windows";
field public static final java.lang.String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";
field public static final java.lang.String DISALLOW_DATA_ROAMING = "no_data_roaming";
@@ -34669,7 +34670,6 @@
field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps";
field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY = "no_install_unknown_sources_globally";
- field public static final java.lang.String DISALLOW_INTELLIGENCE_CAPTURE = "no_intelligence_capture";
field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
field public static final java.lang.String DISALLOW_NETWORK_RESET = "no_network_reset";
@@ -51851,6 +51851,21 @@
}
+package android.view.contentcapture {
+
+ public final class ContentCaptureManager {
+ method public android.content.ComponentName getServiceComponentName();
+ method public boolean isContentCaptureEnabled();
+ method public android.view.ViewStructure newVirtualViewStructure(android.view.autofill.AutofillId, int);
+ method public void notifyViewAppeared(android.view.ViewStructure);
+ method public void notifyViewDisappeared(android.view.autofill.AutofillId);
+ method public void notifyViewTextChanged(android.view.autofill.AutofillId, java.lang.CharSequence, int);
+ method public void setContentCaptureEnabled(boolean);
+ field public static final int FLAG_USER_INPUT = 1; // 0x1
+ }
+
+}
+
package android.view.inputmethod {
public class BaseInputConnection implements android.view.inputmethod.InputConnection {
@@ -52332,21 +52347,6 @@
}
-package android.view.intelligence {
-
- public final class ContentCaptureManager {
- method public android.content.ComponentName getServiceComponentName();
- method public boolean isContentCaptureEnabled();
- method public android.view.ViewStructure newVirtualViewStructure(android.view.autofill.AutofillId, int);
- method public void notifyViewAppeared(android.view.ViewStructure);
- method public void notifyViewDisappeared(android.view.autofill.AutofillId);
- method public void notifyViewTextChanged(android.view.autofill.AutofillId, java.lang.CharSequence, int);
- method public void setContentCaptureEnabled(boolean);
- field public static final int FLAG_USER_INPUT = 1; // 0x1
- }
-
-}
-
package android.view.textclassifier {
public final class ConversationActions implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 9cf66b2..542fdff 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -21,7 +21,9 @@
field public static final java.lang.String BACKUP = "android.permission.BACKUP";
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
+ field public static final java.lang.String BIND_AUGMENTED_AUTOFILL_SERVICE = "android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE";
field public static final deprecated java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
+ field public static final java.lang.String BIND_CONTENT_CAPTURE_SERVICE = "android.permission.BIND_CONTENT_CAPTURE_SERVICE";
field public static final java.lang.String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH";
field public static final java.lang.String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE";
field public static final java.lang.String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
@@ -33,7 +35,6 @@
field public static final java.lang.String BIND_RESOLVER_RANKER_SERVICE = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE";
field public static final java.lang.String BIND_SETTINGS_SUGGESTIONS_SERVICE = "android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE";
- field public static final java.lang.String BIND_SMART_SUGGESTIONS_SERVICE = "android.permission.BIND_SMART_SUGGESTIONS_SERVICE";
field public static final java.lang.String BIND_SOUND_TRIGGER_DETECTION_SERVICE = "android.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE";
field public static final java.lang.String BIND_TELEPHONY_DATA_SERVICE = "android.permission.BIND_TELEPHONY_DATA_SERVICE";
field public static final java.lang.String BIND_TELEPHONY_NETWORK_SERVICE = "android.permission.BIND_TELEPHONY_NETWORK_SERVICE";
@@ -105,11 +106,11 @@
field public static final java.lang.String MANAGE_AUTO_FILL = "android.permission.MANAGE_AUTO_FILL";
field public static final java.lang.String MANAGE_CARRIER_OEM_UNLOCK_STATE = "android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE";
field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
+ field public static final java.lang.String MANAGE_CONTENT_CAPTURE = "android.permission.MANAGE_CONTENT_CAPTURE";
field public static final java.lang.String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING";
field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
field public static final java.lang.String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
field public static final java.lang.String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
- field public static final java.lang.String MANAGE_SMART_SUGGESTIONS = "android.permission.MANAGE_SMART_SUGGESTIONS";
field public static final java.lang.String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER";
field public static final java.lang.String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS";
field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB";
@@ -4858,6 +4859,69 @@
}
+package android.service.autofill.augmented {
+
+ public abstract class AugmentedAutofillService extends android.app.Service {
+ ctor public AugmentedAutofillService();
+ method public void onFillRequest(android.service.autofill.augmented.FillRequest, android.os.CancellationSignal, android.service.autofill.augmented.FillController, android.service.autofill.augmented.FillCallback);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.augmented.AugmentedAutofillService";
+ }
+
+ public final class FillCallback {
+ method public void onSuccess(android.service.autofill.augmented.FillResponse);
+ }
+
+ public final class FillController {
+ method public void autofill(java.util.List<android.util.Pair<android.view.autofill.AutofillId, android.view.autofill.AutofillValue>>);
+ }
+
+ public final class FillRequest {
+ method public android.content.ComponentName getActivityComponent();
+ method public android.view.autofill.AutofillId getFocusedId();
+ method public android.view.autofill.AutofillValue getFocusedValue();
+ method public android.service.autofill.augmented.PresentationParams getPresentationParams();
+ method public int getTaskId();
+ }
+
+ public final class FillResponse implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.augmented.FillResponse> CREATOR;
+ }
+
+ public static final class FillResponse.Builder {
+ ctor public FillResponse.Builder();
+ method public android.service.autofill.augmented.FillResponse build();
+ method public android.service.autofill.augmented.FillResponse.Builder setFillWindow(android.service.autofill.augmented.FillWindow);
+ method public android.service.autofill.augmented.FillResponse.Builder setIgnoredIds(java.util.List<android.view.autofill.AutofillId>);
+ }
+
+ public final class FillWindow implements java.lang.AutoCloseable {
+ ctor public FillWindow();
+ method public void destroy();
+ method public boolean update(android.service.autofill.augmented.PresentationParams.Area, android.view.View, long);
+ field public static final long FLAG_METADATA_ADDRESS = 1L; // 0x1L
+ }
+
+ public abstract class PresentationParams {
+ method public int getFlags();
+ method public android.service.autofill.augmented.PresentationParams.Area getFullArea();
+ method public android.service.autofill.augmented.PresentationParams.Area getSuggestionArea();
+ field public static final int FLAG_HINT_GRAVITY_BOTTOM = 2; // 0x2
+ field public static final int FLAG_HINT_GRAVITY_LEFT = 4; // 0x4
+ field public static final int FLAG_HINT_GRAVITY_RIGHT = 8; // 0x8
+ field public static final int FLAG_HINT_GRAVITY_TOP = 1; // 0x1
+ field public static final int FLAG_HOST_IME = 16; // 0x10
+ field public static final int FLAG_HOST_SYSTEM = 32; // 0x20
+ }
+
+ public static abstract class PresentationParams.Area {
+ method public android.graphics.Rect getBounds();
+ method public android.service.autofill.augmented.PresentationParams.Area getSubArea(android.graphics.Rect);
+ }
+
+}
+
package android.service.carrier {
public abstract class ApnService extends android.app.Service {
@@ -4868,6 +4932,58 @@
}
+package android.service.contentcapture {
+
+ public final class ContentCaptureEventsRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.util.List<android.view.contentcapture.ContentCaptureEvent> getEvents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.contentcapture.ContentCaptureEventsRequest> CREATOR;
+ }
+
+ public abstract class ContentCaptureService extends android.app.Service {
+ ctor public ContentCaptureService();
+ method public final java.util.Set<android.content.ComponentName> getContentCaptureDisabledActivities();
+ method public final java.util.Set<java.lang.String> getContentCaptureDisabledPackages();
+ method public void onActivitySnapshot(android.service.contentcapture.InteractionSessionId, android.service.contentcapture.SnapshotData);
+ method public abstract void onContentCaptureEventsRequest(android.service.contentcapture.InteractionSessionId, android.service.contentcapture.ContentCaptureEventsRequest);
+ method public void onCreateInteractionSession(android.service.contentcapture.InteractionContext, android.service.contentcapture.InteractionSessionId);
+ method public void onDestroyInteractionSession(android.service.contentcapture.InteractionSessionId);
+ method public final void setActivityContentCaptureEnabled(android.content.ComponentName, boolean);
+ method public final void setContentCaptureWhitelist(java.util.List<java.lang.String>, java.util.List<android.content.ComponentName>);
+ method public final void setPackageContentCaptureEnabled(java.lang.String, boolean);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
+ }
+
+ public final class InteractionContext implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.content.ComponentName getActivityComponent();
+ method public int getDisplayId();
+ method public int getFlags();
+ method public int getTaskId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.contentcapture.InteractionContext> CREATOR;
+ field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
+ field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
+ }
+
+ public final class InteractionSessionId implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.contentcapture.InteractionSessionId> CREATOR;
+ }
+
+ public final class SnapshotData implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.app.assist.AssistContent getAssistContent();
+ method public android.os.Bundle getAssistData();
+ method public android.app.assist.AssistStructure getAssistStructure();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.contentcapture.SnapshotData> CREATOR;
+ }
+
+}
+
package android.service.euicc {
public final class EuiccProfileInfo implements android.os.Parcelable {
@@ -4988,111 +5104,6 @@
}
-package android.service.intelligence {
-
- public final class ContentCaptureEventsRequest implements android.os.Parcelable {
- method public int describeContents();
- method public java.util.List<android.view.intelligence.ContentCaptureEvent> getEvents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.service.intelligence.ContentCaptureEventsRequest> CREATOR;
- }
-
- public final class FillCallback {
- method public void onSuccess(android.service.intelligence.FillResponse);
- }
-
- public final class FillController {
- method public void autofill(java.util.List<android.util.Pair<android.view.autofill.AutofillId, android.view.autofill.AutofillValue>>);
- }
-
- public final class FillRequest {
- method public android.view.autofill.AutofillValue getFocusedAutofillValue();
- method public android.view.autofill.AutofillId getFocusedId();
- method public android.service.intelligence.PresentationParams getPresentationParams();
- method public android.service.intelligence.InteractionSessionId getSessionId();
- }
-
- public final class FillResponse implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.service.intelligence.FillResponse> CREATOR;
- }
-
- public static class FillResponse.Builder {
- ctor public FillResponse.Builder();
- method public android.service.intelligence.FillResponse build();
- method public android.service.intelligence.FillResponse.Builder setFillWindow(android.service.intelligence.FillWindow);
- method public android.service.intelligence.FillResponse.Builder setIgnoredIds(java.util.List<android.view.autofill.AutofillId>);
- }
-
- public final class FillWindow {
- ctor public FillWindow();
- method public void destroy();
- method public boolean update(android.service.intelligence.PresentationParams.Area, android.view.View, long);
- field public static final long FLAG_METADATA_ADDRESS = 1L; // 0x1L
- }
-
- public final class InteractionContext implements android.os.Parcelable {
- method public int describeContents();
- method public android.content.ComponentName getActivityComponent();
- method public int getDisplayId();
- method public int getFlags();
- method public int getTaskId();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.service.intelligence.InteractionContext> CREATOR;
- field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
- field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
- }
-
- public final class InteractionSessionId implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.service.intelligence.InteractionSessionId> CREATOR;
- }
-
- public abstract class PresentationParams {
- method public int getFlags();
- method public android.service.intelligence.PresentationParams.Area getFullArea();
- method public android.service.intelligence.PresentationParams.Area getSuggestionArea();
- field public static final int FLAG_HINT_GRAVITY_BOTTOM = 2; // 0x2
- field public static final int FLAG_HINT_GRAVITY_LEFT = 4; // 0x4
- field public static final int FLAG_HINT_GRAVITY_RIGHT = 8; // 0x8
- field public static final int FLAG_HINT_GRAVITY_TOP = 1; // 0x1
- field public static final int FLAG_HOST_IME = 16; // 0x10
- field public static final int FLAG_HOST_SYSTEM = 32; // 0x20
- }
-
- public static abstract class PresentationParams.Area {
- method public android.graphics.Rect getBounds();
- method public android.service.intelligence.PresentationParams.Area getSubArea(android.graphics.Rect);
- }
-
- public abstract class SmartSuggestionsService extends android.app.Service {
- ctor public SmartSuggestionsService();
- method public final java.util.Set<android.content.ComponentName> getContentCaptureDisabledActivities();
- method public final java.util.Set<java.lang.String> getContentCaptureDisabledPackages();
- method public void onActivitySnapshot(android.service.intelligence.InteractionSessionId, android.service.intelligence.SnapshotData);
- method public abstract void onContentCaptureEventsRequest(android.service.intelligence.InteractionSessionId, android.service.intelligence.ContentCaptureEventsRequest);
- method public void onCreateInteractionSession(android.service.intelligence.InteractionContext, android.service.intelligence.InteractionSessionId);
- method public void onDestroyInteractionSession(android.service.intelligence.InteractionSessionId);
- method public void onFillRequest(android.service.intelligence.InteractionSessionId, android.service.intelligence.FillRequest, android.os.CancellationSignal, android.service.intelligence.FillController, android.service.intelligence.FillCallback);
- method public final void setActivityContentCaptureEnabled(android.content.ComponentName, boolean);
- method public final void setContentCaptureWhitelist(java.util.List<java.lang.String>, java.util.List<android.content.ComponentName>);
- method public final void setPackageContentCaptureEnabled(java.lang.String, boolean);
- field public static final java.lang.String SERVICE_INTERFACE = "android.service.intelligence.SmartSuggestionsService";
- }
-
- public final class SnapshotData implements android.os.Parcelable {
- method public int describeContents();
- method public android.app.assist.AssistContent getAssistContent();
- method public android.os.Bundle getAssistData();
- method public android.app.assist.AssistStructure getAssistStructure();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.service.intelligence.SnapshotData> CREATOR;
- }
-
-}
-
package android.service.notification {
public final class Adjustment implements android.os.Parcelable {
@@ -7269,7 +7280,7 @@
}
-package android.view.intelligence {
+package android.view.contentcapture {
public final class ContentCaptureEvent implements android.os.Parcelable {
method public int describeContents();
@@ -7278,13 +7289,13 @@
method public android.view.autofill.AutofillId getId();
method public java.lang.CharSequence getText();
method public int getType();
- method public android.view.intelligence.ViewNode getViewNode();
+ method public android.view.contentcapture.ViewNode getViewNode();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.view.intelligence.ContentCaptureEvent> CREATOR;
- field public static final int TYPE_ACTIVITY_PAUSED = 3; // 0x3
- field public static final int TYPE_ACTIVITY_RESUMED = 2; // 0x2
- field public static final int TYPE_ACTIVITY_STARTED = 1; // 0x1
- field public static final int TYPE_ACTIVITY_STOPPED = 4; // 0x4
+ field public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureEvent> CREATOR;
+ field public static final deprecated int TYPE_ACTIVITY_PAUSED = 3; // 0x3
+ field public static final deprecated int TYPE_ACTIVITY_RESUMED = 2; // 0x2
+ field public static final deprecated int TYPE_ACTIVITY_STARTED = 1; // 0x1
+ field public static final deprecated int TYPE_ACTIVITY_STOPPED = 4; // 0x4
field public static final int TYPE_VIEW_APPEARED = 5; // 0x5
field public static final int TYPE_VIEW_DISAPPEARED = 6; // 0x6
field public static final int TYPE_VIEW_TEXT_CHANGED = 7; // 0x7
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f3f065a..cfda803 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -121,8 +121,8 @@
import android.view.autofill.AutofillManager.AutofillClient;
import android.view.autofill.AutofillPopupWindow;
import android.view.autofill.IAutofillWindowPresenter;
-import android.view.intelligence.ContentCaptureEvent;
-import android.view.intelligence.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureManager;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 0404e80..43e1836 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -165,9 +165,9 @@
import android.view.accessibility.CaptioningManager;
import android.view.autofill.AutofillManager;
import android.view.autofill.IAutoFillManager;
+import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.IContentCaptureManager;
import android.view.inputmethod.InputMethodManager;
-import android.view.intelligence.ContentCaptureManager;
-import android.view.intelligence.IIntelligenceManager;
import android.view.textclassifier.TextClassificationManager;
import android.view.textservice.TextServicesManager;
@@ -1070,7 +1070,7 @@
if (outerContext.isContentCaptureSupported()) {
IBinder b = ServiceManager
.getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
- IIntelligenceManager service = IIntelligenceManager.Stub.asInterface(b);
+ IContentCaptureManager service = IContentCaptureManager.Stub.asInterface(b);
return new ContentCaptureManager(outerContext, service);
}
return null;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index e2c7b85..d7d3cb5 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3939,13 +3939,12 @@
public static final String AUTOFILL_MANAGER_SERVICE = "autofill";
/**
- * Official published name of the smart suggestions service.
+ * Official published name of the content capture service.
*
* @hide
* @see #getSystemService(String)
*/
- // TODO(b/111276913): rename string (will require SELinux change first)
- public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "intelligence";
+ public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
/**
* Use with {@link #getSystemService(String)} to access the
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index abfcfaa..86f81d8 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -948,7 +948,7 @@
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
*/
- public static final String DISALLOW_INTELLIGENCE_CAPTURE = "no_intelligence_capture";
+ public static final String DISALLOW_CONTENT_CAPTURE = "no_content_capture";
/**
* Specifies if user switching is blocked on the current user.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c3217a2..64aa088 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12840,7 +12840,7 @@
/**
* Property used by {@code com.android.server.SystemServer} on start to decide whether
- * the Smart Suggestions service should be created or not
+ * the Content Capture service should be created or not
*
* <p>By default it should *NOT* be set (in which case the decision is based on whether
* the OEM provides an implementation for the service), but it can be overridden to:
@@ -12852,8 +12852,8 @@
*
* @hide
*/
- public static final String SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED =
- "smart_suggestions_service_explicitly_enabled";
+ public static final String CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED =
+ "content_capture_service_explicitly_enabled";
/**
* Settings to backup. This is here so that it's in the same place as the settings
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 573d577..f39ef9a 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -618,7 +618,7 @@
if (SERVICE_INTERFACE.equals(intent.getAction())) {
return mInterface.asBinder();
}
- Log.w(TAG, "Tried to bind to wrong intent: " + intent);
+ Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
return null;
}
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
new file mode 100644
index 0000000..68a86f3
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.autofill.augmented;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.CallSuper;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
+import android.service.autofill.augmented.PresentationParams.SystemPopupPresentationParams;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+import android.view.autofill.IAugmentedAutofillManagerClient;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A service used to augment the Autofill subsystem by potentially providing autofill data when the
+ * "standard" workflow failed (for example, because the standard AutofillService didn't have data).
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class AugmentedAutofillService extends Service {
+
+ private static final String TAG = AugmentedAutofillService.class.getSimpleName();
+
+ // TODO(b/111330312): STOPSHIP use dynamic value, or change to false
+ static final boolean DEBUG = true;
+ static final boolean VERBOSE = false;
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ * To be supported, the service must also require the
+ * {@link android.Manifest.permission#BIND_AUGMENTED_AUTOFILL_SERVICE} permission so
+ * that other applications can not abuse it.
+ */
+ public static final String SERVICE_INTERFACE =
+ "android.service.autofill.augmented.AugmentedAutofillService";
+
+ private Handler mHandler;
+
+ private SparseArray<AutofillProxy> mAutofillProxies;
+
+ private final IAugmentedAutofillService mInterface = new IAugmentedAutofillService.Stub() {
+
+ @Override
+ public void onFillRequest(int sessionId, IBinder client, int taskId,
+ ComponentName componentName, AutofillId focusedId, AutofillValue focusedValue,
+ long requestTime, IFillCallback callback) {
+ mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnFillRequest,
+ AugmentedAutofillService.this, sessionId, client, taskId, componentName,
+ focusedId, focusedValue, requestTime, callback));
+ }
+
+ @Override
+ public void onDestroyFillWindowRequest(int sessionId) {
+ mHandler.sendMessage(
+ obtainMessage(AugmentedAutofillService::handleOnDestroyFillWindowRequest,
+ AugmentedAutofillService.this, sessionId));
+ }
+ };
+
+ @CallSuper
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mHandler = new Handler(Looper.getMainLooper(), null, true);
+ }
+
+ /** @hide */
+ @Override
+ public final IBinder onBind(Intent intent) {
+ if (SERVICE_INTERFACE.equals(intent.getAction())) {
+ return mInterface.asBinder();
+ }
+ Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+ return null;
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnUnbind,
+ AugmentedAutofillService.this));
+ return false;
+ }
+
+ // TODO(b/111330312): add methods to disable autofill per app / activity?
+
+ /**
+ * Asks the service to handle an "augmented" autofill request.
+ *
+ * <p>This method is called when the "stantard" autofill service cannot handle a request, which
+ * typically occurs when:
+ * <ul>
+ * <li>Service does not recognize what should be autofilled.
+ * <li>Service does not have data to fill the request.
+ * <li>Service blacklisted that app (or activity) for autofill.
+ * <li>App disabled itself for autofill.
+ * </ul>
+ *
+ * <p>Differently from the standard autofill workflow, on augmented autofill the service is
+ * responsible to generate the autofill UI and request the Android system to autofill the
+ * activity when the user taps an action in that UI (through the
+ * {@link FillController#autofill(List)} method).
+ *
+ * <p>The service <b>MUST</b> call {@link
+ * FillCallback#onSuccess(android.service.autofill.augmented.FillResponse)} as soon as possible,
+ * passing {@code null} when it cannot fulfill the request.
+ * @param request the request to handle.
+ * @param cancellationSignal signal for observing cancellation requests. The system will use
+ * this to notify you that the fill result is no longer needed and you should stop
+ * handling this fill request in order to save resources.
+ * @param controller object used to interact with the autofill system.
+ * @param callback object used to notify the result of the request. Service <b>must</b> call
+ * {@link FillCallback#onSuccess(android.service.autofill.augmented.FillResponse)}.
+ */
+ public void onFillRequest(@NonNull FillRequest request,
+ @NonNull CancellationSignal cancellationSignal, @NonNull FillController controller,
+ @NonNull FillCallback callback) {
+ }
+
+ private void handleOnFillRequest(int sessionId, @NonNull IBinder client, int taskId,
+ @NonNull ComponentName componentName, @NonNull AutofillId focusedId,
+ @Nullable AutofillValue focusedValue, long requestTime,
+ @NonNull IFillCallback callback) {
+ if (mAutofillProxies == null) {
+ mAutofillProxies = new SparseArray<>();
+ }
+ AutofillProxy proxy = mAutofillProxies.get(sessionId);
+ if (proxy == null) {
+ proxy = new AutofillProxy(sessionId, client, taskId, componentName, focusedId,
+ focusedValue, requestTime, callback);
+ mAutofillProxies.put(sessionId, proxy);
+ } else {
+ // TODO(b/111330312): figure out if it's ok to reuse the proxy; add logging
+ if (DEBUG) Log.d(TAG, "Reusing proxy for session " + sessionId);
+ }
+ // TODO(b/111330312): set cancellation signal
+ final CancellationSignal cancellationSignal = null;
+ onFillRequest(new FillRequest(proxy), cancellationSignal, new FillController(proxy),
+ new FillCallback(proxy));
+ }
+
+ private void handleOnDestroyFillWindowRequest(@NonNull int sessionId) {
+ AutofillProxy proxy = null;
+ if (mAutofillProxies != null) {
+ proxy = mAutofillProxies.get(sessionId);
+ }
+ if (proxy == null) {
+ // TODO(b/111330312): this might be fine, in which case we should logv it
+ Log.w(TAG, "No proxy for session " + sessionId);
+ return;
+ }
+ proxy.destroy();
+ mAutofillProxies.remove(sessionId);
+ }
+
+ private void handleOnUnbind() {
+ if (mAutofillProxies == null) {
+ if (DEBUG) Log.d(TAG, "onUnbind(): no proxy to destroy");
+ return;
+ }
+ final int size = mAutofillProxies.size();
+ if (DEBUG) Log.d(TAG, "onUnbind(): destroying " + size + " proxies");
+ for (int i = 0; i < size; i++) {
+ final AutofillProxy proxy = mAutofillProxies.valueAt(i);
+ try {
+ proxy.destroy();
+ } catch (Exception e) {
+ Log.w(TAG, "error destroying " + proxy);
+ }
+ }
+ mAutofillProxies = null;
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mAutofillProxies != null) {
+ final int size = mAutofillProxies.size();
+ pw.print("Number proxies: "); pw.println(size);
+ for (int i = 0; i < size; i++) {
+ final int sessionId = mAutofillProxies.keyAt(i);
+ final AutofillProxy proxy = mAutofillProxies.valueAt(i);
+ pw.print(i); pw.print(") SessionId="); pw.print(sessionId); pw.println(":");
+ proxy.dump(" ", pw);
+ }
+ }
+ }
+
+ /** @hide */
+ static final class AutofillProxy {
+
+ static final int REPORT_EVENT_ON_SUCCESS = 1;
+ static final int REPORT_EVENT_UI_SHOWN = 2;
+ static final int REPORT_EVENT_UI_DESTROYED = 3;
+
+ @IntDef(prefix = { "REPORT_EVENT_" }, value = {
+ REPORT_EVENT_ON_SUCCESS,
+ REPORT_EVENT_UI_SHOWN,
+ REPORT_EVENT_UI_DESTROYED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface ReportEvent{}
+
+
+ private final Object mLock = new Object();
+ private final IAugmentedAutofillManagerClient mClient;
+ private final int mSessionId;
+ private final IFillCallback mCallback;
+ public final int taskId;
+ public final ComponentName componentName;
+ public final AutofillId focusedId;
+ public final AutofillValue focusedValue;
+
+ // Objects used to log metrics
+ private final long mRequestTime;
+ private long mOnSuccessTime;
+ private long mUiFirstShownTime;
+ private long mUiFirstDestroyedTime;
+
+ @GuardedBy("mLock")
+ private SystemPopupPresentationParams mSmartSuggestion;
+
+ @GuardedBy("mLock")
+ private FillWindow mFillWindow;
+
+ private AutofillProxy(int sessionId, @NonNull IBinder client, int taskId,
+ @NonNull ComponentName componentName, @NonNull AutofillId focusedId,
+ @Nullable AutofillValue focusedValue, long requestTime,
+ @NonNull IFillCallback callback) {
+ mSessionId = sessionId;
+ mClient = IAugmentedAutofillManagerClient.Stub.asInterface(client);
+ mCallback = callback;
+ this.taskId = taskId;
+ this.componentName = componentName;
+ this.focusedId = focusedId;
+ this.focusedValue = focusedValue;
+ this.mRequestTime = requestTime;
+ // TODO(b/111330312): linkToDeath
+ }
+
+ @NonNull
+ public SystemPopupPresentationParams getSmartSuggestionParams() {
+ synchronized (mLock) {
+ if (mSmartSuggestion != null) {
+ return mSmartSuggestion;
+ }
+ Rect rect;
+ try {
+ rect = mClient.getViewCoordinates(focusedId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Could not get coordinates for " + focusedId);
+ return null;
+ }
+ if (rect == null) {
+ if (DEBUG) Log.d(TAG, "getViewCoordinates(" + focusedId + ") returned null");
+ return null;
+ }
+ mSmartSuggestion = new SystemPopupPresentationParams(this, rect);
+ return mSmartSuggestion;
+ }
+ }
+
+ public void autofill(@NonNull List<Pair<AutofillId, AutofillValue>> pairs)
+ throws RemoteException {
+ final int size = pairs.size();
+ final List<AutofillId> ids = new ArrayList<>(size);
+ final List<AutofillValue> values = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ final Pair<AutofillId, AutofillValue> pair = pairs.get(i);
+ ids.add(pair.first);
+ values.add(pair.second);
+ }
+ mClient.autofill(mSessionId, ids, values);
+ }
+
+ public void setFillWindow(@NonNull FillWindow fillWindow) {
+ synchronized (mLock) {
+ mFillWindow = fillWindow;
+ }
+ }
+
+ public FillWindow getFillWindow() {
+ synchronized (mLock) {
+ return mFillWindow;
+ }
+ }
+
+ // Used (mostly) for metrics.
+ public void report(@ReportEvent int event) {
+ switch (event) {
+ case REPORT_EVENT_ON_SUCCESS:
+ if (mOnSuccessTime == 0) {
+ mOnSuccessTime = SystemClock.elapsedRealtime();
+ if (DEBUG) {
+ Slog.d(TAG, "Service responsed in "
+ + TimeUtils.formatDuration(mOnSuccessTime - mRequestTime));
+ }
+ }
+ try {
+ mCallback.onSuccess();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error reporting success: " + e);
+ }
+ break;
+ case REPORT_EVENT_UI_SHOWN:
+ if (mUiFirstShownTime == 0) {
+ mUiFirstShownTime = SystemClock.elapsedRealtime();
+ if (DEBUG) {
+ Slog.d(TAG, "UI shown in "
+ + TimeUtils.formatDuration(mUiFirstShownTime - mRequestTime));
+ }
+ }
+ break;
+ case REPORT_EVENT_UI_DESTROYED:
+ if (mUiFirstDestroyedTime == 0) {
+ mUiFirstDestroyedTime = SystemClock.elapsedRealtime();
+ if (DEBUG) {
+ Slog.d(TAG, "UI destroyed in "
+ + TimeUtils.formatDuration(
+ mUiFirstDestroyedTime - mRequestTime));
+ }
+ }
+ break;
+ default:
+ Slog.w(TAG, "invalid event reported: " + event);
+ }
+ // TODO(b/111330312): log metrics as well
+ }
+
+ public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
+ pw.print(prefix); pw.print("sessionId: "); pw.println(mSessionId);
+ pw.print(prefix); pw.print("taskId: "); pw.println(taskId);
+ pw.print(prefix); pw.print("component: ");
+ pw.println(componentName.flattenToShortString());
+ pw.print(prefix); pw.print("focusedId: "); pw.println(focusedId);
+ if (focusedValue != null) {
+ pw.print(prefix); pw.print("focusedValue: "); pw.println(focusedValue);
+ }
+ pw.print(prefix); pw.print("client: "); pw.println(mClient);
+ final String prefix2 = prefix + " ";
+ if (mFillWindow != null) {
+ pw.print(prefix); pw.println("window:");
+ mFillWindow.dump(prefix2, pw);
+ }
+ if (mSmartSuggestion != null) {
+ pw.print(prefix); pw.println("smartSuggestion:");
+ mSmartSuggestion.dump(prefix2, pw);
+ }
+ if (mOnSuccessTime > 0) {
+ final long responseTime = mOnSuccessTime - mRequestTime;
+ pw.print(prefix); pw.print("response time: ");
+ TimeUtils.formatDuration(responseTime, pw); pw.println();
+ }
+
+ if (mUiFirstShownTime > 0) {
+ final long uiRenderingTime = mUiFirstShownTime - mRequestTime;
+ pw.print(prefix); pw.print("UI rendering time: ");
+ TimeUtils.formatDuration(uiRenderingTime, pw); pw.println();
+ }
+
+ if (mUiFirstDestroyedTime > 0) {
+ final long uiTotalTime = mUiFirstDestroyedTime - mRequestTime;
+ pw.print(prefix); pw.print("UI life time: ");
+ TimeUtils.formatDuration(uiTotalTime, pw); pw.println();
+ }
+ }
+
+ private void destroy() {
+ synchronized (mLock) {
+ if (mFillWindow != null) {
+ if (DEBUG) Log.d(TAG, "destroying window");
+ mFillWindow.destroy();
+ }
+ }
+ }
+ }
+}
diff --git a/core/java/android/service/intelligence/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java
similarity index 92%
rename from core/java/android/service/intelligence/FillCallback.java
rename to core/java/android/service/autofill/augmented/FillCallback.java
index ddf37f7..0546465 100644
--- a/core/java/android/service/intelligence/FillCallback.java
+++ b/core/java/android/service/autofill/augmented/FillCallback.java
@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
/**
* Callback used to indicate at {@link FillRequest} has been fulfilled.
diff --git a/core/java/android/service/intelligence/FillController.java b/core/java/android/service/autofill/augmented/FillController.java
similarity index 90%
rename from core/java/android/service/intelligence/FillController.java
rename to core/java/android/service/autofill/augmented/FillController.java
index 4a9c85d..e65cf47 100644
--- a/core/java/android/service/intelligence/FillController.java
+++ b/core/java/android/service/autofill/augmented/FillController.java
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
-import static android.service.intelligence.SmartSuggestionsService.DEBUG;
+import static android.service.autofill.augmented.AugmentedAutofillService.DEBUG;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.RemoteException;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.util.Log;
import android.util.Pair;
import android.view.autofill.AutofillId;
diff --git a/core/java/android/service/intelligence/FillRequest.java b/core/java/android/service/autofill/augmented/FillRequest.java
similarity index 71%
rename from core/java/android/service/intelligence/FillRequest.java
rename to core/java/android/service/autofill/augmented/FillRequest.java
index 53e99a5..fd75b15 100644
--- a/core/java/android/service/intelligence/FillRequest.java
+++ b/core/java/android/service/autofill/augmented/FillRequest.java
@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.content.ComponentName;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
@@ -27,6 +28,7 @@
* @hide
*/
@SystemApi
+// TODO(b/111330312): pass a requestId and/or sessionId
public final class FillRequest {
final AutofillProxy mProxy;
@@ -37,11 +39,18 @@
}
/**
- * Gets the session associated with this request.
+ * Gets the task of the activity associated with this request.
+ */
+ public int getTaskId() {
+ return mProxy.taskId;
+ }
+
+ /**
+ * Gets the name of the activity associated with this request.
*/
@NonNull
- public InteractionSessionId getSessionId() {
- return mProxy.sessionId;
+ public ComponentName getActivityComponent() {
+ return mProxy.componentName;
}
/**
@@ -56,7 +65,7 @@
* Gets the current value of the field that triggered the request.
*/
@NonNull
- public AutofillValue getFocusedAutofillValue() {
+ public AutofillValue getFocusedValue() {
return mProxy.focusedValue;
}
@@ -72,6 +81,7 @@
@Override
public String toString() {
- return "FillRequest[id=" + mProxy.focusedId + "]";
+ return "FillRequest[act=" + getActivityComponent().flattenToShortString()
+ + ", id=" + mProxy.focusedId + "]";
}
}
diff --git a/core/java/android/service/intelligence/FillResponse.java b/core/java/android/service/autofill/augmented/FillResponse.java
similarity index 97%
rename from core/java/android/service/intelligence/FillResponse.java
rename to core/java/android/service/autofill/augmented/FillResponse.java
index 860c027..7064b6f 100644
--- a/core/java/android/service/intelligence/FillResponse.java
+++ b/core/java/android/service/autofill/augmented/FillResponse.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -50,7 +50,7 @@
* @hide
*/
@SystemApi
- public static class Builder {
+ public static final class Builder {
private FillWindow mFillWindow;
diff --git a/core/java/android/service/intelligence/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java
similarity index 94%
rename from core/java/android/service/intelligence/FillWindow.java
rename to core/java/android/service/autofill/augmented/FillWindow.java
index 39d7e08..9e3aba4 100644
--- a/core/java/android/service/intelligence/FillWindow.java
+++ b/core/java/android/service/autofill/augmented/FillWindow.java
@@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
-import static android.service.intelligence.SmartSuggestionsService.DEBUG;
+import static android.service.autofill.augmented.AugmentedAutofillService.DEBUG;
import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.app.Dialog;
import android.graphics.Rect;
-import android.service.intelligence.PresentationParams.Area;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
+import android.service.autofill.augmented.PresentationParams.Area;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
@@ -60,7 +60,7 @@
* @hide
*/
@SystemApi
-public final class FillWindow {
+public final class FillWindow implements AutoCloseable {
private static final String TAG = "FillWindow";
/** Indicates the data being shown is a physical address */
@@ -238,4 +238,10 @@
}
}
}
+
+ /** @hide */
+ @Override
+ public void close() throws Exception {
+ destroy();
+ }
}
diff --git a/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
new file mode 100644
index 0000000..b3ac2da
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill.augmented;
+
+import android.content.ComponentName;
+import android.os.IBinder;
+
+import android.service.autofill.augmented.IFillCallback;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+
+import java.util.List;
+
+/**
+ * Interface from the system to an Augmented Autofill service.
+ *
+ * @hide
+ */
+oneway interface IAugmentedAutofillService {
+
+ void onFillRequest(int sessionId, in IBinder autofillManagerClient, int taskId,
+ in ComponentName activityComponent, in AutofillId focusedId,
+ in AutofillValue focusedValue, long requestTime, in IFillCallback callback);
+
+ void onDestroyFillWindowRequest(int sessionId);
+}
diff --git a/core/java/android/service/autofill/augmented/IFillCallback.aidl b/core/java/android/service/autofill/augmented/IFillCallback.aidl
new file mode 100644
index 0000000..dac7590
--- /dev/null
+++ b/core/java/android/service/autofill/augmented/IFillCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill.augmented;
+
+import android.os.ICancellationSignal;
+
+/**
+ * Interface to receive the result of an autofill request.
+ *
+ * @hide
+ */
+interface IFillCallback {
+ // TODO(b/111330312): add cancellation (after we have CTS tests, so we can test it)
+// void onCancellable(in ICancellationSignal cancellation);
+ // TODO(b/111330312): might need to pass the response (once IME implements Smart Suggestions)
+ void onSuccess();
+}
diff --git a/core/java/android/service/intelligence/PresentationParams.java b/core/java/android/service/autofill/augmented/PresentationParams.java
similarity index 95%
rename from core/java/android/service/intelligence/PresentationParams.java
rename to core/java/android/service/autofill/augmented/PresentationParams.java
index 9530309..0124ecc 100644
--- a/core/java/android/service/intelligence/PresentationParams.java
+++ b/core/java/android/service/autofill/augmented/PresentationParams.java
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.autofill.augmented;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.graphics.Rect;
-import android.service.intelligence.SmartSuggestionsService.AutofillProxy;
+import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.util.DebugUtils;
import android.view.View;
@@ -174,11 +174,12 @@
*
* @param bounds boundaries relative to this Area.
*
- * @throws {@link IllegalArgumentException} if the {@code bounds} is not fully-contained
- * inside this full Area.
- *
* @return new subarea, or {@code null} if the Smart Suggestion host does not support such
* subaarea.
+ *
+ * @throws IllegalArgumentException if the {@code bounds} is not fully-contained inside this
+ * full Area.
+ *
*/
@Nullable
public Area getSubArea(@NonNull Rect bounds) {
diff --git a/core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
similarity index 94%
rename from core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl
rename to core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
index 23d607d..c032cfd 100644
--- a/core/java/android/service/intelligence/ContentCaptureEventsRequest.aidl
+++ b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
parcelable ContentCaptureEventsRequest;
diff --git a/core/java/android/service/intelligence/ContentCaptureEventsRequest.java b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
similarity index 95%
rename from core/java/android/service/intelligence/ContentCaptureEventsRequest.java
rename to core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
index bc5b92b..df58f52 100644
--- a/core/java/android/service/intelligence/ContentCaptureEventsRequest.java
+++ b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import android.view.intelligence.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureEvent;
import java.util.List;
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
new file mode 100644
index 0000000..3dfeede
--- /dev/null
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.contentcapture;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.CallSuper;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.contentcapture.ContentCaptureEvent;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A service used to capture the content of the screen to provide contextual data in other areas of
+ * the system such as Autofill.
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class ContentCaptureService extends Service {
+
+ private static final String TAG = ContentCaptureService.class.getSimpleName();
+
+ // TODO(b/111330312): STOPSHIP use dynamic value, or change to false
+ static final boolean DEBUG = true;
+ static final boolean VERBOSE = false;
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ *
+ * <p>To be supported, the service must also require the
+ * {@link android.Manifest.permission#BIND_CONTENT_CAPTURE_SERVICE} permission so
+ * that other applications can not abuse it.
+ */
+ public static final String SERVICE_INTERFACE =
+ "android.service.contentcapture.ContentCaptureService";
+
+ private Handler mHandler;
+
+ private final IContentCaptureService mInterface = new IContentCaptureService.Stub() {
+
+ @Override
+ public void onSessionLifecycle(InteractionContext context, String sessionId)
+ throws RemoteException {
+ if (context != null) {
+ mHandler.sendMessage(
+ obtainMessage(ContentCaptureService::handleOnCreateInteractionSession,
+ ContentCaptureService.this, context, sessionId));
+ } else {
+ mHandler.sendMessage(
+ obtainMessage(ContentCaptureService::handleOnDestroyInteractionSession,
+ ContentCaptureService.this, sessionId));
+ }
+ }
+
+ @Override
+ public void onContentCaptureEventsRequest(String sessionId,
+ ContentCaptureEventsRequest request) {
+ mHandler.sendMessage(
+ obtainMessage(ContentCaptureService::handleOnContentCaptureEventsRequest,
+ ContentCaptureService.this, sessionId, request));
+
+ }
+
+ @Override
+ public void onActivitySnapshot(String sessionId, SnapshotData snapshotData) {
+ mHandler.sendMessage(
+ obtainMessage(ContentCaptureService::handleOnActivitySnapshot,
+ ContentCaptureService.this, sessionId, snapshotData));
+ }
+ };
+
+ @CallSuper
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mHandler = new Handler(Looper.getMainLooper(), null, true);
+ }
+
+ /** @hide */
+ @Override
+ public final IBinder onBind(Intent intent) {
+ if (SERVICE_INTERFACE.equals(intent.getAction())) {
+ return mInterface.asBinder();
+ }
+ Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+ return null;
+ }
+
+ /**
+ * Explicitly limits content capture to the given packages and activities.
+ *
+ * <p>When the whitelist is set, it overrides the values passed to
+ * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}
+ * and {@link #setPackageContentCaptureEnabled(String, boolean)}.
+ *
+ * <p>To reset the whitelist, call it passing {@code null} to both arguments.
+ *
+ * <p>Useful when the service wants to restrict content capture to a category of apps, like
+ * chat apps. For example, if the service wants to support view captures on all activities of
+ * app {@code ChatApp1} and just activities {@code act1} and {@code act2} of {@code ChatApp2},
+ * it would call: {@code setContentCaptureWhitelist(Arrays.asList("ChatApp1"),
+ * Arrays.asList(new ComponentName("ChatApp2", "act1"),
+ * new ComponentName("ChatApp2", "act2")));}
+ */
+ public final void setContentCaptureWhitelist(@Nullable List<String> packages,
+ @Nullable List<ComponentName> activities) {
+ //TODO(b/111276913): implement
+ }
+
+ /**
+ * Defines whether content capture should be enabled for activities with such
+ * {@link android.content.ComponentName}.
+ *
+ * <p>Useful to blacklist a particular activity.
+ */
+ public final void setActivityContentCaptureEnabled(@NonNull ComponentName activity,
+ boolean enabled) {
+ //TODO(b/111276913): implement
+ }
+
+ /**
+ * Defines whether content capture should be enabled for activities of the app with such
+ * {@code packageName}.
+ *
+ * <p>Useful to blacklist any activity from a particular app.
+ */
+ public final void setPackageContentCaptureEnabled(@NonNull String packageName,
+ boolean enabled) {
+ //TODO(b/111276913): implement
+ }
+
+ /**
+ * Gets the activities where content capture was disabled by
+ * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}.
+ */
+ @NonNull
+ public final Set<ComponentName> getContentCaptureDisabledActivities() {
+ //TODO(b/111276913): implement
+ return null;
+ }
+
+ /**
+ * Gets the apps where content capture was disabled by
+ * {@link #setPackageContentCaptureEnabled(String, boolean)}.
+ */
+ @NonNull
+ public final Set<String> getContentCaptureDisabledPackages() {
+ //TODO(b/111276913): implement
+ return null;
+ }
+
+ /**
+ * Creates a new interaction session.
+ *
+ * @param context interaction context
+ * @param sessionId the session's Id
+ */
+ public void onCreateInteractionSession(@NonNull InteractionContext context,
+ @NonNull InteractionSessionId sessionId) {
+ if (VERBOSE) {
+ Log.v(TAG, "onCreateInteractionSession(id=" + sessionId + ", ctx=" + context + ")");
+ }
+ }
+
+ /**
+ * Notifies the service of {@link ContentCaptureEvent events} associated with a content capture
+ * session.
+ *
+ * @param sessionId the session's Id
+ * @param request the events
+ */
+ public abstract void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
+ @NonNull ContentCaptureEventsRequest request);
+
+ /**
+ * Notifies the service of {@link SnapshotData snapshot data} associated with a session.
+ *
+ * @param sessionId the session's Id
+ * @param snapshotData the data
+ */
+ public void onActivitySnapshot(@NonNull InteractionSessionId sessionId,
+ @NonNull SnapshotData snapshotData) {}
+
+ /**
+ * Destroys the interaction session.
+ *
+ * @param sessionId the id of the session to destroy
+ */
+ public void onDestroyInteractionSession(@NonNull InteractionSessionId sessionId) {
+ if (VERBOSE) {
+ Log.v(TAG, "onDestroyInteractionSession(id=" + sessionId + ")");
+ }
+ }
+
+ //TODO(b/111276913): consider caching the InteractionSessionId for the lifetime of the session,
+ // so we don't need to create a temporary InteractionSessionId for each event.
+
+ private void handleOnCreateInteractionSession(@NonNull InteractionContext context,
+ @NonNull String sessionId) {
+ onCreateInteractionSession(context, new InteractionSessionId(sessionId));
+ }
+
+ private void handleOnContentCaptureEventsRequest(@NonNull String sessionId,
+ @NonNull ContentCaptureEventsRequest request) {
+ onContentCaptureEventsRequest(new InteractionSessionId(sessionId), request);
+ }
+
+ private void handleOnActivitySnapshot(@NonNull String sessionId,
+ @NonNull SnapshotData snapshotData) {
+ onActivitySnapshot(new InteractionSessionId(sessionId), snapshotData);
+ }
+
+ private void handleOnDestroyInteractionSession(@NonNull String sessionId) {
+ onDestroyInteractionSession(new InteractionSessionId(sessionId));
+ }
+}
diff --git a/core/java/android/service/contentcapture/IContentCaptureService.aidl b/core/java/android/service/contentcapture/IContentCaptureService.aidl
new file mode 100644
index 0000000..29e9abb
--- /dev/null
+++ b/core/java/android/service/contentcapture/IContentCaptureService.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.contentcapture;
+
+import android.service.contentcapture.ContentCaptureEventsRequest;
+import android.service.contentcapture.InteractionContext;
+import android.service.contentcapture.SnapshotData;
+
+import java.util.List;
+
+/**
+ * Interface from the system to a Content Capture service.
+ *
+ * @hide
+ */
+oneway interface IContentCaptureService {
+
+ // Called when session is created (context not null) or destroyed (context null)
+ void onSessionLifecycle(in InteractionContext context, String sessionId);
+
+ void onContentCaptureEventsRequest(String sessionId, in ContentCaptureEventsRequest request);
+
+ void onActivitySnapshot(String sessionId, in SnapshotData snapshotData);
+}
diff --git a/core/java/android/service/intelligence/InteractionContext.aidl b/core/java/android/service/contentcapture/InteractionContext.aidl
similarity index 93%
rename from core/java/android/service/intelligence/InteractionContext.aidl
rename to core/java/android/service/contentcapture/InteractionContext.aidl
index 4ce6aa4..982e095 100644
--- a/core/java/android/service/intelligence/InteractionContext.aidl
+++ b/core/java/android/service/contentcapture/InteractionContext.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
parcelable InteractionContext;
diff --git a/core/java/android/service/intelligence/InteractionContext.java b/core/java/android/service/contentcapture/InteractionContext.java
similarity index 96%
rename from core/java/android/service/intelligence/InteractionContext.java
rename to core/java/android/service/contentcapture/InteractionContext.java
index 7f4283d..f1281ff 100644
--- a/core/java/android/service/intelligence/InteractionContext.java
+++ b/core/java/android/service/contentcapture/InteractionContext.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -37,7 +37,7 @@
/**
* Flag used to indicate that the app explicitly disabled content capture for the activity
* (using
- * {@link android.view.intelligence.ContentCaptureManager#setContentCaptureEnabled()}),
+ * {@link android.view.contentcapture.ContentCaptureManager#setContentCaptureEnabled(boolean)}),
* in which case the service will just receive activity-level events.
*/
public static final int FLAG_DISABLED_BY_APP = 0x1;
diff --git a/core/java/android/service/intelligence/InteractionSessionId.java b/core/java/android/service/contentcapture/InteractionSessionId.java
similarity index 90%
rename from core/java/android/service/intelligence/InteractionSessionId.java
rename to core/java/android/service/contentcapture/InteractionSessionId.java
index 667193b..8411947 100644
--- a/core/java/android/service/intelligence/InteractionSessionId.java
+++ b/core/java/android/service/contentcapture/InteractionSessionId.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
import android.annotation.NonNull;
import android.annotation.SystemApi;
@@ -22,10 +22,12 @@
import android.os.Parcelable;
import java.io.PrintWriter;
-import java.util.UUID;
-// TODO(b/111276913): add javadocs / implement equals/hashcode/string
-/** @hide */
+/**
+ * Identifier for a Content Capture session.
+ *
+ * @hide
+ */
@SystemApi
public final class InteractionSessionId implements Parcelable {
@@ -34,15 +36,6 @@
/**
* Creates a new instance.
*
- * @hide
- */
- public InteractionSessionId() {
- this(UUID.randomUUID().toString());
- }
-
- /**
- * Creates a new instance.
- *
* @param value The internal value.
*
* @hide
diff --git a/core/java/android/service/intelligence/SnapshotData.aidl b/core/java/android/service/contentcapture/SnapshotData.aidl
similarity index 93%
rename from core/java/android/service/intelligence/SnapshotData.aidl
rename to core/java/android/service/contentcapture/SnapshotData.aidl
index 31d1339..a00e852 100644
--- a/core/java/android/service/intelligence/SnapshotData.aidl
+++ b/core/java/android/service/contentcapture/SnapshotData.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
parcelable SnapshotData;
diff --git a/core/java/android/service/intelligence/SnapshotData.java b/core/java/android/service/contentcapture/SnapshotData.java
similarity index 98%
rename from core/java/android/service/intelligence/SnapshotData.java
rename to core/java/android/service/contentcapture/SnapshotData.java
index b9310ea..bc2116a 100644
--- a/core/java/android/service/intelligence/SnapshotData.java
+++ b/core/java/android/service/contentcapture/SnapshotData.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.service.intelligence;
+package android.service.contentcapture;
import android.annotation.NonNull;
import android.annotation.Nullable;
diff --git a/core/java/android/service/intelligence/IIntelligenceService.aidl b/core/java/android/service/intelligence/IIntelligenceService.aidl
deleted file mode 100644
index 2b924fb..0000000
--- a/core/java/android/service/intelligence/IIntelligenceService.aidl
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.intelligence;
-
-import android.os.IBinder;
-import android.service.intelligence.ContentCaptureEventsRequest;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.InteractionContext;
-import android.service.intelligence.SnapshotData;
-
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.intelligence.ContentCaptureEvent;
-
-import java.util.List;
-
-/**
- * Interface from the system to an intelligence service.
- *
- * @hide
- */
- // TODO(b/111276913): rename / update javadoc (once the final name is defined)
-oneway interface IIntelligenceService {
-
- // Called when session is created (context not null) or destroyed (context null)
- void onSessionLifecycle(in InteractionContext context, in InteractionSessionId sessionId);
-
- void onContentCaptureEventsRequest(in InteractionSessionId sessionId,
- in ContentCaptureEventsRequest request);
-
- void onActivitySnapshot(in InteractionSessionId sessionId,
- in SnapshotData snapshotData);
-
- void onAutofillRequest(in InteractionSessionId sessionId, in IBinder autofillManagerClient,
- int autofilSessionId, in AutofillId focusedId,
- in AutofillValue focusedValue, long requestTime);
-
- void onDestroyAutofillWindowsRequest(in InteractionSessionId sessionId);
-}
diff --git a/core/java/android/service/intelligence/InteractionSessionId.aidl b/core/java/android/service/intelligence/InteractionSessionId.aidl
deleted file mode 100644
index a5392b6..0000000
--- a/core/java/android/service/intelligence/InteractionSessionId.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.intelligence;
-
-parcelable InteractionSessionId;
diff --git a/core/java/android/service/intelligence/SmartSuggestionsService.java b/core/java/android/service/intelligence/SmartSuggestionsService.java
deleted file mode 100644
index b684b02..0000000
--- a/core/java/android/service/intelligence/SmartSuggestionsService.java
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.service.intelligence;
-
-import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
-
-import android.annotation.CallSuper;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.service.intelligence.PresentationParams.SystemPopupPresentationParams;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.Pair;
-import android.util.Slog;
-import android.util.TimeUtils;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAugmentedAutofillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * A service used to capture the content of the screen to provide contextual data in other areas of
- * the system such as Autofill.
- *
- * @hide
- */
-@SystemApi
-public abstract class SmartSuggestionsService extends Service {
-
- private static final String TAG = "SmartSuggestionsService";
-
- // TODO(b/111330312): STOPSHIP use dynamic value, or change to false
- static final boolean DEBUG = true;
- static final boolean VERBOSE = false;
-
- /**
- * The {@link Intent} that must be declared as handled by the service.
- * To be supported, the service must also require the
- * {@link android.Manifest.permission#BIND_SMART_SUGGESTIONS_SERVICE} permission so
- * that other applications can not abuse it.
- */
- public static final String SERVICE_INTERFACE =
- "android.service.intelligence.SmartSuggestionsService";
-
- private Handler mHandler;
-
- private ArrayMap<InteractionSessionId, AutofillProxy> mAutofillProxies;
-
- private final IIntelligenceService mInterface = new IIntelligenceService.Stub() {
-
- @Override
- public void onSessionLifecycle(InteractionContext context, InteractionSessionId sessionId)
- throws RemoteException {
- if (context != null) {
- mHandler.sendMessage(
- obtainMessage(SmartSuggestionsService::onCreateInteractionSession,
- SmartSuggestionsService.this, context, sessionId));
- } else {
- mHandler.sendMessage(
- obtainMessage(SmartSuggestionsService::onDestroyInteractionSession,
- SmartSuggestionsService.this, sessionId));
- }
- }
-
- @Override
- public void onContentCaptureEventsRequest(InteractionSessionId sessionId,
- ContentCaptureEventsRequest request) {
- mHandler.sendMessage(
- obtainMessage(SmartSuggestionsService::onContentCaptureEventsRequest,
- SmartSuggestionsService.this, sessionId, request));
-
- }
-
- @Override
- public void onActivitySnapshot(InteractionSessionId sessionId,
- SnapshotData snapshotData) {
- mHandler.sendMessage(
- obtainMessage(SmartSuggestionsService::onActivitySnapshot,
- SmartSuggestionsService.this, sessionId, snapshotData));
- }
-
- @Override
- public void onAutofillRequest(InteractionSessionId sessionId, IBinder client,
- int autofilSessionId, AutofillId focusedId, AutofillValue focusedValue,
- long requestTime) {
- mHandler.sendMessage(obtainMessage(SmartSuggestionsService::handleOnAutofillRequest,
- SmartSuggestionsService.this, sessionId, client, autofilSessionId, focusedId,
- focusedValue, requestTime));
- }
-
- @Override
- public void onDestroyAutofillWindowsRequest(InteractionSessionId sessionId) {
- mHandler.sendMessage(
- obtainMessage(SmartSuggestionsService::handleOnDestroyAutofillWindowsRequest,
- SmartSuggestionsService.this, sessionId));
- }
- };
-
- @CallSuper
- @Override
- public void onCreate() {
- super.onCreate();
- mHandler = new Handler(Looper.getMainLooper(), null, true);
- }
-
- /** @hide */
- @Override
- public final IBinder onBind(Intent intent) {
- if (SERVICE_INTERFACE.equals(intent.getAction())) {
- return mInterface.asBinder();
- }
- Log.w(TAG, "Tried to bind to wrong intent: " + intent);
- return null;
- }
-
- /**
- * Explicitly limits content capture to the given packages and activities.
- *
- * <p>When the whitelist is set, it overrides the values passed to
- * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}
- * and {@link #setPackageContentCaptureEnabled(String, boolean)}.
- *
- * <p>To reset the whitelist, call it passing {@code null} to both arguments.
- *
- * <p>Useful when the service wants to restrict content capture to a category of apps, like
- * chat apps. For example, if the service wants to support view captures on all activities of
- * app {@code ChatApp1} and just activities {@code act1} and {@code act2} of {@code ChatApp2},
- * it would call: {@code setContentCaptureWhitelist(Arrays.asList("ChatApp1"),
- * Arrays.asList(new ComponentName("ChatApp2", "act1"),
- * new ComponentName("ChatApp2", "act2")));}
- */
- public final void setContentCaptureWhitelist(@Nullable List<String> packages,
- @Nullable List<ComponentName> activities) {
- //TODO(b/111276913): implement
- }
-
- /**
- * Defines whether content capture should be enabled for activities with such
- * {@link android.content.ComponentName}.
- *
- * <p>Useful to blacklist a particular activity.
- */
- public final void setActivityContentCaptureEnabled(@NonNull ComponentName activity,
- boolean enabled) {
- //TODO(b/111276913): implement
- }
-
- /**
- * Defines whether content capture should be enabled for activities of the app with such
- * {@code packageName}.
- *
- * <p>Useful to blacklist any activity from a particular app.
- */
- public final void setPackageContentCaptureEnabled(@NonNull String packageName,
- boolean enabled) {
- //TODO(b/111276913): implement
- }
-
- /**
- * Gets the activities where content capture was disabled by
- * {@link #setActivityContentCaptureEnabled(ComponentName, boolean)}.
- */
- @NonNull
- public final Set<ComponentName> getContentCaptureDisabledActivities() {
- //TODO(b/111276913): implement
- return null;
- }
-
- /**
- * Gets the apps where content capture was disabled by
- * {@link #setPackageContentCaptureEnabled(String, boolean)}.
- */
- @NonNull
- public final Set<String> getContentCaptureDisabledPackages() {
- //TODO(b/111276913): implement
- return null;
- }
-
- /**
- * Creates a new interaction session.
- *
- * @param context interaction context
- * @param sessionId the session's Id
- */
- public void onCreateInteractionSession(@NonNull InteractionContext context,
- @NonNull InteractionSessionId sessionId) {
- if (VERBOSE) {
- Log.v(TAG, "onCreateInteractionSession(id=" + sessionId + ", ctx=" + context + ")");
- }
- }
-
- /**
- * Notifies the service of {@link ContentCaptureEvent events} associated with a content capture
- * session.
- *
- * @param sessionId the session's Id
- * @param request the events
- */
- // TODO(b/111276913): rename to onContentCaptureEvents or something like that; also, pass a
- // Request object so it can be extended
- public abstract void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
- @NonNull ContentCaptureEventsRequest request);
-
- private void handleOnAutofillRequest(@NonNull InteractionSessionId sessionId,
- @NonNull IBinder client, int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue, long requestTime) {
- if (mAutofillProxies == null) {
- mAutofillProxies = new ArrayMap<>();
- }
- AutofillProxy proxy = mAutofillProxies.get(sessionId);
- if (proxy == null) {
- proxy = new AutofillProxy(sessionId, client, autofillSessionId, focusedId, focusedValue,
- requestTime);
- mAutofillProxies.put(sessionId, proxy);
- } else {
- // TODO(b/111330312): figure out if it's ok to reuse the proxy; add logging
- if (DEBUG) Log.d(TAG, "Reusing proxy for session " + sessionId);
- }
- // TODO(b/111330312): set cancellation signal
- final CancellationSignal cancellationSignal = null;
- onFillRequest(sessionId, new FillRequest(proxy), cancellationSignal,
- new FillController(proxy), new FillCallback(proxy));
- }
-
- /**
- * Asks the service to handle an "augmented" autofill request.
- *
- * <p>This method is called when the "stantard" autofill service cannot handle a request, which
- * typically occurs when:
- * <ul>
- * <li>Service does not recognize what should be autofilled.
- * <li>Service does not have data to fill the request.
- * <li>Service blacklisted that app (or activity) for autofill.
- * <li>App disabled itself for autofill.
- * </ul>
- *
- * <p>Differently from the standard autofill workflow, on augmented autofill the service is
- * responsible to generate the autofill UI and request the Android system to autofill the
- * activity when the user taps an action in that UI (through the
- * {@link FillController#autofill(List)} method).
- *
- * <p>The service <b>MUST</b> call {@link
- * FillCallback#onSuccess(android.service.intelligence.FillResponse)} as soon as possible,
- * passing {@code null} when it cannot fulfill the request.
- *
- * @param sessionId the session's id
- * @param request the request to handle.
- * @param cancellationSignal signal for observing cancellation requests. The system will use
- * this to notify you that the fill result is no longer needed and you should stop
- * handling this fill request in order to save resources.
- * @param controller object used to interact with the autofill system.
- * @param callback object used to notify the result of the request. Service <b>must</b> call
- * {@link FillCallback#onSuccess(android.service.intelligence.FillResponse)}.
- */
- public void onFillRequest(@NonNull InteractionSessionId sessionId, @NonNull FillRequest request,
- @NonNull CancellationSignal cancellationSignal, @NonNull FillController controller,
- @NonNull FillCallback callback) {
- }
-
- private void handleOnDestroyAutofillWindowsRequest(@NonNull InteractionSessionId sessionId) {
- AutofillProxy proxy = null;
- if (mAutofillProxies != null) {
- proxy = mAutofillProxies.get(sessionId);
- }
- if (proxy == null) {
- // TODO(b/111330312): this might be fine, in which case we should logv it
- Log.w(TAG, "No proxy for session " + sessionId);
- return;
- }
- proxy.destroy();
- mAutofillProxies.remove(sessionId);
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mAutofillProxies != null) {
- final int size = mAutofillProxies.size();
- pw.print("Number proxies: "); pw.println(size);
- for (int i = 0; i < size; i++) {
- final InteractionSessionId sessionId = mAutofillProxies.keyAt(i);
- final AutofillProxy proxy = mAutofillProxies.valueAt(i);
- pw.print(i); pw.print(") SessionId="); pw.print(sessionId); pw.println(":");
- proxy.dump(" ", pw);
- }
- }
- }
-
- /**
- * Notifies the service of {@link SnapshotData snapshot data} associated with a session.
- *
- * @param sessionId the session's Id
- * @param snapshotData the data
- */
- public void onActivitySnapshot(@NonNull InteractionSessionId sessionId,
- @NonNull SnapshotData snapshotData) {}
-
- /**
- * Destroys the interaction session.
- *
- * @param sessionId the id of the session to destroy
- */
- public void onDestroyInteractionSession(@NonNull InteractionSessionId sessionId) {
- if (VERBOSE) {
- Log.v(TAG, "onDestroyInteractionSession(id=" + sessionId + ")");
- }
- }
-
- /** @hide */
- static final class AutofillProxy {
-
- static final int REPORT_EVENT_ON_SUCCESS = 1;
- static final int REPORT_EVENT_UI_SHOWN = 2;
- static final int REPORT_EVENT_UI_DESTROYED = 3;
-
- @IntDef(prefix = { "REPORT_EVENT_" }, value = {
- REPORT_EVENT_ON_SUCCESS,
- REPORT_EVENT_UI_SHOWN,
- REPORT_EVENT_UI_DESTROYED
- })
- @Retention(RetentionPolicy.SOURCE)
- @interface ReportEvent{}
-
-
- private final Object mLock = new Object();
- private final IAugmentedAutofillManagerClient mClient;
- private final int mAutofillSessionId;
- public final InteractionSessionId sessionId;
- public final AutofillId focusedId;
- public final AutofillValue focusedValue;
-
- // Objects used to log metrics
- private final long mRequestTime;
- private long mOnSuccessTime;
- private long mUiFirstShownTime;
- private long mUiFirstDestroyedTime;
-
- @GuardedBy("mLock")
- private SystemPopupPresentationParams mSmartSuggestion;
-
- @GuardedBy("mLock")
- private FillWindow mFillWindow;
-
- private AutofillProxy(@NonNull InteractionSessionId sessionId, @NonNull IBinder client,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue, long requestTime) {
- this.sessionId = sessionId;
- mClient = IAugmentedAutofillManagerClient.Stub.asInterface(client);
- mAutofillSessionId = autofillSessionId;
- this.focusedId = focusedId;
- this.focusedValue = focusedValue;
- this.mRequestTime = requestTime;
- // TODO(b/111330312): linkToDeath
- }
-
- @NonNull
- public SystemPopupPresentationParams getSmartSuggestionParams() {
- synchronized (mLock) {
- if (mSmartSuggestion != null) {
- return mSmartSuggestion;
- }
- Rect rect;
- try {
- rect = mClient.getViewCoordinates(focusedId);
- } catch (RemoteException e) {
- Log.w(TAG, "Could not get coordinates for " + focusedId);
- return null;
- }
- if (rect == null) {
- if (DEBUG) Log.d(TAG, "getViewCoordinates(" + focusedId + ") returned null");
- return null;
- }
- mSmartSuggestion = new SystemPopupPresentationParams(this, rect);
- return mSmartSuggestion;
- }
- }
-
- public void autofill(@NonNull List<Pair<AutofillId, AutofillValue>> pairs)
- throws RemoteException {
- final int size = pairs.size();
- final List<AutofillId> ids = new ArrayList<>(size);
- final List<AutofillValue> values = new ArrayList<>(size);
- for (int i = 0; i < size; i++) {
- final Pair<AutofillId, AutofillValue> pair = pairs.get(i);
- ids.add(pair.first);
- values.add(pair.second);
- }
- mClient.autofill(mAutofillSessionId, ids, values);
- }
-
- public void setFillWindow(@NonNull FillWindow fillWindow) {
- synchronized (mLock) {
- mFillWindow = fillWindow;
- }
- }
-
- public FillWindow getFillWindow() {
- synchronized (mLock) {
- return mFillWindow;
- }
- }
-
- // Used for metrics.
- public void report(@ReportEvent int event) {
- switch (event) {
- case REPORT_EVENT_ON_SUCCESS:
- if (mOnSuccessTime == 0) {
- mOnSuccessTime = SystemClock.elapsedRealtime();
- if (DEBUG) {
- Slog.d(TAG, "Service responsed in "
- + TimeUtils.formatDuration(mOnSuccessTime - mRequestTime));
- }
- }
- break;
- case REPORT_EVENT_UI_SHOWN:
- if (mUiFirstShownTime == 0) {
- mUiFirstShownTime = SystemClock.elapsedRealtime();
- if (DEBUG) {
- Slog.d(TAG, "UI shown in "
- + TimeUtils.formatDuration(mUiFirstShownTime - mRequestTime));
- }
- }
- break;
- case REPORT_EVENT_UI_DESTROYED:
- if (mUiFirstDestroyedTime == 0) {
- mUiFirstDestroyedTime = SystemClock.elapsedRealtime();
- if (DEBUG) {
- Slog.d(TAG, "UI destroyed in "
- + TimeUtils.formatDuration(
- mUiFirstDestroyedTime - mRequestTime));
- }
- }
- break;
- default:
- Slog.w(TAG, "invalid event reported: " + event);
- }
- // TODO(b/111330312): log metrics as well
- }
-
-
- public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
- pw.print(prefix); pw.print("afSessionId: "); pw.println(mAutofillSessionId);
- pw.print(prefix); pw.print("focusedId: "); pw.println(focusedId);
- if (focusedValue != null) {
- pw.print(prefix); pw.print("focusedValue: "); pw.println(focusedValue);
- }
- pw.print(prefix); pw.print("client: "); pw.println(mClient);
- final String prefix2 = prefix + " ";
- if (mFillWindow != null) {
- pw.print(prefix); pw.println("window:");
- mFillWindow.dump(prefix2, pw);
- }
- if (mSmartSuggestion != null) {
- pw.print(prefix); pw.println("smartSuggestion:");
- mSmartSuggestion.dump(prefix2, pw);
- }
- if (mOnSuccessTime > 0) {
- final long responseTime = mOnSuccessTime - mRequestTime;
- pw.print(prefix); pw.print("response time: ");
- TimeUtils.formatDuration(responseTime, pw); pw.println();
- }
-
- if (mUiFirstShownTime > 0) {
- final long uiRenderingTime = mUiFirstShownTime - mRequestTime;
- pw.print(prefix); pw.print("UI rendering time: ");
- TimeUtils.formatDuration(uiRenderingTime, pw); pw.println();
- }
-
- if (mUiFirstDestroyedTime > 0) {
- final long uiTotalTime = mUiFirstDestroyedTime - mRequestTime;
- pw.print(prefix); pw.print("UI life time: ");
- TimeUtils.formatDuration(uiTotalTime, pw); pw.println();
- }
- }
-
- private void destroy() {
- synchronized (mLock) {
- if (mFillWindow != null) {
- if (DEBUG) Log.d(TAG, "destroying window");
- mFillWindow.destroy();
- }
- }
- }
- }
-}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bd2aa64..4297efb7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -109,13 +109,13 @@
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
+import android.view.contentcapture.ContentCaptureManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.inspector.InspectableProperty;
import android.view.inspector.InspectableProperty.EnumMap;
import android.view.inspector.InspectableProperty.FlagMap;
-import android.view.intelligence.ContentCaptureManager;
import android.widget.Checkable;
import android.widget.FrameLayout;
import android.widget.ScrollBarDrawable;
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.aidl b/core/java/android/view/contentcapture/ContentCaptureEvent.aidl
similarity index 94%
rename from core/java/android/view/intelligence/ContentCaptureEvent.aidl
rename to core/java/android/view/contentcapture/ContentCaptureEvent.aidl
index c66a6cb..abaf9ed 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.aidl
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.view.intelligence;
+package android.view.contentcapture;
parcelable ContentCaptureEvent;
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
similarity index 91%
rename from core/java/android/view/intelligence/ContentCaptureEvent.java
rename to core/java/android/view/contentcapture/ContentCaptureEvent.java
index f636281..66fa530 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.view.intelligence;
+package android.view.contentcapture;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -42,22 +42,38 @@
/**
* Called when the activity is started.
+ *
+ * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+ * something related to a session and/or domain.
*/
+ @Deprecated
public static final int TYPE_ACTIVITY_STARTED = 1;
/**
* Called when the activity is resumed.
+ *
+ * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+ * something related to a session and/or domain.
*/
+ @Deprecated
public static final int TYPE_ACTIVITY_RESUMED = 2;
/**
* Called when the activity is paused.
+ *
+ * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+ * something related to a session and/or domain.
*/
+ @Deprecated
public static final int TYPE_ACTIVITY_PAUSED = 3;
/**
* Called when the activity is stopped.
+ *
+ * @deprecated - TODO(b/111276913): we should abstract the Activity lifecycle concepts into
+ * something related to a session and/or domain.
*/
+ @Deprecated
public static final int TYPE_ACTIVITY_STOPPED = 4;
/**
@@ -163,7 +179,7 @@
* Gets optional flags associated with the event.
*
* @return either {@code 0} or
- * {@link android.view.intelligence.ContentCaptureManager#FLAG_USER_INPUT}.
+ * {@link android.view.contentcapture.ContentCaptureManager#FLAG_USER_INPUT}.
*/
public int getFlags() {
return mFlags;
diff --git a/core/java/android/view/intelligence/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
similarity index 95%
rename from core/java/android/view/intelligence/ContentCaptureManager.java
rename to core/java/android/view/contentcapture/ContentCaptureManager.java
index 45518d5..48831da 100644
--- a/core/java/android/view/intelligence/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.view.intelligence;
+package android.view.contentcapture;
-import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_APPEARED;
-import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
-import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_APPEARED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
@@ -31,18 +31,18 @@
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
-import android.service.intelligence.InteractionSessionId;
import android.util.Log;
import android.view.View;
import android.view.ViewStructure;
import android.view.autofill.AutofillId;
-import android.view.intelligence.ContentCaptureEvent.EventType;
+import android.view.contentcapture.ContentCaptureEvent.EventType;
import com.android.internal.os.IResultReceiver;
import com.android.internal.util.Preconditions;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
/*
@@ -58,7 +58,7 @@
@SystemService(Context.CONTENT_CAPTURE_MANAGER_SERVICE)
public final class ContentCaptureManager {
- private static final String TAG = "ContentCaptureManager";
+ private static final String TAG = ContentCaptureManager.class.getSimpleName();
// TODO(b/111276913): define a way to dynamically set them(for example, using settings?)
private static final boolean VERBOSE = false;
@@ -113,10 +113,10 @@
private final Context mContext;
@Nullable
- private final IIntelligenceManager mService;
+ private final IContentCaptureManager mService;
@Nullable
- private InteractionSessionId mId;
+ private String mId;
private int mState = STATE_UNKNOWN;
@@ -137,7 +137,8 @@
private final Handler mHandler;
/** @hide */
- public ContentCaptureManager(@NonNull Context context, @Nullable IIntelligenceManager service) {
+ public ContentCaptureManager(@NonNull Context context,
+ @Nullable IContentCaptureManager service) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
if (VERBOSE) {
Log.v(TAG, "Constructor for " + context.getPackageName());
@@ -165,7 +166,7 @@
return;
}
mState = STATE_WAITING_FOR_SERVER;
- mId = new InteractionSessionId();
+ mId = UUID.randomUUID().toString();
mApplicationToken = token;
mComponentName = componentName;
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
new file mode 100644
index 0000000..8704dad
--- /dev/null
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.contentcapture;
+
+import android.content.ComponentName;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.os.IBinder;
+
+import com.android.internal.os.IResultReceiver;
+
+import java.util.List;
+
+/**
+ * {@hide}
+ */
+oneway interface IContentCaptureManager {
+ void startSession(int userId, IBinder activityToken, in ComponentName componentName,
+ String sessionId, int flags, in IResultReceiver result);
+ void finishSession(int userId, String sessionId, in List<ContentCaptureEvent> events);
+ void sendEvents(int userId, in String sessionId, in List<ContentCaptureEvent> events);
+}
diff --git a/core/java/android/view/intelligence/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java
similarity index 99%
rename from core/java/android/view/intelligence/ViewNode.java
rename to core/java/android/view/contentcapture/ViewNode.java
index ea57461..86b89adb 100644
--- a/core/java/android/view/intelligence/ViewNode.java
+++ b/core/java/android/view/contentcapture/ViewNode.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.view.intelligence;
+package android.view.contentcapture;
import android.annotation.NonNull;
import android.annotation.Nullable;
diff --git a/core/java/android/view/intelligence/IIntelligenceManager.aidl b/core/java/android/view/intelligence/IIntelligenceManager.aidl
deleted file mode 100644
index 882fb26..0000000
--- a/core/java/android/view/intelligence/IIntelligenceManager.aidl
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.intelligence;
-
-import android.content.ComponentName;
-import android.os.IBinder;
-import android.service.intelligence.InteractionSessionId;
-import android.view.intelligence.ContentCaptureEvent;
-
-import com.android.internal.os.IResultReceiver;
-
-import java.util.List;
-
-/**
- * {@hide}
- */
-// TODO(b/111276913): rename once the final name is defined
-oneway interface IIntelligenceManager {
- /**
- * Starts a session, sending the "remote" sessionId to the receiver.
- */
- void startSession(int userId, IBinder activityToken, in ComponentName componentName,
- in InteractionSessionId sessionId, int flags, in IResultReceiver result);
-
- /**
- * Finishes a session.
- */
- void finishSession(int userId, in InteractionSessionId sessionId,
- in List<ContentCaptureEvent> events);
-
- /**
- * Sends a batch of events
- */
- void sendEvents(int userId, in InteractionSessionId sessionId,
- in List<ContentCaptureEvent> events);
-}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 90cf871..2a42232 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -157,6 +157,7 @@
import android.view.animation.AnimationUtils;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
+import android.view.contentcapture.ContentCaptureManager;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
@@ -166,7 +167,6 @@
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
-import android.view.intelligence.ContentCaptureManager;
import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassificationContext;
import android.view.textclassifier.TextClassificationManager;
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 4c1fc5c..9620e4b 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -222,6 +222,13 @@
}
optional Connectivity connectivity = 32;
+ message ContentCapture {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto service_explicitly_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional ContentCapture content_capture = 145;
+
optional SettingProto contact_metadata_sync_enabled = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto contacts_database_wal_enabled = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
@@ -761,13 +768,6 @@
}
optional SmartSelection smart_selection = 108;
- message SmartSuggestions {
- option (android.msg_privacy).dest = DEST_EXPLICIT;
-
- optional SettingProto service_explicitly_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
- }
- optional SmartSuggestions smart_suggestions = 145;
-
message Sms {
option (android.msg_privacy).dest = DEST_EXPLICIT;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3018614..594ae6b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3047,12 +3047,20 @@
<permission android:name="android.permission.BIND_TEXTCLASSIFIER_SERVICE"
android:protectionLevel="signature" />
- <!-- Must be required by a android.service.intelligence.SmartSuggestionsService,
+ <!-- Must be required by a android.service.contentcapture.ContentCaptureService,
to ensure that only the system can bind to it.
@SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
<p>Protection level: signature
-->
- <permission android:name="android.permission.BIND_SMART_SUGGESTIONS_SERVICE"
+ <permission android:name="android.permission.BIND_CONTENT_CAPTURE_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a android.service.autofill.augmented.AugmentedAutofillService,
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE"
android:protectionLevel="signature" />
<!-- Must be required by hotword enrollment application,
@@ -4177,9 +4185,9 @@
<permission android:name="android.permission.MANAGE_AUTO_FILL"
android:protectionLevel="signature" />
- <!-- @SystemApi Allows an application to manage the smart suggestions service.
+ <!-- @SystemApi Allows an application to manage the content capture service.
@hide <p>Not for use by third-party applications.</p> -->
- <permission android:name="android.permission.MANAGE_SMART_SUGGESTIONS"
+ <permission android:name="android.permission.MANAGE_CONTENT_CAPTURE"
android:protectionLevel="signature" />
<!-- Allows an app to set the theme overlay in /vendor/overlay
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 499278c..62ec5c4 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3350,13 +3350,21 @@
-->
<string name="config_defaultTextClassifierPackage" translatable="false"></string>
- <!-- The package name for the system's smart suggestion service.
+ <!-- The package name for the system's content capture service.
This service must be trusted, as it can be activated without explicit consent of the user.
- If no service with the specified name exists on the device, content capture and
- smart suggestions will be disabled.
- Example: "com.android.intelligence/.SmartSuggestionsService"
+ If no service with the specified name exists on the device, content capture will be
+ disabled.
+ Example: "com.android.contentcapture/.ContentcaptureService"
-->
- <string name="config_defaultSmartSuggestionsService" translatable="false"></string>
+ <string name="config_defaultContentCaptureService" translatable="false"></string>
+
+ <!-- The package name for the system's augmented autofill service.
+ This service must be trusted, as it can be activated without explicit consent of the user.
+ If no service with the specified name exists on the device, augmented autofill wil be
+ disabled.
+ Example: "com.android.augmentedautofill/.AugmentedAutofillService"
+ -->
+ <string name="config_defaultAugmentedAutofillService" translatable="false"></string>
<!-- Whether the device uses the default focus highlight when focus state isn't specified. -->
<bool name="config_useDefaultFocusHighlight">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6854a84e..82a679e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3265,7 +3265,8 @@
<java-symbol type="string" name="notification_channel_do_not_disturb" />
<java-symbol type="string" name="config_defaultAutofillService" />
<java-symbol type="string" name="config_defaultTextClassifierPackage" />
- <java-symbol type="string" name="config_defaultSmartSuggestionsService" />
+ <java-symbol type="string" name="config_defaultContentCaptureService" />
+ <java-symbol type="string" name="config_defaultAugmentedAutofillService" />
<java-symbol type="string" name="notification_channel_foreground_service" />
<java-symbol type="string" name="foreground_service_app_in_background" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index ed9c3d5..f1ed1c2 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -183,6 +183,7 @@
Settings.Global.CONNECTIVITY_METRICS_BUFFER_SIZE,
Settings.Global.CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS,
Settings.Global.CONTACT_METADATA_SYNC_ENABLED,
+ Settings.Global.CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED,
Settings.Global.CONVERSATION_ACTIONS_UPDATE_CONTENT_URL,
Settings.Global.CONVERSATION_ACTIONS_UPDATE_METADATA_URL,
Settings.Global.CONTACTS_DATABASE_WAL_ENABLED,
@@ -415,7 +416,6 @@
Settings.Global.SHOW_TEMPERATURE_WARNING,
Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL,
Settings.Global.SMART_SELECTION_UPDATE_METADATA_URL,
- Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED,
Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED,
Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS,
Settings.Global.SMS_OUTGOING_CHECK_MAX_COUNT,
diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 12df263..d087176 100644
--- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -108,7 +108,13 @@
private CarAudioManager mCarAudioManager;
private final ICarVolumeCallback mVolumeChangeCallback = new ICarVolumeCallback.Stub() {
@Override
- public void onGroupVolumeChanged(int groupId, int flags) {
+ public void onGroupVolumeChanged(int zoneId, int groupId, int flags) {
+ // TODO: Include zoneId into consideration.
+ // For instance
+ // - single display + single-zone, ignore zoneId
+ // - multi-display + single-zone, zoneId is fixed, may show volume bar on all displays
+ // - single-display + multi-zone, may show volume bar on primary display only
+ // - multi-display + multi-zone, may show volume bar on display specified by zoneId
VolumeItem volumeItem = mAvailableVolumeItems.get(groupId);
int value = getSeekbarValue(mCarAudioManager, groupId);
// Do not update the progress if it is the same as before. When car audio manager sets
@@ -124,7 +130,7 @@
}
@Override
- public void onMasterMuteChanged(int flags) {
+ public void onMasterMuteChanged(int zoneId, int flags) {
// ignored
}
};
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index df5b146..ad88432 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -418,6 +418,12 @@
Settings.Global.CONTACTS_DATABASE_WAL_ENABLED,
GlobalSettingsProto.CONTACTS_DATABASE_WAL_ENABLED);
+ final long contentCaptureToken = p.start(GlobalSettingsProto.CONTENT_CAPTURE);
+ dumpSetting(s, p,
+ Settings.Global.CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED,
+ GlobalSettingsProto.ContentCapture.SERVICE_EXPLICITLY_ENABLED);
+ p.end(contentCaptureToken);
+
final long dataToken = p.start(GlobalSettingsProto.DATA);
// Settings.Global.DEFAULT_RESTRICT_BACKGROUND_DATA intentionally excluded.
dumpSetting(s, p,
@@ -1165,12 +1171,6 @@
GlobalSettingsProto.SmartSelection.UPDATE_METADATA_URL);
p.end(smartSelectToken);
- final long smartSuggestionsToken = p.start(GlobalSettingsProto.SMART_SUGGESTIONS);
- dumpSetting(s, p,
- Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED,
- GlobalSettingsProto.SmartSuggestions.SERVICE_EXPLICITLY_ENABLED);
- p.end(smartSuggestionsToken);
-
final long smsToken = p.start(GlobalSettingsProto.SMS);
dumpSetting(s, p,
Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 83e8369..e564711 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -130,7 +130,7 @@
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
<uses-permission android:name="android.permission.MANAGE_AUTO_FILL" />
- <uses-permission android:name="android.permission.MANAGE_SMART_SUGGESTIONS" />
+ <uses-permission android:name="android.permission.MANAGE_CONTENT_CAPTURE" />
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.SET_TIME" />
diff --git a/services/Android.bp b/services/Android.bp
index 3390438..58a0997 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -21,9 +21,9 @@
"services.autofill",
"services.backup",
"services.companion",
+ "services.contentcapture",
"services.coverage",
"services.devicepolicy",
- "services.intelligence",
"services.midi",
"services.net",
"services.print",
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 944ee33..e8887e7 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -74,7 +74,6 @@
import com.android.server.LocalServices;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.infra.AbstractMasterSystemService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -100,6 +99,7 @@
private static final Object sLock = AutofillManagerService.class;
+ private static final int MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes
/**
* IME supports Smart Suggestions.
@@ -155,7 +155,7 @@
private final AutofillCompatState mAutofillCompatState = new AutofillCompatState();
private final LocalService mLocalService = new LocalService();
- final IntelligenceManagerInternal mIntelligenceManagerInternal;
+ private final ActivityManagerInternal mAm;
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -184,7 +184,7 @@
public AutofillManagerService(Context context) {
super(context, UserManager.DISALLOW_AUTOFILL);
mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext());
- mIntelligenceManagerInternal = LocalServices.getService(IntelligenceManagerInternal.class);
+ mAm = LocalServices.getService(ActivityManagerInternal.class);
setLogLevelFromSettings();
setMaxPartitionsFromSettings();
@@ -288,6 +288,11 @@
return mSupportedSmartSuggestionModes;
}
+ // Called by AutofillManagerServiceImpl, doesn't need to check permission
+ boolean isInstantServiceAllowed() {
+ return mAllowInstantService;
+ }
+
// Called by Shell command.
void destroySessions(@UserIdInt int userId, IResultReceiver receiver) {
Slog.i(TAG, "destroySessions() for userId " + userId);
@@ -502,6 +507,39 @@
sFullScreenMode = mode;
}
+ // Called by Shell command.
+ void setTemporaryAugmentedAutofillService(@UserIdInt int userId, @NonNull String serviceName,
+ int durationMs) {
+ Slog.i(mTag, "setTemporaryAugmentedAutofillService(" + userId + ") to " + serviceName
+ + " for " + durationMs + "ms");
+ enforceCallingPermissionForManagement();
+
+ Preconditions.checkNotNull(serviceName);
+ if (durationMs > MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS) {
+ throw new IllegalArgumentException("Max duration is "
+ + MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS + " (called with " + durationMs + ")");
+ }
+
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+ if (service != null) {
+ service.mAugmentedAutofillResolver.setTemporaryServiceLocked(serviceName,
+ durationMs);
+ }
+ }
+ }
+
+ // Called by Shell command
+ void resetTemporaryAugmentedAutofillService(@UserIdInt int userId) {
+ enforceCallingPermissionForManagement();
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
+ if (service != null) {
+ service.mAugmentedAutofillResolver.resetTemporaryServiceLocked();
+ }
+ }
+ }
+
private void setLoggingLevelsLocked(boolean debug, boolean verbose) {
com.android.server.autofill.Helper.sDebug = debug;
android.view.autofill.Helper.sDebug = debug;
@@ -877,14 +915,9 @@
throw new IllegalArgumentException(packageName + " is not a valid package", e);
}
- // TODO(b/113281366): rather than always call AM here, call it on demand on
- // getPreviousSessionsLocked()? That way we save space / time here, and don't set
- // a callback on AM unnecessarily (see TODO below :-)
- final ActivityManagerInternal am = LocalServices
- .getService(ActivityManagerInternal.class);
// TODO(b/113281366): add a callback method on AM to be notified when a task is finished
// so we can clean up sessions kept alive
- final int taskId = am.getTaskIdForActivity(activityToken, false);
+ final int taskId = mAm.getTaskIdForActivity(activityToken, false);
final int sessionId;
synchronized (mLock) {
final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 3945c23..5a0d12c 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -73,8 +73,11 @@
import com.android.server.LocalServices;
import com.android.server.autofill.AutofillManagerService.AutofillCompatState;
import com.android.server.autofill.AutofillManagerService.SmartSuggestionMode;
+import com.android.server.autofill.RemoteAugmentedAutofillService.RemoteAugmentedAutofillServiceCallbacks;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.infra.AbstractPerUserSystemService;
+import com.android.server.infra.AbstractRemoteService;
+import com.android.server.infra.FrameworkResourcesServiceNameResolver;
import com.android.server.infra.SecureSettingsServiceNameResolver;
import java.io.PrintWriter;
@@ -152,6 +155,19 @@
/** When was {@link PruneTask} last executed? */
private long mLastPrune = 0;
+ /**
+ * Object used to set the name of the augmented autofill service.
+ */
+ @NonNull
+ final FrameworkResourcesServiceNameResolver mAugmentedAutofillResolver;
+
+ /**
+ * Reference to the {@link RemoteAugmentedAutofillService}, is set on demand.
+ */
+ @GuardedBy("mLock")
+ @Nullable
+ private RemoteAugmentedAutofillService mRemoteAugmentedAutofillService;
+
AutofillManagerServiceImpl(AutofillManagerService master, Object lock, LocalLog requestsHistory,
LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
AutofillCompatState autofillCompatState, boolean disabled) {
@@ -164,6 +180,12 @@
mUi = ui;
mFieldClassificationStrategy = new FieldClassificationStrategy(getContext(), userId);
mAutofillCompatState = autofillCompatState;
+
+ mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(master.getContext(),
+ userId, lock, com.android.internal.R.string.config_defaultAugmentedAutofillService);
+ mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback(
+ () -> updateRemoteAugmentedAutofillService());
+
updateLocked(disabled);
}
@@ -851,6 +873,12 @@
}
pw.print(prefix); pw.print("Default component: "); pw.println(getContext()
.getString(R.string.config_defaultAutofillService));
+ pw.print(prefix); pw.print("mAugmentedAutofillNamer: ");
+ mAugmentedAutofillResolver.dumpShortLocked(pw); pw.println();
+ if (mRemoteAugmentedAutofillService != null) {
+ pw.print(prefix); pw.println("RemoteAugmentedAutofillService: ");
+ mRemoteAugmentedAutofillService.dump(prefix2, pw);
+ }
pw.print(prefix); pw.print("Field classification enabled: ");
pw.println(isFieldClassificationEnabledLocked());
pw.print(prefix); pw.print("Compat pkgs: ");
@@ -992,6 +1020,52 @@
return null;
}
+ @GuardedBy("mLock")
+ @Nullable RemoteAugmentedAutofillService getRemoteAugmentedAutofillServiceLocked() {
+ if (mRemoteAugmentedAutofillService == null) {
+ final String serviceName = mAugmentedAutofillResolver.getServiceNameLocked();
+ if (serviceName == null) {
+ if (mMaster.verbose) {
+ Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): not set");
+ }
+ return null;
+ }
+ final ComponentName componentName = RemoteAugmentedAutofillService.getComponentName(
+ getContext(), serviceName, mUserId,
+ mAugmentedAutofillResolver.isTemporaryLocked());
+ if (componentName == null) return null;
+ if (sVerbose) {
+ Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): " + componentName);
+ }
+
+ mRemoteAugmentedAutofillService = new RemoteAugmentedAutofillService(getContext(),
+ componentName, mUserId, new RemoteAugmentedAutofillServiceCallbacks() {
+ @Override
+ public void onServiceDied(
+ AbstractRemoteService<? extends AbstractRemoteService<?>> service) {
+ // TODO(b/111330312): properly implement
+ Slog.w(TAG, "remote augmented autofill service died");
+ }
+ }, mMaster.isInstantServiceAllowed(), mMaster.verbose);
+ }
+
+ return mRemoteAugmentedAutofillService;
+ }
+
+ /**
+ * Called when the {@link #mAugmentedAutofillResolver} changed (among other places).
+ */
+ private void updateRemoteAugmentedAutofillService() {
+ final String serviceName = mAugmentedAutofillResolver.getServiceNameLocked();
+ if (serviceName == null) {
+ if (sVerbose) Slog.v(TAG, "updateRemoteAugmentedAutofillService(): time's up!");
+ if (mRemoteAugmentedAutofillService != null) {
+ mRemoteAugmentedAutofillService.destroy();
+ mRemoteAugmentedAutofillService = null;
+ }
+ }
+ }
+
private void sendStateToClients(boolean resetClient) {
final RemoteCallbackList<IAutoFillManagerClient> clients;
final int userClientCount;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index 522280e..35c5102 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -104,6 +104,11 @@
pw.println(" set bind-instant-service-allowed [true | false]");
pw.println(" Sets whether binding to services provided by instant apps is allowed");
pw.println("");
+ pw.println(" set temporary-augmented-service USER_ID [COMPONENT_NAME DURATION]");
+ pw.println(" Temporarily (for DURATION ms) changes the augmented autofill service "
+ + "implementation.");
+ pw.println(" To reset, call with just the USER_ID argument.");
+ pw.println("");
pw.println(" list sessions [--user USER_ID]");
pw.println(" Lists all pending sessions.");
pw.println("");
@@ -151,6 +156,8 @@
return setFullScreenMode(pw);
case "bind-instant-service-allowed":
return setBindInstantService(pw);
+ case "temporary-augmented-service":
+ return setTemporaryAugmentedService(pw);
default:
pw.println("Invalid set: " + what);
return -1;
@@ -293,6 +300,20 @@
}
}
+ private int setTemporaryAugmentedService(PrintWriter pw) {
+ final int userId = getNextIntArgRequired();
+ final String serviceName = getNextArg();
+ if (serviceName == null) {
+ mService.resetTemporaryAugmentedAutofillService(userId);
+ return 0;
+ }
+ final int duration = getNextIntArgRequired();
+ mService.setTemporaryAugmentedAutofillService(userId, serviceName, duration);
+ pw.println("AugmentedAutofillService temporarily set to " + serviceName + " for "
+ + duration + "ms");
+ return 0;
+ }
+
private int requestDestroy(PrintWriter pw) {
if (!isNextArgSessions(pw)) {
return -1;
@@ -371,4 +392,8 @@
}
return UserHandle.USER_ALL;
}
+
+ private int getNextIntArgRequired() {
+ return Integer.parseInt(getNextArgRequired());
+ }
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
new file mode 100644
index 0000000..222888c
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.service.autofill.augmented.AugmentedAutofillService;
+import android.service.autofill.augmented.IAugmentedAutofillService;
+import android.service.autofill.augmented.IFillCallback;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
+import android.view.autofill.IAutoFillManagerClient;
+
+import com.android.internal.os.IResultReceiver;
+import com.android.server.infra.AbstractSinglePendingRequestRemoteService;
+
+final class RemoteAugmentedAutofillService
+ extends AbstractSinglePendingRequestRemoteService<RemoteAugmentedAutofillService> {
+
+ private static final String TAG = RemoteAugmentedAutofillService.class.getSimpleName();
+
+ // TODO(b/117779333): changed it so it's permanentely bound
+ private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
+ private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
+
+ private final RemoteAugmentedAutofillServiceCallbacks mCallbacks;
+ private IAugmentedAutofillService mService;
+
+ RemoteAugmentedAutofillService(Context context, ComponentName serviceName,
+ int userId, RemoteAugmentedAutofillServiceCallbacks callbacks,
+ boolean bindInstantServiceAllowed, boolean verbose) {
+ super(context, AugmentedAutofillService.SERVICE_INTERFACE, serviceName, userId, callbacks,
+ bindInstantServiceAllowed, verbose);
+ mCallbacks = callbacks;
+ }
+
+ @Nullable
+ public static ComponentName getComponentName(@NonNull Context context,
+ @NonNull String componentName, @UserIdInt int userId, boolean isTemporary) {
+ int flags = PackageManager.GET_META_DATA;
+ if (!isTemporary) {
+ flags |= PackageManager.MATCH_SYSTEM_ONLY;
+ }
+
+ final ComponentName serviceComponent;
+ ServiceInfo serviceInfo = null;
+ try {
+ serviceComponent = ComponentName.unflattenFromString(componentName);
+ serviceInfo = AppGlobals.getPackageManager().getServiceInfo(serviceComponent, flags,
+ userId);
+ if (serviceInfo == null) {
+ Slog.e(TAG, "Bad service name for flags " + flags + ": " + componentName);
+ return null;
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Error getting service info for '" + componentName + "': " + e);
+ return null;
+ }
+ return serviceComponent;
+ }
+
+ @Override // from AbstractRemoteService
+ protected IInterface getServiceInterface(IBinder service) {
+ mService = IAugmentedAutofillService.Stub.asInterface(service);
+ return mService;
+ }
+
+ @Override // from AbstractRemoteService
+ protected long getTimeoutIdleBindMillis() {
+ return TIMEOUT_IDLE_BIND_MILLIS;
+ }
+
+ @Override // from AbstractRemoteService
+ protected long getRemoteRequestMillis() {
+ return TIMEOUT_REMOTE_REQUEST_MILLIS;
+ }
+
+ /**
+ * Called by {@link Session} to request augmented autofill.
+ */
+ public void onRequestAutofillLocked(int sessionId, @NonNull IAutoFillManagerClient client,
+ int taskId, @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId,
+ @Nullable AutofillValue focusedValue) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingAutofillRequest(this, sessionId, client, taskId,
+ activityComponent, focusedId, focusedValue));
+ }
+
+ /**
+ * Called by {@link Session} when it's time to destroy all augmented autofill requests.
+ */
+ public void onDestroyAutofillWindowsRequest(int sessionId) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingDestroyAutofillWindowsRequest(this, sessionId));
+ }
+
+ private abstract static class MyPendingRequest
+ extends PendingRequest<RemoteAugmentedAutofillService> {
+ protected final int mSessionId;
+
+ private MyPendingRequest(@NonNull RemoteAugmentedAutofillService service, int sessionId) {
+ super(service);
+ mSessionId = sessionId;
+ }
+ }
+
+ private static final class PendingAutofillRequest extends MyPendingRequest {
+ private final @NonNull AutofillId mFocusedId;
+ private final @Nullable AutofillValue mFocusedValue;
+ private final @NonNull IAutoFillManagerClient mClient;
+ private final @NonNull ComponentName mActivityComponent;
+ private final int mTaskId;
+ private final long mRequestTime = SystemClock.elapsedRealtime();
+ private final @NonNull IFillCallback mCallback;
+
+ protected PendingAutofillRequest(@NonNull RemoteAugmentedAutofillService service,
+ int sessionId, @NonNull IAutoFillManagerClient client, int taskId,
+ @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId,
+ @Nullable AutofillValue focusedValue) {
+ super(service, sessionId);
+ mClient = client;
+ mTaskId = taskId;
+ mActivityComponent = activityComponent;
+ mFocusedId = focusedId;
+ mFocusedValue = focusedValue;
+ mCallback = new IFillCallback.Stub() {
+ @Override
+ public void onSuccess() {
+ if (!finish()) return;
+ // NOTE: so far we don't need notify RemoteAugmentedAutofillServiceCallbacks
+ }
+ };
+ }
+
+ @Override
+ public void run() {
+ final RemoteAugmentedAutofillService remoteService = getService();
+ if (remoteService == null) return;
+
+ final IResultReceiver receiver = new IResultReceiver.Stub() {
+
+ @Override
+ public void send(int resultCode, Bundle resultData) throws RemoteException {
+ final IBinder realClient = resultData
+ .getBinder(AutofillManager.EXTRA_AUGMENTED_AUTOFILL_CLIENT);
+ remoteService.mService.onFillRequest(mSessionId, realClient, mTaskId,
+ mActivityComponent, mFocusedId, mFocusedValue, mRequestTime, mCallback);
+ }
+ };
+
+ // TODO(b/111330312): set cancellation signal, timeout (from both mClient and service),
+ // cache IAugmentedAutofillManagerClient reference, etc...
+ try {
+ mClient.getAugmentedAutofillClient(receiver);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "exception handling getAugmentedAutofillClient() for "
+ + mSessionId + ": " + e);
+ finish();
+ }
+ }
+
+ @Override
+ protected void onTimeout(RemoteAugmentedAutofillService remoteService) {
+ Slog.wtf(TAG, "timed out: " + this);
+ // NOTE: so far we don't need notify RemoteAugmentedAutofillServiceCallbacks
+ finish();
+ }
+
+ }
+
+ private static final class PendingDestroyAutofillWindowsRequest extends MyPendingRequest {
+
+ protected PendingDestroyAutofillWindowsRequest(
+ @NonNull RemoteAugmentedAutofillService service, @NonNull int sessionId) {
+ super(service, sessionId);
+ }
+
+ @Override
+ public void run() {
+ final RemoteAugmentedAutofillService remoteService = getService();
+ if (remoteService == null) return;
+
+ try {
+ remoteService.mService.onDestroyFillWindowRequest(mSessionId);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "exception handling onDestroyAutofillWindowsRequest() for "
+ + mSessionId + ": " + e);
+ } finally {
+ // Service is not calling back, so we finish right away.
+ finish();
+ }
+ }
+
+ @Override
+ protected void onTimeout(RemoteAugmentedAutofillService remoteService) {
+ // Should not happen because we called finish() on run(), although currently it might
+ // be called if the service is destroyed while showing it.
+ Slog.e(TAG, "timed out: " + this);
+ }
+ }
+
+ public interface RemoteAugmentedAutofillServiceCallbacks extends VultureCallback {
+ // NOTE: so far we don't need to notify the callback implementation (an inner class on
+ // AutofillManagerServiceImpl) of the request results (success, timeouts, etc..), so this
+ // callback interface is empty.
+ }
+}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index fb64cb2..d76a5df 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -99,8 +99,6 @@
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.autofill.ui.PendingUi;
import com.android.server.infra.AbstractRemoteService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -248,9 +246,18 @@
@GuardedBy("mLock")
private final SparseArray<LogMaker> mRequestLogs = new SparseArray<>(1);
+ /**
+ * Destroys the augmented Autofill UI.
+ */
+ // TODO(b/111330312): this runnable is called when the Autofill session is destroyed, the
+ // main reason being the cases where user tap HOME.
+ // Right now it's completely destroying the UI, but we need to decide whether / how to
+ // properly recover it later (for example, if the user switches back to the activity,
+ // should it be restored? Right not it kind of is, because Autofill's Session trigger a
+ // new FillRequest, which in turn triggers the Augmented Autofill request again)
@GuardedBy("mLock")
@Nullable
- private AugmentedAutofillCallback mAugmentedAutofillCallback;
+ private Runnable mAugmentedAutofillDestroyer;
/**
* Receiver of assist data from the app's {@link Activity}.
@@ -2516,8 +2523,8 @@
// The default autofill service cannot fullfill the request, let's check if the intelligence
// service can.
- mAugmentedAutofillCallback = triggerAugmentedAutofillLocked();
- if (mAugmentedAutofillCallback == null) {
+ mAugmentedAutofillDestroyer = triggerAugmentedAutofillLocked();
+ if (mAugmentedAutofillDestroyer == null) {
if (sVerbose) {
Slog.v(TAG, "canceling session " + id + " when server returned null and there is no"
+ " AugmentedAutofill for user");
@@ -2539,21 +2546,22 @@
/**
* Tries to trigger Augmented Autofill when the standard service could not fulfill a request.
*
- * @return callback to the Augmented Autofill service, or {@code null} if not supported.
+ * @return callback to destroy the autofill UI, or {@code null} if not supported.
*/
// TODO(b/111330312): might need to call it in other places, like when the service returns a
// non-null response but without datasets (for example, just SaveInfo)
@GuardedBy("mLock")
- private AugmentedAutofillCallback triggerAugmentedAutofillLocked() {
+ private Runnable triggerAugmentedAutofillLocked() {
// Check if Smart Suggestions is supported...
final @SmartSuggestionMode int supportedModes = mService
.getSupportedSmartSuggestionModesLocked();
if (supportedModes == 0) return null;
// ...then if the service is set for the user
- final IntelligenceManagerInternal intelligenceManagerInternal = mService
- .getMaster().mIntelligenceManagerInternal;
- if (intelligenceManagerInternal == null) return null;
+
+ final RemoteAugmentedAutofillService remoteService = mService
+ .getRemoteAugmentedAutofillServiceLocked();
+ if (remoteService == null) return null;
// Define which mode will be used
final int mode;
@@ -2584,8 +2592,13 @@
// TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
// furgher AFM -> AFMS calls.
// TODO(b/119638958): add CTS tests
- return intelligenceManagerInternal.requestAutofill(mService.getUserId(), mClient,
- mActivityToken, this.id, mCurrentViewId, currentValue);
+ remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, mCurrentViewId,
+ currentValue);
+
+ if (mAugmentedAutofillDestroyer == null) {
+ mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest(id);
+ }
+ return mAugmentedAutofillDestroyer;
}
@GuardedBy("mLock")
@@ -2866,8 +2879,8 @@
pw.print(prefix); pw.print("mSaveOnAllViewsInvisible: "); pw.println(
mSaveOnAllViewsInvisible);
pw.print(prefix); pw.print("mSelectedDatasetIds: "); pw.println(mSelectedDatasetIds);
- if (mAugmentedAutofillCallback != null) {
- pw.print(prefix); pw.println("has AugmentedAutofillCallback");
+ if (mAugmentedAutofillDestroyer != null) {
+ pw.print(prefix); pw.println("has mAugmentedAutofillDestroyer");
}
mRemoteFillService.dump(prefix, pw);
}
@@ -3045,8 +3058,9 @@
@GuardedBy("mLock")
void destroyAugmentedAutofillWindowsLocked() {
- if (mAugmentedAutofillCallback != null) {
- mAugmentedAutofillCallback.destroy();
+ if (mAugmentedAutofillDestroyer != null) {
+ mAugmentedAutofillDestroyer.run();
+ mAugmentedAutofillDestroyer = null;
}
}
diff --git a/services/intelligence/Android.bp b/services/contentcapture/Android.bp
similarity index 69%
rename from services/intelligence/Android.bp
rename to services/contentcapture/Android.bp
index 2df1235..57e859e 100644
--- a/services/intelligence/Android.bp
+++ b/services/contentcapture/Android.bp
@@ -1,5 +1,5 @@
java_library_static {
- name: "services.intelligence",
+ name: "services.contentcapture",
srcs: ["java/**/*.java"],
libs: ["services.core"],
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
similarity index 68%
rename from services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index a760cbd..872fe42 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
-import static android.Manifest.permission.MANAGE_SMART_SUGGESTIONS;
+import static android.Manifest.permission.MANAGE_CONTENT_CAPTURE;
import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE;
import android.annotation.NonNull;
@@ -32,13 +32,9 @@
import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManager;
-import android.service.intelligence.InteractionSessionId;
import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-import android.view.intelligence.IIntelligenceManager;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.IContentCaptureManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
@@ -58,11 +54,10 @@
* <p>The data collected by this service can be analyzed and combined with other sources to provide
* contextual data in other areas of the system such as Autofill.
*/
-//TODO(b/111276913): rename once the final name is defined
-public final class IntelligenceManagerService extends
- AbstractMasterSystemService<IntelligenceManagerService, IntelligencePerUserService> {
+public final class ContentCaptureManagerService extends
+ AbstractMasterSystemService<ContentCaptureManagerService, ContentCapturePerUserService> {
- private static final String TAG = "IntelligenceManagerService";
+ private static final String TAG = ContentCaptureManagerService.class.getSimpleName();
static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";
@@ -73,32 +68,32 @@
private final LocalService mLocalService = new LocalService();
- public IntelligenceManagerService(Context context) {
- super(context, UserManager.DISALLOW_INTELLIGENCE_CAPTURE);
+ public ContentCaptureManagerService(Context context) {
+ super(context, UserManager.DISALLOW_CONTENT_CAPTURE);
}
@Override // from AbstractMasterSystemService
- protected IntelligencePerUserService newServiceLocked(@UserIdInt int resolvedUserId,
+ protected ContentCapturePerUserService newServiceLocked(@UserIdInt int resolvedUserId,
boolean disabled) {
- return new IntelligencePerUserService(this, mLock, resolvedUserId);
+ return new ContentCapturePerUserService(this, mLock, resolvedUserId);
}
@Override // from SystemService
public void onStart() {
publishBinderService(CONTENT_CAPTURE_MANAGER_SERVICE,
- new IntelligenceManagerServiceStub());
- publishLocalService(IntelligenceManagerInternal.class, mLocalService);
+ new ContentCaptureManagerServiceStub());
+ publishLocalService(ContentCaptureManagerInternal.class, mLocalService);
}
@Override // from AbstractMasterSystemService
- protected void onServiceRemoved(@NonNull IntelligencePerUserService service,
+ protected void onServiceRemoved(@NonNull ContentCapturePerUserService service,
@UserIdInt int userId) {
service.destroyLocked();
}
@Override // from AbstractMasterSystemService
protected void enforceCallingPermissionForManagement() {
- getContext().enforceCallingPermission(MANAGE_SMART_SUGGESTIONS, TAG);
+ getContext().enforceCallingPermission(MANAGE_CONTENT_CAPTURE, TAG);
}
@Override // from AbstractMasterSystemService
@@ -113,7 +108,7 @@
synchronized (mLock) {
if (userId != UserHandle.USER_ALL) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
service.destroySessionsLocked();
}
@@ -139,7 +134,7 @@
synchronized (mLock) {
if (userId != UserHandle.USER_ALL) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
service.listSessionsLocked(sessions);
}
@@ -165,11 +160,11 @@
return mAm;
}
- final class IntelligenceManagerServiceStub extends IIntelligenceManager.Stub {
+ final class ContentCaptureManagerServiceStub extends IContentCaptureManager.Stub {
@Override
public void startSession(@UserIdInt int userId, @NonNull IBinder activityToken,
- @NonNull ComponentName componentName, @NonNull InteractionSessionId sessionId,
+ @NonNull ComponentName componentName, @NonNull String sessionId,
int flags, @NonNull IResultReceiver result) {
Preconditions.checkNotNull(activityToken);
Preconditions.checkNotNull(componentName);
@@ -183,31 +178,31 @@
final int displayId = 0;
synchronized (mLock) {
- final IntelligencePerUserService service = getServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = getServiceForUserLocked(userId);
service.startSessionLocked(activityToken, componentName, taskId, displayId,
sessionId, flags, mAllowInstantService, result);
}
}
@Override
- public void sendEvents(@UserIdInt int userId, @NonNull InteractionSessionId sessionId,
+ public void sendEvents(@UserIdInt int userId, @NonNull String sessionId,
@NonNull List<ContentCaptureEvent> events) {
Preconditions.checkNotNull(sessionId);
Preconditions.checkNotNull(events);
synchronized (mLock) {
- final IntelligencePerUserService service = getServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = getServiceForUserLocked(userId);
service.sendEventsLocked(sessionId, events);
}
}
@Override
- public void finishSession(@UserIdInt int userId, @NonNull InteractionSessionId sessionId,
+ public void finishSession(@UserIdInt int userId, @NonNull String sessionId,
@Nullable List<ContentCaptureEvent> events) {
Preconditions.checkNotNull(sessionId);
synchronized (mLock) {
- final IntelligencePerUserService service = getServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = getServiceForUserLocked(userId);
service.finishSessionLocked(sessionId, events);
}
}
@@ -225,19 +220,19 @@
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback, ResultReceiver resultReceiver)
throws RemoteException {
- new IntelligenceServiceShellCommand(IntelligenceManagerService.this).exec(
+ new ContentCaptureManagerServiceShellCommand(ContentCaptureManagerService.this).exec(
this, in, out, err, args, callback, resultReceiver);
}
}
- private final class LocalService extends IntelligenceManagerInternal {
+ private final class LocalService extends ContentCaptureManagerInternal {
@Override
- public boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId) {
+ public boolean isContentCaptureServiceForUser(int uid, @UserIdInt int userId) {
synchronized (mLock) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
- return service.isIntelligenceServiceForUserLocked(uid);
+ return service.isContentCaptureServiceForUserLocked(uid);
}
}
return false;
@@ -247,27 +242,12 @@
public boolean sendActivityAssistData(@UserIdInt int userId, @NonNull IBinder activityToken,
@NonNull Bundle data) {
synchronized (mLock) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
if (service != null) {
return service.sendActivityAssistDataLocked(activityToken, data);
}
}
return false;
}
-
- @Override
- public AugmentedAutofillCallback requestAutofill(@UserIdInt int userId,
- @NonNull IAutoFillManagerClient client, @NonNull IBinder activityToken,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- synchronized (mLock) {
- final IntelligencePerUserService service = peekServiceForUserLocked(userId);
- if (service != null) {
- return service.requestAutofill(client, activityToken, autofillSessionId,
- focusedId, focusedValue);
- }
- }
- return null;
- }
}
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
similarity index 89%
rename from services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
index 0d92a97..2f78276 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligenceServiceShellCommand.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerServiceShellCommand.java
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
-import static com.android.server.intelligence.IntelligenceManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS;
+import static com.android.server.contentcapture.ContentCaptureManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS;
import android.annotation.NonNull;
import android.os.Bundle;
@@ -30,14 +30,13 @@
import java.util.concurrent.TimeUnit;
/**
- * Shell Command implementation for {@link IntelligenceManagerService}.
+ * Shell Command implementation for {@link ContentCaptureManagerService}.
*/
-//TODO(b/111276913): rename once the final name is defined
-public final class IntelligenceServiceShellCommand extends ShellCommand {
+public final class ContentCaptureManagerServiceShellCommand extends ShellCommand {
- private final IntelligenceManagerService mService;
+ private final ContentCaptureManagerService mService;
- public IntelligenceServiceShellCommand(@NonNull IntelligenceManagerService service) {
+ public ContentCaptureManagerServiceShellCommand(@NonNull ContentCaptureManagerService service) {
mService = service;
}
@@ -64,8 +63,7 @@
@Override
public void onHelp() {
try (PrintWriter pw = getOutPrintWriter();) {
- // TODO(b/111276913): rename "intelligence" once SELinux rule changed
- pw.println("Intelligence Service (intelligence) commands:");
+ pw.println("ContentCapture Service (content_capture) commands:");
pw.println(" help");
pw.println(" Prints this help text.");
pw.println("");
@@ -106,7 +104,7 @@
case "bind-instant-service-allowed":
return setBindInstantService(pw);
case "temporary-service":
- return setTemporaryService();
+ return setTemporaryService(pw);
default:
pw.println("Invalid set: " + what);
return -1;
@@ -137,7 +135,7 @@
}
}
- private int setTemporaryService() {
+ private int setTemporaryService(PrintWriter pw) {
final int userId = getNextIntArgRequired();
final String serviceName = getNextArg();
if (serviceName == null) {
@@ -146,6 +144,8 @@
}
final int duration = getNextIntArgRequired();
mService.setTemporaryService(userId, serviceName, duration);
+ pw.println("ContentCaptureService temporarily set to " + serviceName + " for "
+ + duration + "ms");
return 0;
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
similarity index 77%
rename from services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index e2b8d48..aa171f4 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
@@ -34,46 +34,40 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SnapshotData;
+import android.service.contentcapture.SnapshotData;
import android.util.ArrayMap;
import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-import android.view.intelligence.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
import com.android.server.infra.AbstractPerUserSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
- * Per-user instance of {@link IntelligenceManagerService}.
+ * Per-user instance of {@link ContentCaptureManagerService}.
*/
-//TODO(b/111276913): rename once the final name is defined
-final class IntelligencePerUserService
- extends AbstractPerUserSystemService<IntelligencePerUserService,
- IntelligenceManagerService> {
+final class ContentCapturePerUserService
+ extends
+ AbstractPerUserSystemService<ContentCapturePerUserService, ContentCaptureManagerService> {
- private static final String TAG = "IntelligencePerUserService";
+ private static final String TAG = ContentCaptureManagerService.class.getSimpleName();
@GuardedBy("mLock")
- private final ArrayMap<InteractionSessionId, ContentCaptureSession> mSessions =
+ private final ArrayMap<String, ContentCaptureSession> mSessions =
new ArrayMap<>();
// TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
- protected IntelligencePerUserService(
- IntelligenceManagerService master, Object lock, @UserIdInt int userId) {
+ protected ContentCapturePerUserService(
+ ContentCaptureManagerService master, Object lock, @UserIdInt int userId) {
super(master, new FrameworkResourcesServiceNameResolver(master.getContext(), userId, lock,
- com.android.internal.R.string.config_defaultSmartSuggestionsService), lock, userId);
+ com.android.internal.R.string.config_defaultContentCaptureService), lock, userId);
}
@Override // from PerUserSystemService
@@ -98,12 +92,12 @@
+ " " + serviceComponent.flattenToShortString());
return null;
}
- if (!Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE.equals(si.permission)) {
- Slog.w(TAG, "SmartSuggestionsService from '" + si.packageName
+ if (!Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE.equals(si.permission)) {
+ Slog.w(TAG, "ContentCaptureService from '" + si.packageName
+ "' does not require permission "
- + Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE);
+ + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
throw new SecurityException("Service does not require permission "
- + Manifest.permission.BIND_SMART_SUGGESTIONS_SERVICE);
+ + Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE);
}
return si;
}
@@ -119,7 +113,7 @@
@GuardedBy("mLock")
public void startSessionLocked(@NonNull IBinder activityToken,
@NonNull ComponentName componentName, int taskId, int displayId,
- @NonNull InteractionSessionId sessionId, int flags, boolean bindInstantServiceAllowed,
+ @NonNull String sessionId, int flags, boolean bindInstantServiceAllowed,
@NonNull IResultReceiver resultReceiver) {
if (!isEnabledLocked()) {
sendToClient(resultReceiver, ContentCaptureManager.STATE_DISABLED);
@@ -163,7 +157,7 @@
// TODO(b/111276913): log metrics
@GuardedBy("mLock")
- public void finishSessionLocked(@NonNull InteractionSessionId sessionId,
+ public void finishSessionLocked(@NonNull String sessionId,
@Nullable List<ContentCaptureEvent> events) {
if (!isEnabledLocked()) {
return;
@@ -180,7 +174,7 @@
// TODO(b/111276913): for now we're sending the events and the onDestroy() in 2 separate
// calls because it's not clear yet whether we'll change the manager to send events
// to the service directly (i.e., without passing through system server). Once we
- // decide, we might need to split IIntelligenceService.onSessionLifecycle() in 2
+ // decide, we might need to split IContentCaptureManager.onSessionLifecycle() in 2
// methods, one for start and another for finish (and passing the events to finish),
// otherwise the service might receive the 2 calls out of order.
session.sendEventsLocked(events);
@@ -193,9 +187,9 @@
}
// TODO(b/111276913): need to figure out why some events are sent before session is started;
- // probably because IntelligenceManager is not buffering them until it gets the session back
+ // probably because ContentCaptureManager is not buffering them until it gets the session back
@GuardedBy("mLock")
- public void sendEventsLocked(@NonNull InteractionSessionId sessionId,
+ public void sendEventsLocked(@NonNull String sessionId,
@NonNull List<ContentCaptureEvent> events) {
if (!isEnabledLocked()) {
return;
@@ -216,7 +210,7 @@
@GuardedBy("mLock")
public boolean sendActivityAssistDataLocked(@NonNull IBinder activityToken,
@NonNull Bundle data) {
- final InteractionSessionId id = getInteractionSessionId(activityToken);
+ final String id = getSessionId(activityToken);
if (id != null) {
final ContentCaptureSession session = mSessions.get(id);
final Bundle assistData = data.getBundle(ASSIST_KEY_DATA);
@@ -233,12 +227,12 @@
}
@GuardedBy("mLock")
- public void removeSessionLocked(@NonNull InteractionSessionId sessionId) {
+ public void removeSessionLocked(@NonNull String sessionId) {
mSessions.remove(sessionId);
}
@GuardedBy("mLock")
- public boolean isIntelligenceServiceForUserLocked(int uid) {
+ public boolean isContentCaptureServiceForUserLocked(int uid) {
return uid == getServiceUidLocked();
}
@@ -283,24 +277,6 @@
}
}
- public AugmentedAutofillCallback requestAutofill(@NonNull IAutoFillManagerClient client,
- @NonNull IBinder activityToken, int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- synchronized (mLock) {
- final ContentCaptureSession session = getSession(activityToken);
- if (session != null) {
- // TODO(b/111330312): log metrics
- if (mMaster.verbose) Slog.v(TAG, "requestAugmentedAutofill()");
- return session.requestAutofillLocked(client, autofillSessionId, focusedId,
- focusedValue);
- }
- if (mMaster.debug) {
- Slog.d(TAG, "requestAutofill(): no session for " + activityToken);
- }
- return null;
- }
- }
-
@Override
protected void dumpLocked(String prefix, PrintWriter pw) {
super.dumpLocked(prefix, pw);
@@ -319,10 +295,10 @@
}
/**
- * Returns the InteractionSessionId associated with the given activity.
+ * Returns the session id associated with the given activity.
*/
@GuardedBy("mLock")
- private InteractionSessionId getInteractionSessionId(@NonNull IBinder activityToken) {
+ private String getSessionId(@NonNull IBinder activityToken) {
for (int i = 0; i < mSessions.size(); i++) {
ContentCaptureSession session = mSessions.valueAt(i);
if (session.isActivitySession(activityToken)) {
diff --git a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
similarity index 63%
rename from services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
rename to services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
index 05b8201..2302b7d 100644
--- a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureSession.java
@@ -13,55 +13,49 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.intelligence;
+package com.android.server.contentcapture;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.os.IBinder;
-import android.service.intelligence.InteractionContext;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SmartSuggestionsService;
-import android.service.intelligence.SnapshotData;
+import android.service.contentcapture.ContentCaptureService;
+import android.service.contentcapture.InteractionContext;
+import android.service.contentcapture.InteractionSessionId;
+import android.service.contentcapture.SnapshotData;
import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureEvent;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
+import com.android.server.contentcapture.RemoteContentCaptureService.ContentCaptureServiceCallbacks;
import com.android.server.infra.AbstractRemoteService;
-import com.android.server.intelligence.IntelligenceManagerInternal.AugmentedAutofillCallback;
-import com.android.server.intelligence.RemoteIntelligenceService.RemoteIntelligenceServiceCallbacks;
import java.io.PrintWriter;
import java.util.List;
-final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks {
+final class ContentCaptureSession implements ContentCaptureServiceCallbacks {
private static final String TAG = "ContentCaptureSession";
private final Object mLock;
final IBinder mActivityToken;
- private final IntelligencePerUserService mService;
- private final RemoteIntelligenceService mRemoteService;
+ private final ContentCapturePerUserService mService;
+ private final RemoteContentCaptureService mRemoteService;
private final InteractionContext mInterationContext;
- private final InteractionSessionId mId;
- private AugmentedAutofillCallback mAutofillCallback;
+ private final String mId;
ContentCaptureSession(@NonNull Context context, int userId, @NonNull Object lock,
- @NonNull IBinder activityToken, @NonNull IntelligencePerUserService service,
+ @NonNull IBinder activityToken, @NonNull ContentCapturePerUserService service,
@NonNull ComponentName serviceComponentName, @NonNull ComponentName appComponentName,
- int taskId, int displayId, @NonNull InteractionSessionId sessionId, int flags,
+ int taskId, int displayId, @NonNull String sessionId, int flags,
boolean bindInstantServiceAllowed, boolean verbose) {
mLock = lock;
mActivityToken = activityToken;
mService = service;
mId = Preconditions.checkNotNull(sessionId);
- mRemoteService = new RemoteIntelligenceService(context,
- SmartSuggestionsService.SERVICE_INTERFACE, serviceComponentName, userId, this,
+ mRemoteService = new RemoteContentCaptureService(context,
+ ContentCaptureService.SERVICE_INTERFACE, serviceComponentName, userId, this,
bindInstantServiceAllowed, verbose);
mInterationContext = new InteractionContext(appComponentName, taskId, displayId, flags);
}
@@ -74,7 +68,7 @@
}
/**
- * Notifies the {@link SmartSuggestionsService} that the service started.
+ * Notifies the {@link ContentCaptureService} that the service started.
*/
@GuardedBy("mLock")
public void notifySessionStartedLocked() {
@@ -82,14 +76,14 @@
}
/**
- * Notifies the {@link SmartSuggestionsService} of a batch of events.
+ * Notifies the {@link ContentCaptureService} of a batch of events.
*/
public void sendEventsLocked(@NonNull List<ContentCaptureEvent> events) {
mRemoteService.onContentCaptureEventsRequest(mId, events);
}
/**
- * Notifies the {@link SmartSuggestionsService} of a snapshot of an activity.
+ * Notifies the {@link ContentCaptureService} of a snapshot of an activity.
*/
@GuardedBy("mLock")
public void sendActivitySnapshotLocked(@NonNull SnapshotData snapshotData) {
@@ -97,24 +91,10 @@
}
/**
- * Requests the service to autofill the given field.
- */
- public AugmentedAutofillCallback requestAutofillLocked(@NonNull IAutoFillManagerClient client,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- mRemoteService.onRequestAutofillLocked(mId, client, autofillSessionId, focusedId,
- focusedValue);
- if (mAutofillCallback == null) {
- mAutofillCallback = () -> mRemoteService.onDestroyAutofillWindowsRequest(mId);
- }
- return mAutofillCallback;
- }
-
- /**
* Cleans up the session and removes it from the service.
*
* @param notifyRemoteService whether it should trigger a {@link
- * SmartSuggestionsService#onDestroyInteractionSession(InteractionSessionId)}
+ * ContentCaptureService#onDestroyInteractionSession(InteractionSessionId)}
* request.
*/
@GuardedBy("mLock")
@@ -130,7 +110,7 @@
* Cleans up the session, but not removes it from the service.
*
* @param notifyRemoteService whether it should trigger a {@link
- * SmartSuggestionsService#onDestroyInteractionSession(InteractionSessionId)}
+ * ContentCaptureService#onDestroyInteractionSession(InteractionSessionId)}
* request.
*/
@GuardedBy("mLock")
@@ -138,11 +118,6 @@
if (mService.isVerbose()) {
Slog.v(TAG, "destroyLocked(notifyRemoteService=" + notifyRemoteService + ")");
}
- if (mAutofillCallback != null) {
- mAutofillCallback.destroy();
- mAutofillCallback = null;
- }
-
// TODO(b/111276913): must call client to set session as FINISHED_BY_SERVER
if (notifyRemoteService) {
mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
@@ -173,19 +148,18 @@
@GuardedBy("mLock")
public void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
- pw.print(prefix); pw.print("id: "); mId.dump(pw); pw.println();
+ pw.print(prefix); pw.print("id: "); pw.print(mId); pw.println();
pw.print(prefix); pw.print("context: "); mInterationContext.dump(pw); pw.println();
pw.print(prefix); pw.print("activity token: "); pw.println(mActivityToken);
pw.print(prefix); pw.print("has autofill callback: ");
- pw.println(mAutofillCallback != null);
}
String toShortString() {
- return mId.getValue() + ":" + mActivityToken;
+ return mId + ":" + mActivityToken;
}
@Override
public String toString() {
- return "ContentCaptureSession[id=" + mId.getValue() + ", act=" + mActivityToken + "]";
+ return "ContentCaptureSession[id=" + mId + ", act=" + mActivityToken + "]";
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
new file mode 100644
index 0000000..6a111f2
--- /dev/null
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.service.contentcapture.ContentCaptureEventsRequest;
+import android.service.contentcapture.IContentCaptureService;
+import android.service.contentcapture.InteractionContext;
+import android.service.contentcapture.SnapshotData;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.contentcapture.ContentCaptureEvent;
+
+import com.android.server.infra.AbstractMultiplePendingRequestsRemoteService;
+
+import java.util.List;
+
+final class RemoteContentCaptureService
+ extends AbstractMultiplePendingRequestsRemoteService<RemoteContentCaptureService> {
+
+ private static final String TAG = RemoteContentCaptureService.class.getSimpleName();
+
+ // TODO(b/117779333): changed it so it's permanentely bound
+ private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
+ private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
+
+ private final ContentCaptureServiceCallbacks mCallbacks;
+ private IContentCaptureService mService;
+
+ RemoteContentCaptureService(Context context, String serviceInterface,
+ ComponentName componentName, int userId,
+ ContentCaptureServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
+ boolean verbose) {
+ super(context, serviceInterface, componentName, userId, callbacks,
+ bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
+ mCallbacks = callbacks;
+ }
+
+ @Override // from RemoteService
+ protected IInterface getServiceInterface(@NonNull IBinder service) {
+ mService = IContentCaptureService.Stub.asInterface(service);
+ return mService;
+ }
+
+ // TODO(b/111276913): modify super class to allow permanent binding when value is 0 or negative
+ @Override // from RemoteService
+ protected long getTimeoutIdleBindMillis() {
+ // TODO(b/111276913): read from Settings so it can be changed in the field
+ return TIMEOUT_IDLE_BIND_MILLIS;
+ }
+
+ @Override // from RemoteService
+ protected long getRemoteRequestMillis() {
+ // TODO(b/111276913): read from Settings so it can be changed in the field
+ return TIMEOUT_REMOTE_REQUEST_MILLIS;
+ }
+
+ /**
+ * Called by {@link ContentCaptureSession} to generate a call to the
+ * {@link RemoteContentCaptureService} to indicate the session was created (when {@code context}
+ * is not {@code null} or destroyed (when {@code context} is {@code null}).
+ */
+ public void onSessionLifecycleRequest(@Nullable InteractionContext context,
+ @NonNull String sessionId) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingSessionLifecycleRequest(this, context, sessionId));
+ }
+
+ /**
+ * Called by {@link ContentCaptureSession} to send a batch of events to the service.
+ */
+ public void onContentCaptureEventsRequest(@NonNull String sessionId,
+ @NonNull List<ContentCaptureEvent> events) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingOnContentCaptureEventsRequest(this, sessionId, events));
+ }
+
+ /**
+ * Called by {@link ContentCaptureSession} to send snapshot data to the service.
+ */
+ public void onActivitySnapshotRequest(@NonNull String sessionId,
+ @NonNull SnapshotData snapshotData) {
+ cancelScheduledUnbind();
+ scheduleRequest(new PendingOnActivitySnapshotRequest(this, sessionId, snapshotData));
+ }
+
+ private abstract static class MyPendingRequest
+ extends PendingRequest<RemoteContentCaptureService> {
+ protected final String mSessionId;
+
+ private MyPendingRequest(@NonNull RemoteContentCaptureService service,
+ @NonNull String sessionId) {
+ super(service);
+ mSessionId = sessionId;
+ }
+
+ @Override // from PendingRequest
+ protected final void onTimeout(RemoteContentCaptureService remoteService) {
+ Slog.w(TAG, "timed out handling " + getClass().getSimpleName() + " for "
+ + mSessionId);
+ remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ true);
+ }
+
+ @Override // from PendingRequest
+ public final void run() {
+ final RemoteContentCaptureService remoteService = getService();
+ if (remoteService != null) {
+ try {
+ // We don't expect the service to call us back, so we finish right away.
+ myRun(remoteService);
+ // TODO(b/111330312): not true anymore!!
+ finish();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "exception handling " + getClass().getSimpleName() + " for "
+ + mSessionId + ": " + e);
+ remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ false);
+ }
+ }
+ }
+
+ protected abstract void myRun(@NonNull RemoteContentCaptureService service)
+ throws RemoteException;
+
+ }
+
+ private static final class PendingSessionLifecycleRequest extends MyPendingRequest {
+
+ private final InteractionContext mContext;
+
+ protected PendingSessionLifecycleRequest(@NonNull RemoteContentCaptureService service,
+ @Nullable InteractionContext context, @NonNull String sessionId) {
+ super(service, sessionId);
+ mContext = context;
+ }
+
+ @Override // from MyPendingRequest
+ public void myRun(@NonNull RemoteContentCaptureService remoteService)
+ throws RemoteException {
+ remoteService.mService.onSessionLifecycle(mContext, mSessionId);
+ }
+ }
+
+ private static final class PendingOnContentCaptureEventsRequest extends MyPendingRequest {
+
+ private final List<ContentCaptureEvent> mEvents;
+
+ protected PendingOnContentCaptureEventsRequest(@NonNull RemoteContentCaptureService service,
+ @NonNull String sessionId, @NonNull List<ContentCaptureEvent> events) {
+ super(service, sessionId);
+ mEvents = events;
+ }
+
+ @Override // from MyPendingRequest
+ public void myRun(@NonNull RemoteContentCaptureService remoteService)
+ throws RemoteException {
+ remoteService.mService.onContentCaptureEventsRequest(mSessionId,
+ new ContentCaptureEventsRequest(mEvents));
+ }
+ }
+
+ private static final class PendingOnActivitySnapshotRequest extends MyPendingRequest {
+
+ private final SnapshotData mSnapshotData;
+
+ protected PendingOnActivitySnapshotRequest(@NonNull RemoteContentCaptureService service,
+ @NonNull String sessionId, @NonNull SnapshotData snapshotData) {
+ super(service, sessionId);
+ mSnapshotData = snapshotData;
+ }
+
+ @Override // from MyPendingRequest
+ protected void myRun(@NonNull RemoteContentCaptureService remoteService)
+ throws RemoteException {
+ remoteService.mService.onActivitySnapshot(mSessionId, mSnapshotData);
+ }
+ }
+
+ public interface ContentCaptureServiceCallbacks extends VultureCallback {
+ // To keep it simple, we use the same callback for all failures / timeouts.
+ void onFailureOrTimeout(boolean timedOut);
+ }
+}
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 65537ad..258c325 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -55,7 +55,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.intelligence.IntelligenceManagerInternal;
+import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -158,7 +158,7 @@
private final IUserManager mUm;
private final PackageManager mPm;
private final AppOpsManager mAppOps;
- private final IntelligenceManagerInternal mIm;
+ private final ContentCaptureManagerInternal mContentCaptureInternal;
private final IBinder mPermissionOwner;
private HostClipboardMonitor mHostClipboardMonitor = null;
private Thread mHostMonitorThread = null;
@@ -178,7 +178,7 @@
mPm = getContext().getPackageManager();
mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
- mIm = LocalServices.getService(IntelligenceManagerInternal.class);
+ mContentCaptureInternal = LocalServices.getService(ContentCaptureManagerInternal.class);
final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
mPermissionOwner = permOwner;
if (IS_EMULATOR) {
@@ -652,9 +652,10 @@
case AppOpsManager.OP_READ_CLIPBOARD:
// Clipboard can only be read by applications with focus..
boolean allowed = mWm.isUidFocused(callingUid);
- if (!allowed && mIm != null) {
+ if (!allowed && mContentCaptureInternal != null) {
// ...or the Intelligence Service
- allowed = mIm.isIntelligenceServiceForUser(callingUid, userId);
+ allowed = mContentCaptureInternal.isContentCaptureServiceForUser(callingUid,
+ userId);
}
if (!allowed) {
Slog.e(TAG, "Denying clipboard access to " + callingPackage
diff --git a/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java b/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java
new file mode 100644
index 0000000..726362a
--- /dev/null
+++ b/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.os.Bundle;
+import android.os.IBinder;
+
+/**
+ * ContentCapture Manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class ContentCaptureManagerInternal {
+
+ /**
+ * Checks whether the given {@code uid} owns the
+ * {@link android.service.contentcapture.ContentCaptureService} implementation associated with
+ * the given {@code userId}.
+ */
+ public abstract boolean isContentCaptureServiceForUser(int uid, @UserIdInt int userId);
+
+ /**
+ * Notifies the intelligence service of new assist data for the given activity.
+ *
+ * @return {@code false} if there was no service set for the given user
+ */
+ public abstract boolean sendActivityAssistData(@UserIdInt int userId,
+ @NonNull IBinder activityToken, @NonNull Bundle data);
+}
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index ef9ad8a..c0c4a6e 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -58,7 +58,7 @@
* <ul>
* <li>Disabling the service when {@link UserManager} restrictions change.
* <li>Refreshing the service when its underlying
- * {@link #getSettingsProperty() Settings property} changed.
+ * {@link #getServiceSettingsProperty() Settings property} changed.
* <li>Calling the service when other Settings properties changed.
* </ul>
*
diff --git a/services/core/java/com/android/server/infra/AbstractRemoteService.java b/services/core/java/com/android/server/infra/AbstractRemoteService.java
index 7af1d4c..67b3ecf 100644
--- a/services/core/java/com/android/server/infra/AbstractRemoteService.java
+++ b/services/core/java/com/android/server/infra/AbstractRemoteService.java
@@ -248,7 +248,7 @@
if (checkIfDestroyed() || mCompleted) return;
if (!handleIsBound()) {
- if (mVerbose) Slog.v(mTag, "handlePendingRequest(): queuing" + pendingRequest);
+ if (mVerbose) Slog.v(mTag, "handlePendingRequest(): queuing " + pendingRequest);
handlePendingRequestWhileUnBound(pendingRequest);
handleEnsureBound();
} else {
@@ -379,6 +379,7 @@
final S remoteService = mWeakService.get();
if (remoteService != null) {
+ // TODO(b/117779333): we should probably ignore it if service is destroyed.
Slog.w(mTag, "timed out after " + service.getRemoteRequestMillis() + " ms");
onTimeout(remoteService);
} else {
diff --git a/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java b/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
index 8f8b448..37a1f54 100644
--- a/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
+++ b/services/core/java/com/android/server/infra/AbstractSinglePendingRequestRemoteService.java
@@ -73,7 +73,8 @@
void handlePendingRequestWhileUnBound(@NonNull PendingRequest<S> pendingRequest) {
if (mPendingRequest != null) {
if (mVerbose) {
- Slog.v(mTag, "handlePendingRequestWhileUnBound(): cancelling " + mPendingRequest);
+ Slog.v(mTag, "handlePendingRequestWhileUnBound(): cancelling " + mPendingRequest
+ + " to handle " + pendingRequest);
}
mPendingRequest.cancel();
}
diff --git a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
deleted file mode 100644
index f424869..0000000
--- a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.intelligence;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UserIdInt;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-
-/**
- * Intelligence Manager local system service interface.
- *
- * @hide Only for use within the system server.
- */
-//TODO(b/111276913): rename once the final name is defined
-public abstract class IntelligenceManagerInternal {
-
- /**
- * Checks whether the given {@code uid} owns the
- * {@link android.service.intelligence.SmartSuggestionsService} implementation associated with
- * the given {@code userId}.
- */
- public abstract boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId);
-
- /**
- * Notifies the intelligence service of new assist data for the given activity.
- *
- * @return {@code false} if there was no service set for the given user
- */
- public abstract boolean sendActivityAssistData(@UserIdInt int userId,
- @NonNull IBinder activityToken, @NonNull Bundle data);
-
- /**
- * Asks the intelligence service to provide Augmented Autofill for a given activity.
- *
- * @param userId user handle
- * @param client binder used to communicate with the activity that originated this request.
- * @param activityToken activity that originated this request.
- * @param autofillSessionId autofill session id (must be used on {@code client} calls.
- * @param focusedId id of the the field that triggered this request.
- * @param focusedValue current value of the field that triggered this request.
- *
- * @return {@code false} if the service cannot handle this request, {@code true} otherwise.
- * <b>NOTE: </b> it must return right away; typically it will return {@code false} if the
- * service is disabled (or the activity blacklisted).
- */
- public abstract AugmentedAutofillCallback requestAutofill(@UserIdInt int userId,
- @NonNull IAutoFillManagerClient client, @NonNull IBinder activityToken,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue);
-
- /**
- * Callback used by the Autofill Session to communicate with the Augmented Autofill service.
- */
- public interface AugmentedAutofillCallback {
- // TODO(b/111330312): this method is calling when the Autofill session is destroyed, the
- // main reason being the cases where user tap HOME.
- // Right now it's completely destroying the UI, but we need to decide whether / how to
- // properly recover it later (for example, if the user switches back to the activity,
- // should it be restored? Right not it kind of is, because Autofill's Session trigger a
- // new FillRequest, which in turn triggers the Augmented Autofill request again)
- /**
- * Destroys the Autofill UI.
- */
- void destroy();
- }
-}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 1e287b4..9422182 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -47,7 +47,7 @@
import com.android.server.LocalServices;
import com.android.server.am.AssistDataRequester;
-import com.android.server.intelligence.IntelligenceManagerInternal;
+import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
import java.util.List;
@@ -225,8 +225,8 @@
public void onAssistDataReceivedLocked(Bundle data, int activityIndex,
int activityCount) {
// Try to notify the intelligence service first
- final IntelligenceManagerInternal imService =
- LocalServices.getService(IntelligenceManagerInternal.class);
+ final ContentCaptureManagerInternal imService =
+ LocalServices.getService(ContentCaptureManagerInternal.class);
final IBinder activityToken = topActivities.get(activityIndex);
if (imService == null
|| !imService.sendActivityAssistData(userId, activityToken, data)) {
@@ -236,8 +236,8 @@
}
};
} else {
- final IntelligenceManagerInternal imService =
- LocalServices.getService(IntelligenceManagerInternal.class);
+ final ContentCaptureManagerInternal imService =
+ LocalServices.getService(ContentCaptureManagerInternal.class);
if (imService == null) {
// There is no intelligence service, so there is no point requesting assist data
return;
diff --git a/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java b/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
deleted file mode 100644
index c4fbdca..0000000
--- a/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.intelligence;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.service.intelligence.ContentCaptureEventsRequest;
-import android.service.intelligence.IIntelligenceService;
-import android.service.intelligence.InteractionContext;
-import android.service.intelligence.InteractionSessionId;
-import android.service.intelligence.SnapshotData;
-import android.text.format.DateUtils;
-import android.util.Slog;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillManager;
-import android.view.autofill.AutofillValue;
-import android.view.autofill.IAutoFillManagerClient;
-import android.view.intelligence.ContentCaptureEvent;
-
-import com.android.internal.os.IResultReceiver;
-import com.android.server.infra.AbstractMultiplePendingRequestsRemoteService;
-
-import java.util.List;
-
-//TODO(b/111276913): rename once the final name is defined
-final class RemoteIntelligenceService
- extends AbstractMultiplePendingRequestsRemoteService<RemoteIntelligenceService> {
-
- private static final String TAG = "RemoteIntelligenceService";
-
- private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
- private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
-
- private final RemoteIntelligenceServiceCallbacks mCallbacks;
- private IIntelligenceService mService;
-
- RemoteIntelligenceService(Context context, String serviceInterface,
- ComponentName componentName, int userId,
- RemoteIntelligenceServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
- boolean verbose) {
- super(context, serviceInterface, componentName, userId, callbacks,
- bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
- mCallbacks = callbacks;
- }
-
- @Override // from RemoteService
- protected IInterface getServiceInterface(@NonNull IBinder service) {
- mService = IIntelligenceService.Stub.asInterface(service);
- return mService;
- }
-
- // TODO(b/111276913): modify super class to allow permanent binding when value is 0 or negative
- @Override // from RemoteService
- protected long getTimeoutIdleBindMillis() {
- // TODO(b/111276913): read from Settings so it can be changed in the field
- return TIMEOUT_IDLE_BIND_MILLIS;
- }
-
- @Override // from RemoteService
- protected long getRemoteRequestMillis() {
- // TODO(b/111276913): read from Settings so it can be changed in the field
- return TIMEOUT_REMOTE_REQUEST_MILLIS;
- }
-
- /**
- * Called by {@link ContentCaptureSession} to generate a call to the
- * {@link RemoteIntelligenceService} to indicate the session was created (when {@code context}
- * is not {@code null} or destroyed (when {@code context} is {@code null}).
- */
- public void onSessionLifecycleRequest(@Nullable InteractionContext context,
- @NonNull InteractionSessionId sessionId) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingSessionLifecycleRequest(this, context, sessionId));
- }
-
- /**
- * Called by {@link ContentCaptureSession} to send a batch of events to the service.
- */
- public void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
- @NonNull List<ContentCaptureEvent> events) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingOnContentCaptureEventsRequest(this, sessionId, events));
- }
-
- /**
- * Called by {@link ContentCaptureSession} to send snapshot data to the service.
- */
- public void onActivitySnapshotRequest(@NonNull InteractionSessionId sessionId,
- @NonNull SnapshotData snapshotData) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingOnActivitySnapshotRequest(this, sessionId, snapshotData));
- }
-
- /**
- * Called by {@link ContentCaptureSession} to request augmented autofill.
- */
- public void onRequestAutofillLocked(@NonNull InteractionSessionId sessionId,
- @NonNull IAutoFillManagerClient client, int autofillSessionId,
- @NonNull AutofillId focusedId, @Nullable AutofillValue focusedValue) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingAutofillRequest(this, sessionId, client, autofillSessionId,
- focusedId, focusedValue));
- }
-
- /**
- * Called by {@link ContentCaptureSession} when it's time to destroy all augmented autofill
- * requests.
- */
- public void onDestroyAutofillWindowsRequest(@NonNull InteractionSessionId sessionId) {
- cancelScheduledUnbind();
- scheduleRequest(new PendingDestroyAutofillWindowsRequest(this, sessionId));
- }
-
- private abstract static class MyPendingRequest
- extends PendingRequest<RemoteIntelligenceService> {
- protected final InteractionSessionId mSessionId;
-
- private MyPendingRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId) {
- super(service);
- mSessionId = sessionId;
- }
-
- @Override // from PendingRequest
- protected final void onTimeout(RemoteIntelligenceService remoteService) {
- Slog.w(TAG, "timed out handling " + getClass().getSimpleName() + " for "
- + mSessionId);
- remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ true);
- }
-
- @Override // from PendingRequest
- public final void run() {
- final RemoteIntelligenceService remoteService = getService();
- if (remoteService != null) {
- try {
- // We don't expect the service to call us back, so we finish right away.
- myRun(remoteService);
- // TODO(b/111330312): not true anymore!!
- finish();
- } catch (RemoteException e) {
- Slog.w(TAG, "exception handling " + getClass().getSimpleName() + " for "
- + mSessionId + ": " + e);
- remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ false);
- }
- }
- }
-
- protected abstract void myRun(@NonNull RemoteIntelligenceService service)
- throws RemoteException;
-
- }
-
- private static final class PendingSessionLifecycleRequest extends MyPendingRequest {
-
- private final InteractionContext mContext;
-
- protected PendingSessionLifecycleRequest(@NonNull RemoteIntelligenceService service,
- @Nullable InteractionContext context, @NonNull InteractionSessionId sessionId) {
- super(service, sessionId);
- mContext = context;
- }
-
- @Override // from MyPendingRequest
- public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
- remoteService.mService.onSessionLifecycle(mContext, mSessionId);
- }
- }
-
- private static final class PendingOnContentCaptureEventsRequest extends MyPendingRequest {
-
- private final List<ContentCaptureEvent> mEvents;
-
- protected PendingOnContentCaptureEventsRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId,
- @NonNull List<ContentCaptureEvent> events) {
- super(service, sessionId);
- mEvents = events;
- }
-
- @Override // from MyPendingRequest
- public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
- remoteService.mService.onContentCaptureEventsRequest(mSessionId,
- new ContentCaptureEventsRequest(mEvents));
- }
- }
-
- private static final class PendingOnActivitySnapshotRequest extends MyPendingRequest {
-
- private final SnapshotData mSnapshotData;
-
- protected PendingOnActivitySnapshotRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId,
- @NonNull SnapshotData snapshotData) {
- super(service, sessionId);
- mSnapshotData = snapshotData;
- }
-
- @Override // from MyPendingRequest
- protected void myRun(@NonNull RemoteIntelligenceService remoteService)
- throws RemoteException {
- remoteService.mService.onActivitySnapshot(mSessionId, mSnapshotData);
- }
- }
-
- private static final class PendingAutofillRequest extends MyPendingRequest {
- private final @NonNull AutofillId mFocusedId;
- private final @Nullable AutofillValue mFocusedValue;
- private final @NonNull IAutoFillManagerClient mClient;
- private final int mAutofillSessionId;
- private final long mRequestTime = SystemClock.elapsedRealtime();
-
- protected PendingAutofillRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId, @NonNull IAutoFillManagerClient client,
- int autofillSessionId, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
- super(service, sessionId);
- mClient = client;
- mAutofillSessionId = autofillSessionId;
- mFocusedId = focusedId;
- mFocusedValue = focusedValue;
- }
-
- @Override // from MyPendingRequest
- public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
- final IResultReceiver receiver = new IResultReceiver.Stub() {
-
- @Override
- public void send(int resultCode, Bundle resultData) throws RemoteException {
- final IBinder realClient = resultData
- .getBinder(AutofillManager.EXTRA_AUGMENTED_AUTOFILL_CLIENT);
- remoteService.mService.onAutofillRequest(mSessionId, realClient,
- mAutofillSessionId, mFocusedId, mFocusedValue, mRequestTime);
- }
- };
-
- // TODO(b/111330312): set cancellation signal, timeout (from both mClient and service),
- // cache IAugmentedAutofillManagerClient reference, etc...
- mClient.getAugmentedAutofillClient(receiver);
- }
- }
-
- private static final class PendingDestroyAutofillWindowsRequest extends MyPendingRequest {
-
- protected PendingDestroyAutofillWindowsRequest(@NonNull RemoteIntelligenceService service,
- @NonNull InteractionSessionId sessionId) {
- super(service, sessionId);
- }
-
- @Override
- protected void myRun(@NonNull RemoteIntelligenceService service) throws RemoteException {
- service.mService.onDestroyAutofillWindowsRequest(mSessionId);
- // TODO(b/111330312): implement timeout
- }
- }
-
- public interface RemoteIntelligenceServiceCallbacks extends VultureCallback {
- // To keep it simple, we use the same callback for all failures / timeouts.
- void onFailureOrTimeout(boolean timedOut);
- }
-}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 9b2fbc1..2baef6af 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -239,8 +239,8 @@
"com.android.server.wallpaper.WallpaperManagerService$Lifecycle";
private static final String AUTO_FILL_MANAGER_SERVICE_CLASS =
"com.android.server.autofill.AutofillManagerService";
- private static final String INTELLIGENCE_MANAGER_SERVICE_CLASS =
- "com.android.server.intelligence.IntelligenceManagerService";
+ private static final String CONTENT_CAPTURE_MANAGER_SERVICE_CLASS =
+ "com.android.server.contentcapture.ContentCaptureManagerService";
private static final String TIME_ZONE_RULES_MANAGER_SERVICE_CLASS =
"com.android.server.timezone.RulesManagerService$Lifecycle";
private static final String IOT_SERVICE_CLASS =
@@ -1136,7 +1136,7 @@
traceEnd();
}
- startIntelligenceService(context);
+ startContentCaptureService(context);
// NOTE: ClipboardService indirectly depends on IntelligenceService
traceBeginAndSlog("StartClipboardService");
@@ -2100,18 +2100,18 @@
}, BOOT_TIMINGS_TRACE_LOG);
}
- private void startIntelligenceService(@NonNull Context context) {
+ private void startContentCaptureService(@NonNull Context context) {
// First check if it was explicitly enabled by Settings
boolean explicitlySupported = false;
final String settings = Settings.Global.getString(context.getContentResolver(),
- Settings.Global.SMART_SUGGESTIONS_SERVICE_EXPLICITLY_ENABLED);
+ Settings.Global.CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED);
if (settings != null) {
explicitlySupported = Boolean.parseBoolean(settings);
if (explicitlySupported) {
- Slog.d(TAG, "IntelligenceService explicitly enabled by Settings");
+ Slog.d(TAG, "ContentCaptureService explicitly enabled by Settings");
} else {
- Slog.d(TAG, "IntelligenceService explicitly disabled by Settings");
+ Slog.d(TAG, "ContentCaptureService explicitly disabled by Settings");
return;
}
}
@@ -2119,15 +2119,15 @@
// Then check if OEM overlaid the resource that defines the service.
if (!explicitlySupported) {
final String serviceName = context
- .getString(com.android.internal.R.string.config_defaultSmartSuggestionsService);
+ .getString(com.android.internal.R.string.config_defaultContentCaptureService);
if (TextUtils.isEmpty(serviceName)) {
- Slog.d(TAG, "IntelligenceService disabled because config resource is not overlaid");
+ Slog.d(TAG, "ContentCaptureService disabled because resource is not overlaid");
return;
}
}
- traceBeginAndSlog("StartIntelligenceService");
- mSystemServiceManager.startService(INTELLIGENCE_MANAGER_SERVICE_CLASS);
+ traceBeginAndSlog("StartContentCaptureService");
+ mSystemServiceManager.startService(CONTENT_CAPTURE_MANAGER_SERVICE_CLASS);
traceEnd();
}