BREAKING: Android: Refactor so uimanager can depend on modules/core

Summary:
cc astreet

The goal of this PR is to enable the buck module `uimanager` to depend on `modules/core` without introducing any dependency cycles.

PR #11008 relies on this PR. PR #11008 needs `uimanager` to depend on `modules/core` so that `uimanager` can fire events using `RCTDeviceEventEmitter` which is in `modules/core`.

This PR moved a number of classes and interfaces:
  - `com.facebook.react.modules.debug.DeveloperSettings` -> `com.facebook.react.modules.debug.interfaces.DeveloperSettings`
  - `com.facebook.react.devsupport.DevOptionHandler` -> `com.facebook.react.devsupport.interfaces.DevOptionHandler `
  - `com.facebook.react.devsupport.DevSupportManager` -> `com.facebook.react.devsupport.interfaces.DevSupportManager`
  - `com.facebook.react.devsupport.DevServerHelper.PackagerStatusCallback` -> `com.facebook.react.devsupport.interfaces.PackagerStatusCallback`
  - The class `com.facebook.react.devsupport.StackTraceHelper.StackFrame` was renamed to `StackFram
Closes https://github.com/facebook/react-native/pull/12329

Differential Revision: D4551160

Pulled By: astreet

fbshipit-source-id: 3a78443c4f30469b13ddfbdcc9bbef6af9e8381a
This commit is contained in:
Adam Comella
2017-02-13 11:02:44 -08:00
committed by Facebook Github Bot
parent 4161bada4a
commit ea6845ca22
37 changed files with 158 additions and 51 deletions
@@ -0,0 +1,23 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.modules.appregistry;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.WritableMap;
/**
* JS module interface - main entry point for launching React application for a given key.
*/
public interface AppRegistry extends JavaScriptModule {
void runApplication(String appKey, WritableMap appParameters);
void unmountApplicationComponentAtRootTag(int rootNodeTag);
void startHeadlessTask(int taskId, String taskKey, WritableMap data);
}
@@ -0,0 +1,12 @@
include_defs('//ReactAndroid/DEFS')
android_library(
name = 'appregistry',
srcs = glob(['**/*.java']),
deps = [
react_native_target('java/com/facebook/react/bridge:bridge'),
],
visibility = [
'PUBLIC',
],
)
@@ -9,10 +9,9 @@ android_library(
react_native_dep('third-party/java/jsr-305:jsr-305'),
react_native_target('java/com/facebook/react/bridge:bridge'),
react_native_target('java/com/facebook/react/common:common'),
react_native_target('java/com/facebook/react/devsupport:devsupport'),
react_native_target('java/com/facebook/react/devsupport:interfaces'),
react_native_target('java/com/facebook/react/jstasks:jstasks'),
react_native_target('java/com/facebook/react/module/annotations:annotations'),
react_native_target('java/com/facebook/react/uimanager:uimanager'),
],
visibility = [
'PUBLIC',
@@ -18,7 +18,7 @@ import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType;
import com.facebook.react.devsupport.DevSupportManager;
import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.common.JavascriptException;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.module.annotations.ReactModule;
@@ -0,0 +1,138 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.modules.core;
import java.util.ArrayDeque;
import android.view.Choreographer;
import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.common.ReactConstants;
/**
* A simple wrapper around Choreographer that allows us to control the order certain callbacks
* are executed within a given frame. The main difference is that we enforce this is accessed from
* the UI thread: this is because this ordering cannot be guaranteed across multiple threads.
*/
public class ReactChoreographer {
public static enum CallbackType {
/**
* For use by perf markers that need to happen immediately after draw
*/
PERF_MARKERS(0),
/**
* For use by {@link com.facebook.react.uimanager.UIManagerModule}
*/
DISPATCH_UI(1),
/**
* For use by {@link com.facebook.react.animated.NativeAnimatedModule}
*/
NATIVE_ANIMATED_MODULE(2),
/**
* Events that make JS do things.
*/
TIMERS_EVENTS(3),
/**
* Event used to trigger the idle callback. Called after all UI work has been
* dispatched to JS.
*/
IDLE_EVENT(4),
;
private final int mOrder;
private CallbackType(int order) {
mOrder = order;
}
/*package*/ int getOrder() {
return mOrder;
}
}
private static ReactChoreographer sInstance;
public static ReactChoreographer getInstance() {
UiThreadUtil.assertOnUiThread();
if (sInstance == null) {
sInstance = new ReactChoreographer();
}
return sInstance;
}
private final Choreographer mChoreographer;
private final ReactChoreographerDispatcher mReactChoreographerDispatcher;
private final ArrayDeque<Choreographer.FrameCallback>[] mCallbackQueues;
private int mTotalCallbacks = 0;
private boolean mHasPostedCallback = false;
private ReactChoreographer() {
mChoreographer = Choreographer.getInstance();
mReactChoreographerDispatcher = new ReactChoreographerDispatcher();
mCallbackQueues = new ArrayDeque[CallbackType.values().length];
for (int i = 0; i < mCallbackQueues.length; i++) {
mCallbackQueues[i] = new ArrayDeque<>();
}
}
public void postFrameCallback(CallbackType type, Choreographer.FrameCallback frameCallback) {
UiThreadUtil.assertOnUiThread();
mCallbackQueues[type.getOrder()].addLast(frameCallback);
mTotalCallbacks++;
Assertions.assertCondition(mTotalCallbacks > 0);
if (!mHasPostedCallback) {
mChoreographer.postFrameCallback(mReactChoreographerDispatcher);
mHasPostedCallback = true;
}
}
public void removeFrameCallback(CallbackType type, Choreographer.FrameCallback frameCallback) {
UiThreadUtil.assertOnUiThread();
if (mCallbackQueues[type.getOrder()].removeFirstOccurrence(frameCallback)) {
mTotalCallbacks--;
maybeRemoveFrameCallback();
} else {
FLog.e(ReactConstants.TAG, "Tried to remove non-existent frame callback");
}
}
private void maybeRemoveFrameCallback() {
Assertions.assertCondition(mTotalCallbacks >= 0);
if (mTotalCallbacks == 0 && mHasPostedCallback) {
mChoreographer.removeFrameCallback(mReactChoreographerDispatcher);
mHasPostedCallback = false;
}
}
private class ReactChoreographerDispatcher implements Choreographer.FrameCallback {
@Override
public void doFrame(long frameTimeNanos) {
mHasPostedCallback = false;
for (int i = 0; i < mCallbackQueues.length; i++) {
int initialLength = mCallbackQueues[i].size();
for (int callback = 0; callback < initialLength; callback++) {
mCallbackQueues[i].removeFirst().doFrame(frameTimeNanos);
mTotalCallbacks--;
}
}
maybeRemoveFrameCallback();
}
}
}
@@ -35,11 +35,10 @@ import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.common.SystemClock;
import com.facebook.react.devsupport.DevSupportManager;
import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.jstasks.HeadlessJsTaskEventListener;
import com.facebook.react.jstasks.HeadlessJsTaskContext;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.ReactChoreographer;
/**
* Native module for JS timer execution. Timers fire on frame boundaries.
@@ -24,6 +24,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.modules.debug.interfaces.DeveloperSettings;
/**
* Module that records debug information during transitions (animated navigation events such as
@@ -2,7 +2,7 @@ include_defs('//ReactAndroid/DEFS')
android_library(
name = 'debug',
srcs = glob(['**/*.java']),
srcs = glob(['*.java']),
deps = [
react_native_dep('libraries/fbcore/src/main/java/com/facebook/common/logging:logging'),
react_native_dep('third-party/java/infer-annotations:infer-annotations'),
@@ -10,6 +10,7 @@ android_library(
react_native_target('java/com/facebook/react/bridge:bridge'),
react_native_target('java/com/facebook/react/common:common'),
react_native_target('java/com/facebook/react/module/annotations:annotations'),
react_native_target('java/com/facebook/react/modules/debug:interfaces'),
react_native_target('java/com/facebook/react/uimanager:uimanager'),
],
visibility = [
@@ -17,3 +18,12 @@ android_library(
],
)
android_library(
name = 'interfaces',
srcs = glob(['interfaces/*.java']),
deps = [
],
visibility = [
'PUBLIC',
],
)
@@ -7,7 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.modules.debug;
package com.facebook.react.modules.debug.interfaces;
/**
* Provides access to React Native developers settings.