<commit_before>﻿using Android.Graphics;
using Android.Graphics.Drawables;
using Math = System.Math;
using FFImageLoading.Helpers;
using Android.Content;
using Android.App;
using Android.Content.PM;
using FFImageLoading.Drawables;
using System;
using FFImageLoading.Work;
using System.Collections.Concurrent;
using System.Linq;

namespace FFImageLoading.Cache
{
    public class ImageCache : ImageCache<SelfDisposingBitmapDrawable>
    {
        private ImageCache(int maxCacheSize, IMiniLogger logger, bool verboseLogging) : base(maxCacheSize, logger, verboseLogging)
        {
        }

        static IImageCache<SelfDisposingBitmapDrawable> _instance;
        public static IImageCache<SelfDisposingBitmapDrawable> Instance
        {
            get
            {
                return _instance ?? (_instance = new ImageCache<SelfDisposingBitmapDrawable>(ImageService.Instance.Config.MaxMemoryCacheSize, ImageService.Instance.Config.Logger, ImageService.Instance.Config.VerboseMemoryCacheLogging));
            }
        }
    }

    public class ImageCache<TValue> : IImageCache<TValue> where TValue: Java.Lang.Object, ISelfDisposingBitmapDrawable
    {
        const int BYTES_PER_ARGB_8888_PIXEL = 4;
        const int LOW_MEMORY_BYTE_ARRAY_POOL_DIVISOR = 2;
        const int BITMAP_POOL_TARGET_SCREENS = 4;
        const int MEMORY_CACHE_TARGET_SCREENS = 4;
        const int ARRAY_POOL_SIZE_BYTES = 4 * 1024 * 1024;

        readonly ReuseBitmapDrawableCache<TValue> _cache;
        readonly ConcurrentDictionary<string, ImageInformation> _imageInformations;
        readonly IMiniLogger _logger;
        readonly object _lock = new object();

