Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a275a9b0 authored by David Tseng's avatar David Tseng Committed by Android (Google) Code Review
Browse files

Merge "Fix and improve RequestFocusTest" into main

parents 35b9b241 7a69759a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ public class RequestFocus extends Activity {

        // bottom right button starts with the focus.
        final Button bottomRightButton = findViewById(R.id.bottomRightButton);
        bottomRightButton.setFocusableInTouchMode(true);
        bottomRightButton.requestFocus();
        bottomRightButton.setText("I should have focus");
    }
+111 −101
Original line number Diff line number Diff line
@@ -16,71 +16,79 @@

package android.widget.focus;

import static org.junit.Assert.*;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;

import android.os.Handler;
import android.test.ActivityInstrumentationTestCase2;
import android.util.AndroidRuntimeException;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
import android.widget.Button;

import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.frameworks.coretests.R;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;

/**
 * {@link RequestFocusTest} is set up to exercise cases where the views that
 * have focus become invisible or GONE.
 */
public class RequestFocusTest extends ActivityInstrumentationTestCase2<RequestFocus> {

@RunWith(AndroidJUnit4.class)
public class RequestFocusTest {
    private Button mTopLeftButton;
    private Button mBottomLeftButton;
    private Button mTopRightButton;
    private Button mBottomRightButton;
    private Handler mHandler;

