diff options
| author | Felipe Leme <felipeal@google.com> | 2018-11-07 01:21:47 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2018-11-07 01:21:47 +0000 |
| commit | 15fe040f8726a71e5221e2759960ff4a217c40dc (patch) | |
| tree | fa14164eca6aa35771f596700ee5fc18e36b1d7b /core/java/android | |
| parent | b95e7b7bc210b142b1d64cf16cf8634d768ac236 (diff) | |
| parent | 7a53408d196d6a288d9a6745d98db697cb2a411f (diff) | |
Merge "Initial implementation of IntelligenceService.onContentCaptureEvents()"
Diffstat (limited to 'core/java/android')
7 files changed, 177 insertions, 16 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 8d54e91b93e4..86ed267eafdb 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -120,6 +120,7 @@ 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.IntelligenceManager; import android.widget.AdapterView; import android.widget.Toast; @@ -1023,6 +1024,31 @@ public class Activity extends ContextThemeWrapper return mIntelligenceManager; } + private void notifyIntelligenceManagerIfNeeded(@ContentCaptureEvent.EventType int event) { + final IntelligenceManager im = getIntelligenceManager(); + if (im == null || !im.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()); + break; + case ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED: + im.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); + break; + default: + Log.w(TAG, "notifyIntelligenceManagerIfNeeded(): invalid type " + event); + } + } + @Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(newBase); @@ -1099,11 +1125,7 @@ public class Activity extends ContextThemeWrapper mRestoredFromBundle = savedInstanceState != null; mCalled = true; - if (getIntelligenceManager() != null) { - //TODO(b/111276913): decide whether the screen_obs session id should be saved / restored - // in the activity bundle. - mIntelligenceManager.onActivityCreated(mToken, getComponentName()); - } + notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_CREATED); } /** @@ -1337,6 +1359,7 @@ public class Activity extends ContextThemeWrapper if (mAutoFillResetNeeded) { getAutofillManager().onVisibleForAutofill(); } + notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STARTED); } /** @@ -1419,6 +1442,7 @@ public class Activity extends ContextThemeWrapper } } } + notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_RESUMED); mCalled = true; } @@ -1812,6 +1836,7 @@ public class Activity extends ContextThemeWrapper mAutoFillIgnoreFirstResumePause = false; } } + notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_PAUSED); mCalled = true; } @@ -2000,6 +2025,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); } } @@ -2071,9 +2097,8 @@ public class Activity extends ContextThemeWrapper getApplication().dispatchActivityDestroyed(this); - if (getIntelligenceManager() != null) { - mIntelligenceManager.onActivityDestroyed(); - } + notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED); + } /** diff --git a/core/java/android/service/intelligence/IIntelligenceService.aidl b/core/java/android/service/intelligence/IIntelligenceService.aidl index ee93326d2e3c..bacad8b44783 100644 --- a/core/java/android/service/intelligence/IIntelligenceService.aidl +++ b/core/java/android/service/intelligence/IIntelligenceService.aidl @@ -19,6 +19,11 @@ package android.service.intelligence; import android.service.intelligence.InteractionSessionId; import android.service.intelligence.InteractionContext; +import android.view.intelligence.ContentCaptureEvent; + +import java.util.List; + + /** * Interface from the system to an intelligence service. * @@ -28,4 +33,7 @@ oneway interface IIntelligenceService { // Called when session is created (context not null) or destroyed (context null) void onSessionLifecycle(in InteractionContext context, in InteractionSessionId sessionId); + + void onContentCaptureEvents(in InteractionSessionId sessionId, + in List<ContentCaptureEvent> events); } diff --git a/core/java/android/service/intelligence/IntelligenceService.java b/core/java/android/service/intelligence/IntelligenceService.java index ce0a88a3faca..a2b60f044657 100644 --- a/core/java/android/service/intelligence/IntelligenceService.java +++ b/core/java/android/service/intelligence/IntelligenceService.java @@ -70,6 +70,14 @@ public abstract class IntelligenceService extends Service { IntelligenceService.this, sessionId)); } } + @Override + public void onContentCaptureEvents(InteractionSessionId sessionId, + List<ContentCaptureEvent> events) { + mHandler.sendMessage( + obtainMessage(IntelligenceService::onContentCaptureEvent, + IntelligenceService.this, sessionId, events)); + + } }; @CallSuper @@ -105,6 +113,7 @@ public abstract class IntelligenceService extends Service { * @param sessionId the session's Id * @param events the events */ + // TODO(b/111276913): rename to onContentCaptureEvents public abstract void onContentCaptureEvent(@NonNull InteractionSessionId sessionId, @NonNull List<ContentCaptureEvent> events); diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.aidl b/core/java/android/view/intelligence/ContentCaptureEvent.aidl new file mode 100644 index 000000000000..c66a6cb0d486 --- /dev/null +++ b/core/java/android/view/intelligence/ContentCaptureEvent.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.intelligence; + +parcelable ContentCaptureEvent; diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.java b/core/java/android/view/intelligence/ContentCaptureEvent.java index d6aec344171d..2530ae3b3124 100644 --- a/core/java/android/view/intelligence/ContentCaptureEvent.java +++ b/core/java/android/view/intelligence/ContentCaptureEvent.java @@ -30,6 +30,11 @@ import java.lang.annotation.RetentionPolicy; @SystemApi public final class ContentCaptureEvent implements Parcelable { + /** @hide */ + public static final int TYPE_ACTIVITY_DESTROYED = -2; + /** @hide */ + public static final int TYPE_ACTIVITY_CREATED = -1; + /** * Called when the activity is started. */ @@ -85,10 +90,18 @@ public final class ContentCaptureEvent implements Parcelable { TYPE_VIEW_TEXT_CHANGED }) @Retention(RetentionPolicy.SOURCE) - @interface EventType{} + public @interface EventType{} + + private final int mType; + private final long mEventTime; + private final int mFlags; + /** @hide */ - ContentCaptureEvent() { + public ContentCaptureEvent(int type, long eventTime, int flags) { + mType = type; + mEventTime = eventTime; + mFlags = flags; } /** @@ -99,14 +112,14 @@ public final class ContentCaptureEvent implements Parcelable { * {@link #TYPE_VIEW_ADDED}, {@link #TYPE_VIEW_REMOVED}, or {@link #TYPE_VIEW_TEXT_CHANGED}. */ public @EventType int getType() { - return 42; + return mType; } /** * Gets when the event was generated, in ms. */ public long getEventTime() { - return 48151623; + return mEventTime; } /** @@ -116,7 +129,7 @@ public final class ContentCaptureEvent implements Parcelable { * {@link android.view.intelligence.IntelligenceManager#FLAG_USER_INPUT}. */ public int getFlags() { - return 0; + return mFlags; } /** @@ -150,13 +163,25 @@ public final class ContentCaptureEvent implements Parcelable { } @Override + public String toString() { + final StringBuilder string = new StringBuilder("ContentCaptureEvent[type=") + .append(getTypeAsString(mType)).append(", time=").append(mEventTime); + if (mFlags > 0) { + string.append(", flags=").append(mFlags); + } + return string.append(']').toString(); + } + + @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel parcel, int flags) { - // TODO(b/111276913): implement + parcel.writeInt(mType); + parcel.writeLong(mEventTime); + parcel.writeInt(mFlags); } public static final Parcelable.Creator<ContentCaptureEvent> CREATOR = @@ -164,8 +189,10 @@ public final class ContentCaptureEvent implements Parcelable { @Override public ContentCaptureEvent createFromParcel(Parcel parcel) { - // TODO(b/111276913): implement - return null; + final int type = parcel.readInt(); + final long eventTime = parcel.readLong(); + final int flags = parcel.readInt(); + return new ContentCaptureEvent(type, eventTime, flags); } @Override @@ -173,4 +200,27 @@ public final class ContentCaptureEvent implements Parcelable { return new ContentCaptureEvent[size]; } }; + + + /** @hide */ + public static String getTypeAsString(@EventType int type) { + switch (type) { + case TYPE_ACTIVITY_STARTED: + return "ACTIVITY_STARTED"; + case TYPE_ACTIVITY_RESUMED: + return "ACTIVITY_RESUMED"; + case TYPE_ACTIVITY_PAUSED: + return "ACTIVITY_PAUSED"; + case TYPE_ACTIVITY_STOPPED: + return "ACTIVITY_STOPPED"; + case TYPE_VIEW_ADDED: + return "VIEW_ADDED"; + case TYPE_VIEW_REMOVED: + return "VIEW_REMOVED"; + case TYPE_VIEW_TEXT_CHANGED: + return "VIEW_TEXT_CHANGED"; + default: + return "UKNOWN_TYPE: " + type; + } + } } diff --git a/core/java/android/view/intelligence/IIntelligenceManager.aidl b/core/java/android/view/intelligence/IIntelligenceManager.aidl index f4901c371614..7bbe99a9ad48 100644 --- a/core/java/android/view/intelligence/IIntelligenceManager.aidl +++ b/core/java/android/view/intelligence/IIntelligenceManager.aidl @@ -17,9 +17,15 @@ package android.view.intelligence; import android.content.ComponentName; + import android.os.IBinder; + +import android.view.intelligence.ContentCaptureEvent; + import com.android.internal.os.IResultReceiver; +import java.util.List; + /** * {@hide} */ @@ -33,6 +39,14 @@ oneway interface IIntelligenceManager { /** * Finishes a session. */ + // TODO(b/111276913): pass just (global) session id void finishSession(int userId, IBinder activityToken, in ComponentName componentName, int localSessionId, int globalSessionId); + + /** + * Sends a batch of events + */ + // TODO(b/111276913): pass just (global) session id + void sendEvents(int userId, IBinder activityToken, in ComponentName componentName, + int localSessionId, int globalSessionId, in List<ContentCaptureEvent> events); } diff --git a/core/java/android/view/intelligence/IntelligenceManager.java b/core/java/android/view/intelligence/IntelligenceManager.java index b1d06f7fccfd..a30d77e4d446 100644 --- a/core/java/android/view/intelligence/IntelligenceManager.java +++ b/core/java/android/view/intelligence/IntelligenceManager.java @@ -24,13 +24,17 @@ import android.content.Context; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; +import android.os.SystemClock; import android.util.Log; +import android.view.intelligence.ContentCaptureEvent.EventType; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.IResultReceiver; import com.android.internal.util.Preconditions; import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; import java.util.Set; /** @@ -161,6 +165,38 @@ public final class IntelligenceManager { } } + /** + * Used for intermediate events (i.e, other than created and destroyed). + * + * @hide + */ + public void onActivityLifecycleEvent(@EventType int type) { + if (!isContentCaptureEnabled()) return; + + //TODO(b/111276913): should buffer event (and call service on handler thread), instead of + // calling right away + final ContentCaptureEvent event = new ContentCaptureEvent(type, SystemClock.uptimeMillis(), + 0); + final List<ContentCaptureEvent> events = Arrays.asList(event); + + synchronized (mLock) { + //TODO(b/111276913): check session state; for example, how to handle if it's waiting for + // remote id + + if (VERBOSE) { + Log.v(TAG, "onActivityLifecycleEvent() for " + mComponentName.flattenToShortString() + + ": " + ContentCaptureEvent.getTypeAsString(type)); + } + + try { + mService.sendEvents(mContext.getUserId(), mApplicationToken, mComponentName, + mLocalSessionId, mRemoteSessionId, events); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + /** @hide */ public void onActivityDestroyed() { if (!isContentCaptureEnabled()) return; |
