@@ -154,6 +154,13 @@ class DialogInstallActivity : ComponentActivity() {
154154 /* * Headless parse budget. Exceeding it falls back to the dialog rather than hanging. */
155155 private const val PARSE_TIMEOUT_MS = 30_000L
156156
157+ /* *
158+ * One grep-able tag for the whole notification-install path. The flow crosses an activity,
159+ * a store, a notifier and a broadcast receiver, so "which branch did it take" is otherwise
160+ * not answerable from a log.
161+ */
162+ private const val LOG = " NotifInstall"
163+
157164 /* * Rounded at the top only — the bottom edge runs off the screen. */
158165 private val SHEET_SHAPE = RoundedCornerShape (topStart = 28 .dp, topEnd = 28 .dp)
159166 }
@@ -225,6 +232,7 @@ class DialogInstallActivity : ComponentActivity() {
225232 * as they do from the dialog.
226233 */
227234 private fun installFromNotificationAction () {
235+ Timber .i(" $LOG : firing install from the notification action" )
228236 viewModel.confirmInstall(trackDialogTarget = true )
229237 lifecycleScope.launch {
230238 // confirmInstall publishes the real session id asynchronously (ackpine mints it).
@@ -267,8 +275,9 @@ class DialogInstallActivity : ComponentActivity() {
267275 private fun HeadlessNotificationInstall (mode : ExternalOpenMode , uri : Uri ) {
268276 val context = LocalContext .current
269277 LaunchedEffect (uri) {
278+ Timber .i(" $LOG : mode=$mode , parsing $uri " )
270279 runCatching { parseAndPush(context, uri) }.onFailure { e ->
271- Timber .e(e, " Headless parse failed for $uri " )
280+ Timber .e(e, " $LOG : parse threw - giving up " )
272281 finish()
273282 return @LaunchedEffect
274283 }
@@ -277,24 +286,32 @@ class DialogInstallActivity : ComponentActivity() {
277286 viewModel.uiState.map { it.pendingApkInfo }.filterNotNull().first()
278287 }
279288 if (apkInfo == null ) {
280- Timber .w(" Headless parse produced nothing — falling back to the dialog" )
289+ Timber .w(" $LOG : no parse result within ${ PARSE_TIMEOUT_MS } ms - falling back to the dialog" )
281290 skipInitialParse = true
282291 fallbackToDialog()
283292 return @LaunchedEffect
284293 }
285294
295+ Timber .i(" $LOG : parsed ${apkInfo.packageName} , ${apkInfo.splitEntries.size} split(s)" )
296+
286297 // Auto mode installs without asking, but not past a risk the user has never seen.
287298 // A downgrade or a signature mismatch still gets the prompt.
288299 val risks = detectInstallRisks(apkInfo)
289300 if (mode == ExternalOpenMode .AutoNotification && risks.isEmpty()) {
301+ Timber .i(" $LOG : auto mode, no risks - installing without asking" )
290302 installFromNotificationAction()
291303 return @LaunchedEffect
292304 }
293305
294306 // Checked before stashing: a prompt that cannot be posted would strand the install
295307 // with nothing on screen, and the dialog is the only fallback left.
296- val entry = if (promptNotifier.canPost()) viewModel.stashPendingInstall() else null
308+ if (risks.isNotEmpty()) Timber .i(" $LOG : ${risks.size} risk(s) - asking rather than auto-installing" )
309+ val canPost = promptNotifier.canPost()
310+ if (! canPost) Timber .w(" $LOG : notifications unavailable" )
311+ val entry = if (canPost) viewModel.stashPendingInstall() else null
312+ if (canPost && entry == null ) Timber .w(" $LOG : nothing to stash - staging the APKs must have failed" )
297313 if (entry == null || ! promptNotifier.prompt(entry)) {
314+ Timber .w(" $LOG : falling back to the dialog" )
298315 entry?.let {
299316 viewModel.restorePendingInstall(it)
300317 PendingInstallStore .consume(it.id)
@@ -303,6 +320,7 @@ class DialogInstallActivity : ComponentActivity() {
303320 fallbackToDialog()
304321 return @LaunchedEffect
305322 }
323+ Timber .i(" $LOG : prompt ${entry.id} posted for ${entry.packageName} , ${entry.apkUris.size} staged uri(s)" )
306324 finish()
307325 }
308326 }
@@ -324,6 +342,7 @@ class DialogInstallActivity : ComponentActivity() {
324342 if (pendingId != null ) {
325343 val entry = PendingInstallStore .consume(pendingId)
326344 promptNotifier.cancel(pendingId)
345+ Timber .i(" $LOG : resuming $pendingId , found=${entry != null } " )
327346 if (entry == null ) {
328347 // The process died while the prompt sat in the shade, taking the parse with it.
329348 // Nothing installable is left, so don't pretend otherwise.
0 commit comments