1ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande/*
2ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande * Copyright (C) 2016 The Android Open Source Project
3ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande *
4ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande * Licensed under the Apache License, Version 2.0 (the "License");
5ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande * you may not use this file except in compliance with the License.
6ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande * You may obtain a copy of the License at
7ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande *
8ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande *      http://www.apache.org/licenses/LICENSE-2.0
9ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande *
10ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande * Unless required by applicable law or agreed to in writing, software
11ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande * distributed under the License is distributed on an "AS IS" BASIS,
12ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande * See the License for the specific language governing permissions and
14ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande * limitations under the License.
15ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande */
16ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
17ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandepackage com.android.server.wifi;
18ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
19ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport static org.junit.Assert.assertEquals;
20ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport static org.junit.Assert.assertNotNull;
21ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport static org.junit.Assert.assertNull;
22ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport static org.mockito.Mockito.when;
23ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport static org.mockito.MockitoAnnotations.initMocks;
24ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
25ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport android.net.wifi.ScanResult;
26ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport android.net.wifi.WifiSsid;
27ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport android.test.suitebuilder.annotation.SmallTest;
28ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport android.util.Log;
29ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
30ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport com.android.server.wifi.anqp.ANQPElement;
31ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport com.android.server.wifi.anqp.Constants;
32ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport com.android.server.wifi.hotspot2.ANQPData;
33ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport com.android.server.wifi.hotspot2.AnqpCache;
34ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport com.android.server.wifi.hotspot2.NetworkDetail;
35ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
36ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport org.junit.Test;
37ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport org.mockito.Mock;
38ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
39ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport java.util.ArrayList;
40ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport java.util.Arrays;
41ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport java.util.HashMap;
42ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport java.util.List;
43ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandeimport java.util.Map;
44ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
45ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
46ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande/**
47ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande * Unit tests for {@link com.android.server.wifi.hotspot2.AnqpCache}.
48ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande */
49ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande@SmallTest
50ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpandepublic class AnqpCacheTest {
51ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
52ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static final String TAG = "AnqpCacheTest";
53ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
54ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static class NetworkDescription {
55ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        ScanDetail[] mScanDetails;
56ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        static int[] sChannels = new int[]{2412, 2437, 2462, 5180, 5220, 5745, 5825};
57ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        static int[] sRSSIs = new int[]{ -50, -80, -60, -80, -55, -90, -75};
58ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
59ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        NetworkDescription(String ssid, String bssidPrefix) {
60ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(ssid);
61ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            mScanDetails = new ScanDetail[sChannels.length];
62ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            for (int i = 0; i < sChannels.length; i++) {
63ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                String bssid = String.format("%s:%02x", bssidPrefix, i);
64ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                ScanResult.InformationElement[] ie = new ScanResult.InformationElement[1];
65ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                ie[0] = ScanResults.generateSsidIe(ssid);
66ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                List<String> anqpLines = new ArrayList<String>();
67ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                NetworkDetail nd = new NetworkDetail(bssid, ie,
68ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                        new ArrayList<String>(), sChannels[i]);
69ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                mScanDetails[i] = new ScanDetail(nd, wifiSsid,
70ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                        bssid, "", sRSSIs[i], sChannels[i], Long.MAX_VALUE, ie, anqpLines);
71ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            }
72ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        }
73ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    }
74ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
75ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static final String ATT_SSID         = "att_wifi";
76ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static final String ATT_BSSID_PREFIX = "aa:44:bb:55:cc";
77ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static final String TWC_SSID         = "TWCWIFI";
78ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static final String TWC_BSSID_PREFIX = "11:aa:22:bb:33";
79ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
80ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static ScanDetail[] getAttWifiNetworkDescription() {
81ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        NetworkDescription network = new NetworkDescription(ATT_SSID, ATT_BSSID_PREFIX);
82ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        return network.mScanDetails;
83ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    }
84ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
85ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static ScanDetail[] getTwcWifiNetworkDescription() {
86ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        NetworkDescription network = new NetworkDescription(TWC_SSID, TWC_BSSID_PREFIX);
87ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        return network.mScanDetails;
88ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    }
89ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
90ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static List<Constants.ANQPElementType> buildQueryList() {
91ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        List<Constants.ANQPElementType> list = Arrays.asList(
92ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                Constants.ANQPElementType.class.getEnumConstants());
93ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        return list;
94ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    }
95ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
96ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static Map<Constants.ANQPElementType, ANQPElement> buildAnqpResult() {
97ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        Map<Constants.ANQPElementType, ANQPElement> elements = new HashMap<>();
98ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        List<Constants.ANQPElementType> list = Arrays.asList(
99ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                Constants.ANQPElementType.class.getEnumConstants());
100ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        for (final Constants.ANQPElementType type : list) {
101ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            ANQPElement element = new ANQPElement(type) {
102ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                @Override
103ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                public Constants.ANQPElementType getID() {
104ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                    return super.getID();
105ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande                }
106ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            };
107ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            elements.put(type, element);
108ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        }
109ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
110ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        return elements;
111ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    }
112ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
113ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private void advanceTimeAndTrimCache(long howManyMillis) {
114ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        mCurrentTimeMillis += howManyMillis;
115ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        Log.d(TAG, "Time set to " + mCurrentTimeMillis);
116ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        when(mClock.currentTimeMillis()).thenReturn(mCurrentTimeMillis);
117ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        mCache.clear(false, true);
118ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    }
119ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
120ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    public AnqpCacheTest() {}
121ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
122ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static final long SECOND_MS = 1000;
123ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    private static final long MINUTE_MS = 60 * SECOND_MS;
124ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
125ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    @Mock Clock mClock;
126ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    long mCurrentTimeMillis = 1000000000;
127ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    AnqpCache mCache;
128ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
129ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    /** verify that ANQP data is cached per the (rather abstract) spec */
130ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    @Test
131ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    public void basicAddQueryAndExpiry() {
132ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        initMocks(this);
133ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
134ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        AnqpCache cache = mCache = new AnqpCache(mClock);
135ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        advanceTimeAndTrimCache(0);
136ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
137ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        List<Constants.ANQPElementType> queryList = buildQueryList();
138ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
139ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        ScanDetail[] attScanDetails = getAttWifiNetworkDescription();
140ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        ScanDetail[] twcScanDetails = getTwcWifiNetworkDescription();
141ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
142ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        /* query att network at time 0 */
143ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        for (ScanDetail scanDetail : attScanDetails) {
144ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            cache.initiate(scanDetail.getNetworkDetail(), queryList);
145ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        }
146ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
147ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        /* verify that no data can be returned */
148ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        for (ScanDetail scanDetail : attScanDetails) {
149ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            ANQPData data = cache.getEntry(scanDetail.getNetworkDetail());
150ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            assertNull(data);
151ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        }
152ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
153ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        /* update ANQP results after 1 min */
154ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        advanceTimeAndTrimCache(1 * MINUTE_MS);
155ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
156ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        Map<Constants.ANQPElementType, ANQPElement> anqpResults = buildAnqpResult();
157ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
158ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        for (ScanDetail scanDetail : attScanDetails) {
159ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            cache.update(scanDetail.getNetworkDetail(), anqpResults);
160ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        }
161ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
162ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        /* check ANQP results after another 1 min */
163ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        advanceTimeAndTrimCache(1 * MINUTE_MS);
164ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
165ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        for (ScanDetail scanDetail : attScanDetails) {
166ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            ANQPData data = cache.getEntry(scanDetail.getNetworkDetail());
167ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            assertNotNull(data);
168ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            NetworkDetail nd = data.getNetwork();
169ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            Map<Constants.ANQPElementType, ANQPElement> anqp = data.getANQPElements();
170ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            assertEquals(scanDetail.getBSSIDString(), nd.getBSSIDString());
171ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            assertEquals(anqpResults.size(), anqp.size());
172ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        }
173ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
174ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        /* query ANQP results for twcwifi after another 10 min */
175ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        advanceTimeAndTrimCache(10 * MINUTE_MS);
176ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
177ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        for (ScanDetail scanDetail : twcScanDetails) {
178ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            cache.initiate(scanDetail.getNetworkDetail(), queryList);
179ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        }
180ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
181ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        /* update ANQP results for twcwifi after another 10 min */
182ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        advanceTimeAndTrimCache(1 * MINUTE_MS);
183ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
184ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        for (ScanDetail scanDetail : twcScanDetails) {
185ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            cache.update(scanDetail.getNetworkDetail(), anqpResults);
186ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        }
187ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
188ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        /* check all results after 1 minute */
189ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        advanceTimeAndTrimCache(1 * MINUTE_MS);
190ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
191ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        for (ScanDetail scanDetail : attScanDetails) {
192ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            ANQPData data = cache.getEntry(scanDetail.getNetworkDetail());
193ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            assertNull(data);
194ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        }
195ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
196ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        for (ScanDetail scanDetail : twcScanDetails) {
197ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            ANQPData data = cache.getEntry(scanDetail.getNetworkDetail());
198ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            assertNotNull(data);
199ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            NetworkDetail nd = data.getNetwork();
200ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            Map<Constants.ANQPElementType, ANQPElement> anqp = data.getANQPElements();
201ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            assertEquals(scanDetail.getBSSIDString(), nd.getBSSIDString());
202ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande            assertEquals(anqpResults.size(), anqp.size());
203ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande        }
204ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande    }
205ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande}
206ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
207ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
208ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
209ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
210ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
211ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
212ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
213ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
214ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
215ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
216ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
217ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
218ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
219ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
220ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
221ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
222ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
223ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
224ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
225ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
226ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
227ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
228ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
229ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
230ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
231ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
232ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
233ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
234ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
235ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
236ae815bc71287f8a85727034c40bb07247a3d9415Vinit Deshpande
237