    public RequestFocusTest() {
        super(RequestFocus.class);
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();
    @Rule
    public ActivityScenarioRule<RequestFocus> activityRule =
            new ActivityScenarioRule<>(RequestFocus.class);

        final RequestFocus a = getActivity();
    @Before
    public void setViewFieldsAndForceNonTouchMode() throws Exception {
        activityRule.getScenario().onActivity(a -> {
            mHandler = a.getHandler();
            mTopLeftButton = (Button) a.findViewById(R.id.topLeftButton);
            mBottomLeftButton = (Button) a.findViewById(R.id.bottomLeftButton);
            mTopRightButton = (Button) a.findViewById(R.id.topRightButton);
            mBottomRightButton = (Button) a.findViewById(R.id.bottomRightButton);
    }

    // Test that setUp did what we expect it to do.  These asserts
    // can't go in SetUp, or the test will hang.
    @MediumTest
    public void testSetUpConditions() throws Exception {
            assertNotNull(mHandler);
            assertNotNull(mTopLeftButton);
            assertNotNull(mTopRightButton);
            assertNotNull(mBottomLeftButton);
            assertNotNull(mBottomRightButton);
            assertTrue("requestFocus() should work from onCreate.", mBottomRightButton.hasFocus());
        });

        // Force non-touch mode by sending a key.
        android.app.Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
        instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
        instrumentation.waitForIdleSync(); // Wait for UI thread to be idle
    }

    // Test that a posted requestFocus works.
    @Test
    @LargeTest
    public void testPostedRequestFocus() throws Exception {
        mHandler.post(new Runnable() { public void run() {
        mHandler.post(new Runnable() {
            public void run() {
                mBottomLeftButton.requestFocus();
        }});
            }
        });
        synchronized (this) {
            try {
                wait(500);
@@ -92,6 +100,7 @@ public class RequestFocusTest extends ActivityInstrumentationTestCase2<RequestFo
    }

    // Test that a requestFocus from the wrong thread fails.
    @Test
    @MediumTest
    public void testWrongThreadRequestFocusFails() throws Exception {
        try {
@@ -112,30 +121,30 @@ public class RequestFocusTest extends ActivityInstrumentationTestCase2<RequestFo
     *
     * @throws Exception If an error occurs.
     */
    @UiThreadTest
    public void testOnFocusChangeCallbackOrderWhenClearingFocusOfFirstFocusable()
            throws Exception {
    @Test
    @LargeTest
    public void testOnFocusChangeCallbackOrderWhenClearingFocusOfFirstFocusable() throws Exception {
        activityRule.getScenario().onActivity(a -> {
            // Get the first focusable.
            Button clearingFocusButton = mTopLeftButton;
            Button gainingFocusButton = mTopLeftButton;

            // Make sure that the clearing focus View is the first focusable.
        View focusCandidate = clearingFocusButton.getRootView().getParent().focusSearch(null,
                View.FOCUS_FORWARD);
        assertSame("The clearing focus button is the first focusable.",
                clearingFocusButton, focusCandidate);
        assertSame("The gaining focus button is the first focusable.",
                gainingFocusButton, focusCandidate);
            View focusCandidate = clearingFocusButton.getRootView().getParent().focusSearch(
                    null, View.FOCUS_FORWARD);
            assertSame("The clearing focus button is the first focusable.", clearingFocusButton,
                    focusCandidate);
            assertSame("The gaining focus button is the first focusable.", gainingFocusButton,
                    focusCandidate);

            // Focus the clearing focus button.
            clearingFocusButton.requestFocus();
            assertTrue(clearingFocusButton.hasFocus());

            // Register the invocation order checker.
        CombinedListeners mock = mock(CombinedListeners.class);
            OnFocusChangeListener mock = mock(OnFocusChangeListener.class);
            clearingFocusButton.setOnFocusChangeListener(mock);
            gainingFocusButton.setOnFocusChangeListener(mock);
        clearingFocusButton.getViewTreeObserver().addOnGlobalFocusChangeListener(mock);

            // Try to clear focus.
            clearingFocusButton.clearFocus();
@@ -143,12 +152,10 @@ public class RequestFocusTest extends ActivityInstrumentationTestCase2<RequestFo
            // Check that no callback was invoked since focus did not move.
            InOrder inOrder = inOrder(mock);
            inOrder.verify(mock).onFocusChange(clearingFocusButton, false);
        inOrder.verify(mock).onGlobalFocusChanged(clearingFocusButton, gainingFocusButton);
            inOrder.verify(mock).onFocusChange(gainingFocusButton, true);
        });
    }

    public interface CombinedListeners extends OnFocusChangeListener, OnGlobalFocusChangeListener {}

    /**
     * This tests check whether the on focus change callbacks are invoked in
     * the proper order when a View loses focus and the framework gives it to
@@ -156,29 +163,31 @@ public class RequestFocusTest extends ActivityInstrumentationTestCase2<RequestFo
     *
     * @throws Exception
     */
    @UiThreadTest
    @Test
    @LargeTest
    public void testOnFocusChangeCallbackOrderWhenClearingFocusOfNotFirstFocusable()
            throws Exception {
        activityRule.getScenario().onActivity(a -> {
            Button clearingFocusButton = mTopRightButton;
            Button gainingFocusButton = mTopLeftButton;

            // Make sure that the clearing focus View is not the first focusable.
        View focusCandidate = clearingFocusButton.getRootView().getParent().focusSearch(null,
                View.FOCUS_FORWARD);
            View focusCandidate = clearingFocusButton.getRootView().getParent().focusSearch(
                    null, View.FOCUS_FORWARD);

            assertNotSame("The clearing focus button is not the first focusable.",
                    clearingFocusButton, focusCandidate);
        assertSame("The gaining focus button is the first focusable.",
                gainingFocusButton, focusCandidate);
            assertSame("The gaining focus button is the first focusable.", gainingFocusButton,
                    focusCandidate);

            // Focus the clearing focus button.
            clearingFocusButton.requestFocus();
            assertTrue(clearingFocusButton.hasFocus());

            // Register the invocation order checker.
        CombinedListeners mock = mock(CombinedListeners.class);
            OnFocusChangeListener mock = mock(OnFocusChangeListener.class);
            clearingFocusButton.setOnFocusChangeListener(mock);
            gainingFocusButton.setOnFocusChangeListener(mock);
        clearingFocusButton.getViewTreeObserver().addOnGlobalFocusChangeListener(mock);

            // Try to clear focus.
            clearingFocusButton.clearFocus();
@@ -186,7 +195,8 @@ public class RequestFocusTest extends ActivityInstrumentationTestCase2<RequestFo
            // Check that no callback was invoked since focus did not move.
            InOrder inOrder = inOrder(mock);
            inOrder.verify(mock).onFocusChange(clearingFocusButton, false);
        inOrder.verify(mock).onGlobalFocusChanged(clearingFocusButton, gainingFocusButton);

            inOrder.verify(mock).onFocusChange(gainingFocusButton, true);
        });
    }
}