OSDN Git Service

Add preference group for saved devcies.
authorjackqdyulei <jackqdyulei@google.com>
Tue, 21 Nov 2017 18:44:21 +0000 (10:44 -0800)
committerjackqdyulei <jackqdyulei@google.com>
Mon, 27 Nov 2017 20:56:44 +0000 (12:56 -0800)
Currently it only contains bluetooth devices.

Bug: 3240835
Test: RunSettingsRoboTests
Change-Id: Ief102e7174a4c4610dbda6b728419b303ff928f9

res/xml/connected_devices.xml
src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java
src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java [new file with mode: 0644]
src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
src/com/android/settings/connecteddevice/SavedDeviceGroupController.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java
tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java [new file with mode: 0644]

index d24dd51..497a485 100644 (file)
@@ -22,4 +22,8 @@
     <PreferenceCategory
         android:key="connected_device_list"
         android:title="@string/connected_device_connected_title"/>
+
+    <PreferenceCategory
+        android:key="saved_device_list"
+        android:title="@string/connected_device_saved_title"/>
 </PreferenceScreen>
index e053bc9..127730b 100644 (file)
@@ -149,9 +149,22 @@ public abstract class BluetoothDeviceUpdater implements BluetoothCallback {
     }
 
     /**
+     * Return {@code true} if {@code cachedBluetoothDevice} matches this
+     * {@link BluetoothDeviceUpdater} and should stay in the list, otherwise return {@code false}
+     */
+    public abstract boolean isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice);
+
+    /**
      * Update whether to show {@cde cachedBluetoothDevice} in the list.
      */
-    abstract public void update(CachedBluetoothDevice cachedBluetoothDevice);
+    protected void update(CachedBluetoothDevice cachedBluetoothDevice) {
+        if (isFilterMatched(cachedBluetoothDevice)) {
+            // Add the preference if it is new one
+            addPreference(cachedBluetoothDevice);
+        } else {
+            removePreference(cachedBluetoothDevice);
+        }
+    }
 
     /**
      * Add the {@link Preference} that represents the {@code cachedDevice}
index 239e405..deab29f 100644 (file)
@@ -51,16 +51,8 @@ public class ConnectedBluetoothDeviceUpdater extends BluetoothDeviceUpdater {
     }
 
     @Override
-    public void update(CachedBluetoothDevice cachedDevice) {
+    public boolean isFilterMatched(CachedBluetoothDevice cachedDevice) {
         final BluetoothDevice device = cachedDevice.getDevice();
-        final boolean filterMatch =
-                device.getBondState() == BluetoothDevice.BOND_BONDED && device.isConnected();
-
-        if (filterMatch) {
-            // Add the preference if it is new one
-            addPreference(cachedDevice);
-        } else {
-            removePreference(cachedDevice);
-        }
+        return device.getBondState() == BluetoothDevice.BOND_BONDED && device.isConnected();
     }
 }
diff --git a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
new file mode 100644 (file)
index 0000000..da7679a
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ * 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.settings.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.support.annotation.VisibleForTesting;
+
+import com.android.settings.connecteddevice.DevicePreferenceCallback;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+
+/**
+ * Maintain and update saved bluetooth devices(bonded but not connected)
+ */
+public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater {
+
+    public SavedBluetoothDeviceUpdater(DashboardFragment fragment,
+            DevicePreferenceCallback devicePreferenceCallback) {
+        super(fragment, devicePreferenceCallback);
+    }
+
+    @VisibleForTesting
+    SavedBluetoothDeviceUpdater(DashboardFragment fragment,
+            DevicePreferenceCallback devicePreferenceCallback,
+            LocalBluetoothManager localBluetoothManager) {
+        super(fragment, devicePreferenceCallback, localBluetoothManager);
+    }
+
+    @Override
+    public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
+        if (state == BluetoothAdapter.STATE_CONNECTED) {
+            removePreference(cachedDevice);
+        } else if (state == BluetoothAdapter.STATE_DISCONNECTED) {
+            addPreference(cachedDevice);
+        }
+    }
+
+    @Override
+    public boolean isFilterMatched(CachedBluetoothDevice cachedDevice) {
+        final BluetoothDevice device = cachedDevice.getDevice();
+        return device.getBondState() == BluetoothDevice.BOND_BONDED && !device.isConnected();
+    }
+}
index 14acd89..8b0e568 100644 (file)
@@ -62,9 +62,8 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         final Lifecycle lifecycle = getLifecycle();
 
-        final ConnectedDeviceGroupController connectedDeviceGroupController =
-                new ConnectedDeviceGroupController(this, lifecycle);
-        controllers.add(connectedDeviceGroupController);
+        controllers.add(new ConnectedDeviceGroupController(this, lifecycle));
+        controllers.add(new SavedDeviceGroupController(this, lifecycle));
         return controllers;
 
     }
