diff options
| author | 2018-12-10 12:13:31 -0800 | |
|---|---|---|
| committer | 2018-12-12 13:36:49 -0800 | |
| commit | 4017b209f8eb5f5ff42870658a827d45e6c0866d (patch) | |
| tree | 720a81afa656bee2fa6cc207306bf4c755726b60 | |
| parent | 7b6e54c3e3a86b74d42111228df21b7aa8fa8edf (diff) | |
Improved ContentCapture capture by flushing its buffer after some time idle.
Right now the value is hardcoded to 5s, but it will be dynamically configurable.
Bug: 119220549
Test: manual verification
Test: atest CtsContentCaptureServiceTestCases
Change-Id: I230dee32d215d099a323499e55b4347e817907a0
| -rw-r--r-- | core/java/android/view/contentcapture/ContentCaptureManager.java | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java index 1889692ea831..cc0264ac0bc9 100644 --- a/core/java/android/view/contentcapture/ContentCaptureManager.java +++ b/core/java/android/view/contentcapture/ContentCaptureManager.java @@ -31,7 +31,9 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.RemoteException; +import android.os.SystemClock; import android.util.Log; +import android.util.TimeUtils; import android.view.View; import android.view.ViewStructure; import android.view.autofill.AutofillId; @@ -98,6 +100,12 @@ public final class ContentCaptureManager { */ public static final int STATE_DISABLED = 3; + /** + * Handler message used to flush the buffer. + */ + private static final int MSG_FLUSH = 1; + + private static final String BG_THREAD_NAME = "intel_svc_streamer_thread"; /** @@ -106,6 +114,12 @@ public final class ContentCaptureManager { // TODO(b/111276913): use settings private static final int MAX_BUFFER_SIZE = 100; + /** + * Frequency the buffer is flushed if stale. + */ + // TODO(b/111276913): use settings + private static final int FLUSHING_FREQUENCY_MS = 5_000; + @NonNull private final AtomicBoolean mDisabled = new AtomicBoolean(); @@ -136,6 +150,9 @@ public final class ContentCaptureManager { // held at the Application level private final Handler mHandler; + // Used just for debugging purposes (on dump) + private long mNextFlush; + /** @hide */ public ContentCaptureManager(@NonNull Context context, @Nullable IContentCaptureManager service) { @@ -207,9 +224,17 @@ public final class ContentCaptureManager { mEvents = new ArrayList<>(MAX_BUFFER_SIZE); } mEvents.add(event); + final int numberEvents = mEvents.size(); - if (numberEvents < MAX_BUFFER_SIZE && !forceFlush) { - // Buffering events, return right away... + + // TODO(b/120784831): need to optimize it so we buffer changes until a number of X are + // buffered (either total or per autofillid). For + // example, if the user typed "a", "b", "c" and the threshold is 3, we should buffer + // "a" and "b" then send "abc". + final boolean bufferEvent = numberEvents < MAX_BUFFER_SIZE; + + if (bufferEvent && !forceFlush) { + handleScheduleFlush(); return; } @@ -236,10 +261,38 @@ public final class ContentCaptureManager { return; } + handleForceFlush(); + } + + private void handleScheduleFlush() { + if (mHandler.hasMessages(MSG_FLUSH)) { + // "Renew" the flush message by removing the previous one + mHandler.removeMessages(MSG_FLUSH); + } + mNextFlush = SystemClock.elapsedRealtime() + FLUSHING_FREQUENCY_MS; + if (VERBOSE) { + Log.v(TAG, "Scheduled to flush in " + FLUSHING_FREQUENCY_MS + "ms: " + mNextFlush); + } + mHandler.sendMessageDelayed( + obtainMessage(ContentCaptureManager::handleFlushIfNeeded, this).setWhat(MSG_FLUSH), + FLUSHING_FREQUENCY_MS); + } + + private void handleFlushIfNeeded() { + if (mEvents.isEmpty()) { + if (VERBOSE) Log.v(TAG, "Nothing to flush"); + return; + } + handleForceFlush(); + } + + private void handleForceFlush() { + final int numberEvents = mEvents.size(); try { if (DEBUG) { Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getActivityDebugName()); } + mHandler.removeMessages(MSG_FLUSH); mService.sendEvents(mContext.getUserId(), mId, mEvents); // TODO(b/111276913): decide whether we should clear or set it to null, as each has // its own advantages: clearing will save extra allocations while the session is @@ -307,6 +360,7 @@ public final class ContentCaptureManager { mApplicationToken = null; mComponentName = null; mEvents = null; + mHandler.removeMessages(MSG_FLUSH); } /** @@ -443,7 +497,7 @@ public final class ContentCaptureManager { pw.print(prefix2); pw.print("component name: "); pw.println(mComponentName.flattenToShortString()); } - if (mEvents != null) { + if (mEvents != null && !mEvents.isEmpty()) { final int numberEvents = mEvents.size(); pw.print(prefix2); pw.print("buffered events: "); pw.print(numberEvents); pw.print('/'); pw.println(MAX_BUFFER_SIZE); @@ -455,6 +509,9 @@ public final class ContentCaptureManager { pw.println(); } } + pw.print(prefix2); pw.print("flush frequency: "); pw.println(FLUSHING_FREQUENCY_MS); + pw.print(prefix2); pw.print("next flush: "); + TimeUtils.formatDuration(mNextFlush - SystemClock.elapsedRealtime(), pw); pw.println(); } } |