        public ImageCache(int maxCacheSize, IMiniLogger logger, bool verboseLogging)
        {
            _logger = logger;
            int memoryCacheSize;
            int bitmapPoolSize;

            var context = new ContextWrapper(Application.Context);
            var am = (ActivityManager)context?.GetSystemService(Context.ActivityService);

            bool amIsLowRamDevice = false;
            int amLargeMemoryClass = 128;
            int amMemoryClass = 48;

            if (am != null)
            {
                amIsLowRamDevice = am.IsLowRamDevice;
                amMemoryClass = am.MemoryClass;
                amLargeMemoryClass = am.LargeMemoryClass;
            }

            bool isLowMemoryDevice = Utils.HasKitKat() && amIsLowRamDevice;
            bool isLargeHeapEnabled = Utils.HasHoneycomb() && (context.ApplicationInfo.Flags & ApplicationInfoFlags.LargeHeap) != 0;
            int memoryClass = isLargeHeapEnabled ? amLargeMemoryClass : amMemoryClass;
            int maxSize = (int)(1024 * 1024 * (isLowMemoryDevice ? 0.33f * memoryClass : 0.4f * memoryClass));

            var metrics = context.Resources.DisplayMetrics;
            int widthPixels = metrics.WidthPixels;
            int heightPixels = metrics.HeightPixels;
            int screenSize = widthPixels * heightPixels * BYTES_PER_ARGB_8888_PIXEL;

            int targetBitmapPoolSize = screenSize * BITMAP_POOL_TARGET_SCREENS;
            int targetMemoryCacheSize = screenSize * MEMORY_CACHE_TARGET_SCREENS;
            int arrayPoolSize = isLowMemoryDevice ? ARRAY_POOL_SIZE_BYTES / LOW_MEMORY_BYTE_ARRAY_POOL_DIVISOR : ARRAY_POOL_SIZE_BYTES;
            int availableSize = maxSize - arrayPoolSize;

            if (maxCacheSize >= (int)(1024 * 1024 * 16))
            {
                float part = maxCacheSize / (BITMAP_POOL_TARGET_SCREENS + MEMORY_CACHE_TARGET_SCREENS);
                memoryCacheSize = (int)Math.Round(part * MEMORY_CACHE_TARGET_SCREENS);
                bitmapPoolSize = (int)Math.Round(part * BITMAP_POOL_TARGET_SCREENS);
            }
            else if (targetMemoryCacheSize + targetBitmapPoolSize <= availableSize)
            {
                memoryCacheSize = targetMemoryCacheSize;
                bitmapPoolSize = targetBitmapPoolSize;
            }
            else
            {
                float part = availableSize / (BITMAP_POOL_TARGET_SCREENS + MEMORY_CACHE_TARGET_SCREENS);
                memoryCacheSize = (int)Math.Round(part * MEMORY_CACHE_TARGET_SCREENS);<commit_msg>Fixes #1050 - NoSuchMethodError on Android SDK <= 19<commit_after>﻿using Android.Graphics;
using Android.Graphics.Drawables;
using Math = System.Math;
using FFImageLoading.Helpers;
using Android.Content;
using Android.App;
using Android.Content.PM;
using FFImageLoading.Drawables;
using System;
using FFImageLoading.Work;
using System.Collections.Concurrent;
using System.Linq;

namespace FFImageLoading.Cache
{
    public class ImageCache : ImageCache<SelfDisposingBitmapDrawable>
    {
        private ImageCache(int maxCacheSize, IMiniLogger logger, bool verboseLogging) : base(maxCacheSize, logger, verboseLogging)
        {
        }

        static IImageCache<SelfDisposingBitmapDrawable> _instance;
        public static IImageCache<SelfDisposingBitmapDrawable> Instance
        {
            get
            {
                return _instance ?? (_instance = new ImageCache<SelfDisposingBitmapDrawable>(ImageService.Instance.Config.MaxMemoryCacheSize, ImageService.Instance.Config.Logger, ImageService.Instance.Config.VerboseMemoryCacheLogging));
            }
        }
    }

    public class ImageCache<TValue> : IImageCache<TValue> where TValue: Java.Lang.Object, ISelfDisposingBitmapDrawable
    {
        const int BYTES_PER_ARGB_8888_PIXEL = 4;
        const int LOW_MEMORY_BYTE_ARRAY_POOL_DIVISOR = 2;
        const int BITMAP_POOL_TARGET_SCREENS = 4;
        const int MEMORY_CACHE_TARGET_SCREENS = 4;
        const int ARRAY_POOL_SIZE_BYTES = 4 * 1024 * 1024;

        readonly ReuseBitmapDrawableCache<TValue> _cache;
        readonly ConcurrentDictionary<string, ImageInformation> _imageInformations;
        readonly IMiniLogger _logger;
        readonly object _lock = new object();

        public ImageCache(int maxCacheSize, IMiniLogger logger, bool verboseLogging)
        {
            _logger = logger;
            int memoryCacheSize;
            int bitmapPoolSize;

            var context = new ContextWrapper(Application.Context);
            var am = (ActivityManager)context?.GetSystemService(Context.ActivityService);

            bool isLowMemoryDevice = true;
            int amLargeMemoryClass = 128;
            int amMemoryClass = 48;

            if (am != null)
            {
                if (Utils.HasKitKat())
                    isLowMemoryDevice = am.IsLowRamDevice;

                amMemoryClass = am.MemoryClass;
                amLargeMemoryClass = am.LargeMemoryClass;
            }

            bool isLargeHeapEnabled = Utils.HasHoneycomb() && (context.ApplicationInfo.Flags & ApplicationInfoFlags.LargeHeap) != 0;
            int memoryClass = isLargeHeapEnabled ? amLargeMemoryClass : amMemoryClass;
            int maxSize = (int)(1024 * 1024 * (isLowMemoryDevice ? 0.33f * memoryClass : 0.4f * memoryClass));

            var metrics = context.Resources.DisplayMetrics;
            int widthPixels = metrics.WidthPixels;
            int heightPixels = metrics.HeightPixels;
            int screenSize = widthPixels * heightPixels * BYTES_PER_ARGB_8888_PIXEL;

            int targetBitmapPoolSize = screenSize * BITMAP_POOL_TARGET_SCREENS;
            int targetMemoryCacheSize = screenSize * MEMORY_CACHE_TARGET_SCREENS;
            int arrayPoolSize = isLowMemoryDevice ? ARRAY_POOL_SIZE_BYTES / LOW_MEMORY_BYTE_ARRAY_POOL_DIVISOR : ARRAY_POOL_SIZE_BYTES;
            int availableSize = maxSize - arrayPoolSize;

            if (maxCacheSize >= (int)(1024 * 1024 * 16))
            {
                float part = maxCacheSize / (BITMAP_POOL_TARGET_SCREENS + MEMORY_CACHE_TARGET_SCREENS);
                memoryCacheSize = (int)Math.Round(part * MEMORY_CACHE_TARGET_SCREENS);
                bitmapPoolSize = (int)Math.Round(part * BITMAP_POOL_TARGET_SCREENS);
            }
            else if (targetMemoryCacheSize + targetBitmapPoolSize <= availableSize)
            {
                memoryCacheSize = targetMemoryCacheSize;
                bitmapPoolSize = targetBitmapPoolSize;
            }
            else
            {
                float part = availableSize / (BITMAP_POOL_TARGET_SCREENS + MEMORY_CACHE_TARGET_SCREENS);
                memoryCacheSize = (int)Math.Round(part * MEMORY_CACHE_TARGET_SCREENS);
{'fraction_non_alphanumeric': 0.06888304233436977, 'fraction_numerical': 0.012676393207366658, 'mean_word_length': 2.6728151075977165, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5317695', 'n_tokens_mistral': 2419, 'n_tokens_neox': 2274, 'n_words': 461}