diff options
64 files changed, 1511 insertions, 1099 deletions
diff --git a/Android.bp b/Android.bp index 34162d1fcc1d..2ae7d6c1a0a4 100644 --- a/Android.bp +++ b/Android.bp @@ -268,6 +268,8 @@ java_defaults { "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 @@ java_defaults { "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 @@ java_defaults { "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 f7060f341ace..76dddb5fc1dc 100644 --- a/api/current.txt +++ b/api/current.txt @@ -34659,6 +34659,7 @@ package android.os { 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"; @@ -34668,7 +34669,6 @@ package android.os { 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"; @@ -51850,6 +51850,21 @@ package android.view.autofill { } +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 { @@ -52331,21 +52346,6 @@ package android.view.inspector { } -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 9cf66b2707fd..542fdff8d0c3 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -21,7 +21,9 @@ package android { 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 @@ package android { 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 @@ package android { 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 { } +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.carrier { } +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.euicc { } -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.accessibility { } -package android.view.intelligence { +package android.view.contentcapture { public final class ContentCaptureEvent implements android.os.Parcelable { method public int describeContents(); @@ -7278,13 +7289,13 @@ package android.view.intelligence { 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 f3f065a27e6f..cfda8037072f 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -121,8 +121,8 @@ import android.view.autofill.AutofillManager; 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 0404e80df9e2..43e183665435 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -165,9 +165,9 @@ import android.view.accessibility.AccessibilityManager; 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 @@ final class SystemServiceRegistry { 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 e2c7b85b3280..d7d3cb543af9 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3939,13 +3939,12 @@ public abstract class Context { 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 abfcfaacde21..86f81d81a6c7 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -948,7 +948,7 @@ public class UserManager { * @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 c3217a2189cf..64aa088e26bd 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -12840,7 +12840,7 @@ public final class Settings { /** * 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 @@ public final class Settings { * * @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 573d57779df7..f39ef9afdb3c 100644 --- a/core/java/android/service/autofill/AutofillService.java +++ b/core/java/android/service/autofill/AutofillService.java @@ -618,7 +618,7 @@ public abstract class AutofillService extends Service { 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/intelligence/SmartSuggestionsService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java index b684b0208d8d..68a86f3c8bca 100644 --- a/core/java/android/service/intelligence/SmartSuggestionsService.java +++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.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 static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; @@ -32,16 +32,16 @@ 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.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 android.view.intelligence.ContentCaptureEvent; import com.android.internal.annotations.GuardedBy; @@ -51,18 +51,17 @@ 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. + * 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 SmartSuggestionsService extends Service { +public abstract class AugmentedAutofillService extends Service { - private static final String TAG = "SmartSuggestionsService"; + private static final String TAG = AugmentedAutofillService.class.getSimpleName(); // TODO(b/111330312): STOPSHIP use dynamic value, or change to false static final boolean DEBUG = true; @@ -71,63 +70,32 @@ public abstract class SmartSuggestionsService extends Service { /** * 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 + * {@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.intelligence.SmartSuggestionsService"; + "android.service.autofill.augmented.AugmentedAutofillService"; private Handler mHandler; - private ArrayMap<InteractionSessionId, AutofillProxy> mAutofillProxies; + private SparseArray<AutofillProxy> mAutofillProxies; - private final IIntelligenceService mInterface = new IIntelligenceService.Stub() { + private final IAugmentedAutofillService mInterface = new IAugmentedAutofillService.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)); + 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 onDestroyAutofillWindowsRequest(InteractionSessionId sessionId) { + public void onDestroyFillWindowRequest(int sessionId) { mHandler.sendMessage( - obtainMessage(SmartSuggestionsService::handleOnDestroyAutofillWindowsRequest, - SmartSuggestionsService.this, sessionId)); + obtainMessage(AugmentedAutofillService::handleOnDestroyFillWindowRequest, + AugmentedAutofillService.this, sessionId)); } }; @@ -144,118 +112,18 @@ public abstract class SmartSuggestionsService extends Service { 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; } - /** - * 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 + ")"); - } + @Override + public boolean onUnbind(Intent intent) { + mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnUnbind, + AugmentedAutofillService.this)); + return false; } - /** - * 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)); - } + // TODO(b/111330312): add methods to disable autofill per app / activity? /** * Asks the service to handle an "augmented" autofill request. @@ -275,24 +143,44 @@ public abstract class SmartSuggestionsService extends Service { * {@link FillController#autofill(List)} method). * * <p>The service <b>MUST</b> call {@link - * FillCallback#onSuccess(android.service.intelligence.FillResponse)} as soon as possible, + * FillCallback#onSuccess(android.service.autofill.augmented.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)}. + * {@link FillCallback#onSuccess(android.service.autofill.augmented.FillResponse)}. */ - public void onFillRequest(@NonNull InteractionSessionId sessionId, @NonNull FillRequest request, + public void onFillRequest(@NonNull FillRequest request, @NonNull CancellationSignal cancellationSignal, @NonNull FillController controller, @NonNull FillCallback callback) { } - private void handleOnDestroyAutofillWindowsRequest(@NonNull InteractionSessionId sessionId) { + 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); @@ -306,13 +194,31 @@ public abstract class SmartSuggestionsService extends Service { 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 InteractionSessionId sessionId = mAutofillProxies.keyAt(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); @@ -320,26 +226,6 @@ public abstract class SmartSuggestionsService extends Service { } } - /** - * 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 { @@ -358,8 +244,10 @@ public abstract class SmartSuggestionsService extends Service { private final Object mLock = new Object(); private final IAugmentedAutofillManagerClient mClient; - private final int mAutofillSessionId; - public final InteractionSessionId sessionId; + private final int mSessionId; + private final IFillCallback mCallback; + public final int taskId; + public final ComponentName componentName; public final AutofillId focusedId; public final AutofillValue focusedValue; @@ -375,12 +263,15 @@ public abstract class SmartSuggestionsService extends Service { @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; + 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); - mAutofillSessionId = autofillSessionId; + mCallback = callback; + this.taskId = taskId; + this.componentName = componentName; this.focusedId = focusedId; this.focusedValue = focusedValue; this.mRequestTime = requestTime; @@ -419,7 +310,7 @@ public abstract class SmartSuggestionsService extends Service { ids.add(pair.first); values.add(pair.second); } - mClient.autofill(mAutofillSessionId, ids, values); + mClient.autofill(mSessionId, ids, values); } public void setFillWindow(@NonNull FillWindow fillWindow) { @@ -434,7 +325,7 @@ public abstract class SmartSuggestionsService extends Service { } } - // Used for metrics. + // Used (mostly) for metrics. public void report(@ReportEvent int event) { switch (event) { case REPORT_EVENT_ON_SUCCESS: @@ -445,6 +336,11 @@ public abstract class SmartSuggestionsService extends Service { + 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) { @@ -471,9 +367,11 @@ public abstract class SmartSuggestionsService extends Service { // 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("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); diff --git a/core/java/android/service/intelligence/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java index ddf37f737296..054646572a58 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 index 4a9c85de1fa2..e65cf47e1645 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 index 53e99a5fd3b8..fd75b156858e 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 @@ import android.view.autofill.AutofillValue; * @hide */ @SystemApi +// TODO(b/111330312): pass a requestId and/or sessionId public final class FillRequest { final AutofillProxy mProxy; @@ -37,11 +39,18 @@ public final class FillRequest { } /** - * 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 @@ public final class FillRequest { * 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 @@ public final class FillRequest { @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 index 860c0275732a..7064b6fe8079 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 @@ public final class FillResponse implements Parcelable { * @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 index 39d7e08a68d9..9e3aba416f9c 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 @@ import java.lang.annotation.RetentionPolicy; * @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 @@ public final class FillWindow { } } } + + /** @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 000000000000..b3ac2da1c17e --- /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 000000000000..dac75904f4fc --- /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 index 95303099793a..0124ecca740d 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 @@ public abstract class PresentationParams { * * @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 index 23d607d9838c..c032cfdb9677 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 index bc5b92bce999..df58f52dc59c 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 000000000000..3dfeeded5946 --- /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 000000000000..29e9abbc6263 --- /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 index 4ce6aa45d4a1..982e095894fb 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 index 7f4283db28d2..f1281ff01033 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 @@ public final class InteractionContext implements Parcelable { /** * 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 index 667193b14113..84119472ca32 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.Parcel; 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 @@ public final class InteractionSessionId implements Parcelable { /** * 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 index 31d13390d2b8..a00e852625ee 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 index b9310eae6cb5..bc2116a441aa 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 2b924fbaadc4..000000000000 --- 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 a5392b684a11..000000000000 --- 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/view/View.java b/core/java/android/view/View.java index bd2aa64b33a1..4297efb71ad0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -109,13 +109,13 @@ import android.view.animation.Transformation; 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 index c66a6cb0d486..abaf9ed7d7e9 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 index f63628105cba..66fa530758e7 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 @@ public final class ContentCaptureEvent implements Parcelable { /** * 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 @@ public final class ContentCaptureEvent implements Parcelable { * 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 index 45518d5e5943..48831daf75e8 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.Handler; 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 @@ import java.util.concurrent.atomic.AtomicBoolean; @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 @@ public final class ContentCaptureManager { 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 @@ public final class ContentCaptureManager { 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 @@ public final class ContentCaptureManager { return; } mState = STATE_WAITING_FOR_SERVER; - mId = new InteractionSessionId(); + mId = UUID.randomUUID().toString(); mApplicationToken = token; mComponentName = componentName; diff --git a/core/java/android/view/intelligence/IIntelligenceManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl index 882fb2674bf1..8704dad2ea08 100644 --- a/core/java/android/view/intelligence/IIntelligenceManager.aidl +++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl @@ -14,12 +14,11 @@ * limitations under the License. */ -package android.view.intelligence; +package android.view.contentcapture; import android.content.ComponentName; +import android.view.contentcapture.ContentCaptureEvent; import android.os.IBinder; -import android.service.intelligence.InteractionSessionId; -import android.view.intelligence.ContentCaptureEvent; import com.android.internal.os.IResultReceiver; @@ -28,23 +27,9 @@ 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. - */ +oneway interface IContentCaptureManager { 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); + 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 index ea57461f0933..86b89adb5ce3 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/widget/TextView.java b/core/java/android/widget/TextView.java index 90cf871830fd..2a4223201af1 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -157,6 +157,7 @@ import android.view.accessibility.AccessibilityNodeInfo; 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.ExtractedText; 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 4c1fc5c89b0d..9620e4b276d7 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -222,6 +222,13 @@ message GlobalSettingsProto { } 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 @@ message GlobalSettingsProto { } 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 3018614fee61..594ae6b2f333 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 499278cf5a16..62ec5c474297 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 6854a84e950a..82a679e14534 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 ed9c3d5b2b70..f1ed1c2952e9 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -183,6 +183,7 @@ public class SettingsBackupTest { 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 @@ public class SettingsBackupTest { 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/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index df5b1467f9d9..ad884320ba0b 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 @@ class SettingsProtoDumpUtil { 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 @@ class SettingsProtoDumpUtil { 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 83e83693375b..e564711cfa00 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 33904383f84a..58a09977596f 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -21,9 +21,9 @@ java_library { "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 944ee3390150..e8887e7a2ebe 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.FgThread; 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 @@ public final class AutofillManagerService 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 @@ public final class AutofillManagerService 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 final class AutofillManagerService 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 @@ public final class AutofillManagerService 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 @@ public final class AutofillManagerService 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 @@ public final class AutofillManagerService 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 3945c23eabc7..5a0d12cfd8e5 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.internal.logging.nano.MetricsProto.MetricsEvent; 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 @@ final class AutofillManagerServiceImpl /** 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 @@ final class AutofillManagerServiceImpl 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 @@ final class AutofillManagerServiceImpl } 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 @@ final class AutofillManagerServiceImpl 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 522280e4690b..35c51027df86 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 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { 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 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { 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 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { } } + 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 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { } 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 000000000000..222888cc8ce3 --- /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 fb64cb28619d..d76a5dff36d3 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.AutofillManagerService.SmartSuggestionMode; 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 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @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 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // 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 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState /** * 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 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // 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 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState 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 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @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 index 2df123500a54..57e859ebe121 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 index a760cbd039e4..872fe4229479 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.ResultReceiver; 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 @@ import java.util.List; * <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 @@ public final class IntelligenceManagerService extends 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 @@ public final class IntelligenceManagerService extends 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 @@ public final class IntelligenceManagerService extends 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 @@ public final class IntelligenceManagerService extends 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 @@ public final class IntelligenceManagerService extends 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 final class IntelligenceManagerService extends 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 final class IntelligenceManagerService extends 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 index 0d92a972aa96..2f78276bb533 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.CountDownLatch; 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 @@ public final class IntelligenceServiceShellCommand extends ShellCommand { @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 @@ public final class IntelligenceServiceShellCommand extends ShellCommand { 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 @@ public final class IntelligenceServiceShellCommand extends ShellCommand { } } - private int setTemporaryService() { + private int setTemporaryService(PrintWriter pw) { final int userId = getNextIntArgRequired(); final String serviceName = getNextArg(); if (serviceName == null) { @@ -146,6 +144,8 @@ public final class IntelligenceServiceShellCommand extends ShellCommand { } 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 index e2b8d48ea123..aa171f4a0818 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.content.pm.ServiceInfo; 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 @@ final class IntelligencePerUserService + " " + 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 @@ final class IntelligencePerUserService @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 @@ final class IntelligencePerUserService // 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 @@ final class IntelligencePerUserService // 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 @@ final class IntelligencePerUserService } // 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 @@ final class IntelligencePerUserService @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 @@ final class IntelligencePerUserService } @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 @@ final class IntelligencePerUserService } } - 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 @@ final class IntelligencePerUserService } /** - * 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 index 05b8201f112e..2302b7db3723 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 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks } /** - * 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 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks } /** - * 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 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks } /** - * 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 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks * 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 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks 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 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks @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 000000000000..6a111f238073 --- /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 65537adccbc6..258c325716f2 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 android.util.SparseArray; 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 @@ public class ClipboardService extends SystemService { 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 @@ public class ClipboardService extends SystemService { 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 @@ public class ClipboardService extends SystemService { 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 000000000000..726362a7df36 --- /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 ef9ad8ae770c..c0c4a6e8310e 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 @@ import java.util.List; * <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 7af1d4ca94ef..67b3ecf4896e 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 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S>> 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 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S>> 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 8f8b448a7a66..37a1f5471f7b 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 @@ public abstract class AbstractSinglePendingRequestRemoteService< 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 f424869a428e..000000000000 --- 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 1e287b4e412e..942218244505 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 android.view.IRecentsAnimationRunner; 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 @@ class RecentsAnimation implements RecentsAnimationCallbacks, 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 @@ class RecentsAnimation implements RecentsAnimationCallbacks, } }; } 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 c4fbdca0ff2f..000000000000 --- 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 c4d2a914facf..744d386d7430 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -239,8 +239,8 @@ public final class SystemServer { "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 @@ public final class SystemServer { traceEnd(); } - startIntelligenceService(context); + startContentCaptureService(context); // NOTE: ClipboardService indirectly depends on IntelligenceService traceBeginAndSlog("StartClipboardService"); @@ -2100,18 +2100,18 @@ public final class SystemServer { }, 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 @@ public final class SystemServer { // 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(); } |