OSDN Git Service

Update output chooser for calls
authorJulia Reynolds <juliacr@google.com>
Wed, 20 Dec 2017 14:53:59 +0000 (09:53 -0500)
committerJulia Reynolds <juliacr@google.com>
Sat, 20 Jan 2018 15:29:41 +0000 (15:29 +0000)
- Hide media routes while in call
- Change the title while in call
- Add a title while not in call, too

Bug: 63096355
Test: manual
Change-Id: Ib7bcd314efb010fe903327dd4d9bdbfe521c1f73

packages/SystemUI/res/layout/output_chooser.xml
packages/SystemUI/res/layout/output_chooser_item.xml
packages/SystemUI/src/com/android/systemui/volume/MediaRouterWrapper.java [new file with mode: 0644]
packages/SystemUI/src/com/android/systemui/volume/OutputChooserDialog.java
packages/SystemUI/src/com/android/systemui/volume/OutputChooserLayout.java
packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
packages/SystemUI/tests/AndroidManifest.xml
packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java [new file with mode: 0644]

index 3d0ab35..b96f447 100644 (file)
@@ -14,7 +14,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<!-- extends FrameLayout -->
+<!-- extends LinearLayout -->
 <com.android.systemui.volume.OutputChooserLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:sysui="http://schemas.android.com/apk/res-auto"
     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:orientation="vertical">
 
         <TextView
-            android:id="@android:id/title"
+            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>
index ed7df4b..c3ddbbe 100644 (file)
@@ -30,6 +30,7 @@
         android:layout_height="@dimen/qs_detail_item_icon_size"
         android:layout_marginStart="@dimen/qs_detail_item_icon_marginStart"
         android:layout_marginEnd="@dimen/qs_detail_item_icon_marginEnd"
+        android:background="?android:selectableItemBackgroundBorderless"
         android:tint="?android:attr/textColorPrimary"/>
 
     <LinearLayout
diff --git a/packages/SystemUI/src/com/android/systemui/volume/MediaRouterWrapper.java b/packages/SystemUI/src/com/android/systemui/volume/MediaRouterWrapper.java
new file mode 100644 (file)
index 0000000..3423452
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume;
+
+import android.support.v7.media.MediaRouteSelector;
+import android.support.v7.media.MediaRouter;
+
+import java.util.List;
+
+/**
+ * Wrapper for final class MediaRouter, for testing.
+ */
+public class MediaRouterWrapper {
+
+    private final MediaRouter mRouter;
+
+    public MediaRouterWrapper(MediaRouter router)
+    {
+        mRouter = router;
+    }
+
+    public void addCallback(MediaRouteSelector selector, MediaRouter.Callback callback, int flags) {
+        mRouter.addCallback(selector, callback, flags);
+    }
+
+    public void removeCallback(MediaRouter.Callback callback) {
+        mRouter.removeCallback(callback);
+    }
+
+    public void unselect(int reason) {
+        mRouter.unselect(reason);
+    }
+
+    public List<MediaRouter.RouteInfo> getRoutes() {
+        return mRouter.getRoutes();
+    }
+}
\ No newline at end of file
index f8843a9..e0af9ba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ import android.os.SystemClock;
 import android.support.v7.media.MediaControlIntent;
 import android.support.v7.media.MediaRouteSelector;
 import android.support.v7.media.MediaRouter;
+import android.telecom.TelecomManager;
 import android.util.Log;
 import android.util.Pair;
 
@@ -54,7 +55,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
@@ -65,15 +65,17 @@ public class OutputChooserDialog extends SystemUIDialog
     private static final int MAX_DEVICES = 10;
 
     private static final long UPDATE_DELAY_MS = 300L;
-    static final int MSG_UPDATE_ITEMS = 1;
+    private static final int MSG_UPDATE_ITEMS = 1;
 
     private final Context mContext;
-    private final BluetoothController mController;
-    private final WifiManager mWifiManager;
+    private final BluetoothController mBluetoothController;
+    private WifiManager mWifiManager;
     private OutputChooserLayout mView;
