From 1e12d38fd26f34a0b00f92fec47de510b9e11cfd Mon Sep 17 00:00:00 2001 From: Manabu-GT Date: Thu, 21 May 2026 02:17:52 -0600 Subject: [PATCH 1/2] [fix] drop FLAG_ACTIVITY_NEW_TASK when launching BugReportActivity from an Activity context Xiaomi/MIUI silently blocks startActivity calls that pair FLAG_ACTIVITY_NEW_TASK with a transparent destination via its pop-up window gate, causing the "Create Report" button in DebugPanelDialog to do nothing when a draft already exists (#251). The flag was added for the FAB's overlay (non-Activity) context and was applied indiscriminately to the in-Activity caller; now it is only added when the caller context does not unwrap to an Activity. Also collapses the throwing Context.findActivity() into a single nullable findActivityOrNull(), since its only caller (Views.kt) was wrapping it in runCatching to get nullable semantics anyway. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../debugoverlay/internal/bugreport/ui/BugReportActivity.kt | 5 +++-- .../com/ms/square/debugoverlay/internal/util/Contexts.kt | 6 +++--- .../com/ms/square/debugoverlay/internal/util/Views.kt | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/bugreport/ui/BugReportActivity.kt b/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/bugreport/ui/BugReportActivity.kt index 1570bd97..3d57fd52 100644 --- a/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/bugreport/ui/BugReportActivity.kt +++ b/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/bugreport/ui/BugReportActivity.kt @@ -33,6 +33,7 @@ import com.ms.square.debugoverlay.internal.Logger import com.ms.square.debugoverlay.internal.bugreport.BugReportGenerator import com.ms.square.debugoverlay.internal.bugreport.model.BugReportResult import com.ms.square.debugoverlay.internal.bugreport.model.UserInput +import com.ms.square.debugoverlay.internal.util.findActivityOrNull import com.ms.square.debugoverlay.internal.util.isDarkTheme import com.ms.square.debugoverlay.internal.util.runCatchingNonCancellation import com.ms.square.debugoverlay.model.ExportResult @@ -331,7 +332,7 @@ internal class BugReportActivity : ComponentActivity() { companion object { fun launchWithDraftPicker(context: Context) { val intent = Intent(context, BugReportActivity::class.java).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + if (context.findActivityOrNull() == null) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) putExtra(INTENT_EXTRA_SHOW_DRAFT_PICKER, true) } context.startActivity(intent) @@ -339,7 +340,7 @@ internal class BugReportActivity : ComponentActivity() { fun launchWithMetadataDialog(context: Context, bugCapturedFolderPath: String) { val intent = Intent(context, BugReportActivity::class.java).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + if (context.findActivityOrNull() == null) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) putExtra(INTENT_EXTRA_CAPTURE_FOLDER, bugCapturedFolderPath) } context.startActivity(intent) diff --git a/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Contexts.kt b/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Contexts.kt index 1cd1238e..ccb67e44 100644 --- a/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Contexts.kt +++ b/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Contexts.kt @@ -11,8 +11,8 @@ internal fun Context.defaultDisplay(): Display? { return dm?.getDisplay(Display.DEFAULT_DISPLAY) } -internal tailrec fun Context.findActivity(): Activity = when (this) { +internal tailrec fun Context.findActivityOrNull(): Activity? = when (this) { is Activity -> this - is ContextWrapper -> this.baseContext.findActivity() - else -> throw IllegalArgumentException("Could not find activity!") + is ContextWrapper -> this.baseContext.findActivityOrNull() + else -> null } diff --git a/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Views.kt b/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Views.kt index 909f2404..9310abf8 100644 --- a/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Views.kt +++ b/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Views.kt @@ -6,7 +6,7 @@ import curtains.phoneWindow internal fun View.findActivity(): Activity? { val callback = phoneWindow?.callback - // check for the callback first as context.findActivity() won't work for certain contexts such as DecorContext. - // for dialogs, callback could be non-Activity (ex..DialogWrapper), so fallback to the findActivity for those cases. - return callback as? Activity ?: runCatching { context.findActivity() }.getOrNull() + // check for the callback first as context unwrapping won't work for certain contexts such as DecorContext. + // for dialogs, callback could be non-Activity (ex..DialogWrapper), so fallback to unwrapping the context. + return callback as? Activity ?: context.findActivityOrNull() } From fd2b55c1d8c50238d2bfd69a190ec3f75f8079d6 Mon Sep 17 00:00:00 2001 From: Manabu-GT Date: Thu, 21 May 2026 17:10:08 -0600 Subject: [PATCH 2/2] [refactor] rename View.findActivity to findActivityOrNull for symmetry Pairs with the Context.findActivityOrNull rename in the parent commit so both extensions communicate their nullable return type consistently via the OrNull suffix. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ms/square/debugoverlay/internal/OverlayViewManager.kt | 7 ++++--- .../com/ms/square/debugoverlay/internal/util/Views.kt | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/OverlayViewManager.kt b/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/OverlayViewManager.kt index 9f8e8861..e9a620d9 100644 --- a/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/OverlayViewManager.kt +++ b/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/OverlayViewManager.kt @@ -37,7 +37,7 @@ import com.ms.square.debugoverlay.internal.data.source.OverlayPreferences import com.ms.square.debugoverlay.internal.data.source.SharedPreferencesOverlayPreferences import com.ms.square.debugoverlay.internal.ui.DebugPanelActivity import com.ms.square.debugoverlay.internal.ui.DraggableOverlayPanel -import com.ms.square.debugoverlay.internal.util.findActivity +import com.ms.square.debugoverlay.internal.util.findActivityOrNull import com.ms.square.debugoverlay.internal.util.isDarkTheme import curtains.Curtains import curtains.OnRootViewsChangedListener @@ -182,7 +182,7 @@ internal class OverlayViewManager( } // Exclude windows belonging to DebugOverlay's own activities - if (view.findActivity()?.isDebugOverlayActivity() == true) return@lastOrNull false + if (view.findActivityOrNull()?.isDebugOverlayActivity() == true) return@lastOrNull false view.windowToken != null && view.isShown } @@ -388,7 +388,8 @@ internal class OverlayViewManager( DebugOverlay.overlayDataRepository.stopJankStatsTracking(activity) } } - private fun isCurrentTarget(activity: Activity): Boolean = currentTargetWindowView?.findActivity() === activity + private fun isCurrentTarget(activity: Activity): Boolean = + currentTargetWindowView?.findActivityOrNull() === activity } } diff --git a/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Views.kt b/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Views.kt index 9310abf8..97783fa8 100644 --- a/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Views.kt +++ b/debugoverlay-core/src/main/kotlin/com/ms/square/debugoverlay/internal/util/Views.kt @@ -4,7 +4,7 @@ import android.app.Activity import android.view.View import curtains.phoneWindow -internal fun View.findActivity(): Activity? { +internal fun View.findActivityOrNull(): Activity? { val callback = phoneWindow?.callback // check for the callback first as context unwrapping won't work for certain contexts such as DecorContext. // for dialogs, callback could be non-Activity (ex..DialogWrapper), so fallback to unwrapping the context.