Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
Add support for performance monitor (#1401)
Browse files Browse the repository at this point in the history
* Add support for performance monitor.

* Add performance monitor switch to developer options
  • Loading branch information
bluemarvin authored and keianhzo committed Jul 17, 2019
1 parent 240f6ac commit 1232479
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 24 deletions.
36 changes: 36 additions & 0 deletions app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.function.Consumer;

import androidx.annotation.IntDef;
Expand Down Expand Up @@ -144,6 +146,7 @@ public void run() {
private boolean mConnectionAvailable = true;
private AudioManager mAudioManager;
private Widget mActiveDialog;
private Set<String> mPoorPerformanceWhiteList;

private boolean callOnAudioManager(Consumer<AudioManager> fn) {
if (mAudioManager == null) {
Expand Down Expand Up @@ -243,6 +246,7 @@ protected void onCreate(Bundle savedInstanceState) {
GeolocationWrapper.update(this);

mConnectivityReceiver = new ConnectivityReceiver();
mPoorPerformanceWhiteList = new HashSet<>();
}

protected void initializeWorld() {
Expand Down Expand Up @@ -852,6 +856,38 @@ public void dismiss() {
});
}

@Keep
@SuppressWarnings("unused")
private void handlePoorPerformance() {
runOnUiThread(() -> {
if (!mSettings.isPerformanceMonitorEnabled()) {
return;
}
// Don't block poorly performing immersive pages.
if (mIsPresentingImmersive) {
return;
}
if (mWindowWidget == null) {
return;
}
final String originalUrl = SessionStore.get().getCurrentUri();
if (mPoorPerformanceWhiteList.contains(originalUrl)) {
return;
}
SessionStore.get().loadUri("about:blank");
final String[] buttons = {getString(R.string.ok_button), null, getString(R.string.performance_unblock_page)};
mWindowWidget.showButtonPrompt(getString(R.string.performance_title), getString(R.string.performance_message), buttons, new GeckoSession.PromptDelegate.ButtonCallback() {
@Override
public void confirm(int button) {
if (button == 0) {
mPoorPerformanceWhiteList.add(originalUrl);
SessionStore.get().loadUri(originalUrl);
}
}
});
});
}

void createOffscreenDisplay() {
int[] ids = new int[1];
GLES20.glGenTextures(1, ids, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ SettingsStore getInstance(final @NonNull Context aContext) {
public final static boolean CONSOLE_LOGS_DEFAULT = false;
public final static boolean ENV_OVERRIDE_DEFAULT = false;
public final static boolean MULTIPROCESS_DEFAULT = false;
public final static boolean PERFORMANCE_MONITOR_DEFAULT = true;
public final static boolean TRACKING_DEFAULT = true;
public final static boolean SERVO_DEFAULT = false;
public final static int UA_MODE_DEFAULT = GeckoSessionSettings.USER_AGENT_MODE_VR;
Expand Down Expand Up @@ -179,6 +180,16 @@ public void setMultiprocessEnabled(boolean isEnabled) {
editor.commit();
}

public boolean isPerformanceMonitorEnabled() {
return mPrefs.getBoolean(mContext.getString(R.string.settings_key_performance_monitor), PERFORMANCE_MONITOR_DEFAULT);
}

public void setPerformanceMonitorEnabled(boolean isEnabled) {
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(mContext.getString(R.string.settings_key_performance_monitor), isEnabled);
editor.commit();
}

public boolean isServoEnabled() {
return isServoAvailable() && mPrefs.getBoolean(mContext.getString(R.string.settings_key_servo), SERVO_DEFAULT);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,16 @@ public void showAlert(String title, @NonNull String msg, @NonNull AlertCallback
mAlertPrompt.show(REQUEST_FOCUS);
}

public void showButtonPrompt(String title, @NonNull String msg, @NonNull String[] btnMsg, @NonNull ButtonCallback callback) {
mConfirmPrompt = new ConfirmPromptWidget(getContext());
mConfirmPrompt.mWidgetPlacement.parentHandle = getHandle();
mConfirmPrompt.setTitle(title);
mConfirmPrompt.setMessage(msg);
mConfirmPrompt.setButtons(btnMsg);
mConfirmPrompt.setDelegate(callback);
mConfirmPrompt.show(REQUEST_FOCUS);
}

// PromptDelegate

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class DeveloperOptionsView extends SettingsView {
private SwitchSetting mRemoteDebuggingSwitch;
private SwitchSetting mConsoleLogsSwitch;
private SwitchSetting mMultiprocessSwitch;
private SwitchSetting mPerformanceSwitch;
private SwitchSetting mServoSwitch;
private SingleEditSetting mHomepageEdit;
private String mDefaultHomepageUrl;
Expand Down Expand Up @@ -73,6 +74,10 @@ private void initialize(Context aContext) {
mMultiprocessSwitch.setOnCheckedChangeListener(mMultiprocessListener);
setMultiprocess(SettingsStore.getInstance(getContext()).isMultiprocessEnabled(), false);

mPerformanceSwitch = findViewById(R.id.performance_monitor_switch);
mPerformanceSwitch.setOnCheckedChangeListener(mPerformanceListener);
setPerformance(SettingsStore.getInstance(getContext()).isPerformanceMonitorEnabled(), false);

mServoSwitch = findViewById(R.id.servo_switch);
if (!isServoAvailable()) {
mServoSwitch.setVisibility(View.GONE);
Expand Down Expand Up @@ -130,6 +135,10 @@ protected void onDismiss() {
setMultiprocess(value, doApply);
};

private SwitchSetting.OnCheckedChangeListener mPerformanceListener = (compoundButton, value, doApply) -> {
setPerformance(value, doApply);
};

private SwitchSetting.OnCheckedChangeListener mServoListener = (compoundButton, b, doApply) -> {
setServo(b, true);
};
Expand Down Expand Up @@ -200,6 +209,14 @@ private void setMultiprocess(boolean value, boolean doApply) {
}
}

private void setPerformance(boolean value, boolean doApply) {
mPerformanceSwitch.setOnCheckedChangeListener(null);
mPerformanceSwitch.setValue(value, false);
mPerformanceSwitch.setOnCheckedChangeListener(mPerformanceListener);

SettingsStore.getInstance(getContext()).setPerformanceMonitorEnabled(value);
}

private void setServo(boolean value, boolean doApply) {
mServoSwitch.setOnCheckedChangeListener(null);
mServoSwitch.setValue(value, false);
Expand Down
25 changes: 25 additions & 0 deletions app/src/main/cpp/BrowserWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "vrb/ModelLoaderAndroid.h"
#include "vrb/NodeFactoryObj.h"
#include "vrb/ParserObj.h"
#include "vrb/PerformanceMonitor.h"
#include "vrb/RenderContext.h"
#include "vrb/RenderState.h"
#include "vrb/SurfaceTextureFactory.h"
Expand Down Expand Up @@ -118,6 +119,25 @@ SurfaceObserver::SurfaceTextureCreationError(const std::string& aName, const std

}

class PerformanceObserver;
typedef std::shared_ptr<PerformanceObserver> PerformanceObserverPtr;

class PerformanceObserver : public PerformanceMonitorObserver {
public:
void PoorPerformanceDetected(const double& aTargetFrameRate, const double& aAverageFrameRate) override;
void PerformanceRestored(const double& aTargetFrameRate, const double& aAverageFrameRate) override;
};

void
PerformanceObserver::PoorPerformanceDetected(const double& aTargetFrameRate, const double& aAverageFrameRate) {
crow::VRBrowser::HandlePoorPerformance();
}

void
PerformanceObserver::PerformanceRestored(const double& aTargetFrameRate, const double& aAverageFrameRate) {

}

} // namespace

namespace crow {
Expand Down Expand Up @@ -160,6 +180,7 @@ struct BrowserWorld::State {
LoadingAnimationPtr loadingAnimation;
SplashAnimationPtr splashAnimation;
VRVideoPtr vrVideo;
PerformanceMonitorPtr monitor;

State() : paused(true), glInitialized(false), modelsLoaded(false), env(nullptr), cylinderDensity(0.0f), nearClip(0.1f),
farClip(300.0f), activity(nullptr), windowsInitialized(false), exitImmersiveRequested(false), loaderDelay(0) {
Expand All @@ -183,6 +204,8 @@ struct BrowserWorld::State {
fadeAnimation = FadeAnimation::Create(create);
loadingAnimation = LoadingAnimation::Create(create);
splashAnimation = SplashAnimation::Create(create);
monitor = PerformanceMonitor::Create(create);
monitor->AddPerformanceMonitorObserver(std::make_shared<PerformanceObserver>());
}

void CheckBackButton();
Expand Down Expand Up @@ -540,12 +563,14 @@ void
BrowserWorld::Pause() {
ASSERT_ON_RENDER_THREAD();
m.paused = true;
m.monitor->Pause();
}

void
BrowserWorld::Resume() {
ASSERT_ON_RENDER_THREAD();
m.paused = false;
m.monitor->Resume();
}

bool
Expand Down
56 changes: 33 additions & 23 deletions app/src/main/cpp/VRBrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,29 +48,32 @@ const char* kSetDeviceType = "setDeviceType";
const char* kSetDeviceTypeSignature = "(I)V";
const char* kHaltActivity = "haltActivity";
const char* kHaltActivitySignature = "(I)V";

JNIEnv* sEnv;
jclass sBrowserClass;
jobject sActivity;
jmethodID sDispatchCreateWidget;
jmethodID sDispatchCreateWidgetLayer;
jmethodID sHandleMotionEvent;
jmethodID sHandleScrollEvent;
jmethodID sHandleAudioPose;
jmethodID sHandleGesture;
jmethodID sHandleResize;
jmethodID sHandleBack;
jmethodID sRegisterExternalContext;
jmethodID sPauseCompositor;
jmethodID sResumeCompositor;
jmethodID sRenderPointerLayer;
jmethodID sGetStorageAbsolutePath;
jmethodID sIsOverrideEnvPathEnabled;
jmethodID sGetActiveEnvironment;
jmethodID sGetPointerColor;
jmethodID sAreLayersEnabled;
jmethodID sSetDeviceType;
jmethodID sHaltActivity;
const char* kHandlePoorPerformance = "handlePoorPerformance";
const char* kHandlePoorPerformanceSignature = "()V";

JNIEnv* sEnv = nullptr;
jclass sBrowserClass = nullptr;
jobject sActivity = nullptr;
jmethodID sDispatchCreateWidget = nullptr;
jmethodID sDispatchCreateWidgetLayer = nullptr;
jmethodID sHandleMotionEvent = nullptr;
jmethodID sHandleScrollEvent = nullptr;
jmethodID sHandleAudioPose = nullptr;
jmethodID sHandleGesture = nullptr;
jmethodID sHandleResize = nullptr;
jmethodID sHandleBack = nullptr;
jmethodID sRegisterExternalContext = nullptr;
jmethodID sPauseCompositor = nullptr;
jmethodID sResumeCompositor = nullptr;
jmethodID sRenderPointerLayer = nullptr;
jmethodID sGetStorageAbsolutePath = nullptr;
jmethodID sIsOverrideEnvPathEnabled = nullptr;
jmethodID sGetActiveEnvironment = nullptr;
jmethodID sGetPointerColor = nullptr;
jmethodID sAreLayersEnabled = nullptr;
jmethodID sSetDeviceType = nullptr;
jmethodID sHaltActivity = nullptr;
jmethodID sHandlePoorPerformance = nullptr;
}

namespace crow {
Expand Down Expand Up @@ -109,6 +112,7 @@ VRBrowser::InitializeJava(JNIEnv* aEnv, jobject aActivity) {
sAreLayersEnabled = FindJNIMethodID(sEnv, sBrowserClass, kAreLayersEnabled, kAreLayersEnabledSignature);
sSetDeviceType = FindJNIMethodID(sEnv, sBrowserClass, kSetDeviceType, kSetDeviceTypeSignature);
sHaltActivity = FindJNIMethodID(sEnv, sBrowserClass, kHaltActivity, kHaltActivitySignature);
sHandlePoorPerformance = FindJNIMethodID(sEnv, sBrowserClass, kHandlePoorPerformance, kHandlePoorPerformanceSignature);
}

void
Expand Down Expand Up @@ -316,5 +320,11 @@ VRBrowser::HaltActivity(const jint aReason) {
CheckJNIException(sEnv, __FUNCTION__);
}

void
VRBrowser::HandlePoorPerformance() {
if (!ValidateMethodID(sEnv, sActivity, sHandlePoorPerformance, __FUNCTION__)) { return; }
sEnv->CallVoidMethod(sActivity, sHandlePoorPerformance);
CheckJNIException(sEnv, __FUNCTION__);
}

} // namespace crow
1 change: 1 addition & 0 deletions app/src/main/cpp/VRBrowser.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ int32_t GetPointerColor();
bool AreLayersEnabled();
void SetDeviceType(const jint aType);
void HaltActivity(const jint aReason);
void HandlePoorPerformance();
} // namespace VRBrowser;

} // namespace crow
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/res/layout/options_developer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@
android:layout_height="wrap_content"
app:description="@string/developer_options_multiprocess" />

<org.mozilla.vrbrowser.ui.views.settings.SwitchSetting
android:id="@+id/performance_monitor_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:description="@string/developer_options_performance_monitor" />

<org.mozilla.vrbrowser.ui.views.settings.SwitchSetting
android:id="@+id/servo_switch"
android:layout_width="match_parent"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/non_L10n.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<string name="settings_key_console_logs" translatable="false">settings_console_logs</string>
<string name="settings_key_environment_override" translatable="false">settings_environment_override</string>
<string name="settings_key_multiprocess" translatable="false">settings_environment_multiprocess</string>
<string name="settings_key_performance_monitor" translatable="false">settings_performance_monitor</string>
<string name="settings_key_servo" translatable="false">settings_environment_servo</string>
<string name="settings_key_tracking_protection" translatable="false">settings_tracking_protection</string>
<string name="settings_key_user_agent_version" translatable="false">settings_user_agent_version</string>
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@
A dialog should appear with a field labeled with the text, 'Enable Multiprocess'. -->
<string name="developer_options_multiprocess">Enable Multiprocess</string>

<!-- This string labels and On/Off switch in the developer options dialog and is used to toggle
the performance monitor. The Performance monitor is used to detect pages that cause the
browser to run below a target framerate and pauses the page to restore performance.
-->
<string name="developer_options_performance_monitor">Enable Performance Monitor</string>

<!-- The string labels an On/Off switch in the developer options dialog and is used to toggle enabling Servo. -->
<string name="developer_options_servo">Enable Servo</string>

Expand Down Expand Up @@ -699,4 +705,11 @@
<!-- This string is displayed in the message body of the alert dialog shown when the user does not have permission to run the application on the device.
'%1$s' will be replace at runtime with the app's name. -->
<string name="not_entitled_message">%1$s does not have permission to run on this device and will now exit.</string>

<!-- This string is displayed in a button that when pressed allows a user to view a page that has been blocked from being displayed.-->
<string name="performance_unblock_page">Unblock Page</string>
<!-- This string is displayed as the title of a dialog displayed when poor web page performance has been detected. -->
<string name="performance_title">Poor Performance Detected</string>
<!-- This string is displayed as the message body of a dialog displayed when poor web page performance has been detected and the page has been unloaded to restore performance. -->
<string name="performance_message">The current web page is affecting performance and has been suspended. Reducing the window size can help improve a web page with poor performance.</string>
</resources>

0 comments on commit 1232479

Please sign in to comment.