199e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kastenpackage com.bumptech.glide.load.engine.cache; 289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectimport android.annotation.TargetApi; 489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectimport android.app.ActivityManager; 589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectimport android.content.Context; 689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectimport android.os.Build; 789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectimport android.util.DisplayMetrics; 889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectimport android.util.Log; 989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project/** 1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project * A calculator that tries to intelligently determine cache sizes for a given device based on some constants and the 1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project * devices screen density, width, and height. 1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project */ 1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectpublic class MemorySizeCalculator { 1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project private static final String TAG = "MemorySizeCalculator"; 1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project static final int BYTES_PER_ARGB_8888_PIXEL = 4; 1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project static final int MEMORY_CACHE_TARGET_SCREENS = 2; 1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project static final int BITMAP_POOL_TARGET_SCREENS = 3; 2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 2134fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn static final float MAX_SIZE_MULTIPLIER = 0.4f; 22c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kasten static final float LOW_MEMORY_MAX_SIZE_MULTIPLIER = 0.33f; 2389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project private final int bitmapPoolSize; 2434fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn private final int memoryCacheSize; 252b01f009428797ee9154649411a64b522946e966Andy Hung 269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten interface ScreenDimensions { 279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int getWidthPixels(); 2889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project int getHeightPixels(); 2989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 311ab85ec401801ef9a9184650d0f5a1639b45eeb9Glenn Kasten public MemorySizeCalculator(Context context) { 32a70eef730d7665c9f4b2dfd25faf072785f80a2dDean Wheatley this((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE), 33e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent new DisplayMetricsScreenDimensions(context.getResources().getDisplayMetrics())); 34cd04484f4837b8ca0041d118286ab6a98e84fc75Andy Hung } 35ed30470cf0a20c0c1edb2b82075985ccaa6c75c1Ray Essick 36ed30470cf0a20c0c1edb2b82075985ccaa6c75c1Ray Essick MemorySizeCalculator(ActivityManager activityManager, ScreenDimensions screenDimensions) { 37fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin final int maxSize = getMaxSize(activityManager); 38b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald 39b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald final int screenSize = screenDimensions.getWidthPixels() * screenDimensions.getHeightPixels() 4053c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung * BYTES_PER_ARGB_8888_PIXEL; 41511754b5839fd9b09fc56b89ae007fbc39084a33Glenn Kasten 4289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project int targetPoolSize = screenSize * BITMAP_POOL_TARGET_SCREENS; 4333005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh int targetMemoryCacheSize = screenSize * MEMORY_CACHE_TARGET_SCREENS; 4433005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh 458cf3a0788df2ee184b498086b1b8da322eeadccaIvan Lozano if (targetMemoryCacheSize + targetPoolSize <= maxSize) { 468cf3a0788df2ee184b498086b1b8da322eeadccaIvan Lozano memoryCacheSize = targetMemoryCacheSize; 47a7f03353d5f172016f324e2a01f301cca6794152Andy Hung bitmapPoolSize = targetPoolSize; 48a7f03353d5f172016f324e2a01f301cca6794152Andy Hung } else { 494ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung int part = Math.round((float) maxSize / (BITMAP_POOL_TARGET_SCREENS + MEMORY_CACHE_TARGET_SCREENS)); 50a7f03353d5f172016f324e2a01f301cca6794152Andy Hung memoryCacheSize = part * MEMORY_CACHE_TARGET_SCREENS; 514ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung bitmapPoolSize = part * BITMAP_POOL_TARGET_SCREENS; 524ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung } 534ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung 54a7f03353d5f172016f324e2a01f301cca6794152Andy Hung if (Log.isLoggable(TAG, Log.DEBUG)) { 55a7f03353d5f172016f324e2a01f301cca6794152Andy Hung Log.d(TAG, "Calculated memory cache size: " + toMb(memoryCacheSize) + " pool size: " + toMb(bitmapPoolSize) 56a7f03353d5f172016f324e2a01f301cca6794152Andy Hung + " memory class limited? " + (targetMemoryCacheSize + targetPoolSize > maxSize) + " max size: " 57a7f03353d5f172016f324e2a01f301cca6794152Andy Hung + toMb(maxSize) + " memoryClass: " + activityManager.getMemoryClass() + " isLowMemoryDevice: " 58a7f03353d5f172016f324e2a01f301cca6794152Andy Hung + isLowMemoryDevice(activityManager)); 59a7f03353d5f172016f324e2a01f301cca6794152Andy Hung } 60a7f03353d5f172016f324e2a01f301cca6794152Andy Hung } 61a7f03353d5f172016f324e2a01f301cca6794152Andy Hung 62a7f03353d5f172016f324e2a01f301cca6794152Andy Hung /** 63a7f03353d5f172016f324e2a01f301cca6794152Andy Hung * Returns the recommended memory cache size for the device it is run on in bytes. 647f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung */ 657f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung public int getMemoryCacheSize() { 667f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung return memoryCacheSize; 677f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung } 687f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung 69ffa3695a012d22c6c81cf311232c5c84c06f9219Andy Hung /** 70ffa3695a012d22c6c81cf311232c5c84c06f9219Andy Hung * Returns the recommended bitmap pool size for the device it is run on in bytes. 71ffa3695a012d22c6c81cf311232c5c84c06f9219Andy Hung */ 72ffa3695a012d22c6c81cf311232c5c84c06f9219Andy Hung public int getBitmapPoolSize() { 73ffa3695a012d22c6c81cf311232c5c84c06f9219Andy Hung return bitmapPoolSize; 74ffa3695a012d22c6c81cf311232c5c84c06f9219Andy Hung } 75ffa3695a012d22c6c81cf311232c5c84c06f9219Andy Hung 76ffa3695a012d22c6c81cf311232c5c84c06f9219Andy Hung private static int getMaxSize(ActivityManager activityManager) { 777f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung final int memoryClassBytes = activityManager.getMemoryClass() * 1024 * 1024; 787f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung final boolean isLowMemoryDevice = isLowMemoryDevice(activityManager); 797f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung return Math.round(memoryClassBytes 807f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung * (isLowMemoryDevice ? LOW_MEMORY_MAX_SIZE_MULTIPLIER : MAX_SIZE_MULTIPLIER)); 817f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung } 827f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung 837f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung private static int toMb(int bytes) { 847f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung return bytes / (1024 * 1024); 8526145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung } 8626145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung 8726145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung @TargetApi(Build.VERSION_CODES.KITKAT) 8826145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung private static boolean isLowMemoryDevice(ActivityManager activityManager) { 8926145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung final int sdkInt = Build.VERSION.SDK_INT; 9026145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung return sdkInt < Build.VERSION_CODES.HONEYCOMB 9126145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung || (sdkInt >= Build.VERSION_CODES.KITKAT && activityManager.isLowRamDevice()); 9226145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung } 9326145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung 9426145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung private static class DisplayMetricsScreenDimensions implements ScreenDimensions { 956c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia private final DisplayMetrics displayMetrics; 9626145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung 9726145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung public DisplayMetricsScreenDimensions(DisplayMetrics displayMetrics) { 9826145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung this.displayMetrics = displayMetrics; 9926145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung } 10026145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung 10126145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung @Override 10226145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung public int getWidthPixels() { 10333005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh return displayMetrics.widthPixels; 10433005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh } 105e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten 106fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten @Override 10733005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh public int getHeightPixels() { 10833005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh return displayMetrics.heightPixels; 109d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten } 110d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten } 111d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten} 11204cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten