diff --git a/android/app/src/cpp/android_host_interface.cpp b/android/app/src/cpp/android_host_interface.cpp
index 1aed1d7d0..c68d535d1 100644
--- a/android/app/src/cpp/android_host_interface.cpp
+++ b/android/app/src/cpp/android_host_interface.cpp
@@ -39,6 +39,7 @@ static jclass s_String_class;
 static jclass s_AndroidHostInterface_class;
 static jmethodID s_AndroidHostInterface_constructor;
 static jfieldID s_AndroidHostInterface_field_mNativePointer;
+static jfieldID s_AndroidHostInterface_field_mEmulationActivity;
 static jmethodID s_AndroidHostInterface_method_reportError;
 static jmethodID s_AndroidHostInterface_method_reportMessage;
 static jmethodID s_AndroidHostInterface_method_openAssetStream;
@@ -464,11 +465,13 @@ void AndroidHostInterface::EmulationThreadEntryPoint(JNIEnv* env, jobject emulat
   emulation_activity = env->NewGlobalRef(emulation_activity);
   Assert(emulation_activity != nullptr);
 
+
   {
     std::unique_lock<std::mutex> lock(m_mutex);
     m_emulation_thread_running.store(true);
     m_emulation_activity_object = emulation_activity;
     m_emulation_thread_id = std::this_thread::get_id();
+    env->SetObjectField(m_java_object, s_AndroidHostInterface_field_mEmulationActivity, emulation_activity);
   }
 
   ApplySettings(true);
@@ -500,6 +503,7 @@ void AndroidHostInterface::EmulationThreadEntryPoint(JNIEnv* env, jobject emulat
       callback();
       lock.lock();
     }
+    env->SetObjectField(m_java_object, s_AndroidHostInterface_field_mEmulationActivity, nullptr);
     m_emulation_thread_running.store(false);
     m_emulation_thread_id = {};
     m_emulation_activity_object = {};
@@ -974,6 +978,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
                           "(Landroid/content/Context;Lcom/github/stenzek/duckstation/FileHelper;)V")) == nullptr ||
       (s_AndroidHostInterface_field_mNativePointer =
          env->GetFieldID(s_AndroidHostInterface_class, "mNativePointer", "J")) == nullptr ||
