summaryrefslogtreecommitdiff
path: root/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
blob: fe0b3123eb25a63b9960d7ea39d88c7fcf18646f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.notification.row;

import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.Log;

import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * A cache for inline images of image messages.
 */
public class NotificationInlineImageCache implements NotificationInlineImageResolver.ImageCache {
    private static final String TAG = NotificationInlineImageCache.class.getSimpleName();

    private NotificationInlineImageResolver mResolver;
    private final ConcurrentHashMap<Uri, PreloadImageTask> mCache;

    public NotificationInlineImageCache() {
        mCache = new ConcurrentHashMap<>();
    }

    @Override
    public void setImageResolver(NotificationInlineImageResolver resolver) {
        mResolver = resolver;
    }

    @Override
    public boolean hasEntry(Uri uri) {
        return mCache.containsKey(uri);
    }

    @Override
    public void preload(Uri uri) {
        PreloadImageTask newTask = new PreloadImageTask(mResolver);
        newTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, uri);
        mCache.put(uri, newTask);
    }

    @Override
    public Drawable get(Uri uri, long timeoutMs) {
        Drawable result = null;
        try {
            result = mCache.get(uri).get(timeoutMs, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | ExecutionException
                | TimeoutException | CancellationException ex) {
            Log.d(TAG, "get: Failed get image from " + uri + " " + ex);
        }
        return result;
    }

    @Override
    public void purge() {
        Set<Uri> wantedSet = mResolver.getWantedUriSet();
        mCache.entrySet().removeIf(entry -> !wantedSet.contains(entry.getKey()));
    }

    @Override
    public void cancelRunningTasks() {
        mCache.forEach((key, value) -> {
            if (value.getStatus() != AsyncTask.Status.FINISHED) {
                value.cancel(true);
            }
        });
    }

    private static class PreloadImageTask extends AsyncTask<Uri, Void, Drawable> {
        private final NotificationInlineImageResolver mResolver;

        PreloadImageTask(NotificationInlineImageResolver resolver) {
            mResolver = resolver;
        }

        @Override
        protected Drawable doInBackground(Uri... uris) {
            Uri target = uris[0];
            return mResolver.resolveImage(target);
        }
    }
}