-    private final MediaRouter mRouter;
+    private final MediaRouterWrapper mRouter;
     private final MediaRouterCallback mRouterCallback;
     private long mLastUpdateTime;
+    private boolean mIsInCall;
+    protected boolean isAttached;
 
     private final MediaRouteSelector mRouteSelector;
     private Drawable mDefaultIcon;
@@ -81,12 +83,14 @@ public class OutputChooserDialog extends SystemUIDialog
     private Drawable mSpeakerIcon;
     private Drawable mSpeakerGroupIcon;
 
-    public OutputChooserDialog(Context context) {
+    public OutputChooserDialog(Context context, MediaRouterWrapper router) {
         super(context);
         mContext = context;
-        mController = Dependency.get(BluetoothController.class);
+        mBluetoothController = Dependency.get(BluetoothController.class);
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
-        mRouter = MediaRouter.getInstance(context);
+        TelecomManager tm = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
+        mIsInCall = tm.isInCall();
+        mRouter = router;
         mRouterCallback = new MediaRouterCallback();
         mRouteSelector = new MediaRouteSelector.Builder()
                 .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
@@ -96,27 +100,38 @@ public class OutputChooserDialog extends SystemUIDialog
         context.registerReceiver(mReceiver, filter);
     }
 
+    protected void setIsInCall(boolean inCall) {
+        mIsInCall = inCall;
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.output_chooser);
         setCanceledOnTouchOutside(true);
         setOnDismissListener(this::onDismiss);
-        setTitle(R.string.output_title);
 
         mView = findViewById(R.id.output_chooser);
         mView.setCallback(this);
 
+        if (mIsInCall) {
+            mView.setTitle(R.string.output_calls_title);
+        } else {
+            mView.setTitle(R.string.output_title);
+        }
+
         mDefaultIcon = mContext.getDrawable(R.drawable.ic_cast);
         mTvIcon = mContext.getDrawable(R.drawable.ic_tv);
         mSpeakerIcon = mContext.getDrawable(R.drawable.ic_speaker);
         mSpeakerGroupIcon = mContext.getDrawable(R.drawable.ic_speaker_group);
 
         final boolean wifiOff = !mWifiManager.isWifiEnabled();
-        final boolean btOff = !mController.isBluetoothEnabled();
-        if (wifiOff || btOff) {
+        final boolean btOff = !mBluetoothController.isBluetoothEnabled();
+        if (wifiOff && btOff) {
             mView.setEmptyState(getDisabledServicesMessage(wifiOff, btOff));
         }
+        // time out after 5 seconds
+        mView.postDelayed(() -> updateItems(true), 5000);
     }
 
     protected void cleanUp() {}
@@ -131,15 +146,19 @@ public class OutputChooserDialog extends SystemUIDialog
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
 
-        mRouter.addCallback(mRouteSelector, mRouterCallback,
-                MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
-        mController.addCallback(mCallback);
+        if (!mIsInCall) {
+            mRouter.addCallback(mRouteSelector, mRouterCallback,
+                    MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
+        }
+        mBluetoothController.addCallback(mCallback);
+        isAttached = true;
     }
 
     @Override
     public void onDetachedFromWindow() {
+        isAttached = false;
         mRouter.removeCallback(mRouterCallback);
-        mController.removeCallback(mCallback);
+        mBluetoothController.removeCallback(mCallback);
         super.onDetachedFromWindow();
     }
 
@@ -154,9 +173,8 @@ public class OutputChooserDialog extends SystemUIDialog
         if (item == null || item.tag == null) return;
         if (item.deviceType == OutputChooserLayout.Item.DEVICE_TYPE_BT) {
             final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
-            if (device != null && device.getMaxConnectionState()
-                    == BluetoothProfile.STATE_DISCONNECTED) {
-                mController.connect(device);
+            if (device.getMaxConnectionState() == BluetoothProfile.STATE_DISCONNECTED) {
+                mBluetoothController.connect(device);
             }
         } else if (item.deviceType == OutputChooserLayout.Item.DEVICE_TYPE_MEDIA_ROUTER) {
             final MediaRouter.RouteInfo route = (MediaRouter.RouteInfo) item.tag;
@@ -171,18 +189,16 @@ public class OutputChooserDialog extends SystemUIDialog
         if (item == null || item.tag == null) return;
         if (item.deviceType == OutputChooserLayout.Item.DEVICE_TYPE_BT) {
             final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
-            if (device != null) {
-                mController.disconnect(device);
-            }
+            mBluetoothController.disconnect(device);
         } else if (item.deviceType == OutputChooserLayout.Item.DEVICE_TYPE_MEDIA_ROUTER) {
             mRouter.unselect(UNSELECT_REASON_DISCONNECTED);
         }
     }
 
-    private void updateItems() {
+    private void updateItems(boolean timeout) {
         if (SystemClock.uptimeMillis() - mLastUpdateTime < UPDATE_DELAY_MS) {
             mHandler.removeMessages(MSG_UPDATE_ITEMS);
-            mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_UPDATE_ITEMS),
+            mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_UPDATE_ITEMS, timeout),
                     mLastUpdateTime + UPDATE_DELAY_MS);
             return;
         }
@@ -194,14 +210,16 @@ public class OutputChooserDialog extends SystemUIDialog
         addBluetoothDevices(items);
 
         // Add remote displays
-        addRemoteDisplayRoutes(items);
+        if (!mIsInCall) {
+            addRemoteDisplayRoutes(items);
+        }
 
-        Collections.sort(items, ItemComparator.sInstance);
+        items.sort(ItemComparator.sInstance);
 
-        if (items.size() == 0) {
+        if (items.size() == 0 && timeout) {
             String emptyMessage = mContext.getString(R.string.output_none_found);
             final boolean wifiOff = !mWifiManager.isWifiEnabled();
-            final boolean btOff = !mController.isBluetoothEnabled();
+            final boolean btOff = !mBluetoothController.isBluetoothEnabled();
             if (wifiOff || btOff) {
                 emptyMessage = getDisabledServicesMessage(wifiOff, btOff);
             }
@@ -219,12 +237,12 @@ public class OutputChooserDialog extends SystemUIDialog
     }
 
     private void addBluetoothDevices(List<OutputChooserLayout.Item> items) {
-        final Collection<CachedBluetoothDevice> devices = mController.getDevices();
+        final Collection<CachedBluetoothDevice> devices = mBluetoothController.getDevices();
         if (devices != null) {
             int connectedDevices = 0;
             int count = 0;
             for (CachedBluetoothDevice device : devices) {
-                if (mController.getBondState(device) == BluetoothDevice.BOND_NONE) continue;
+                if (mBluetoothController.getBondState(device) == BluetoothDevice.BOND_NONE) continue;
                 final int majorClass = device.getBtClass().getMajorDeviceClass();
                 if (majorClass != BluetoothClass.Device.Major.AUDIO_VIDEO
                         && majorClass != BluetoothClass.Device.Major.UNCATEGORIZED) {
@@ -328,22 +346,22 @@ public class OutputChooserDialog extends SystemUIDialog
     private final class MediaRouterCallback extends MediaRouter.Callback {
         @Override
         public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) {
-            updateItems();
+            updateItems(false);
         }
 
         @Override
         public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) {
-            updateItems();
+            updateItems(false);
         }
 
         @Override
         public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo info) {
-            updateItems();
+            updateItems(false);
         }
 
         @Override
         public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo route) {
-            dismiss();
+            updateItems(false);
         }
     }
 
@@ -361,12 +379,12 @@ public class OutputChooserDialog extends SystemUIDialog
     private final BluetoothController.Callback mCallback = new BluetoothController.Callback() {
         @Override
         public void onBluetoothStateChange(boolean enabled) {
-            updateItems();
+            updateItems(false);
         }
 
         @Override
         public void onBluetoothDevicesChanged() {
-            updateItems();
+            updateItems(false);
         }
     };
 
@@ -393,7 +411,7 @@ public class OutputChooserDialog extends SystemUIDialog
         public void handleMessage(Message message) {
             switch (message.what) {
                 case MSG_UPDATE_ITEMS:
-                    updateItems();
+                    updateItems((Boolean) message.obj);
                     break;
             }
         }
index 22ced60..d4c6f89 100644 (file)
@@ -29,8 +29,8 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
-import android.widget.FrameLayout;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.systemui.FontSizeUtils;
@@ -40,11 +40,10 @@ import com.android.systemui.qs.AutoSizingList;
 /**
  * Limited height list of devices.
  */
-public class OutputChooserLayout extends FrameLayout {
+public class OutputChooserLayout extends LinearLayout {
     private static final String TAG = "OutputChooserLayout";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private final int mQsDetailIconOverlaySize;
     private final Context mContext;
     private final H mHandler = new H();
     private final Adapter mAdapter = new Adapter();
@@ -55,6 +54,7 @@ public class OutputChooserLayout extends FrameLayout {
     private AutoSizingList mItemList;
     private View mEmpty;
     private TextView mEmptyText;
+    private TextView mTitle;
 
     private Item[] mItems;
 
@@ -62,8 +62,6 @@ public class OutputChooserLayout extends FrameLayout {
         super(context, attrs);
         mContext = context;
         mTag = TAG;
-        mQsDetailIconOverlaySize = (int) getResources().getDimension(
-                R.dimen.qs_detail_icon_overlay_size);
     }
 
     @Override
@@ -74,7 +72,8 @@ public class OutputChooserLayout extends FrameLayout {
         mItemList.setAdapter(mAdapter);
         mEmpty = findViewById(android.R.id.empty);
         mEmpty.setVisibility(GONE);
-        mEmptyText = mEmpty.findViewById(android.R.id.title);
+        mEmptyText = mEmpty.findViewById(R.id.empty_text);
+        mTitle = findViewById(R.id.title);
     }
 
     @Override
@@ -84,17 +83,21 @@ public class OutputChooserLayout extends FrameLayout {
         int count = mItemList.getChildCount();
         for (int i = 0; i < count; i++) {
             View item = mItemList.getChildAt(i);
-            FontSizeUtils.updateFontSize(item, android.R.id.title,
+            FontSizeUtils.updateFontSize(item, R.id.empty_text,
                     R.dimen.qs_detail_item_primary_text_size);
             FontSizeUtils.updateFontSize(item, android.R.id.summary,
                     R.dimen.qs_detail_item_secondary_text_size);
+            FontSizeUtils.updateFontSize(item, android.R.id.title,
+                    R.dimen.qs_detail_header_text_size);
         }
     }
 
+    public void setTitle(int title) {
+            mTitle.setText(title);
+    }
+
     public void setEmptyState(String text) {
-        mEmpty.post(() -> {
-            mEmptyText.setText(text);
-        });
+        mEmptyText.setText(text);
     }
 
     @Override
@@ -176,11 +179,6 @@ public class OutputChooserLayout extends FrameLayout {
             } else {
                 iv.setImageResource(item.iconResId);
             }
-            iv.getOverlay().clear();
-            if (item.overlay != null) {
-                item.overlay.setBounds(0, 0, mQsDetailIconOverlaySize, mQsDetailIconOverlaySize);
-                iv.getOverlay().add(item.overlay);
-            }
             final TextView title = view.findViewById(android.R.id.title);
             title.setText(item.line1);
             final TextView summary =  view.findViewById(android.R.id.summary);
index 9f7c5a7..e76bf57 100644 (file)
@@ -47,6 +47,7 @@ import android.os.Message;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.provider.Settings.Global;
+import android.support.v7.media.MediaRouter;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
@@ -858,7 +859,8 @@ public class VolumeDialogImpl implements VolumeDialog {
             if (mOutputChooserDialog != null) {
                 return;
             }
-            mOutputChooserDialog = new OutputChooserDialog(mContext) {
+            mOutputChooserDialog = new OutputChooserDialog(mContext,
+                    new MediaRouterWrapper(MediaRouter.getInstance(mContext))) {
                 @Override
                 protected void cleanUp() {
                     synchronized (mOutputChooserLock) {
index e74736a..859dc2f 100644 (file)
@@ -46,6 +46,7 @@
     <uses-permission android:name="android.permission.STATUS_BAR" />
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
     <uses-permission android:name="android.permission.REAL_GET_TASKS" />
+    <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
 
     <application>
         <uses-library android:name="android.test.runner" />
index fbcbd20..4c7c1d1 100644 (file)
@@ -83,7 +83,7 @@ public abstract class SysuiTestCase {
         return null;
     }
 
-    public Context getContext() {
+    public SysuiTestableContext getContext() {
         return mContext;
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/OutputChooserDialogTest.java
new file mode 100644 (file)
index 0000000..537d606
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume;
+
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothProfile;
+import android.net.wifi.WifiManager;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v7.media.MediaRouter;
+import android.telecom.TelecomManager;
+import android.widget.TextView;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.BluetoothController;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class OutputChooserDialogTest extends SysuiTestCase {
+
+    OutputChooserDialog mDialog;
+
+    @Mock
+    private BluetoothController mController;
+    @Mock
+    private WifiManager mWifiManager;
+    @Mock
+    private TelecomManager mTelecomManager;
+
+    @Mock
+    private MediaRouterWrapper mRouter;
+
+
+    @Before
+    @UiThreadTest
+    public void setup() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mController = mDependency.injectMockDependency(BluetoothController.class);
+        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+
+        getContext().addMockSystemService(WifiManager.class, mWifiManager);
+        getContext().addMockSystemService(TelecomManager.class, mTelecomManager);
+
+        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();
+
+        OutputChooserLayout.Item item = new OutputChooserLayout.Item();
+        item.deviceType = OutputChooserLayout.Item.DEVICE_TYPE_MEDIA_ROUTER;
+        MediaRouter.RouteInfo info = mock(MediaRouter.RouteInfo.class);
+        when(info.isEnabled()).thenReturn(true);
+        item.tag = info;
+
+        mDialog.onDetailItemClick(item);
+        verify(info, times(1)).select();
+        verify(mController, never()).connect(any());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testClickBtItemConnectsBt() {
+        showDialog();
+
+        OutputChooserLayout.Item item = new OutputChooserLayout.Item();
+        item.deviceType = OutputChooserLayout.Item.DEVICE_TYPE_BT;
+        CachedBluetoothDevice btDevice = mock(CachedBluetoothDevice.class);
+        when(btDevice.getMaxConnectionState()).thenReturn(BluetoothProfile.STATE_DISCONNECTED);
+        item.tag = btDevice;
+
+        mDialog.onDetailItemClick(item);
+        verify(mController, times(1)).connect(any());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testTitleNotInCall() {
+        showDialog();
+
+        assertTrue(((TextView) mDialog.findViewById(R.id.title))
+                .getText().toString().contains("Media"));
+    }
+
+    @Test
+    @UiThreadTest
+    public void testTitleInCall() {
+        mDialog.setIsInCall(true);
+        showDialog();
+
+        assertTrue(((TextView) mDialog.findViewById(R.id.title))
+                .getText().toString().contains("Phone"));
+    }
+
+    @Test
+    @UiThreadTest
+    public void testNoMediaScanIfInCall() {
+        mDialog.setIsInCall(true);
+        mDialog.onAttachedToWindow();
+
+        verify(mRouter, never()).addCallback(any(), any(), anyInt());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testMediaScanIfNotInCall() {
+        mDialog.setIsInCall(false);
+        mDialog.onAttachedToWindow();
+
+        verify(mRouter, times(1)).addCallback(any(), any(), anyInt());
+    }
+}