Feature: Disable annotation features while PDF search is active.

To improve the search experience and prevent UI overlap between the search bar and the annotation toolbar, this CL introduces the following changes:
- UI: Hides the annotation toolbar automatically when text search is initiated.
- Interaction: Disables PDF ink interaction while search is active, ensuring touch events (like swipes) are used for result navigation rather than drawing.
- State Restoration: Automatically restores the annotation toolbar to its previous dock position once search is closed.

Bug: b/477204335
Test: ./gradlew :pdf:pdf-ink:connectedAndroidTest
Change-Id: Ia9866740efbc350a9e336bdeb69e1d610d23a1b3
diff --git a/pdf/pdf-ink/src/androidTest/kotlin/androidx/pdf/ink/fragment/EditablePdfViewerFragmentTests.kt b/pdf/pdf-ink/src/androidTest/kotlin/androidx/pdf/ink/fragment/EditablePdfViewerFragmentTests.kt
index 50bb509..99c1f01 100644
--- a/pdf/pdf-ink/src/androidTest/kotlin/androidx/pdf/ink/fragment/EditablePdfViewerFragmentTests.kt
+++ b/pdf/pdf-ink/src/androidTest/kotlin/androidx/pdf/ink/fragment/EditablePdfViewerFragmentTests.kt
@@ -52,6 +52,7 @@
 import androidx.test.espresso.action.Tap
 import androidx.test.espresso.action.ViewActions
 import androidx.test.espresso.action.ViewActions.click
+import androidx.test.espresso.action.ViewActions.swipeUp
 import androidx.test.espresso.action.ViewActions.typeText
 import androidx.test.espresso.assertion.ViewAssertions.matches
 import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
@@ -61,6 +62,8 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
 import kotlin.test.assertNotNull
 import org.hamcrest.CoreMatchers.not
 import org.junit.After
@@ -312,6 +315,81 @@
         }
     }
 