diff --git a/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java b/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java
new file mode 100644 (file)
index 0000000..7445047
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ * 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.settings.connecteddevice;
+
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.bluetooth.BluetoothDeviceUpdater;
+import com.android.settings.bluetooth.SavedBluetoothDeviceUpdater;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+/**
+ * Controller to maintain the {@link PreferenceGroup} for all
+ * saved devices. It uses {@link DevicePreferenceCallback} to add/remove {@link Preference}
+ */
+public class SavedDeviceGroupController extends AbstractPreferenceController
+        implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop,
+        DevicePreferenceCallback {
+
+    private static final String KEY = "saved_device_list";
+
+    @VisibleForTesting
+    PreferenceGroup mPreferenceGroup;
+    private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
+
+    public SavedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle) {
+        super(fragment.getContext());
+        init(lifecycle, new SavedBluetoothDeviceUpdater(fragment, SavedDeviceGroupController.this));
+    }
+
+    @VisibleForTesting
+    SavedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle,
+            BluetoothDeviceUpdater bluetoothDeviceUpdater) {
+        super(fragment.getContext());
+        init(lifecycle, bluetoothDeviceUpdater);
+    }
+
+    @Override
+    public void onStart() {
+        mBluetoothDeviceUpdater.registerCallback();
+    }
+
+    @Override
+    public void onStop() {
+        mBluetoothDeviceUpdater.unregisterCallback();
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
+        mPreferenceGroup.setVisible(false);
+        mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
+        mBluetoothDeviceUpdater.forceUpdate();
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY;
+    }
+
+    @Override
+    public void onDeviceAdded(Preference preference) {
+        if (mPreferenceGroup.getPreferenceCount() == 0) {
+            mPreferenceGroup.setVisible(true);
+        }
+        mPreferenceGroup.addPreference(preference);
+    }
+
+    @Override
+    public void onDeviceRemoved(Preference preference) {
+        mPreferenceGroup.removePreference(preference);
+        if (mPreferenceGroup.getPreferenceCount() == 0) {
+            mPreferenceGroup.setVisible(false);
+        }
+    }
+
+    private void init(Lifecycle lifecycle, BluetoothDeviceUpdater bluetoothDeviceUpdater) {
+        if (lifecycle != null) {
+            lifecycle.addObserver(this);
+        }
+        mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
+    }
+}
index 525f70e..d5abd93 100644 (file)
@@ -73,8 +73,8 @@ public class BluetoothDeviceUpdaterTest {
         mBluetoothDeviceUpdater = new BluetoothDeviceUpdater(mDashboardFragment,
                 mDevicePreferenceCallback, null) {
             @Override
-            public void update(CachedBluetoothDevice cachedBluetoothDevice) {
-                // do nothing
+            public boolean isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice) {
+                return true;
             }
         };
         mBluetoothDeviceUpdater.setPrefContext(mContext);
diff --git a/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java
new file mode 100644 (file)
index 0000000..d0f367e
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ * 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.settings.bluetooth;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.Context;
+
+import com.android.settings.TestConfig;
+import com.android.settings.connecteddevice.DevicePreferenceCallback;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION_O)
+public class SavedBluetoothDeviceUpdaterTest {
+    @Mock
+    private DashboardFragment mDashboardFragment;
+    @Mock
+    private DevicePreferenceCallback mDevicePreferenceCallback;
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
+
+    private Context mContext;
+    private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = RuntimeEnvironment.application;
+        doReturn(mContext).when(mDashboardFragment).getContext();
+        doReturn(mBluetoothDevice).when(mCachedBluetoothDevice).getDevice();
+
+        mBluetoothDeviceUpdater = spy(new SavedBluetoothDeviceUpdater(mDashboardFragment,
+                mDevicePreferenceCallback, null));
+        mBluetoothDeviceUpdater.setPrefContext(mContext);
+        doNothing().when(mBluetoothDeviceUpdater).addPreference(any());
+        doNothing().when(mBluetoothDeviceUpdater).removePreference(any());
+    }
+
+    @Test
+    public void testUpdate_filterMatch_addPreference() {
+        doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState();
+        doReturn(false).when(mBluetoothDevice).isConnected();
+
+        mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+        verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
+    }
+
+    @Test
+    public void testUpdate_filterNotMatch_removePreference() {
+        doReturn(BluetoothDevice.BOND_NONE).when(mBluetoothDevice).getBondState();
+        doReturn(true).when(mBluetoothDevice).isConnected();
+
+        mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
+
+        verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
+    }
+
+    @Test
+    public void testOnConnectionStateChanged_deviceConnected_removePreference() {
+        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothAdapter.STATE_CONNECTED);
+
+        verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
+    }
+
+    @Test
+    public void testOnConnectionStateChanged_deviceDisconnected_addPreference() {
+        mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothAdapter.STATE_DISCONNECTED);
+
+        verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
+    }
+
+}