Merge "Use LruCache to cache advanced bluetooth deivce icon" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-04-23 11:59:04 +00:00
committed by Android (Google) Code Review
2 changed files with 101 additions and 1 deletions

View File

@@ -24,6 +24,10 @@ import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -32,12 +36,16 @@ import android.os.SystemClock;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
import android.util.LruCache;
import android.util.Pair;
import androidx.annotation.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.settingslib.R;
import com.android.settingslib.Utils;
import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.AdaptiveOutlineDrawable;
import java.util.ArrayList;
import java.util.Collection;
@@ -100,6 +108,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
private boolean mIsHearingAidProfileConnectedFail = false;
// Group second device for Hearing Aid
private CachedBluetoothDevice mSubDevice;
@VisibleForTesting
LruCache<String, BitmapDrawable> mDrawableCache;
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
@@ -131,6 +141,19 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
mDevice = device;
fillData();
mHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID;
initDrawableCache();
}
private void initDrawableCache() {
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = maxMemory / 8;
mDrawableCache = new LruCache<String, BitmapDrawable>(cacheSize) {
@Override
protected int sizeOf(String key, BitmapDrawable bitmap) {
return bitmap.getBitmap().getByteCount() / 1024;
}
};
}
/**
@@ -381,6 +404,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
if (dev != null) {
final boolean successful = dev.removeBond();
if (successful) {
releaseLruCache();
if (BluetoothUtils.D) {
Log.d(TAG, "Command sent successfully:REMOVE_BOND " + describe(null));
}
@@ -500,7 +524,21 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
}
void refresh() {
dispatchAttributesChanged();
ThreadUtils.postOnBackgroundThread(() -> {
if (BluetoothUtils.isAdvancedDetailsHeader(mDevice)) {
Uri uri = BluetoothUtils.getUriMetaData(getDevice(),
BluetoothDevice.METADATA_MAIN_ICON);
if (uri != null && mDrawableCache.get(uri.toString()) == null) {
mDrawableCache.put(uri.toString(),
(BitmapDrawable) BluetoothUtils.getBtDrawableWithDescription(
mContext, this).first);
}
}
ThreadUtils.postOnMainThread(() -> {
dispatchAttributesChanged();
});
});
}
public void setJustDiscovered(boolean justDiscovered) {
@@ -1178,4 +1216,28 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
mSubDevice.mJustDiscovered = tmpJustDiscovered;
fetchActiveDevices();
}
/**
* Get cached bluetooth icon with description
*/
public Pair<Drawable, String> getDrawableWithDescription() {
Uri uri = BluetoothUtils.getUriMetaData(mDevice, BluetoothDevice.METADATA_MAIN_ICON);
if (BluetoothUtils.isAdvancedDetailsHeader(mDevice) && uri != null) {
BitmapDrawable drawable = mDrawableCache.get(uri.toString());
if (drawable != null) {
Resources resources = mContext.getResources();
return new Pair<>(new AdaptiveOutlineDrawable(
resources, drawable.getBitmap()),
BluetoothUtils.getBtClassDrawableWithDescription(mContext, this).second);
}
refresh();
}
return BluetoothUtils.getBtRainbowDrawableWithDescription(mContext, this);
}
void releaseLruCache() {
mDrawableCache.evictAll();
}
}

View File

@@ -35,6 +35,7 @@ import android.media.AudioManager;
import com.android.settingslib.R;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settingslib.widget.AdaptiveOutlineDrawable;
import org.junit.Before;
import org.junit.Test;
@@ -957,4 +958,41 @@ public class CachedBluetoothDeviceTest {
// Should not crash
}
@Test
public void getDrawableWithDescription_isAdvancedDevice_returnAdvancedIcon() {
when(mDevice.getMetadata(BluetoothDevice.METADATA_MAIN_ICON))
.thenReturn("fake_uri".getBytes());
when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("true".getBytes());
mCachedDevice.refresh();
assertThat(mCachedDevice.getDrawableWithDescription().first).isInstanceOf(
AdaptiveOutlineDrawable.class);
}
@Test
public void getDrawableWithDescription_isNotAdvancedDevice_returnBluetoothIcon() {
when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("false".getBytes());
mCachedDevice.refresh();
assertThat(mCachedDevice.getDrawableWithDescription().first).isNotInstanceOf(
AdaptiveOutlineDrawable.class);
}
@Test
public void releaseLruCache_lruCacheShouldBeRelease() {
when(mDevice.getMetadata(BluetoothDevice.METADATA_MAIN_ICON))
.thenReturn("fake_uri".getBytes());
when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("true".getBytes());
mCachedDevice.refresh();
mCachedDevice.releaseLruCache();
assertThat(mCachedDevice.mDrawableCache.size()).isEqualTo(0);
}
}