@Override public void doFrame(long frameTimeNanos) { if (isPaused.get() && !isRunningTasks.get()) { return; } // If the JS thread is busy for multiple frames we cancel any other pending runnable. if (mCurrentIdleCallbackRunnable != null) { mCurrentIdleCallbackRunnable.cancel(); } mCurrentIdleCallbackRunnable = new IdleCallbackRunnable(frameTimeNanos); getReactApplicationContext().runOnJSQueueThread(mCurrentIdleCallbackRunnable); Assertions.assertNotNull(mReactChoreographer).postFrameCallback( ReactChoreographer.CallbackType.IDLE_EVENT, this); }
/** * Calls all timers that have expired since the last time this frame callback was called. */ @Override public void doFrame(long frameTimeNanos) { if (isPaused.get()) { return; } long frameTimeMillis = frameTimeNanos / 1000000; synchronized (mTimerGuard) { while (!mTimers.isEmpty() && mTimers.peek().mTargetTime < frameTimeMillis) { Timer timer = mTimers.poll(); WritableArray timersForContext = mTimersToCall.get(timer.mExecutorToken); if (timersForContext == null) { timersForContext = Arguments.createArray(); mTimersToCall.put(timer.mExecutorToken, timersForContext); } timersForContext.pushInt(timer.mCallbackID); if (timer.mRepeat) { timer.mTargetTime = frameTimeMillis + timer.mInterval; mTimers.add(timer); } else { mTimerIdsToTimers.remove(timer.mCallbackID); } } } for (Map.Entry<ExecutorToken, WritableArray> entry : mTimersToCall.entrySet()) { getReactApplicationContext().getJSModule(entry.getKey(), JSTimersExecution.class) .callTimers(entry.getValue()); } mTimersToCall.clear(); Assertions.assertNotNull(mReactChoreographer) .postFrameCallback(ReactChoreographer.CallbackType.TIMERS_EVENTS, this); }
private void setChoreographerCallback() { if (!mFrameCallbackPosted) { Assertions.assertNotNull(mReactChoreographer).postFrameCallback( ReactChoreographer.CallbackType.TIMERS_EVENTS, mFrameCallback); mFrameCallbackPosted = true; } }
private void clearChoreographerCallback() { if (mFrameCallbackPosted) { Assertions.assertNotNull(mReactChoreographer).removeFrameCallback( ReactChoreographer.CallbackType.TIMERS_EVENTS, mFrameCallback); mFrameCallbackPosted = false; } }
@Override public void onHostResume() { UiThreadUtil.assertOnUiThread(); Assertions.assumeCondition(mCurrentFrameCallback == null); if (mRCTEventEmitter == null) { mRCTEventEmitter = mReactContext.getJSModule(RCTEventEmitter.class); } mCurrentFrameCallback = new ScheduleDispatchFrameCallback(); ReactChoreographer.getInstance() .postFrameCallback(ReactChoreographer.CallbackType.TIMERS_EVENTS, mCurrentFrameCallback); }
@Override public void doFrame(long frameTimeNanos) { UiThreadUtil.assertOnUiThread(); if (mShouldStop) { return; } Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ScheduleDispatchFrameCallback"); try { moveStagedEventsToDispatchQueue(); if (!mHasDispatchScheduled) { mHasDispatchScheduled = true; Systrace.startAsyncFlow( Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ScheduleDispatchFrameCallback", mHasDispatchScheduledCount); mReactContext.runOnJSQueueThread(mDispatchEventsRunnable); } ReactChoreographer.getInstance() .postFrameCallback(ReactChoreographer.CallbackType.TIMERS_EVENTS, this); } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } }
@Before public void prepareModules() { PowerMockito.mockStatic(Arguments.class); when(Arguments.createArray()).thenAnswer( new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { return new JavaOnlyArray(); } }); PowerMockito.mockStatic(SystemClock.class); when(SystemClock.currentTimeMillis()).thenReturn(mCurrentTimeNs / 1000000); when(SystemClock.nanoTime()).thenReturn(mCurrentTimeNs); mChoreographerMock = mock(ReactChoreographer.class); PowerMockito.mockStatic(ReactChoreographer.class); when(ReactChoreographer.getInstance()).thenReturn(mChoreographerMock); CatalystInstance reactInstance = mock(CatalystInstance.class); ReactApplicationContext reactContext = mock(ReactApplicationContext.class); when(reactContext.getCatalystInstance()).thenReturn(reactInstance); mCurrentTimeNs = 0; mPostFrameCallbackHandler = new PostFrameCallbackHandler(); doAnswer(mPostFrameCallbackHandler) .when(mChoreographerMock) .postFrameCallback( eq(ReactChoreographer.CallbackType.TIMERS_EVENTS), any(Choreographer.FrameCallback.class)); mTiming = new Timing(reactContext); mJSTimersMock = mock(JSTimersExecution.class); mExecutorTokenMock = mock(ExecutorToken.class); when(reactContext.getJSModule(mExecutorTokenMock, JSTimersExecution.class)).thenReturn(mJSTimersMock); mTiming.initialize(); }
@Override public void initialize() { // Safe to acquire choreographer here, as initialize() is invoked from UI thread. mReactChoreographer = ReactChoreographer.getInstance(); getReactApplicationContext().addLifecycleEventListener(this); HeadlessJsTaskContext headlessJsTaskContext = HeadlessJsTaskContext.getInstance(getReactApplicationContext()); headlessJsTaskContext.addTaskEventListener(this); }
private void setChoreographerCallback() { if (!mFrameCallbackPosted) { Assertions.assertNotNull(mReactChoreographer).postFrameCallback( ReactChoreographer.CallbackType.TIMERS_EVENTS, mTimerFrameCallback); mFrameCallbackPosted = true; } }
private void clearChoreographerCallback() { HeadlessJsTaskContext headlessJsTaskContext = HeadlessJsTaskContext.getInstance(getReactApplicationContext()); if (mFrameCallbackPosted && isPaused.get() && !headlessJsTaskContext.hasActiveTasks()) { Assertions.assertNotNull(mReactChoreographer).removeFrameCallback( ReactChoreographer.CallbackType.TIMERS_EVENTS, mTimerFrameCallback); mFrameCallbackPosted = false; } }
private void setChoreographerIdleCallback() { if (!mFrameIdleCallbackPosted) { Assertions.assertNotNull(mReactChoreographer).postFrameCallback( ReactChoreographer.CallbackType.IDLE_EVENT, mIdleFrameCallback); mFrameIdleCallbackPosted = true; } }
private void clearChoreographerIdleCallback() { if (mFrameIdleCallbackPosted) { Assertions.assertNotNull(mReactChoreographer).removeFrameCallback( ReactChoreographer.CallbackType.IDLE_EVENT, mIdleFrameCallback); mFrameIdleCallbackPosted = false; } }
@Override public void initialize() { // Safe to acquire choreographer here, as initialize() is invoked from UI thread. mReactChoreographer = ReactChoreographer.getInstance(); ReactApplicationContext reactCtx = getReactApplicationContext(); UIManagerModule uiManager = reactCtx.getNativeModule(UIManagerModule.class); final NativeAnimatedNodesManager nodesManager = new NativeAnimatedNodesManager(uiManager); mAnimatedFrameCallback = new GuardedChoreographerFrameCallback(reactCtx) { @Override protected void doFrameGuarded(final long frameTimeNanos) { ArrayList<UIThreadOperation> operations; synchronized (mOperationsCopyLock) { operations = mReadyOperations; mReadyOperations = null; } if (operations != null) { for (int i = 0, size = operations.size(); i < size; i++) { operations.get(i).execute(nodesManager); } } if (nodesManager.hasActiveAnimations()) { nodesManager.runUpdates(frameTimeNanos); } // TODO: Would be great to avoid adding this callback in case there are no active animations // and no outstanding tasks on the operations queue. Apparently frame callbacks can only // be posted from the UI thread and therefore we cannot schedule them directly from // @ReactMethod methods Assertions.assertNotNull(mReactChoreographer).postFrameCallback( ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mAnimatedFrameCallback); } }; reactCtx.addLifecycleEventListener(this); }
@Override public void initialize() { // Safe to acquire choreographer here, as initialize() is invoked from UI thread. mReactChoreographer = ReactChoreographer.getInstance(); getReactApplicationContext().addLifecycleEventListener(this); }
private void post() { ReactChoreographer.getInstance() .postFrameCallback(ReactChoreographer.CallbackType.TIMERS_EVENTS, mCurrentFrameCallback); }
@Override public void initialize() { // Safe to acquire choreographer here, as initialize() is invoked from UI thread. mReactChoreographer = ReactChoreographer.getInstance(); ReactApplicationContext reactCtx = getReactApplicationContext(); UIImplementation uiImplementation = reactCtx.getNativeModule(UIManagerModule.class).getUIImplementation(); final NativeAnimatedNodesManager nodesManager = new NativeAnimatedNodesManager(uiImplementation); mAnimatedFrameCallback = new GuardedChoreographerFrameCallback(reactCtx) { @Override protected void doFrameGuarded(final long frameTimeNanos) { ArrayList<UIThreadOperation> operations; synchronized (mOperationsCopyLock) { operations = mReadyOperations; mReadyOperations = null; } if (operations != null) { for (int i = 0, size = operations.size(); i < size; i++) { operations.get(i).execute(nodesManager); } } if (nodesManager.hasActiveAnimations()) { nodesManager.runUpdates(frameTimeNanos); } // TODO: Would be great to avoid adding this callback in case there are no active animations // and no outstanding tasks on the operations queue. Apparently frame callbacks can only // be posted from the UI thread and therefore we cannot schedule them directly from // @ReactMethod methods Assertions.assertNotNull(mReactChoreographer).postFrameCallback( ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mAnimatedFrameCallback); } }; reactCtx.addLifecycleEventListener(this); }
private void clearFrameCallback() { Assertions.assertNotNull(mReactChoreographer).removeFrameCallback( ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mAnimatedFrameCallback); }
private void enqueueFrameCallback() { Assertions.assertNotNull(mReactChoreographer).postFrameCallback( ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mAnimatedFrameCallback); }
/** * Calls all timers that have expired since the last time this frame callback was called. */ @Override public void doFrame(long frameTimeNanos) { if (isPaused.get() && !isRunningTasks.get()) { return; } long frameTimeMillis = frameTimeNanos / 1000000; synchronized (mTimerGuard) { while (!mTimers.isEmpty() && mTimers.peek().mTargetTime < frameTimeMillis) { Timer timer = mTimers.poll(); WritableArray timersForContext = mTimersToCall.get(timer.mExecutorToken); if (timersForContext == null) { timersForContext = Arguments.createArray(); mTimersToCall.put(timer.mExecutorToken, timersForContext); } timersForContext.pushInt(timer.mCallbackID); if (timer.mRepeat) { timer.mTargetTime = frameTimeMillis + timer.mInterval; mTimers.add(timer); } else { SparseArray<Timer> timers = mTimerIdsToTimers.get(timer.mExecutorToken); if (timers != null) { timers.remove(timer.mCallbackID); if (timers.size() == 0) { mTimerIdsToTimers.remove(timer.mExecutorToken); } } } } } for (Map.Entry<ExecutorToken, WritableArray> entry : mTimersToCall.entrySet()) { getReactApplicationContext().getJSModule(entry.getKey(), JSTimersExecution.class) .callTimers(entry.getValue()); } mTimersToCall.clear(); Assertions.assertNotNull(mReactChoreographer) .postFrameCallback(ReactChoreographer.CallbackType.TIMERS_EVENTS, this); }