summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjackqdyulei <jackqdyulei@google.com>2019-02-22 12:42:07 -0800
committerjackqdyulei <jackqdyulei@google.com>2019-02-22 14:46:10 -0800
commit5e5dd25b8f4d170dda01a3f729068d277b202deb (patch)
tree43f5acc228ab72bcf61e8f9244b947652423f0c6
parent5cb4d251ee67eb232700844573b4a2936815cc08 (diff)
downloadpackages_apps_Settings-5e5dd25b8f4d170dda01a3f729068d277b202deb.tar.gz
packages_apps_Settings-5e5dd25b8f4d170dda01a3f729068d277b202deb.tar.bz2
packages_apps_Settings-5e5dd25b8f4d170dda01a3f729068d277b202deb.zip
Fix issues in BT detail header
1. Update isAvailable() in controller 2. Update method to get fast pair icon Bug: 124455912 Test: RunSettingsRoboTests Change-Id: I24a04c8c91d74e9b8b7e8746ad6279fafa37f0a9
-rw-r--r--src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java54
-rw-r--r--src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java8
-rw-r--r--src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java7
-rw-r--r--tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java17
-rw-r--r--tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java19
5 files changed, 85 insertions, 20 deletions
diff --git a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
index a09018ea39..34a758bf9c 100644
--- a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
@@ -18,16 +18,19 @@ package com.android.settings.bluetooth;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
+import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
-import androidx.core.graphics.drawable.IconCompat;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
@@ -37,20 +40,29 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.LayoutPreference;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* This class adds a header with device name and status (connected/disconnected, etc.).
*/
public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceController implements
LifecycleObserver, OnStart, OnStop, CachedBluetoothDevice.Callback {
+ private static final String TAG = "AdvancedBtHeaderCtrl";
@VisibleForTesting
LayoutPreference mLayoutPreference;
+ @VisibleForTesting
+ final Map<String, Bitmap> mIconCache;
private CachedBluetoothDevice mCachedDevice;
public AdvancedBluetoothDetailsHeaderController(Context context, String prefKey) {
super(context, prefKey);
+ mIconCache = new HashMap<>();
}
@Override
@@ -65,6 +77,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
super.displayPreference(screen);
mLayoutPreference = screen.findPreference(getPreferenceKey());
mLayoutPreference.setVisible(isAvailable());
+
refresh();
}
@@ -76,6 +89,14 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
@Override
public void onStop() {
mCachedDevice.unregisterCallback(this::onDeviceAttributesChanged);
+
+ // Destroy icon bitmap associated with this header
+ for (Bitmap bitmap : mIconCache.values()) {
+ if (bitmap != null) {
+ bitmap.recycle();
+ }
+ }
+ mIconCache.clear();
}
public void init(CachedBluetoothDevice cachedBluetoothDevice) {
@@ -140,8 +161,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
final String iconUri = Utils.getStringMetaData(bluetoothDevice, iconMetaKey);
if (iconUri != null) {
final ImageView imageView = linearLayout.findViewById(R.id.header_icon);
- final IconCompat iconCompat = IconCompat.createWithContentUri(iconUri);
- imageView.setImageBitmap(iconCompat.getBitmap());
+ updateIcon(imageView, iconUri);
}
final int batteryLevel = Utils.getIntMetaData(bluetoothDevice, batteryMetaKey);
@@ -181,11 +201,35 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
BluetoothDevice.METADATA_MAIN_ICON);
if (iconUri != null) {
final ImageView imageView = linearLayout.findViewById(R.id.header_icon);
- final IconCompat iconCompat = IconCompat.createWithContentUri(iconUri);
- imageView.setImageBitmap(iconCompat.getBitmap());
+ updateIcon(imageView, iconUri);
}
}
+ /**
+ * Update icon by {@code iconUri}. If icon exists in cache, use it; otherwise extract it
+ * from uri in background thread and update it in main thread.
+ */
+ @VisibleForTesting
+ void updateIcon(ImageView imageView, String iconUri) {
+ if (mIconCache.containsKey(iconUri)) {
+ imageView.setImageBitmap(mIconCache.get(iconUri));
+ return;
+ }
+
+ ThreadUtils.postOnBackgroundThread(() -> {
+ try {
+ final Bitmap bitmap = MediaStore.Images.Media.getBitmap(
+ mContext.getContentResolver(), Uri.parse(iconUri));
+ ThreadUtils.postOnMainThread(() -> {
+ mIconCache.put(iconUri, bitmap);
+ imageView.setImageBitmap(bitmap);
+ });
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to get bitmap for: " + iconUri);
+ }
+ });
+ }
+
@Override
public void onDeviceAttributesChanged() {
if (mCachedDevice != null) {
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java b/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
index af150527c4..a7fae1441f 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
@@ -16,7 +16,6 @@
package com.android.settings.bluetooth;
-import android.bluetooth.BluetoothDevice;
import android.content.Context;
import androidx.preference.PreferenceFragmentCompat;
@@ -44,13 +43,6 @@ public class BluetoothDetailsButtonsController extends BluetoothDetailsControlle
mIsConnected = device.isConnected();
}
- @Override
- public boolean isAvailable() {
- final boolean unthetheredHeadset = Utils.getBooleanMetaData(mCachedDevice.getDevice(),
- BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET);
- return !unthetheredHeadset;
- }
-
private void onForgetButtonPressed() {
ForgetDeviceDialogFragment fragment =
ForgetDeviceDialogFragment.newInstance(mCachedDevice.getAddress());
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
index 994daa7860..fd805b828f 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
@@ -16,6 +16,7 @@
package com.android.settings.bluetooth;
+import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.Pair;
@@ -51,6 +52,12 @@ public class BluetoothDetailsHeaderController extends BluetoothDetailsController
}
@Override
+ public boolean isAvailable() {
+ return !Utils.getBooleanMetaData(mCachedDevice.getDevice(),
+ BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET);
+ }
+
+ @Override
protected void init(PreferenceScreen screen) {
final LayoutPreference headerPreference = screen.findPreference(KEY_DEVICE_HEADER);
mHeaderController = EntityHeaderController.newInstance(mFragment.getActivity(), mFragment,
diff --git a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
index e6462731b9..53fac3ca5f 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
@@ -18,13 +18,16 @@ package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
+import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -50,12 +53,17 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{
private static final int BATTERY_LEVEL_MAIN = 30;
private static final int BATTERY_LEVEL_LEFT = 25;
private static final int BATTERY_LEVEL_RIGHT = 45;
+ private static final String ICON_URI = "content://test.provider/icon.png";
private Context mContext;
@Mock
private BluetoothDevice mBluetoothDevice;
@Mock
+ private Bitmap mBitmap;
+ @Mock
+ private ImageView mImageView;
+ @Mock
private CachedBluetoothDevice mCachedDevice;
private AdvancedBluetoothDetailsHeaderController mController;
private LayoutPreference mLayoutPreference;
@@ -142,6 +150,15 @@ public class AdvancedBluetoothDetailsHeaderControllerTest{
BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
}
+ @Test
+ public void updateIcon_existInCache_setImageBitmap() {
+ mController.mIconCache.put(ICON_URI, mBitmap);
+
+ mController.updateIcon(mImageView, ICON_URI);
+
+ verify(mImageView).setImageBitmap(mBitmap);
+ }
+
private void assertBatteryLevel(LinearLayout linearLayout, int batteryLevel) {
final TextView textView = linearLayout.findViewById(R.id.bt_battery_summary);
assertThat(textView.getText().toString()).isEqualTo(
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java
index 930d9cbe08..cf119eaa10 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java
@@ -19,18 +19,12 @@ package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.bluetooth.BluetoothDevice;
import android.graphics.drawable.Drawable;
-import android.view.View;
-
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentTransaction;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -62,6 +56,8 @@ public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsContro
private LocalBluetoothManager mBluetoothManager;
@Mock
private CachedBluetoothDeviceManager mCachedDeviceManager;
+ @Mock
+ private BluetoothDevice mBluetoothDevice;
@Override
public void setUp() {
@@ -77,6 +73,7 @@ public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsContro
mPreference.setKey(mController.getPreferenceKey());
mScreen.addPreference(mPreference);
setupDevice(mDeviceConfig);
+ when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice);
}
@After
@@ -124,4 +121,12 @@ public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsContro
inOrder.verify(mHeaderController)
.setSummary(mContext.getString(R.string.bluetooth_connecting));
}
+
+ @Test
+ public void isAvailable_unthetheredHeadset_returnFalse() {
+ when(mBluetoothDevice.getMetadata(
+ BluetoothDevice.METADATA_IS_UNTHETHERED_HEADSET)).thenReturn("true");
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
}