• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.bumptech.glide.load.engine.cache;
2 
3 import android.annotation.TargetApi;
4 import android.app.ActivityManager;
5 import android.content.Context;
6 import android.os.Build;
7 import android.util.DisplayMetrics;
8 import android.util.Log;
9 
10 /**
11  * A calculator that tries to intelligently determine cache sizes for a given device based on some constants and the
12  * devices screen density, width, and height.
13  */
14 public class MemorySizeCalculator {
15     private static final String TAG = "MemorySizeCalculator";
16 
17     static final int BYTES_PER_ARGB_8888_PIXEL = 4;
18     static final int MEMORY_CACHE_TARGET_SCREENS = 2;
19     static final int BITMAP_POOL_TARGET_SCREENS = 3;
20 
21     static final float MAX_SIZE_MULTIPLIER = 0.4f;
22     static final float LOW_MEMORY_MAX_SIZE_MULTIPLIER = 0.33f;
23     private final int bitmapPoolSize;
24     private final int memoryCacheSize;
25 
26     interface ScreenDimensions {
getWidthPixels()27         int getWidthPixels();
getHeightPixels()28         int getHeightPixels();
29     }
30 
MemorySizeCalculator(Context context)31     public MemorySizeCalculator(Context context) {
32         this((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE),
33                 new DisplayMetricsScreenDimensions(context.getResources().getDisplayMetrics()));
34     }
35 
MemorySizeCalculator(ActivityManager activityManager, ScreenDimensions screenDimensions)36     MemorySizeCalculator(ActivityManager activityManager, ScreenDimensions screenDimensions) {
37         final int maxSize = getMaxSize(activityManager);
38 
39         final int screenSize = screenDimensions.getWidthPixels() * screenDimensions.getHeightPixels()
40                 * BYTES_PER_ARGB_8888_PIXEL;
41 
42         int targetPoolSize = screenSize * BITMAP_POOL_TARGET_SCREENS;
43         int targetMemoryCacheSize = screenSize * MEMORY_CACHE_TARGET_SCREENS;
44 
45         if (targetMemoryCacheSize + targetPoolSize <= maxSize) {
46             memoryCacheSize = targetMemoryCacheSize;
47             bitmapPoolSize = targetPoolSize;
48         } else {
49             int part = Math.round((float) maxSize / (BITMAP_POOL_TARGET_SCREENS + MEMORY_CACHE_TARGET_SCREENS));
50             memoryCacheSize = part * MEMORY_CACHE_TARGET_SCREENS;
51             bitmapPoolSize = part * BITMAP_POOL_TARGET_SCREENS;
52         }
53 
54         if (Log.isLoggable(TAG, Log.DEBUG)) {
55             Log.d(TAG, "Calculated memory cache size: " + toMb(memoryCacheSize) + " pool size: " + toMb(bitmapPoolSize)
56                     + " memory class limited? " + (targetMemoryCacheSize + targetPoolSize > maxSize) + " max size: "
57                     + toMb(maxSize) + " memoryClass: " + activityManager.getMemoryClass() + " isLowMemoryDevice: "
58                     + isLowMemoryDevice(activityManager));
59         }
60     }
61 
62     /**
63      * Returns the recommended memory cache size for the device it is run on in bytes.
64      */
getMemoryCacheSize()65     public int getMemoryCacheSize() {
66         return memoryCacheSize;
67     }
68 
69     /**
70      * Returns the recommended bitmap pool size for the device it is run on in bytes.
71      */
getBitmapPoolSize()72     public int getBitmapPoolSize() {
73         return bitmapPoolSize;
74     }
75 
getMaxSize(ActivityManager activityManager)76     private static int getMaxSize(ActivityManager activityManager) {
77         final int memoryClassBytes = activityManager.getMemoryClass() * 1024 * 1024;
78         final boolean isLowMemoryDevice = isLowMemoryDevice(activityManager);
79         return Math.round(memoryClassBytes
80                 * (isLowMemoryDevice ? LOW_MEMORY_MAX_SIZE_MULTIPLIER : MAX_SIZE_MULTIPLIER));
81     }
82 
toMb(int bytes)83     private static int toMb(int bytes) {
84         return bytes / (1024 * 1024);
85     }
86 
87     @TargetApi(Build.VERSION_CODES.KITKAT)
isLowMemoryDevice(ActivityManager activityManager)88     private static boolean isLowMemoryDevice(ActivityManager activityManager) {
89         final int sdkInt = Build.VERSION.SDK_INT;
90         return sdkInt < Build.VERSION_CODES.HONEYCOMB
91                 || (sdkInt >= Build.VERSION_CODES.KITKAT && activityManager.isLowRamDevice());
92     }
93 
94     private static class DisplayMetricsScreenDimensions implements ScreenDimensions {
95         private final DisplayMetrics displayMetrics;
96 
DisplayMetricsScreenDimensions(DisplayMetrics displayMetrics)97         public DisplayMetricsScreenDimensions(DisplayMetrics displayMetrics) {
98             this.displayMetrics = displayMetrics;
99         }
100 
101         @Override
getWidthPixels()102         public int getWidthPixels() {
103             return displayMetrics.widthPixels;
104         }
105 
106         @Override
getHeightPixels()107         public int getHeightPixels() {
108             return displayMetrics.heightPixels;
109         }
110     }
111 }
112