+    @Test
+    fun test_annotationToolbarHidden_onSearchActive() {
+        if (!isRequiredSdkExtensionAvailable()) return
+
+        loadDocumentAndSetupFragment()
+        enterEditMode()
+
+        // assert annotation toolbar is visible in edit mode
+        onView(withId(R.id.annotationToolbar)).check(matches(isDisplayed()))
+        performDragAndDrop(
+            toolbarId = R.id.annotationToolbar,
+            to = ToolbarViewActions.DragTarget.LEFT,
+        )
+        onIdle()
+
+        // Enable search on fragment
+        scenario.onFragment { fragment -> fragment.isTextSearchActive = true }
+
+        // assert annotation toolbar is hidden when search is initiated
+        onView(withId(R.id.annotationToolbar)).check(matches(not(isDisplayed())))
+
+        // disable search on fragment
+        scenario.onFragment { fragment -> fragment.isTextSearchActive = false }
+
+        // assert toolbar is shown again at the previous position
+        onView(withId(R.id.annotationToolbar)).check(matches(isDisplayed()))
+        scenario.onFragment { fragment ->
+            assertEquals(DOCK_STATE_START, fragment.annotationToolbar.dockState)
+        }
+    }
+
+    @Test
+    fun test_annotationInteractionDisabled_onSearchActive() {
+        if (!isRequiredSdkExtensionAvailable()) return
+
+        loadDocumentAndSetupFragment()
+        enterEditMode()
+
+        var firstVisiblePage: Int
+        var pdfView: PdfView? = null
+
+        // Enable search on fragment
+        scenario.onFragment { fragment ->
+            fragment.isTextSearchActive = true
+            pdfView = fragment.getPdfViewInstance()
+        }
+        requireNotNull(pdfView)
+        // extract first visible page initially
+        firstVisiblePage = pdfView.firstVisiblePage
+
+        // Swipe up to verify the PDF scrolls; ink interaction should be disabled during search
+        onView(isRoot()).perform(swipeUp())
+        // extract first visible page after swipe
+        val firstVisiblePageAfterSwipe = pdfView.firstVisiblePage
+
+        assertNotEquals(firstVisiblePage, firstVisiblePageAfterSwipe)
+    }
+
+    @Test
+    fun test_annotationToolbar_isHidden_forFormFilling() {
+        if (!isRequiredSdkExtensionAvailable()) return
+
+        loadDocumentAndSetupFragment(file = FORM_WITH_CHECKBOX_PDF)
+
+        // Click on a form widget to start form filling journey
+        onView(withId(PdfFragmentR.id.pdfContentLayout))
+            .perform(clickOnPdfPoint(PdfPoint(0, PointF(145f, 80f))))
+
+        scenario.onFragment { fragment -> fragment.pdfFormFillingIdlingResource.increment() }
+        onIdle()
+
+        // assert annotation toolbar is hidden
+        onView(withId(R.id.annotationToolbar)).check(matches(not(isDisplayed())))
+    }
+
     private fun longClickAtCenter() {
         onView(isRoot())
             .perform(
@@ -332,6 +410,7 @@
     companion object {
         private const val TEST_DOCUMENT_FILE = "sample.pdf"
         private const val FORM_PDF = "text_form.pdf"
+        private const val FORM_WITH_CHECKBOX_PDF = "sample_form.pdf"
         private const val REQUIRED_EXTENSION_VERSION = 18
 
         fun isRequiredSdkExtensionAvailable(): Boolean {
diff --git a/pdf/pdf-ink/src/main/kotlin/androidx/pdf/ink/EditableDocumentViewModel.kt b/pdf/pdf-ink/src/main/kotlin/androidx/pdf/ink/EditableDocumentViewModel.kt
index 9fa4451..b04e667 100644
--- a/pdf/pdf-ink/src/main/kotlin/androidx/pdf/ink/EditableDocumentViewModel.kt
+++ b/pdf/pdf-ink/src/main/kotlin/androidx/pdf/ink/EditableDocumentViewModel.kt
@@ -134,6 +134,14 @@
 
     internal var visiblePageRange: IntRange = 0..0
 
+    internal val shouldShowAnnotationToolbar: StateFlow<Boolean> =
+        combine(pdfEditModeFlow, isTextSearchActiveFlow) { pdfEditMode, isTextSearchActive ->
+                pdfEditMode is PdfEditMode.Enabled &&
+                    pdfEditMode.journey == EDITING_JOURNEY_ANNOTATIONS &&
+                    !isTextSearchActive
+            }
+            .stateIn(viewModelScope, SharingStarted.Eagerly, false)
+
     /** Reactive state that combines multiple flows to determine if interaction is enabled. */
     internal val isAnnotationInteractionEnabled: StateFlow<Boolean> =
         combine(
@@ -141,12 +149,14 @@
                 areAnnotationsVisibleFlow,
                 _applyEditsStatus,
                 _isPdfViewGestureActive,
-            ) { pdfEditMode, isVisible, status, isGestureActive ->
+                isTextSearchActiveFlow,
+            ) { pdfEditMode, isVisible, status, isGestureActive, isTextSearchActive ->
                 (pdfEditMode is PdfEditMode.Enabled &&
                     pdfEditMode.journey == EDITING_JOURNEY_ANNOTATIONS) &&
                     isVisible &&
                     status != ApplyEditsState.InProgress &&
-                    !isGestureActive
+                    !isGestureActive &&
+                    !isTextSearchActive
             }
             .stateIn(viewModelScope, SharingStarted.Eagerly, false)
 
diff --git a/pdf/pdf-ink/src/main/kotlin/androidx/pdf/ink/EditablePdfViewerFragment.kt b/pdf/pdf-ink/src/main/kotlin/androidx/pdf/ink/EditablePdfViewerFragment.kt
index 22c7173..024d3a1 100644
--- a/pdf/pdf-ink/src/main/kotlin/androidx/pdf/ink/EditablePdfViewerFragment.kt
+++ b/pdf/pdf-ink/src/main/kotlin/androidx/pdf/ink/EditablePdfViewerFragment.kt
@@ -35,6 +35,7 @@
 import androidx.annotation.RestrictTo
 import androidx.annotation.VisibleForTesting
 import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.view.isVisible
 import androidx.fragment.app.viewModels
 import androidx.ink.authoring.InProgressStrokeId
 import androidx.ink.authoring.InProgressStrokesView
@@ -219,7 +220,7 @@
 
     private val toolbarLayoutChangeListener =
         View.OnLayoutChangeListener {
-            v,
+            _,
             left,
             top,
             right,
@@ -387,6 +388,12 @@
 
     private fun setupUiStateCollectors() {
         collectFlowOnLifecycleScope {
+            documentViewModel.shouldShowAnnotationToolbar.collect {
+                updateAnnotationToolbarVisibility(it)
+            }
+        }
+
+        collectFlowOnLifecycleScope {
             documentViewModel.pdfEditModeFlow.collect { editMode ->
                 if (editMode is PdfEditMode.Enabled) onEnterEditMode() else onExitEditMode()
                 updateUiForEditMode(editMode)
@@ -455,13 +462,17 @@
         }
     }
 
+    private fun updateAnnotationToolbarVisibility(isAnnotationToolbarVisible: Boolean) {
+        toolbarCoordinator.isVisible = isAnnotationToolbarVisible
+        annotationToolbar.isVisible = isAnnotationToolbarVisible
+    }
+
     private fun updateUiForAnnotationsEditMode(isEnabled: Boolean) {
         PdfFeatureFlags.isMultiTouchScrollEnabled = isEnabled
 
-        annotationToolbar.visibility = if (isEnabled) VISIBLE else GONE
-
         if (isEnabled) {
             pdfView.clearCurrentSelection()
+
             // Wait for the toolbar to be laid out, as we need to utilize its width and height
             annotationToolbar.post { wetStrokesView.maskPath = createToolbarMaskPath() }
         } else {
diff --git a/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfDocumentViewModel.kt b/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfDocumentViewModel.kt
index b276f62..49c8a14 100644
--- a/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfDocumentViewModel.kt
+++ b/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfDocumentViewModel.kt
@@ -130,6 +130,9 @@
     internal val isTextSearchActiveFromState: Boolean
         get() = state[TEXT_SEARCH_STATE_KEY] ?: false
 
+    protected val isTextSearchActiveFlow: StateFlow<Boolean> =
+        state.getStateFlow(TEXT_SEARCH_STATE_KEY, false)
+
     /** isImmersiveModeFromState as set in [state] */
     internal val isImmersiveModeDesired: Boolean
         get() = state[IMMERSIVE_MODE_STATE_KEY] ?: false