Move Sampling profiler from DevSupportManagerBase to BridgeDevSupportManager

Summary:
## Rationale
The sampling profiler not supported with bridgeless mode. Why: [the sampling profiler uses the JavaScriptExecutorFactory](https://www.internalfb.com/code/fbsource/[927e2dc640a45e7e408f621cb06f6b1056ce357a]/xplat/js/react-native-github/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java?lines=654-655), which is explicitly not implemented in bridgeless mode: [AsyncDevSupportManager.java](https://www.internalfb.com/code/fbsource/[927e2dc640a45e7e408f621cb06f6b1056ce357a]/fbandroid/java/com/facebook/venice/AsyncDevSupportManagerImpl.java?lines=108).

So, this diff moves the sampling profiler into BridgeDevSupportManager.

Changelog: [Internal]

Reviewed By: JoshuaGross

Differential Revision: D29006837

fbshipit-source-id: 2bb2889253b33d7b5b00d3e935e8d624f1c3612e
This commit is contained in:
Ramanpreet Nara
2021-06-10 16:47:20 -07:00
committed by Facebook GitHub Bot
parent 61dda3242d
commit 67a486e577
2 changed files with 78 additions and 73 deletions
@@ -8,6 +8,7 @@
package com.facebook.react.devsupport;
import android.content.Context;
import android.widget.Toast;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.debug.holder.PrinterHolder;
@@ -16,14 +17,17 @@ import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.JSBundleLoader;
import com.facebook.react.bridge.JavaJSExecutor;
import com.facebook.react.bridge.JavaScriptExecutorFactory;
import com.facebook.react.bridge.ReactMarker;
import com.facebook.react.bridge.ReactMarkerConstants;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.common.futures.SimpleSettableFuture;
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
import com.facebook.react.devsupport.interfaces.DevOptionHandler;
import com.facebook.react.devsupport.interfaces.DevSplitBundleCallback;
import com.facebook.react.packagerconnection.RequestHandler;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@@ -57,6 +61,8 @@ import java.util.concurrent.TimeoutException;
* {@code <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>}
*/
public final class BridgeDevSupportManager extends DevSupportManagerBase {
private boolean mIsSamplingProfilerEnabled = false;
public BridgeDevSupportManager(
Context applicationContext,
ReactInstanceDevHelper reactInstanceManagerHelper,
@@ -75,6 +81,32 @@ public final class BridgeDevSupportManager extends DevSupportManagerBase {
devBundleDownloadListener,
minNumShakes,
customPackagerCommandHandlers);
if (getDevSettings().isStartSamplingProfilerOnInit()) {
// Only start the profiler. If its already running, there is an error
if (!mIsSamplingProfilerEnabled) {
toggleJSSamplingProfiler();
} else {
Toast.makeText(
applicationContext,
"JS Sampling Profiler was already running, so did not start the sampling profiler",
Toast.LENGTH_LONG)
.show();
}
}
addCustomDevOption(
mIsSamplingProfilerEnabled
? applicationContext.getString(
com.facebook.react.R.string.catalyst_sample_profiler_disable)
: applicationContext.getString(
com.facebook.react.R.string.catalyst_sample_profiler_enable),
new DevOptionHandler() {
@Override
public void onOptionSelected() {
toggleJSSamplingProfiler();
}
});
}
@Override
@@ -173,4 +205,50 @@ public final class BridgeDevSupportManager extends DevSupportManagerBase {
reloadJSFromServer(bundleURL);
}
}
/** Starts of stops the sampling profiler */
private void toggleJSSamplingProfiler() {
JavaScriptExecutorFactory javaScriptExecutorFactory =
getReactInstanceDevHelper().getJavaScriptExecutorFactory();
if (!mIsSamplingProfilerEnabled) {
try {
javaScriptExecutorFactory.startSamplingProfiler();
Toast.makeText(getApplicationContext(), "Starting Sampling Profiler", Toast.LENGTH_SHORT)
.show();
} catch (UnsupportedOperationException e) {
Toast.makeText(
getApplicationContext(),
javaScriptExecutorFactory.toString() + " does not support Sampling Profiler",
Toast.LENGTH_LONG)
.show();
} finally {
mIsSamplingProfilerEnabled = true;
}
} else {
try {
final String outputPath =
File.createTempFile(
"sampling-profiler-trace", ".cpuprofile", getApplicationContext().getCacheDir())
.getPath();
javaScriptExecutorFactory.stopSamplingProfiler(outputPath);
Toast.makeText(
getApplicationContext(),
"Saved results from Profiler to " + outputPath,
Toast.LENGTH_LONG)
.show();
} catch (IOException e) {
FLog.e(
ReactConstants.TAG,
"Could not create temporary file for saving results from Sampling Profiler");
} catch (UnsupportedOperationException e) {
Toast.makeText(
getApplicationContext(),
javaScriptExecutorFactory.toString() + "does not support Sampling Profiler",
Toast.LENGTH_LONG)
.show();
} finally {
mIsSamplingProfilerEnabled = false;
}
}
}
}
@@ -29,7 +29,6 @@ import com.facebook.infer.annotation.Assertions;
import com.facebook.react.R;
import com.facebook.react.bridge.DefaultNativeModuleCallExceptionHandler;
import com.facebook.react.bridge.JSBundleLoader;
import com.facebook.react.bridge.JavaScriptExecutorFactory;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactMarker;
import com.facebook.react.bridge.ReactMarkerConstants;
@@ -51,7 +50,6 @@ import com.facebook.react.modules.core.RCTNativeAppEventEmitter;
import com.facebook.react.packagerconnection.RequestHandler;
import com.facebook.react.packagerconnection.Responder;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@@ -76,7 +74,6 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
private static final String FLIPPER_DEBUGGER_URL =
"flipper://null/Hermesdebuggerrn?device=React%20Native";
private static final String FLIPPER_DEVTOOLS_URL = "flipper://null/React?device=React%20Native";
private boolean mIsSamplingProfilerEnabled = false;
private static final String EXOPACKAGE_LOCATION_FORMAT =
"/data/local/tmp/exopackage/%s//secondary-dex";
@@ -201,19 +198,6 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
mRedBoxHandler = redBoxHandler;
mDevLoadingViewController = new DevLoadingViewController(reactInstanceDevHelper);
if (mDevSettings.isStartSamplingProfilerOnInit()) {
// Only start the profiler. If its already running, there is an error
if (!mIsSamplingProfilerEnabled) {
toggleJSSamplingProfiler();
} else {
Toast.makeText(
mApplicationContext,
"JS Sampling Profiler was already running, so did not start the sampling profiler",
Toast.LENGTH_LONG)
.show();
}
}
}
@Override
@@ -533,17 +517,6 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
}
});
options.put(
mIsSamplingProfilerEnabled
? mApplicationContext.getString(R.string.catalyst_sample_profiler_disable)
: mApplicationContext.getString(R.string.catalyst_sample_profiler_enable),
new DevOptionHandler() {
@Override
public void onOptionSelected() {
toggleJSSamplingProfiler();
}
});
options.put(
mDevSettings.isFpsDebugEnabled()
? mApplicationContext.getString(R.string.catalyst_perf_monitor_stop)
@@ -612,52 +585,6 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
}
}
/** Starts of stops the sampling profiler */
private void toggleJSSamplingProfiler() {
JavaScriptExecutorFactory javaScriptExecutorFactory =
mReactInstanceDevHelper.getJavaScriptExecutorFactory();
if (!mIsSamplingProfilerEnabled) {
try {
javaScriptExecutorFactory.startSamplingProfiler();
Toast.makeText(mApplicationContext, "Starting Sampling Profiler", Toast.LENGTH_SHORT)
.show();
} catch (UnsupportedOperationException e) {
Toast.makeText(
mApplicationContext,
javaScriptExecutorFactory.toString() + " does not support Sampling Profiler",
Toast.LENGTH_LONG)
.show();
} finally {
mIsSamplingProfilerEnabled = true;
}
} else {
try {
final String outputPath =
File.createTempFile(
"sampling-profiler-trace", ".cpuprofile", mApplicationContext.getCacheDir())
.getPath();
javaScriptExecutorFactory.stopSamplingProfiler(outputPath);
Toast.makeText(
mApplicationContext,
"Saved results from Profiler to " + outputPath,
Toast.LENGTH_LONG)
.show();
} catch (IOException e) {
FLog.e(
ReactConstants.TAG,
"Could not create temporary file for saving results from Sampling Profiler");
} catch (UnsupportedOperationException e) {
Toast.makeText(
mApplicationContext,
javaScriptExecutorFactory.toString() + "does not support Sampling Profiler",
Toast.LENGTH_LONG)
.show();
} finally {
mIsSamplingProfilerEnabled = false;
}
}
}
/**
* {@link ReactInstanceDevCommandsHandler} is responsible for enabling/disabling dev support when
* a React view is attached/detached or when application state changes (e.g. the application is