16a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistpackage com.android.server.wifi.hotspot2; 26a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist 3ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport com.android.server.wifi.Clock; 46a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport com.android.server.wifi.anqp.ANQPElement; 577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport com.android.server.wifi.anqp.Constants; 66a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist 71d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistimport java.util.ArrayList; 86a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistimport java.util.Collections; 91d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistimport java.util.HashMap; 101d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistimport java.util.List; 1177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.util.Map; 126a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist 136a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvistpublic class ANQPData { 145bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist /** 155bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist * The regular cache time for entries with a non-zero domain id. 165bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist */ 1777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist private static final long ANQP_QUALIFIED_CACHE_TIMEOUT = 3600000L; 185bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist /** 195bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist * The cache time for entries with a zero domain id. The zero domain id indicates that ANQP 205bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist * data from the AP may change at any time, thus a relatively short cache time is given to 215bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist * such data, but still long enough to avoid excessive querying. 225bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist */ 2382414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist private static final long ANQP_UNQUALIFIED_CACHE_TIMEOUT = 300000L; 245bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist /** 255bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist * This is the hold off time for pending queries, i.e. the time during which subsequent queries 265bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist * are squelched. 275bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist */ 285bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist private static final long ANQP_HOLDOFF_TIME = 10000L; 2977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist 3082414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist /** 3182414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist * Max value for the retry counter for unanswered queries. This limits the maximum time-out to 3282414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist * ANQP_HOLDOFF_TIME * 2^MAX_RETRY. With current values this results in 640s. 3382414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist */ 3482414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist private static final int MAX_RETRY = 6; 3582414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist 3677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist private final NetworkDetail mNetwork; 3777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist private final Map<Constants.ANQPElementType, ANQPElement> mANQPElements; 386a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist private final long mCtime; 3977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist private final long mExpiry; 4082414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist private final int mRetry; 41ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande private final Clock mClock; 4277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist 43ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande public ANQPData(Clock clock, NetworkDetail network, 4477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist Map<Constants.ANQPElementType, ANQPElement> anqpElements) { 456a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist 46ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande mClock = clock; 4777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist mNetwork = network; 481d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist mANQPElements = anqpElements != null ? new HashMap<>(anqpElements) : null; 49ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande mCtime = mClock.currentTimeMillis(); 5082414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist mRetry = 0; 515bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist if (anqpElements == null) { 525bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist mExpiry = mCtime + ANQP_HOLDOFF_TIME; 535bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist } 545bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist else if (network.getAnqpDomainID() == 0) { 555bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist mExpiry = mCtime + ANQP_UNQUALIFIED_CACHE_TIMEOUT; 565bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist } 575bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist else { 585bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist mExpiry = mCtime + ANQP_QUALIFIED_CACHE_TIMEOUT; 595bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist } 606a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist } 616a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist 62ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande public ANQPData(Clock clock, NetworkDetail network, ANQPData existing) { 63ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande mClock = clock; 6482414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist mNetwork = network; 6582414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist mANQPElements = null; 66ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande mCtime = mClock.currentTimeMillis(); 6782414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist if (existing == null) { 6882414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist mRetry = 0; 6982414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist mExpiry = mCtime + ANQP_HOLDOFF_TIME; 7082414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist } 7182414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist else { 7282414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist mRetry = Math.max(existing.getRetry() + 1, MAX_RETRY); 7382414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist mExpiry = ANQP_HOLDOFF_TIME * (1<<mRetry); 7482414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist } 7582414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist } 7682414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist 771d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist public List<Constants.ANQPElementType> disjoint(List<Constants.ANQPElementType> querySet) { 781d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist if (mANQPElements == null) { 791d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist // Ignore the query set for pending responses, it has minimal probability to happen 801d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist // and a new query will be reissued on the next round anyway. 811d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist return null; 821d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist } 831d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist else { 841d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist List<Constants.ANQPElementType> additions = new ArrayList<>(); 851d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist for (Constants.ANQPElementType element : querySet) { 861d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist if (!mANQPElements.containsKey(element)) { 871d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist additions.add(element); 881d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist } 891d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist } 901d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist return additions.isEmpty() ? null : additions; 911d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist } 921d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist } 931d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist 9477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist public Map<Constants.ANQPElementType, ANQPElement> getANQPElements() { 955bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist return Collections.unmodifiableMap(mANQPElements); 966a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist } 9777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist 9877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist public NetworkDetail getNetwork() { 9977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist return mNetwork; 10077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist } 10177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist 1025bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist public boolean expired() { 103ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande return expired(mClock.currentTimeMillis()); 10477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist } 10577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist 10677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist public boolean expired(long at) { 1075bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist return mExpiry <= at; 10877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist } 10977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist 1101d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist protected boolean hasData() { 1111d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist return mANQPElements != null; 1121d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist } 1131d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist 1141d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist protected void merge(Map<Constants.ANQPElementType, ANQPElement> data) { 1151d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist if (data != null) { 1161d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist mANQPElements.putAll(data); 1171d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist } 1181d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist } 1191d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist 1205bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist protected boolean isValid(NetworkDetail nwk) { 1215bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist return mANQPElements != null && 1225bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist nwk.getAnqpDomainID() == mNetwork.getAnqpDomainID() && 123ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande mExpiry > mClock.currentTimeMillis(); 124ef1567e413c9ed5f5c4fdb9e354861632f7b2f87Jan Nordqvist } 125ef1567e413c9ed5f5c4fdb9e354861632f7b2f87Jan Nordqvist 12682414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist private int getRetry() { 12782414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist return mRetry; 12882414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist } 12982414ead13eb2554cf412ad00a30d9e21499bf75Jan Nordqvist 1309f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist public String toString(boolean brief) { 131a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist StringBuilder sb = new StringBuilder(); 132a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist sb.append(mNetwork.toKeyString()).append(", domid ").append(mNetwork.getAnqpDomainID()); 133a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist if (mANQPElements == null) { 134a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist sb.append(", unresolved, "); 135a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist } 136a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist else { 137a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist sb.append(", ").append(mANQPElements.size()).append(" elements, "); 138a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist } 139ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande long now = mClock.currentTimeMillis(); 140a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist sb.append(Utils.toHMS(now-mCtime)).append(" old, expires in "). 141a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist append(Utils.toHMS(mExpiry-now)).append(' '); 1429f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist if (brief) { 1439f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist sb.append(expired(now) ? 'x' : '-'); 1449f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist sb.append(mANQPElements == null ? 'u' : '-'); 1459f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist } 1469f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist else if (mANQPElements != null) { 1479f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist sb.append(" data=").append(mANQPElements); 1489f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist } 149a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist return sb.toString(); 150a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist } 1519f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist 1529f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist @Override 1539f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist public String toString() { 1549f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist return toString(true); 1559f7795c694d048fdfecc4117cf5ddbd3e6ae1406Jan Nordqvist } 1566a3903fed590e369b576bddbe1ae2d788768ddfeJan Nordqvist} 157