Merge "Improve ResolverActivity UX on TV"
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index a4cd4f1..8d3c572 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -353,7 +353,11 @@
finish();
}
});
- if (isVoiceInteraction()) {
+
+ boolean hasTouchScreen = getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN);
+
+ if (isVoiceInteraction() || !hasTouchScreen) {
rdl.setCollapsed(false);
}
@@ -1301,10 +1305,11 @@
// In case this method is called again (due to activity recreation), avoid adding a new
// header if one is already present.
- if (useHeader && listView != null && listView.getHeaderViewsCount() == 0) {
+ if (useHeader && listView.getHeaderViewsCount() == 0) {
listView.setHeaderDividersEnabled(true);
listView.addHeaderView(LayoutInflater.from(this).inflate(
- R.layout.resolver_different_item_header, listView, false));
+ R.layout.resolver_different_item_header, listView, false),
+ null, false);
}
}
@@ -1367,6 +1372,8 @@
if (useLayoutWithDefault() && filteredPosition != ListView.INVALID_POSITION) {
setAlwaysButtonEnabled(true, filteredPosition, false);
mOnceButton.setEnabled(true);
+ // Focus the button if we already have the default option
+ mOnceButton.requestFocus();
return;
}
@@ -1499,6 +1506,7 @@
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
currentAdapterView.smoothScrollToPosition(checkedPos);
+ mOnceButton.requestFocus();
}
mLastSelected = checkedPos;
} else {
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 1bb2ba2..e0c3823 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -187,7 +187,7 @@
public void setCollapsed(boolean collapsed) {
if (!isLaidOut()) {
- mOpenOnLayout = collapsed;
+ mOpenOnLayout = !collapsed;
} else {
smoothScrollTo(collapsed ? mCollapsibleHeight : 0, 0);
}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 8622b7e..c086421 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -54,6 +54,7 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager.ShareShortcutInfo;
+import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -977,6 +978,7 @@
serviceTargets,
TARGET_TYPE_CHOOSER_TARGET)
);
+
// Thread.sleep shouldn't be a thing in an integration test but it's
// necessary here because of the way the code is structured
// TODO: restructure the tests b/129870719
@@ -1075,7 +1077,29 @@
// This test is too long and too slow and should not be taken as an example for future tests.
@Test
- public void testDirectTargetLoggingWithAppTargetNotRanked() throws InterruptedException {
+ public void testDirectTargetLoggingWithAppTargetNotRankedPortrait()
+ throws InterruptedException {
+ testDirectTargetLoggingWithAppTargetNotRanked(Configuration.ORIENTATION_PORTRAIT, 4);
+ }
+
+ @Test
+ public void testDirectTargetLoggingWithAppTargetNotRankedLandscape()
+ throws InterruptedException {
+ testDirectTargetLoggingWithAppTargetNotRanked(Configuration.ORIENTATION_LANDSCAPE, 8);
+ }
+
+ private void testDirectTargetLoggingWithAppTargetNotRanked(
+ int orientation, int appTargetsExpected
+ ) throws InterruptedException {
+ Configuration configuration =
+ new Configuration(InstrumentationRegistry.getInstrumentation().getContext()
+ .getResources().getConfiguration());
+ configuration.orientation = orientation;
+
+ sOverrides.resources = Mockito.spy(
+ InstrumentationRegistry.getInstrumentation().getContext().getResources());
+ when(sOverrides.resources.getConfiguration()).thenReturn(configuration);
+
Intent sendIntent = createSendTextIntent();
// We need app targets for direct targets to get displayed
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(15);
@@ -1111,8 +1135,10 @@
// TODO: restructure the tests b/129870719
Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
- assertThat("Chooser should have 20 targets (4 apps, 1 direct, 15 A-Z)",
- activity.getAdapter().getCount(), is(20));
+ assertThat(
+ String.format("Chooser should have %d targets (%d apps, 1 direct, 15 A-Z)",
+ appTargetsExpected + 16, appTargetsExpected),
+ activity.getAdapter().getCount(), is(appTargetsExpected + 16));
assertThat("Chooser should have exactly one selectable direct target",
activity.getAdapter().getSelectableServiceTargetCount(), is(1));
assertThat("The resolver info must match the resolver info used to create the target",