Fix ReactIdleDetection from Android X migration

Summary:
The implementation for this class was commented out in D14200097.

ServerSnapshotTests rely on this class to decide when test app setup is finished [here](diffusion/FBS/browse/master/fbandroid/instrumentation_tests/com/facebook/react/screenshots/shared/ReactNativeScreenshotTestCase.java;676aecf86a816bba8eb8571bc327e77c8f2e149b$164).

The only change I made is to use InstrumentationRegistry from Androidx instead of support.

Reviewed By: rickhanlonii, mdvacca

Differential Revision: D15068069

fbshipit-source-id: c69c7d46a1068836f9a9303de11e9a7a36b4e6d9
This commit is contained in:
Joshua Gross
2019-10-05 01:53:01 -07:00
committed by Facebook Github Bot
parent 375ef14c04
commit 6166645560
@@ -6,7 +6,14 @@
*/
package com.facebook.react.testing.idledetection;
import android.app.Instrumentation;
import android.os.SystemClock;
import androidx.test.InstrumentationRegistry;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.modules.core.ChoreographerCompat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class ReactIdleDetectionUtil {
@@ -21,96 +28,93 @@ public class ReactIdleDetectionUtil {
*/
public static void waitForBridgeAndUIIdle(
ReactBridgeIdleSignaler idleSignaler, final ReactContext reactContext, long timeoutMs) {
UiThreadUtil.assertNotOnUiThread();
return;
// TODO: re-enable after cleanup of android-x migration
// UiThreadUtil.assertNotOnUiThread();
//
// long startTime = SystemClock.uptimeMillis();
// waitInner(idleSignaler, timeoutMs);
//
// long timeToWait = Math.max(1, timeoutMs - (SystemClock.uptimeMillis() - startTime));
// waitForChoreographer(timeToWait);
// waitForJSIdle(reactContext);
//
// timeToWait = Math.max(1, timeoutMs - (SystemClock.uptimeMillis() - startTime));
// waitInner(idleSignaler, timeToWait);
// timeToWait = Math.max(1, timeoutMs - (SystemClock.uptimeMillis() - startTime));
// waitForChoreographer(timeToWait);
long startTime = SystemClock.uptimeMillis();
waitInner(idleSignaler, timeoutMs);
long timeToWait = Math.max(1, timeoutMs - (SystemClock.uptimeMillis() - startTime));
waitForChoreographer(timeToWait);
waitForJSIdle(reactContext);
timeToWait = Math.max(1, timeoutMs - (SystemClock.uptimeMillis() - startTime));
waitInner(idleSignaler, timeToWait);
timeToWait = Math.max(1, timeoutMs - (SystemClock.uptimeMillis() - startTime));
waitForChoreographer(timeToWait);
}
// private static void waitForChoreographer(long timeToWait) {
// final int waitFrameCount = 2;
// final CountDownLatch latch = new CountDownLatch(1);
// UiThreadUtil.runOnUiThread(
// new Runnable() {
// @Override
// public void run() {
// final ChoreographerCompat choreographerCompat = ChoreographerCompat.getInstance();
// choreographerCompat.postFrameCallback(
// new ChoreographerCompat.FrameCallback() {
//
// private int frameCount = 0;
//
// @Override
// public void doFrame(long frameTimeNanos) {
// frameCount++;
// if (frameCount == waitFrameCount) {
// latch.countDown();
// } else {
// choreographerCompat.postFrameCallback(this);
// }
// }
// });
// }
// });
// try {
// if (!latch.await(timeToWait, TimeUnit.MILLISECONDS)) {
// throw new RuntimeException("Timed out waiting for Choreographer");
// }
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// }
//
// private static void waitForJSIdle(ReactContext reactContext) {
// if (!reactContext.hasActiveCatalystInstance()) {
// return;
// }
// final CountDownLatch latch = new CountDownLatch(1);
//
// reactContext.runOnJSQueueThread(
// new Runnable() {
// @Override
// public void run() {
// latch.countDown();
// }
// });
//
// try {
// if (!latch.await(5000, TimeUnit.MILLISECONDS)) {
// throw new RuntimeException("Timed out waiting for JS thread");
// }
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// }
//
// private static void waitInner(ReactBridgeIdleSignaler idleSignaler, long timeToWait) {
// // TODO gets broken in gradle, do we need it?
// Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
// long startTime = SystemClock.uptimeMillis();
// boolean bridgeWasIdle = false;
// while (SystemClock.uptimeMillis() - startTime < timeToWait) {
// boolean bridgeIsIdle = idleSignaler.isBridgeIdle();
// if (bridgeIsIdle && bridgeWasIdle) {
// return;
// }
// bridgeWasIdle = bridgeIsIdle;
// long newTimeToWait = Math.max(1, timeToWait - (SystemClock.uptimeMillis() - startTime));
// idleSignaler.waitForIdle(newTimeToWait);
// instrumentation.waitForIdleSync();
// }
// throw new RuntimeException("Timed out waiting for bridge and UI idle!");
// }
private static void waitForChoreographer(long timeToWait) {
final int waitFrameCount = 2;
final CountDownLatch latch = new CountDownLatch(1);
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
final ChoreographerCompat choreographerCompat = ChoreographerCompat.getInstance();
choreographerCompat.postFrameCallback(
new ChoreographerCompat.FrameCallback() {
private int frameCount = 0;
@Override
public void doFrame(long frameTimeNanos) {
frameCount++;
if (frameCount == waitFrameCount) {
latch.countDown();
} else {
choreographerCompat.postFrameCallback(this);
}
}
});
}
});
try {
if (!latch.await(timeToWait, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("Timed out waiting for Choreographer");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void waitForJSIdle(ReactContext reactContext) {
if (!reactContext.hasActiveCatalystInstance()) {
return;
}
final CountDownLatch latch = new CountDownLatch(1);
reactContext.runOnJSQueueThread(
new Runnable() {
@Override
public void run() {
latch.countDown();
}
});
try {
if (!latch.await(5000, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("Timed out waiting for JS thread");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void waitInner(ReactBridgeIdleSignaler idleSignaler, long timeToWait) {
// TODO gets broken in gradle, do we need it?
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
long startTime = SystemClock.uptimeMillis();
boolean bridgeWasIdle = false;
while (SystemClock.uptimeMillis() - startTime < timeToWait) {
boolean bridgeIsIdle = idleSignaler.isBridgeIdle();
if (bridgeIsIdle && bridgeWasIdle) {
return;
}
bridgeWasIdle = bridgeIsIdle;
long newTimeToWait = Math.max(1, timeToWait - (SystemClock.uptimeMillis() - startTime));
idleSignaler.waitForIdle(newTimeToWait);
instrumentation.waitForIdleSync();
}
throw new RuntimeException("Timed out waiting for bridge and UI idle!");
}
}