summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Julia Reynolds <juliacr@google.com> 2018-01-23 13:55:18 -0500
committer Julia Reynolds <juliacr@google.com> 2018-01-24 15:22:25 +0000
commitf5e4182d2fdf7cee3a95ed4734b7b2533bdeddc9 (patch)
tree84e173b94e869467e6fb30e59b0a525fc29d2e4b
parent25ff1cd41f27adee9d2f399883cef924c4e9a1fa (diff)
Output chooser layout updates
- Anchor output chooser to volume buttons - Dismiss output chooser if volume dialog becomes visible Test: manual, runtest systemui Fixes: 72319160 Bug: 63096355 Change-Id: Ibca7576f287655fb5c98554e67781ec53152ddef
-rw-r--r--packages/SystemUI/res/layout/output_chooser.xml79
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/OutputChooserDialog.java105
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java48
5 files changed, 193 insertions, 54 deletions
diff --git a/packages/SystemUI/res/layout/output_chooser.xml b/packages/SystemUI/res/layout/output_chooser.xml
index b96f44750a0c..b9f7b152ecac 100644
--- a/packages/SystemUI/res/layout/output_chooser.xml
+++ b/packages/SystemUI/res/layout/output_chooser.xml
@@ -15,47 +15,56 @@
limitations under the License.
-->
<!-- extends LinearLayout -->
-<com.android.systemui.volume.OutputChooserLayout
+<com.android.systemui.HardwareUiLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:sysui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/output_chooser"
- android:minWidth="320dp"
- android:minHeight="320dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="20dp" >
-
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textDirection="locale"
- android:textAppearance="@style/TextAppearance.QS.DetailHeader"
- android:layout_marginBottom="20dp" />
-
- <com.android.systemui.qs.AutoSizingList
- android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_marginBottom="0dp"
+ android:clipToPadding="false"
+ android:theme="@style/qs_theme"
+ android:clipChildren="false">
+ <com.android.systemui.volume.OutputChooserLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:sysui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/output_chooser"
+ android:layout_width="@dimen/output_chooser_panel_width"
+ android:layout_height="@dimen/output_chooser_panel_width"
+ android:layout_gravity="center_vertical|end"
android:orientation="vertical"
- sysui:itemHeight="@dimen/qs_detail_item_height"
- style="@style/AutoSizingList"/>
-
- <LinearLayout
- android:id="@android:id/empty"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center"
- android:gravity="center"
- android:orientation="vertical">
+ android:translationZ="8dp"
+ android:padding="20dp" >
<TextView
- android:id="@+id/empty_text"
+ android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textDirection="locale"
- android:layout_marginTop="20dp"
- android:textAppearance="@style/TextAppearance.QS.DetailEmpty"/>
- </LinearLayout>
-</com.android.systemui.volume.OutputChooserLayout>
+ android:textAppearance="@style/TextAppearance.QS.DetailHeader"
+ android:layout_marginBottom="20dp" />
+
+ <com.android.systemui.qs.AutoSizingList
+ android:id="@android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ sysui:itemHeight="@dimen/qs_detail_item_height"
+ style="@style/AutoSizingList"/>
+
+ <LinearLayout
+ android:id="@android:id/empty"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/empty_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textDirection="locale"
+ android:layout_marginTop="20dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailEmpty"/>
+ </LinearLayout>
+ </com.android.systemui.volume.OutputChooserLayout>
+</com.android.systemui.HardwareUiLayout>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b749a18a8c68..a90106d7131a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -267,6 +267,8 @@
<dimen name="volume_dialog_panel_width">120dp</dimen>
+ <dimen name="output_chooser_panel_width">320dp</dimen>
+
<!-- Gravity for the notification panel -->
<integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index ca34345d923b..948178802003 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -58,6 +58,7 @@ public class HardwareUiLayout extends FrameLayout implements Tunable {
private boolean mRoundedDivider;
private int mRotation = ROTATION_NONE;
private boolean mRotatedBackground;
+ private boolean mSwapOrientation = true;
public HardwareUiLayout(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -145,6 +146,10 @@ public class HardwareUiLayout extends FrameLayout implements Tunable {
updateRotation();
}
+ public void setSwapOrientation(boolean swapOrientation) {
+ mSwapOrientation = swapOrientation;
+ }
+
private void updateRotation() {
int rotation = RotationUtils.getRotation(getContext());
if (rotation != mRotation) {
@@ -173,7 +178,9 @@ public class HardwareUiLayout extends FrameLayout implements Tunable {
if (to == ROTATION_SEASCAPE) {
swapOrder(linearLayout);
}
- linearLayout.setOrientation(LinearLayout.HORIZONTAL);
+ if (mSwapOrientation) {
+ linearLayout.setOrientation(LinearLayout.HORIZONTAL);
+ }
swapDimens(this.mChild);
}
} else {
@@ -184,7 +191,9 @@ public class HardwareUiLayout extends FrameLayout implements Tunable {
if (from == ROTATION_SEASCAPE) {
swapOrder(linearLayout);
}
- linearLayout.setOrientation(LinearLayout.VERTICAL);
+ if (mSwapOrientation) {
+ linearLayout.setOrientation(LinearLayout.VERTICAL);
+ }
swapDimens(mChild);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/OutputChooserDialog.java b/packages/SystemUI/src/com/android/systemui/volume/OutputChooserDialog.java
index e0af9baf0bb0..e3c8503077d8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/OutputChooserDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/OutputChooserDialog.java
@@ -22,6 +22,7 @@ import static android.support.v7.media.MediaRouter.UNSELECT_REASON_DISCONNECTED;
import static com.android.settingslib.bluetooth.Utils.getBtClassDrawableWithDescription;
+import android.app.Dialog;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
@@ -30,6 +31,8 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.net.wifi.WifiManager;
@@ -43,12 +46,16 @@ import android.support.v7.media.MediaRouter;
import android.telecom.TelecomManager;
import android.util.Log;
import android.util.Pair;
+import android.view.Window;
+import android.view.WindowManager;
import com.android.settingslib.Utils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.systemui.Dependency;
+import com.android.systemui.HardwareUiLayout;
+import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.statusbar.policy.BluetoothController;
import java.io.IOException;
@@ -58,7 +65,7 @@ import java.util.Collection;
import java.util.Comparator;
import java.util.List;
-public class OutputChooserDialog extends SystemUIDialog
+public class OutputChooserDialog extends Dialog
implements DialogInterface.OnDismissListener, OutputChooserLayout.Callback {
private static final String TAG = Util.logTag(OutputChooserDialog.class);
@@ -82,9 +89,11 @@ public class OutputChooserDialog extends SystemUIDialog
private Drawable mTvIcon;
private Drawable mSpeakerIcon;
private Drawable mSpeakerGroupIcon;
+ private HardwareUiLayout mHardwareLayout;
+ private final VolumeDialogController mController;
public OutputChooserDialog(Context context, MediaRouterWrapper router) {
- super(context);
+ super(context, com.android.systemui.R.style.qs_theme);
mContext = context;
mBluetoothController = Dependency.get(BluetoothController.class);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -98,6 +107,22 @@ public class OutputChooserDialog extends SystemUIDialog
final IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.registerReceiver(mReceiver, filter);
+
+ mController = Dependency.get(VolumeDialogController.class);
+
+ // Window initialization
+ Window window = getWindow();
+ window.requestFeature(Window.FEATURE_NO_TITLE);
+ window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+ window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
+ | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
+ window.addFlags(
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+ window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
}
protected void setIsInCall(boolean inCall) {
@@ -112,6 +137,9 @@ public class OutputChooserDialog extends SystemUIDialog
setOnDismissListener(this::onDismiss);
mView = findViewById(R.id.output_chooser);
+ mHardwareLayout = HardwareUiLayout.get(mView);
+ mHardwareLayout.setOutsideTouchListener(view -> dismiss());
+ mHardwareLayout.setSwapOrientation(false);
mView.setCallback(this);
if (mIsInCall) {
@@ -151,6 +179,7 @@ public class OutputChooserDialog extends SystemUIDialog
MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
}
mBluetoothController.addCallback(mCallback);
+ mController.addCallback(mControllerCallbackH, mHandler);
isAttached = true;
}
@@ -158,6 +187,7 @@ public class OutputChooserDialog extends SystemUIDialog
public void onDetachedFromWindow() {
isAttached = false;
mRouter.removeCallback(mRouterCallback);
+ mController.removeCallback(mControllerCallbackH);
mBluetoothController.removeCallback(mCallback);
super.onDetachedFromWindow();
}
@@ -169,6 +199,38 @@ public class OutputChooserDialog extends SystemUIDialog
}
@Override
+ public void show() {
+ super.show();
+ mHardwareLayout.setTranslationX(getAnimTranslation());
+ mHardwareLayout.setAlpha(0);
+ mHardwareLayout.animate()
+ .alpha(1)
+ .translationX(0)
+ .setDuration(300)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .withEndAction(() -> getWindow().getDecorView().requestAccessibilityFocus())
+ .start();
+ }
+
+ @Override
+ public void dismiss() {
+ mHardwareLayout.setTranslationX(0);
+ mHardwareLayout.setAlpha(1);
+ mHardwareLayout.animate()
+ .alpha(0)
+ .translationX(getAnimTranslation())
+ .setDuration(300)
+ .withEndAction(() -> super.dismiss())
+ .setInterpolator(new SystemUIInterpolators.LogAccelerateInterpolator())
+ .start();
+ }
+
+ private float getAnimTranslation() {
+ return getContext().getResources().getDimension(
+ com.android.systemui.R.dimen.output_chooser_panel_width) / 2;
+ }
+
+ @Override
public void onDetailItemClick(OutputChooserLayout.Item item) {
if (item == null || item.tag == null) return;
if (item.deviceType == OutputChooserLayout.Item.DEVICE_TYPE_BT) {
@@ -416,4 +478,41 @@ public class OutputChooserDialog extends SystemUIDialog
}
}
};
+
+ private final VolumeDialogController.Callbacks mControllerCallbackH
+ = new VolumeDialogController.Callbacks() {
+ @Override
+ public void onShowRequested(int reason) {
+ dismiss();
+ }
+
+ @Override
+ public void onDismissRequested(int reason) {}
+
+ @Override
+ public void onScreenOff() {
+ dismiss();
+ }
+
+ @Override
+ public void onStateChanged(VolumeDialogController.State state) {}
+
+ @Override
+ public void onLayoutDirectionChanged(int layoutDirection) {}
+
+ @Override
+ public void onConfigurationChanged() {}
+
+ @Override
+ public void onShowVibrateHint() {}
+
+ @Override
+ public void onShowSilentHint() {}
+
+ @Override
+ public void onShowSafetyWarning(int flags) {}
+
+ @Override
+ public void onAccessibilityModeChanged(Boolean showA11yStream) {}
+ };
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java
index 537d606365c4..de99d71351c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java
@@ -38,6 +38,7 @@ import android.widget.TextView;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.statusbar.policy.BluetoothController;
import org.junit.After;
@@ -54,6 +55,8 @@ public class OutputChooserDialogTest extends SysuiTestCase {
OutputChooserDialog mDialog;
@Mock
+ private VolumeDialogController mVolumeController;
+ @Mock
private BluetoothController mController;
@Mock
private WifiManager mWifiManager;
@@ -69,6 +72,7 @@ public class OutputChooserDialogTest extends SysuiTestCase {
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
+ mVolumeController = mDependency.injectMockDependency(VolumeDialogController.class);
mController = mDependency.injectMockDependency(BluetoothController.class);
when(mWifiManager.isWifiEnabled()).thenReturn(true);
@@ -78,20 +82,10 @@ public class OutputChooserDialogTest extends SysuiTestCase {
mDialog = new OutputChooserDialog(getContext(), mRouter);
}
- @After
- @UiThreadTest
- public void tearDown() throws Exception {
- mDialog.dismiss();
- }
-
- private void showDialog() {
- mDialog.show();
- }
-
@Test
@UiThreadTest
public void testClickMediaRouterItemConnectsMedia() {
- showDialog();
+ mDialog.show();
OutputChooserLayout.Item item = new OutputChooserLayout.Item();
item.deviceType = OutputChooserLayout.Item.DEVICE_TYPE_MEDIA_ROUTER;
@@ -102,12 +96,13 @@ public class OutputChooserDialogTest extends SysuiTestCase {
mDialog.onDetailItemClick(item);
verify(info, times(1)).select();
verify(mController, never()).connect(any());
+ mDialog.dismiss();
}
@Test
@UiThreadTest
public void testClickBtItemConnectsBt() {
- showDialog();
+ mDialog.show();
OutputChooserLayout.Item item = new OutputChooserLayout.Item();
item.deviceType = OutputChooserLayout.Item.DEVICE_TYPE_BT;
@@ -117,25 +112,28 @@ public class OutputChooserDialogTest extends SysuiTestCase {
mDialog.onDetailItemClick(item);
verify(mController, times(1)).connect(any());
+ mDialog.dismiss();
}
@Test
@UiThreadTest
public void testTitleNotInCall() {
- showDialog();
+ mDialog.show();
assertTrue(((TextView) mDialog.findViewById(R.id.title))
.getText().toString().contains("Media"));
+ mDialog.dismiss();
}
@Test
@UiThreadTest
public void testTitleInCall() {
mDialog.setIsInCall(true);
- showDialog();
+ mDialog.show();
assertTrue(((TextView) mDialog.findViewById(R.id.title))
.getText().toString().contains("Phone"));
+ mDialog.dismiss();
}
@Test
@@ -155,4 +153,26 @@ public class OutputChooserDialogTest extends SysuiTestCase {
verify(mRouter, times(1)).addCallback(any(), any(), anyInt());
}
+
+ @Test
+ @UiThreadTest
+ public void testRegisterCallbacks() {
+ mDialog.setIsInCall(false);
+ mDialog.onAttachedToWindow();
+
+ verify(mRouter, times(1)).addCallback(any(), any(), anyInt());
+ verify(mController, times(1)).addCallback(any());
+ verify(mVolumeController, times(1)).addCallback(any(), any());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testUnregisterCallbacks() {
+ mDialog.setIsInCall(false);
+ mDialog.onDetachedFromWindow();
+
+ verify(mRouter, times(1)).removeCallback(any());
+ verify(mController, times(1)).removeCallback(any());
+ verify(mVolumeController, times(1)).removeCallback(any());
+ }
}