+      (s_AndroidHostInterface_field_mEmulationActivity =
+         env->GetFieldID(s_AndroidHostInterface_class, "mEmulationActivity", "Lcom/github/stenzek/duckstation/EmulationActivity;")) == nullptr ||
       (s_AndroidHostInterface_method_reportError =
          env->GetMethodID(s_AndroidHostInterface_class, "reportError", "(Ljava/lang/String;)V")) == nullptr ||
       (s_AndroidHostInterface_method_reportMessage =
diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java b/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java
index 9c62dc993..d77187484 100644
--- a/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java
+++ b/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java
@@ -24,6 +24,7 @@ public class AndroidHostInterface {
     private long mNativePointer;
     private Context mContext;
     private FileHelper mFileHelper;
+    private EmulationActivity mEmulationActivity;
 
     public AndroidHostInterface(Context context, FileHelper fileHelper) {
         this.mContext = context;
@@ -50,6 +51,8 @@ public class AndroidHostInterface {
         mContext = context;
     }
 
+    public EmulationActivity getEmulationActivity() { return mEmulationActivity; }
+
     static public native String getScmVersion();
 
     static public native String getFullScmVersion();
diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerButtonView.java b/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerButtonView.java
index 9718bb697..a23deb056 100644
--- a/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerButtonView.java
+++ b/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerButtonView.java
@@ -17,7 +17,8 @@ public final class TouchscreenControllerButtonView extends View {
     {
         NONE,
         FAST_FORWARD,
-        ANALOG_TOGGLE
+        ANALOG_TOGGLE,
+        OPEN_PAUSE_MENU,
     }
 
     private Drawable mUnpressedDrawable;
@@ -144,11 +145,17 @@ public final class TouchscreenControllerButtonView extends View {
                 break;
 
             case ANALOG_TOGGLE: {
-                if (mPressed)
+                if (!mPressed)
                     AndroidHostInterface.getInstance().toggleControllerAnalogMode();
             }
             break;
 
+            case OPEN_PAUSE_MENU: {
+                if (!mPressed)
+                    AndroidHostInterface.getInstance().getEmulationActivity().openPauseMenu();
+            }
+            break;
+
             case NONE:
             default:
                 break;
diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerView.java b/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerView.java
index 6b61b6a36..1ce1d438a 100644
--- a/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerView.java
+++ b/android/app/src/main/java/com/github/stenzek/duckstation/TouchscreenControllerView.java
@@ -312,6 +312,8 @@ public class TouchscreenControllerView extends FrameLayout {
                 TouchscreenControllerButtonView.Hotkey.FAST_FORWARD, false);
         linkHotkeyButton(mMainView, R.id.controller_button_analog, "AnalogToggle",
                 TouchscreenControllerButtonView.Hotkey.ANALOG_TOGGLE, false);
+        linkHotkeyButton(mMainView, R.id.controller_button_pause, "OpenPauseMenu",
+                TouchscreenControllerButtonView.Hotkey.OPEN_PAUSE_MENU, true);
 
         linkButton(mMainView, R.id.controller_button_a, "AButton", "A", true, true);
         linkButton(mMainView, R.id.controller_button_b, "BButton", "B", true, true);
diff --git a/android/app/src/main/res/drawable/ic_controller_pause_button.xml b/android/app/src/main/res/drawable/ic_controller_pause_button.xml
new file mode 100644
index 000000000..b929a59f9
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_controller_pause_button.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24"
+    android:tint="?attr/colorControlNormal">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M9,16h2L11,8L9,8v8zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM13,16h2L15,8h-2v8z"/>
+</vector>
diff --git a/android/app/src/main/res/layout/layout_touchscreen_controller_analog_stick.xml b/android/app/src/main/res/layout/layout_touchscreen_controller_analog_stick.xml
index 12c999580..b36cb67e1 100644
--- a/android/app/src/main/res/layout/layout_touchscreen_controller_analog_stick.xml
+++ b/android/app/src/main/res/layout/layout_touchscreen_controller_analog_stick.xml
@@ -158,4 +158,15 @@
         app:layout_constraintStart_toStartOf="parent"
         app:pressedDrawable="@drawable/ic_controller_analog_button_pressed"
         app:unpressedDrawable="@drawable/ic_controller_analog_button" />
+
+    <com.github.stenzek.duckstation.TouchscreenControllerButtonView
+        android:id="@+id/controller_button_pause"
+        android:layout_width="35dp"
+        android:layout_height="35dp"
+        android:layout_marginTop="20dp"
+        android:layout_marginRight="20dp"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:pressedDrawable="@drawable/ic_controller_pause_button"
+        app:unpressedDrawable="@drawable/ic_controller_pause_button" />
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/android/app/src/main/res/layout/layout_touchscreen_controller_analog_sticks.xml b/android/app/src/main/res/layout/layout_touchscreen_controller_analog_sticks.xml
index c21ad0753..389f55266 100644
--- a/android/app/src/main/res/layout/layout_touchscreen_controller_analog_sticks.xml
+++ b/android/app/src/main/res/layout/layout_touchscreen_controller_analog_sticks.xml
@@ -180,4 +180,15 @@
         app:layout_constraintStart_toStartOf="parent"
         app:pressedDrawable="@drawable/ic_controller_analog_button_pressed"
         app:unpressedDrawable="@drawable/ic_controller_analog_button" />
+
+    <com.github.stenzek.duckstation.TouchscreenControllerButtonView
+        android:id="@+id/controller_button_pause"
+        android:layout_width="35dp"
+        android:layout_height="35dp"
+        android:layout_marginTop="20dp"
+        android:layout_marginRight="20dp"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:pressedDrawable="@drawable/ic_controller_pause_button"
+        app:unpressedDrawable="@drawable/ic_controller_pause_button" />
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/android/app/src/main/res/layout/layout_touchscreen_controller_digital.xml b/android/app/src/main/res/layout/layout_touchscreen_controller_digital.xml
index acd45928a..2cf99ca02 100644
--- a/android/app/src/main/res/layout/layout_touchscreen_controller_digital.xml
+++ b/android/app/src/main/res/layout/layout_touchscreen_controller_digital.xml
@@ -142,4 +142,15 @@
         app:layout_constraintStart_toStartOf="parent"
         app:pressedDrawable="@drawable/ic_controller_fast_forward_pressed"
         app:unpressedDrawable="@drawable/ic_controller_fast_forward" />
+
+    <com.github.stenzek.duckstation.TouchscreenControllerButtonView
+        android:id="@+id/controller_button_pause"
+        android:layout_width="35dp"
+        android:layout_height="35dp"
+        android:layout_marginTop="20dp"
+        android:layout_marginRight="20dp"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:pressedDrawable="@drawable/ic_controller_pause_button"
+        app:unpressedDrawable="@drawable/ic_controller_pause_button" />
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/android/app/src/main/res/layout/layout_touchscreen_controller_lightgun.xml b/android/app/src/main/res/layout/layout_touchscreen_controller_lightgun.xml
index 63f0bf354..110969741 100644
--- a/android/app/src/main/res/layout/layout_touchscreen_controller_lightgun.xml
+++ b/android/app/src/main/res/layout/layout_touchscreen_controller_lightgun.xml
@@ -41,4 +41,15 @@
         app:layout_constraintStart_toStartOf="parent"
         app:pressedDrawable="@drawable/ic_controller_fast_forward_pressed"
         app:unpressedDrawable="@drawable/ic_controller_fast_forward" />
+
+    <com.github.stenzek.duckstation.TouchscreenControllerButtonView
+        android:id="@+id/controller_button_pause"
+        android:layout_width="35dp"
+        android:layout_height="35dp"
+        android:layout_marginTop="20dp"
+        android:layout_marginRight="20dp"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:pressedDrawable="@drawable/ic_controller_pause_button"
+        app:unpressedDrawable="@drawable/ic_controller_pause_button" />
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file