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 17 package com.android.server.wifi.hotspot2; 18 19 import com.android.internal.annotations.VisibleForTesting; 20 import com.android.server.wifi.Clock; 21 import com.android.server.wifi.hotspot2.anqp.ANQPElement; 22 import com.android.server.wifi.hotspot2.anqp.Constants; 23 24 import java.io.PrintWriter; 25 import java.util.ArrayList; 26 import java.util.HashMap; 27 import java.util.List; 28 import 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 */ 34 public 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 AnqpCache(Clock clock)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 */ addEntry(ANQPNetworkKey key, Map<Constants.ANQPElementType, ANQPElement> anqpElements)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 * Add or update additional ANQP elements to an ANQP entry associated with a given key. This 63 * method is useful for Venue URL or any other ANQP element which is queried after a connection 64 * is made. 65 * 66 * @param key The key that's associated with the entry 67 * @param anqpElements The additional ANQP elements from the AP, post connection 68 */ addOrUpdateEntry(ANQPNetworkKey key, Map<Constants.ANQPElementType, ANQPElement> anqpElements)69 public void addOrUpdateEntry(ANQPNetworkKey key, 70 Map<Constants.ANQPElementType, ANQPElement> anqpElements) { 71 if (!mANQPCache.containsKey(key)) { 72 // Create a new entry 73 addEntry(key, anqpElements); 74 return; 75 } 76 mANQPCache.get(key).update(anqpElements); 77 } 78 79 /** 80 * Get the ANQP data associated with the given AP. 81 * 82 * @param key The key that's associated with the entry 83 * @return {@link ANQPData} 84 */ getEntry(ANQPNetworkKey key)85 public ANQPData getEntry(ANQPNetworkKey key) { 86 return mANQPCache.get(key); 87 } 88 89 /** 90 * Go through the cache to remove any expired entries. 91 */ sweep()92 public void sweep() { 93 long now = mClock.getElapsedSinceBootMillis(); 94 // Check if it is time to perform the sweep. 95 if (now < mLastSweep + CACHE_SWEEP_INTERVAL_MILLISECONDS) { 96 return; 97 } 98 99 // Get all expired keys. 100 List<ANQPNetworkKey> expiredKeys = new ArrayList<>(); 101 for (Map.Entry<ANQPNetworkKey, ANQPData> entry : mANQPCache.entrySet()) { 102 if (entry.getValue().expired(now)) { 103 expiredKeys.add(entry.getKey()); 104 } 105 } 106 107 // Remove all expired entries. 108 for (ANQPNetworkKey key : expiredKeys) { 109 mANQPCache.remove(key); 110 } 111 mLastSweep = now; 112 } 113 dump(PrintWriter out)114 public void dump(PrintWriter out) { 115 out.println("Last sweep " + Utils.toHMS(mClock.getElapsedSinceBootMillis() - mLastSweep) 116 + " ago."); 117 for (Map.Entry<ANQPNetworkKey, ANQPData> entry : mANQPCache.entrySet()) { 118 out.println(entry.getKey() + ": " + entry.getValue()); 119 } 120 } 121 122 /** 123 * Flush the ANQP cache 124 */ flush()125 public void flush() { 126 mANQPCache.clear(); 127 mLastSweep = mClock.getElapsedSinceBootMillis(); 128 } 129 } 130