Revert "Used ElapsedRealtimeNanos instead of Choreographer times..."
Revert submission 23545138
Reason for revert: DroidMonitor: Potential culprit for Bug b/287509119 - verifying through ABTD before revert submission. This is part of the standard investigation process, and does not mean your CL will be reverted.
Reverted changes: /q/submissionid:23545138
Change-Id: Ieddacb27fcd6026641f602f4bfaffbb4d4b864e9
diff --git a/viewcapturelib/src/com/android/app/viewcapture/SettingsAwareViewCapture.kt b/viewcapturelib/src/com/android/app/viewcapture/SettingsAwareViewCapture.kt
index 9a857c3..8a3cf1c 100644
--- a/viewcapturelib/src/com/android/app/viewcapture/SettingsAwareViewCapture.kt
+++ b/viewcapturelib/src/com/android/app/viewcapture/SettingsAwareViewCapture.kt
@@ -25,6 +25,7 @@
import android.os.Process
import android.provider.Settings
import android.util.Log
+import android.view.Choreographer
import android.window.IDumpCallback
import androidx.annotation.AnyThread
import androidx.annotation.VisibleForTesting
@@ -39,8 +40,8 @@
*/
class SettingsAwareViewCapture
@VisibleForTesting
-internal constructor(private val context: Context, executor: Executor)
- : ViewCapture(DEFAULT_MEMORY_SIZE, DEFAULT_INIT_POOL_SIZE, executor) {
+internal constructor(private val context: Context, choreographer: Choreographer, executor: Executor)
+ : ViewCapture(DEFAULT_MEMORY_SIZE, DEFAULT_INIT_POOL_SIZE, choreographer, executor) {
/** Dumps all the active view captures to the wm trace directory via LauncherAppService */
private val mDumpCallback: IDumpCallback.Stub = object : IDumpCallback.Stub() {
override fun onDump(out: ParcelFileDescriptor) {
@@ -90,7 +91,7 @@
fun getInstance(context: Context): ViewCapture = when {
INSTANCE != null -> INSTANCE!!
Looper.myLooper() == Looper.getMainLooper() -> SettingsAwareViewCapture(
- context.applicationContext,
+ context.applicationContext, Choreographer.getInstance(),
createAndStartNewLooperExecutor("SAViewCapture",
Process.THREAD_PRIORITY_FOREGROUND)).also { INSTANCE = it }
else -> try {
diff --git a/viewcapturelib/src/com/android/app/viewcapture/SimpleViewCapture.kt b/viewcapturelib/src/com/android/app/viewcapture/SimpleViewCapture.kt
index 420faca..2773f6b 100644
--- a/viewcapturelib/src/com/android/app/viewcapture/SimpleViewCapture.kt
+++ b/viewcapturelib/src/com/android/app/viewcapture/SimpleViewCapture.kt
@@ -1,6 +1,8 @@
package com.android.app.viewcapture
import android.os.Process
+import android.view.Choreographer
open class SimpleViewCapture(threadName: String) : ViewCapture(DEFAULT_MEMORY_SIZE, DEFAULT_INIT_POOL_SIZE,
+ MAIN_EXECUTOR.submit { Choreographer.getInstance() }.get(),
createAndStartNewLooperExecutor(threadName, Process.THREAD_PRIORITY_FOREGROUND))
\ No newline at end of file
diff --git a/viewcapturelib/src/com/android/app/viewcapture/ViewCapture.java b/viewcapturelib/src/com/android/app/viewcapture/ViewCapture.java
index bbd797e..e635e85 100644
--- a/viewcapturelib/src/com/android/app/viewcapture/ViewCapture.java
+++ b/viewcapturelib/src/com/android/app/viewcapture/ViewCapture.java
@@ -24,10 +24,10 @@
import android.media.permission.SafeCloseable;
import android.os.HandlerThread;
import android.os.Looper;
-import android.os.SystemClock;
import android.os.Trace;
import android.text.TextUtils;
import android.util.SparseArray;
+import android.view.Choreographer;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
@@ -54,7 +54,6 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -84,13 +83,16 @@
private final List<WindowListener> mListeners = new ArrayList<>();
protected final Executor mBgExecutor;
+ private final Choreographer mChoreographer;
// Pool used for capturing view tree on the UI thread.
private ViewRef mPool = new ViewRef();
private boolean mIsEnabled = true;
- protected ViewCapture(int memorySize, int initPoolSize, Executor bgExecutor) {
+ protected ViewCapture(int memorySize, int initPoolSize, Choreographer choreographer,
+ Executor bgExecutor) {
mMemorySize = memorySize;
+ mChoreographer = choreographer;
mBgExecutor = bgExecutor;
mBgExecutor.execute(() -> initPool(initPoolSize));
}
@@ -187,8 +189,6 @@
.setPackage(context.getPackageName())
.addAllWindowData(getWindowData(context, classList, l -> l.mIsActive).get())
.addAllClassname(toStringList(classList))
- .setRealToElapsedTimeOffsetNanos(TimeUnit.MILLISECONDS
- .toNanos(System.currentTimeMillis()) - SystemClock.elapsedRealtimeNanos())
.build();
}
@@ -289,7 +289,7 @@
ViewRef captured = mViewRef.next;
if (captured != null) {
captured.callback = mCaptureCallback;
- captured.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
+ captured.choreographerTimeNanos = mChoreographer.getFrameTimeNanos();
mBgExecutor.execute(captured);
}
mIsFirstFrame = false;
@@ -302,12 +302,12 @@
*/
@WorkerThread
private void captureViewPropertiesBg(ViewRef viewRefStart) {
- long elapsedRealtimeNanos = viewRefStart.elapsedRealtimeNanos;
+ long choreographerTimeNanos = viewRefStart.choreographerTimeNanos;
mFrameIndexBg++;
if (mFrameIndexBg >= mMemorySize) {
mFrameIndexBg = 0;
}
- mFrameTimesNanosBg[mFrameIndexBg] = elapsedRealtimeNanos;
+ mFrameTimesNanosBg[mFrameIndexBg] = choreographerTimeNanos;
ViewPropertyRef recycle = mNodesBg[mFrameIndexBg];
@@ -555,7 +555,7 @@
public ViewRef next;
public Consumer<ViewRef> callback = null;
- public long elapsedRealtimeNanos = 0;
+ public long choreographerTimeNanos = 0;
public void transferTo(ViewPropertyRef out) {
out.childCount = this.childCount;
diff --git a/viewcapturelib/src/com/android/app/viewcapture/proto/view_capture.proto b/viewcapturelib/src/com/android/app/viewcapture/proto/view_capture.proto
index c73ce8b..6e71889 100644
--- a/viewcapturelib/src/com/android/app/viewcapture/proto/view_capture.proto
+++ b/viewcapturelib/src/com/android/app/viewcapture/proto/view_capture.proto
@@ -34,10 +34,6 @@
repeated WindowData windowData = 2;
optional string package = 3;
repeated string classname = 4;
-
- /* offset between real-time clock and elapsed time clock in nanoseconds.
- Calculated as: 1000000 * System.currentTimeMillis() - SystemClock.elapsedRealtimeNanos() */
- optional fixed64 real_to_elapsed_time_offset_nanos = 5;
}
message WindowData {
@@ -51,7 +47,7 @@
}
message FrameData {
- optional int64 timestamp = 1; // unit is elapsed realtime nanos
+ optional int64 timestamp = 1; // choreographer timestamp in nanoseconds
optional ViewNode node = 2;
}
diff --git a/viewcapturelib/tests/com/android/app/viewcapture/SettingsAwareViewCaptureTest.kt b/viewcapturelib/tests/com/android/app/viewcapture/SettingsAwareViewCaptureTest.kt
index 631ce85..2157ee4 100644
--- a/viewcapturelib/tests/com/android/app/viewcapture/SettingsAwareViewCaptureTest.kt
+++ b/viewcapturelib/tests/com/android/app/viewcapture/SettingsAwareViewCaptureTest.kt
@@ -50,7 +50,8 @@
Settings.Global.putInt(context.contentResolver, VIEW_CAPTURE_ENABLED, 0)
activityScenarioRule.scenario.onActivity { activity ->
- val viewCapture: ViewCapture = SettingsAwareViewCapture(context, MAIN_EXECUTOR)
+ val viewCapture: ViewCapture =
+ SettingsAwareViewCapture(context, Choreographer.getInstance(), MAIN_EXECUTOR)
val rootView: View = activity.findViewById(android.R.id.content)
val closeable: SafeCloseable = viewCapture.startCapture(rootView, "rootViewId")
@@ -69,7 +70,8 @@
Settings.Global.putInt(context.contentResolver, VIEW_CAPTURE_ENABLED, 1)
activityScenarioRule.scenario.onActivity { activity ->
- val viewCapture: ViewCapture = SettingsAwareViewCapture(context, MAIN_EXECUTOR)
+ val viewCapture: ViewCapture =
+ SettingsAwareViewCapture(context, Choreographer.getInstance(), MAIN_EXECUTOR)
val rootView: View = activity.findViewById(android.R.id.content)
val closeable: SafeCloseable = viewCapture.startCapture(rootView, "rootViewId")
diff --git a/viewcapturelib/tests/com/android/app/viewcapture/ViewCaptureTest.kt b/viewcapturelib/tests/com/android/app/viewcapture/ViewCaptureTest.kt
index 47f1a7b..b341fe9 100644
--- a/viewcapturelib/tests/com/android/app/viewcapture/ViewCaptureTest.kt
+++ b/viewcapturelib/tests/com/android/app/viewcapture/ViewCaptureTest.kt
@@ -19,6 +19,7 @@
import android.content.Intent
import android.media.permission.SafeCloseable
import android.testing.AndroidTestingRunner
+import android.view.Choreographer
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
@@ -40,7 +41,7 @@
private val initPoolSize = 15
private val viewCapture by lazy {
object :
- ViewCapture(memorySize, initPoolSize, MAIN_EXECUTOR) {}
+ ViewCapture(memorySize, initPoolSize, Choreographer.getInstance(), MAIN_EXECUTOR) {}
}
private val activityIntent =
@@ -51,29 +52,33 @@
@Test
fun testWindowListenerDumpsOneFrameAfterInvalidate() {
activityScenarioRule.scenario.onActivity { activity ->
- val closeable = startViewCaptureAndInvalidateNTimes(1, activity)
- val rootView = activity.findViewById<View>(android.R.id.content)
- val data = viewCapture.getDumpTask(rootView).get().get()
+ Choreographer.getInstance().postFrameCallback {
+ val closeable = startViewCaptureAndInvalidateNTimes(1, activity)
+ val rootView = activity.findViewById<View>(android.R.id.content)
+ val data = viewCapture.getDumpTask(rootView).get().get()
- assertEquals(1, data.frameDataList.size)
- verifyTestActivityViewHierarchy(data)
- closeable.close()
+ assertEquals(1, data.frameDataList.size)
+ verifyTestActivityViewHierarchy(data)
+ closeable.close()
+ }
}
}
@Test
fun testWindowListenerDumpsCorrectlyAfterRecyclingStarted() {
activityScenarioRule.scenario.onActivity { activity ->
- val closeable = startViewCaptureAndInvalidateNTimes(memorySize + 5, activity)
- val rootView = activity.findViewById<View>(android.R.id.content)
- val data = viewCapture.getDumpTask(rootView).get().get()
+ Choreographer.getInstance().postFrameCallback {
+ val closeable = startViewCaptureAndInvalidateNTimes(memorySize + 5, activity)
+ val rootView = activity.findViewById<View>(android.R.id.content)
+ val data = viewCapture.getDumpTask(rootView).get().get()
- // since ViewCapture MEMORY_SIZE is [viewCaptureMemorySize], only
- // [viewCaptureMemorySize] frames are exported, although the view is invalidated
- // [viewCaptureMemorySize + 5] times
- assertEquals(memorySize, data.frameDataList.size)
- verifyTestActivityViewHierarchy(data)
- closeable.close()
+ // since ViewCapture MEMORY_SIZE is [viewCaptureMemorySize], only
+ // [viewCaptureMemorySize] frames are exported, although the view is invalidated
+ // [viewCaptureMemorySize + 5] times
+ assertEquals(memorySize, data.frameDataList.size)
+ verifyTestActivityViewHierarchy(data)
+ closeable.close()
+ }
}
}