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

Commit f5e4182d authored by Julia Reynolds's avatar Julia Reynolds
Browse files

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
parent 25ff1cd4
Loading
Loading
Loading
Loading
+44 −35
Original line number Diff line number Diff line
@@ -15,15 +15,23 @@
     limitations under the License.
-->
<!-- extends LinearLayout -->
<com.android.systemui.HardwareUiLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    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:minWidth="320dp"
    android:minHeight="320dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
        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"
        android:translationZ="8dp"
        android:padding="20dp" >

        <TextView
@@ -59,3 +67,4 @@
                android:textAppearance="@style/TextAppearance.QS.DetailEmpty"/>
        </LinearLayout>
    </com.android.systemui.volume.OutputChooserLayout>
</com.android.systemui.HardwareUiLayout>
+2 −0
Original line number Diff line number Diff line
@@ -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 -->

+11 −2
Original line number Diff line number Diff line
@@ -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);
                }
                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);
                }
                if (mSwapOrientation) {
                    linearLayout.setOrientation(LinearLayout.VERTICAL);
                }
                swapDimens(mChild);
            }
        }
+102 −3
Original line number Diff line number Diff line
@@ -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();
    }
@@ -168,6 +198,38 @@ public class OutputChooserDialog extends SystemUIDialog
        cleanUp();
    }

    @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;
@@ -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
+34 −14
Original line number Diff line number Diff line
@@ -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;
@@ -53,6 +54,8 @@ public class OutputChooserDialogTest extends SysuiTestCase {

    OutputChooserDialog mDialog;

    @Mock
    private VolumeDialogController mVolumeController;
    @Mock
    private BluetoothController mController;
    @Mock
@@ -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());
    }
}