Don't focus on views that are detached from window
Fixes: 169273707
Test: atest CarUILibUnitTests, and manual test
Change-Id: I3d5eff609e75471209f373688e88826509c1eb48
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTest.java
index 7524b27..9c1ce88 100644
--- a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTest.java
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/FocusAreaTest.java
@@ -55,6 +55,8 @@
private View mChild;
private View mDefaultFocus;
private View mNonChild;
+ private View mChild1;
+ private View mChild2;
@Before
public void setUp() {
@@ -65,6 +67,8 @@
mChild = mActivity.findViewById(R.id.child);
mDefaultFocus = mActivity.findViewById(R.id.default_focus);
mNonChild = mActivity.findViewById(R.id.non_child);
+ mChild1 = mActivity.findViewById(R.id.child1);
+ mChild2 = mActivity.findViewById(R.id.child2);
}
@Test
@@ -176,6 +180,24 @@
node.recycle();
}
+ @Test
+ public void testLastFocusedViewRemoved() {
+ mChild1.post(() -> {
+ // Focus on mChild1 in mFocusArea2, then mChild in mFocusArea .
+ mChild1.requestFocus();
+ assertThat(mChild1.isFocused()).isTrue();
+ mChild.requestFocus();
+ assertThat(mChild.isFocused()).isTrue();
+
+ // Remove mChild1 in mFocusArea2, then Perform ACTION_FOCUS on mFocusArea2.
+ mFocusArea2.removeView(mChild1);
+ mFocusArea2.performAccessibilityAction(ACTION_FOCUS, null);
+
+ // mChild2 in mFocusArea2 should get focused.
+ assertThat(mChild2.isFocused()).isTrue();
+ });
+ }
+
private void assertBoundsOffset(
@NonNull AccessibilityNodeInfo node, int leftPx, int topPx, int rightPx, int bottomPx) {
Bundle extras = node.getExtras();
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/res/layout/focus_area_test_activity.xml b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/focus_area_test_activity.xml
index 209e911..524de8d 100644
--- a/car-ui-lib/car-ui-lib/src/androidTest/res/layout/focus_area_test_activity.xml
+++ b/car-ui-lib/car-ui-lib/src/androidTest/res/layout/focus_area_test_activity.xml
@@ -50,11 +50,22 @@
android:layout_height="100dp"/>
<com.android.car.ui.TestFocusArea
android:id="@+id/focus_area2"
- android:layout_width="100dp"
- android:layout_height="100dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
app:highlightPaddingHorizontal="10dp"
app:highlightPaddingVertical="20dp"
app:highlightPaddingStart="30dp"
app:highlightPaddingTop="40dp"
- app:startBoundOffset="50dp"/>
+ app:startBoundOffset="50dp">
+ <View
+ android:id="@+id/child1"
+ android:focusable="true"
+ android:layout_width="100dp"
+ android:layout_height="100dp"/>
+ <View
+ android:id="@+id/child2"
+ android:focusable="true"
+ android:layout_width="100dp"
+ android:layout_height="100dp"/>
+ </com.android.car.ui.TestFocusArea>
</LinearLayout>
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/FocusArea.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/FocusArea.java
index 72261a7..f5c6c1d 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/FocusArea.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/FocusArea.java
@@ -673,7 +673,7 @@
}
private boolean requestFocus(@Nullable View view) {
- if (view == null) {
+ if (view == null || !view.isAttachedToWindow()) {
return false;
}
// Exit touch mode and focus the view. The view may not be focusable in touch mode, so we