diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index 6b8370c8895..74ce6e58533 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -292,9 +292,18 @@ public class ReactInstanceManager { public @Nullable Activity getCurrentActivity() { return ReactInstanceManager.this.mCurrentActivity; } + + @Override + public JavaScriptExecutorFactory getJavaScriptExecutorFactory() { + return ReactInstanceManager.this.getJSExecutorFactory(); + } }; } + private JavaScriptExecutorFactory getJSExecutorFactory() { + return mJavaScriptExecutorFactory; + } + public DevSupportManager getDevSupportManager() { return mDevSupportManager; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSCJavaScriptExecutorFactory.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSCJavaScriptExecutorFactory.java index ed60de01710..2d0be622101 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSCJavaScriptExecutorFactory.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSCJavaScriptExecutorFactory.java @@ -24,6 +24,18 @@ public class JSCJavaScriptExecutorFactory implements JavaScriptExecutorFactory { return new JSCJavaScriptExecutor(jscConfig); } + @Override + public void startSamplingProfiler() { + throw new UnsupportedOperationException( + "Starting sampling profiler not supported on " + toString()); + } + + @Override + public void stopSamplingProfiler(String filename) { + throw new UnsupportedOperationException( + "Stopping sampling profiler not supported on " + toString()); + } + @Override public String toString() { return "JSCExecutor"; diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaScriptExecutorFactory.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaScriptExecutorFactory.java index 6aee7949a71..cf277a5b441 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaScriptExecutorFactory.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaScriptExecutorFactory.java @@ -8,4 +8,17 @@ package com.facebook.react.bridge; public interface JavaScriptExecutorFactory { JavaScriptExecutor create() throws Exception; + + /** + * Starts the sampling profiler for this specific JavaScriptExecutor Sampling profiler is usually + * a singleton on the runtime, hence the method exists here and not in {@link JavaScriptExecutor} + */ + void startSamplingProfiler(); + + /** + * Stops the Sampling profile + * + * @param filename The filename where the results of the sampling profiler are dumped to + */ + void stopSamplingProfiler(String filename); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ProxyJavaScriptExecutor.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ProxyJavaScriptExecutor.java index 154bf756a78..6f22da805ea 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ProxyJavaScriptExecutor.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ProxyJavaScriptExecutor.java @@ -31,6 +31,18 @@ public class ProxyJavaScriptExecutor extends JavaScriptExecutor { public JavaScriptExecutor create() throws Exception { return new ProxyJavaScriptExecutor(mJavaJSExecutorFactory.create()); } + + @Override + public void startSamplingProfiler() { + throw new UnsupportedOperationException( + "Starting sampling profiler not supported on " + toString()); + } + + @Override + public void stopSamplingProfiler(String filename) { + throw new UnsupportedOperationException( + "Stopping sampling profiler not supported on " + toString()); + } } static { diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java index 0fea0516b9f..fcbddf92e46 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java @@ -29,6 +29,7 @@ import com.facebook.react.R; import com.facebook.react.bridge.CatalystInstance; import com.facebook.react.bridge.DefaultNativeModuleCallExceptionHandler; import com.facebook.react.bridge.JavaJSExecutor; +import com.facebook.react.bridge.JavaScriptExecutorFactory; import com.facebook.react.bridge.NativeDeltaClient; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactMarker; @@ -553,13 +554,48 @@ public class DevSupportManagerImpl new DevOptionHandler() { @Override public void onOptionSelected() { - Intent intent = - new Intent( - mApplicationContext.getPackageName() - + (mIsSamplingProfilerEnabled - ? DISABLE_SAMPLING_PROFILER - : ENABLE_SAMPLING_PROFILER)); - mApplicationContext.sendBroadcast(intent); + JavaScriptExecutorFactory javaScriptExecutorFactory = + mReactInstanceManagerHelper.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(); + } + } 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(); + } + } mIsSamplingProfilerEnabled = !mIsSamplingProfilerEnabled; } }); diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/ReactInstanceManagerDevHelper.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/ReactInstanceManagerDevHelper.java index f9ce6a706ea..6cb86590225 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/ReactInstanceManagerDevHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/ReactInstanceManagerDevHelper.java @@ -9,6 +9,7 @@ package com.facebook.react.devsupport; import android.app.Activity; import androidx.annotation.Nullable; import com.facebook.react.bridge.JavaJSExecutor; +import com.facebook.react.bridge.JavaScriptExecutorFactory; import com.facebook.react.bridge.NativeDeltaClient; /** @@ -29,4 +30,6 @@ public interface ReactInstanceManagerDevHelper { /** Get reference to top level #{link Activity} attached to react context */ @Nullable Activity getCurrentActivity(); + + JavaScriptExecutorFactory getJavaScriptExecutorFactory(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutorFactory.java b/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutorFactory.java index 21f1efa8a34..4795bf453a0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutorFactory.java +++ b/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutorFactory.java @@ -29,6 +29,18 @@ public class JSCExecutorFactory implements JavaScriptExecutorFactory { return new JSCExecutor(jscConfig); } + @Override + public void startSamplingProfiler() { + throw new UnsupportedOperationException( + "Starting sampling profiler not supported on " + toString()); + } + + @Override + public void stopSamplingProfiler(String filename) { + throw new UnsupportedOperationException( + "Stopping sampling profiler not supported on " + toString()); + } + @Override public String toString() { return "JSIExecutor+JSCRuntime";