1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wifi.hotspot2;
18
19import com.android.internal.annotations.VisibleForTesting;
20import com.android.server.wifi.Clock;
21import com.android.server.wifi.hotspot2.anqp.ANQPElement;
22import com.android.server.wifi.hotspot2.anqp.Constants;
23
24import java.io.PrintWriter;
25import java.util.ArrayList;
26import java.util.HashMap;
27import java.util.List;
28import java.util.Map;
29
30/**
31 * Cache for storing ANQP data.  This is simply a data cache, all the logic related to
32 * ANQP data query will be handled elsewhere (e.g. the consumer of the cache).
33 */
34public class AnqpCache {
35    @VisibleForTesting
36    public static final long CACHE_SWEEP_INTERVAL_MILLISECONDS = 60000L;
37
38    private long mLastSweep;
39    private Clock mClock;
40
41    private final Map<ANQPNetworkKey, ANQPData> mANQPCache;
42
43    public AnqpCache(Clock clock) {
44        mClock = clock;
45        mANQPCache = new HashMap<>();
46        mLastSweep = mClock.getElapsedSinceBootMillis();
47    }
48
49    /**
50     * Add an ANQP entry associated with the given key.
51     *
52     * @param key The key that's associated with the entry
53     * @param anqpElements The ANQP elements from the AP
54     */
55    public void addEntry(ANQPNetworkKey key,
56            Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
57        ANQPData data = new ANQPData(mClock, anqpElements);
58        mANQPCache.put(key, data);
59    }
60
61    /**
62     * Get the ANQP data associated with the given AP.
63     *
64     * @param key The key that's associated with the entry
65     * @return {@link ANQPData}
66     */
67    public ANQPData getEntry(ANQPNetworkKey key) {
68        return mANQPCache.get(key);
69    }
70
71    /**
72     * Go through the cache to remove any expired entries.
73     */
74    public void sweep() {
75        long now = mClock.getElapsedSinceBootMillis();
76        // Check if it is time to perform the sweep.
77        if (now < mLastSweep + CACHE_SWEEP_INTERVAL_MILLISECONDS) {
78            return;
79        }
80
81        // Get all expired keys.
82        List<ANQPNetworkKey> expiredKeys = new ArrayList<>();
83        for (Map.Entry<ANQPNetworkKey, ANQPData> entry : mANQPCache.entrySet()) {
84            if (entry.getValue().expired(now)) {
85                expiredKeys.add(entry.getKey());
86            }
87        }
88
89        // Remove all expired entries.
90        for (ANQPNetworkKey key : expiredKeys) {
91            mANQPCache.remove(key);
92        }
93        mLastSweep = now;
94    }
95
96    public void dump(PrintWriter out) {
97        out.println("Last sweep " + Utils.toHMS(mClock.getElapsedSinceBootMillis() - mLastSweep)
98                + " ago.");
99        for (Map.Entry<ANQPNetworkKey, ANQPData> entry : mANQPCache.entrySet()) {
100            out.println(entry.getKey() + ": " + entry.getValue());
101        }
102    }
103}
104