Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ecb08be2 authored by Felipe Leme's avatar Felipe Leme
Browse files

Split IntelligenceManager / IntelligenceService.

This name is too generic, so we split it in 2 parts:

- ContentCaptureManager: the public API used by views and apps to report their
  structure.
- SmartSuggestionsServiec: the system service use to consume these events and
  provide autofill suggestions.

This CL also:

- Optimizes ContentCaptureManager allocation so they are not created on contexts that are not
  capturing events (such as views from the system server).
- Uses a generic ContentCaptureEventsRequest (rather than a list of events) to make it easier
  to be extended.
- Fixed IntelligencePerUserService so it clears the sessions when the
  implementation changes.

Test: manual verification

Bug: 119776618
Bug: 117944706
Bug: 119638877

Change-Id: I069bcd23dda94afe18b2781fd3981b8b555afa56
parent 71988345
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -290,7 +290,6 @@ java_defaults {
        "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/notification/INotificationListener.aidl",
        "core/java/android/service/notification/IStatusBarNotificationHolder.aidl",
        "core/java/android/service/notification/IConditionListener.aidl",
+2 −2
Original line number Diff line number Diff line
@@ -51966,8 +51966,8 @@ package android.view.inputmethod {
package android.view.intelligence {
  public final class IntelligenceManager {
    method public android.content.ComponentName getIntelligenceServiceComponentName();
  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);
+23 −19
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ package android {
    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";
    field public static final java.lang.String BIND_INTELLIGENCE_SERVICE = "android.permission.BIND_INTELLIGENCE_SERVICE";
    field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
    field public static final java.lang.String BIND_NETWORK_RECOMMENDATION_SERVICE = "android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE";
    field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
@@ -34,6 +33,7 @@ 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";
@@ -4980,6 +4980,13 @@ 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);
  }
@@ -5014,16 +5021,6 @@ package android.service.intelligence {
    field public static final long FLAG_METADATA_ADDRESS = 1L; // 0x1L
  }

  public abstract class IntelligenceService extends android.app.Service {
    ctor public IntelligenceService();
    method public void onActivitySnapshot(android.service.intelligence.InteractionSessionId, android.service.intelligence.SnapshotData);
    method public abstract void onContentCaptureEvent(android.service.intelligence.InteractionSessionId, java.util.List<android.view.intelligence.ContentCaptureEvent>);
    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);
    field public static final java.lang.String SERVICE_INTERFACE = "android.service.intelligence.IntelligenceService";
  }

  public final class InteractionContext implements android.os.Parcelable {
    method public int describeContents();
    method public android.content.ComponentName getActivityComponent();
@@ -5059,6 +5056,21 @@ package android.service.intelligence {
    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();
@@ -7243,14 +7255,6 @@ package android.view.intelligence {
    field public static final int TYPE_VIEW_TEXT_CHANGED = 7; // 0x7
  }

  public final class IntelligenceManager {
    method public java.util.Set<android.content.ComponentName> getContentCaptureDisabledActivities();
    method public java.util.Set<java.lang.String> getContentCaptureDisabledPackages();
    method public void setActivityContentCaptureEnabled(android.content.ComponentName, boolean);
    method public void setContentCaptureWhitelist(java.util.List<java.lang.String>, java.util.List<android.content.ComponentName>);
    method public void setPackageContentCaptureEnabled(java.lang.String, boolean);
  }

  public final class ViewNode extends android.app.assist.AssistStructure.ViewNode {
    method public android.view.autofill.AutofillId getParentAutofillId();
  }
+30 −23
Original line number Diff line number Diff line
@@ -122,7 +122,7 @@ 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.IntelligenceManager;
import android.view.intelligence.ContentCaptureManager;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
@@ -824,8 +824,8 @@ public class Activity extends ContextThemeWrapper
    /** The autofill manager. Always access via {@link #getAutofillManager()}. */
    @Nullable private AutofillManager mAutofillManager;

    /** The screen observation manager. Always access via {@link #getIntelligenceManager()}. */
    @Nullable private IntelligenceManager mIntelligenceManager;
    /** The content capture manager. Always access via {@link #getContentCaptureManager()}. */
    @Nullable private ContentCaptureManager mContentCaptureManager;

    private final ArrayList<Application.ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
            new ArrayList<Application.ActivityLifecycleCallbacks>();
@@ -1016,39 +1016,39 @@ public class Activity extends ContextThemeWrapper
    }

    /**
     * (Creates, sets, and ) returns the intelligence manager
     * (Creates, sets, and ) returns the content capture manager
     *
     * @return The intelligence manager
     * @return The content capture manager
     */
    @NonNull private IntelligenceManager getIntelligenceManager() {
        if (mIntelligenceManager == null) {
            mIntelligenceManager = getSystemService(IntelligenceManager.class);
    @NonNull private ContentCaptureManager getContentCaptureManager() {
        if (mContentCaptureManager == null) {
            mContentCaptureManager = getSystemService(ContentCaptureManager.class);
        }
        return mIntelligenceManager;
        return mContentCaptureManager;
    }

    private void notifyIntelligenceManagerIfNeeded(@ContentCaptureEvent.EventType int event) {
        final IntelligenceManager im = getIntelligenceManager();
        if (im == null || !im.isContentCaptureEnabled()) {
    private void notifyContentCaptureManagerIfNeeded(@ContentCaptureEvent.EventType int event) {
        final ContentCaptureManager cm = getContentCaptureManager();
        if (cm == null || !cm.isContentCaptureEnabled()) {
            return;
        }
        switch (event) {
            case ContentCaptureEvent.TYPE_ACTIVITY_CREATED:
                //TODO(b/111276913): decide whether the InteractionSessionId should be
                // saved / restored in the activity bundle.
                im.onActivityCreated(mToken, getComponentName());
                cm.onActivityCreated(mToken, getComponentName());
                break;
            case ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED:
                im.onActivityDestroyed();
                cm.onActivityDestroyed();
                break;
            case ContentCaptureEvent.TYPE_ACTIVITY_STARTED:
            case ContentCaptureEvent.TYPE_ACTIVITY_RESUMED:
            case ContentCaptureEvent.TYPE_ACTIVITY_PAUSED:
            case ContentCaptureEvent.TYPE_ACTIVITY_STOPPED:
                im.onActivityLifecycleEvent(event);
                cm.onActivityLifecycleEvent(event);
                break;
            default:
                Log.w(TAG, "notifyIntelligenceManagerIfNeeded(): invalid type " + event);
                Log.w(TAG, "notifyContentCaptureManagerIfNeeded(): invalid type " + event);
        }
    }

@@ -1057,6 +1057,7 @@ public class Activity extends ContextThemeWrapper
        super.attachBaseContext(newBase);
        if (newBase != null) {
            newBase.setAutofillClient(this);
            newBase.setContentCaptureSupported(true);
        }
    }

@@ -1066,6 +1067,12 @@ public class Activity extends ContextThemeWrapper
        return this;
    }

    /** @hide */
    @Override
    public boolean isContentCaptureSupported() {
        return true;
    }

    /**
     * Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
     * lifecycle callbacks for only this Activity.
@@ -1410,7 +1417,7 @@ public class Activity extends ContextThemeWrapper
        mRestoredFromBundle = savedInstanceState != null;
        mCalled = true;

        notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_CREATED);
        notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_CREATED);
    }

    /**
@@ -1644,7 +1651,7 @@ public class Activity extends ContextThemeWrapper
        if (mAutoFillResetNeeded) {
            getAutofillManager().onVisibleForAutofill();
        }
        notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STARTED);
        notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STARTED);
    }

    /**
@@ -1735,7 +1742,7 @@ public class Activity extends ContextThemeWrapper
                }
            }
        }
        notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_RESUMED);
        notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_RESUMED);
        mCalled = true;
    }

@@ -2129,7 +2136,7 @@ public class Activity extends ContextThemeWrapper
                mAutoFillIgnoreFirstResumePause = false;
            }
        }
        notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_PAUSED);
        notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_PAUSED);
        mCalled = true;
    }

@@ -2318,7 +2325,7 @@ public class Activity extends ContextThemeWrapper
                getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_CANCEL,
                        mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
            }
            notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STOPPED);
            notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STOPPED);
        }
    }

@@ -2390,7 +2397,7 @@ public class Activity extends ContextThemeWrapper

        dispatchActivityDestroyed();

        notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED);
        notifyContentCaptureManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED);

    }

@@ -6806,7 +6813,7 @@ public class Activity extends ContextThemeWrapper
    }

    void dumpIntelligenceManager(String prefix, PrintWriter writer) {
        final IntelligenceManager im = getIntelligenceManager();
        final ContentCaptureManager im = getContentCaptureManager();
        if (im != null) {
            im.dump(prefix, writer);
        } else {
+14 −0
Original line number Diff line number Diff line
@@ -217,6 +217,8 @@ class ContextImpl extends Context {
    private AutofillClient mAutofillClient = null;
    private boolean mIsAutofillCompatEnabled;

    private boolean mIsContentCaptureSupported = false;

    private final Object mSync = new Object();

    @GuardedBy("mSync")
@@ -2376,6 +2378,18 @@ class ContextImpl extends Context {
        mIsAutofillCompatEnabled = autofillCompatEnabled;
    }

    /** @hide */
    @Override
    public boolean isContentCaptureSupported() {
        return mIsContentCaptureSupported;
    }

    /** @hide */
    @Override
    public void setContentCaptureSupported(boolean supported) {
        mIsContentCaptureSupported = supported;
    }

    @UnsupportedAppUsage
    static ContextImpl createSystemContext(ActivityThread mainThread) {
        LoadedApk packageInfo = new LoadedApk(mainThread);
Loading