1/*
2 * Copyright (C) 2006 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.internal.telephony.dataconnection;
18
19import android.content.Context;
20import android.net.ConnectivityManager;
21import android.net.NetworkCapabilities;
22import android.net.NetworkRequest;
23import android.net.StringNetworkSpecifier;
24import android.os.Binder;
25import android.os.HandlerThread;
26import android.os.Looper;
27import android.os.Message;
28import android.support.test.filters.FlakyTest;
29import android.telephony.Rlog;
30import android.test.AndroidTestCase;
31import android.test.suitebuilder.annotation.SmallTest;
32
33import com.android.internal.telephony.ContextFixture;
34import com.android.internal.telephony.mocks.ConnectivityServiceMock;
35import com.android.internal.telephony.mocks.DcTrackerMock;
36import com.android.internal.telephony.mocks.PhoneSwitcherMock;
37import com.android.internal.telephony.mocks.SubscriptionControllerMock;
38import com.android.internal.telephony.mocks.SubscriptionMonitorMock;
39import com.android.internal.telephony.mocks.TelephonyRegistryMock;
40
41import org.junit.Ignore;
42
43public class TelephonyNetworkFactoryTest extends AndroidTestCase {
44    private final static String LOG_TAG = "TelephonyNetworkFactoryTest";
45
46    private void waitABit() {
47        try {
48            Thread.sleep(250);
49        } catch (Exception e) {}
50    }
51
52    private String mTestName = "";
53
54    private void log(String str) {
55        Rlog.d(LOG_TAG + " " + mTestName, str);
56    }
57
58    private class TestSetup {
59        final TelephonyRegistryMock telephonyRegistryMock;
60        final PhoneSwitcherMock phoneSwitcherMock;
61        final SubscriptionControllerMock subscriptionControllerMock;
62        final SubscriptionMonitorMock subscriptionMonitorMock;
63        final HandlerThread handlerThread;
64        final ConnectivityServiceMock connectivityServiceMock;
65        final Looper looper;
66        DcTrackerMock dcTrackerMock;
67        final Context contextMock;
68        private Object mLock = new Object();
69        private static final int MAX_INIT_WAIT_MS = 30000; // 30 seconds
70
71        TestSetup(int numPhones) {
72            handlerThread = new HandlerThread("TelephonyNetworkFactoryTest") {
73                @Override
74                public void onLooperPrepared() {
75                    synchronized (mLock) {
76                        if (dcTrackerMock == null) dcTrackerMock = new DcTrackerMock();
77                        mLock.notifyAll();
78                    }
79                }
80            };
81            handlerThread.start();
82            // wait until dct created
83            synchronized (mLock) {
84                try {
85                    mLock.wait(MAX_INIT_WAIT_MS);
86                } catch (InterruptedException ie) {
87                }
88                if (dcTrackerMock == null) fail("failed to initialize dct");
89            }
90            looper = handlerThread.getLooper();
91
92            final ContextFixture contextFixture = new ContextFixture();
93            String[] networkConfigString = getContext().getResources().getStringArray(
94                    com.android.internal.R.array.networkAttributes);
95            contextFixture.putStringArrayResource(com.android.internal.R.array.networkAttributes,
96                    networkConfigString);
97            contextMock = contextFixture.getTestDouble();
98
99            connectivityServiceMock = new ConnectivityServiceMock(contextMock);
100            ConnectivityManager cm =
101                    new ConnectivityManager(contextMock, connectivityServiceMock);
102            contextFixture.setSystemService(Context.CONNECTIVITY_SERVICE, cm);
103
104            telephonyRegistryMock = new TelephonyRegistryMock();
105            phoneSwitcherMock = new PhoneSwitcherMock(numPhones, looper);
106            subscriptionControllerMock =
107                    new SubscriptionControllerMock(contextMock, telephonyRegistryMock, numPhones);
108            subscriptionMonitorMock = new SubscriptionMonitorMock(numPhones);
109        }
110
111        void die() {
112            connectivityServiceMock.die();
113            looper.quit();
114            handlerThread.quit();
115        }
116    }
117
118    private TelephonyNetworkFactory makeTnf(int phoneId, TestSetup ts) {
119        return new TelephonyNetworkFactory(ts.phoneSwitcherMock, ts.subscriptionControllerMock,
120                ts.subscriptionMonitorMock, ts.looper, ts.contextMock, phoneId, ts.dcTrackerMock);
121    }
122
123    private NetworkRequest makeSubSpecificDefaultRequest(TestSetup ts, int subId) {
124        NetworkCapabilities netCap = (new NetworkCapabilities()).
125                addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).
126                addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED).
127                addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
128        netCap.setNetworkSpecifier(new StringNetworkSpecifier(Integer.toString(subId)));
129        return ts.connectivityServiceMock.requestNetwork(netCap, null, 0, new Binder(), -1);
130    }
131    private NetworkRequest makeSubSpecificMmsRequest(TestSetup ts, int subId) {
132        NetworkCapabilities netCap = (new NetworkCapabilities()).
133                addCapability(NetworkCapabilities.NET_CAPABILITY_MMS).
134                addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED).
135                addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
136        netCap.setNetworkSpecifier(new StringNetworkSpecifier(Integer.toString(subId)));
137        return ts.connectivityServiceMock.requestNetwork(netCap, null, 0, new Binder(), -1);
138    }
139
140
141    /**
142     * Test that phone active changes cause the DcTracker to get poked.
143     */
144    @FlakyTest
145    @SmallTest
146    public void testActive() throws Exception {
147        mTestName = "testActive";
148        final int numberOfPhones = 1;
149        final int phoneId = 0;
150        final int subId = 0;
151
152        TestSetup ts = new TestSetup(numberOfPhones);
153
154        makeTnf(phoneId, ts);
155
156        ts.subscriptionControllerMock.setDefaultDataSubId(subId);
157        ts.subscriptionControllerMock.setSlotSubId(phoneId, subId);
158        ts.subscriptionMonitorMock.notifySubscriptionChanged(phoneId);
159        ts.subscriptionMonitorMock.notifyDefaultSubscriptionChanged(phoneId);
160
161        log("addDefaultRequest");
162        ts.connectivityServiceMock.addDefaultRequest();
163        waitABit();
164        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 0) {
165            fail("pretest of LiveRequests != 0");
166        }
167
168        log("setPhoneActive true: phoneId = " + phoneId);
169        ts.phoneSwitcherMock.setPhoneActive(phoneId, true);
170        waitABit();
171        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 1) {
172            fail("post-active test of LiveRequests != 1");
173        }
174
175        log("makeSubSpecificDefaultRequest: subId = " + subId);
176        NetworkRequest subSpecificDefault = makeSubSpecificDefaultRequest(ts, subId);
177        waitABit();
178        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 2) {
179            fail("post-second-request test of LiveRequests != 2");
180        }
181
182        log("setPhoneActive false: phoneId = " + phoneId);
183        ts.phoneSwitcherMock.setPhoneActive(phoneId, false);
184        waitABit();
185        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 0) {
186            fail("post-inactive test of LiveRequests != 0");
187        }
188
189        log("makeSubSpecificDefaultRequest: subId = " + subId);
190        NetworkRequest subSpecificMms = makeSubSpecificMmsRequest(ts, subId);
191        waitABit();
192        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 0) {
193            fail("post-mms-add test of LiveRequests != 0");
194        }
195
196        log("setPhoneActive true: phoneId = " + phoneId);
197        ts.phoneSwitcherMock.setPhoneActive(phoneId, true);
198        waitABit();
199        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 3) {
200            fail("post-active-mms-add test of LiveRequests != 3");
201        }
202
203        log("releaseNetworkRequest: subSpecificDefault = " + subSpecificDefault);
204        ts.connectivityServiceMock.releaseNetworkRequest(subSpecificDefault);
205        waitABit();
206        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 2) {
207            fail("post-remove-default test of LiveRequests != 2");
208        }
209
210        log("setPhoneActive false: phoneId = " + phoneId);
211        ts.phoneSwitcherMock.setPhoneActive(phoneId, false);
212        waitABit();
213        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 0) {
214            fail("test 8, LiveRequests != 0");
215        }
216
217        log("releaseNetworkRequest: subSpecificMms = " + subSpecificMms);
218        ts.connectivityServiceMock.releaseNetworkRequest(subSpecificMms);
219        waitABit();
220        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 0) {
221            fail("test 9, LiveRequests != 0");
222        }
223
224        log("setPhoneActive true: phoneId = " + phoneId);
225        ts.phoneSwitcherMock.setPhoneActive(phoneId, true);
226        waitABit();
227        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 1) {
228            fail("test 10, LiveRequests != 1," + ts.dcTrackerMock.getNumberOfLiveRequests());
229        }
230
231        ts.die();
232    }
233
234    /**
235     * Test that network request changes cause the DcTracker to get poked.
236     */
237    @SmallTest
238    public void testRequests() throws Exception {
239        mTestName = "testActive";
240        final int numberOfPhones = 2;
241        final int phoneId = 0;
242        final int altPhoneId = 1;
243        final int subId = 0;
244        final int altSubId = 1;
245        final int unusedSubId = 2;
246
247        TestSetup ts = new TestSetup(numberOfPhones);
248
249        makeTnf(phoneId, ts);
250
251        ts.subscriptionControllerMock.setDefaultDataSubId(subId);
252        ts.subscriptionControllerMock.setSlotSubId(phoneId, subId);
253        ts.subscriptionMonitorMock.notifySubscriptionChanged(phoneId);
254        ts.subscriptionMonitorMock.notifyDefaultSubscriptionChanged(phoneId);
255        waitABit();
256
257        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 0) {
258            fail("test 1, LiveRequests != 0");
259        }
260
261        ts.phoneSwitcherMock.setPhoneActive(phoneId, true);
262        waitABit();
263        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 0) {
264            fail("test 2, LiveRequests != 0");
265        }
266
267        ts.connectivityServiceMock.addDefaultRequest();
268        waitABit();
269        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 1) {
270            fail("test 3, LiveRequests != 1");
271        }
272
273        ts.subscriptionControllerMock.setSlotSubId(altPhoneId, altSubId);
274        waitABit();
275        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 1) {
276            fail("test 4, LiveRequests != 1");
277        }
278
279        ts.subscriptionControllerMock.setDefaultDataSubId(altSubId);
280        ts.subscriptionMonitorMock.notifyDefaultSubscriptionChanged(phoneId);
281        ts.subscriptionMonitorMock.notifyDefaultSubscriptionChanged(altPhoneId);
282        waitABit();
283        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 0) {
284            fail("test 5, LiveRequests != 0");
285        }
286
287        makeSubSpecificMmsRequest(ts, subId);
288        waitABit();
289        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 1) {
290            fail("test 6,  LiveRequests != 1");
291        }
292
293        ts.subscriptionControllerMock.setSlotSubId(phoneId, unusedSubId);
294        ts.subscriptionMonitorMock.notifySubscriptionChanged(phoneId);
295        waitABit();
296        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 0) {
297            fail("test 7,  LiveRequests != 0");
298        }
299
300        makeSubSpecificDefaultRequest(ts, subId);
301        waitABit();
302        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 0) {
303            fail("test 8, LiveRequests != 0");
304        }
305
306        ts.subscriptionControllerMock.setSlotSubId(phoneId, subId);
307        ts.subscriptionMonitorMock.notifySubscriptionChanged(phoneId);
308        waitABit();
309        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 2) {
310            fail("test 9,  LiveRequests != 2");
311        }
312
313        ts.subscriptionControllerMock.setDefaultDataSubId(subId);
314        ts.subscriptionMonitorMock.notifyDefaultSubscriptionChanged(phoneId);
315        ts.subscriptionMonitorMock.notifyDefaultSubscriptionChanged(altPhoneId);
316        ts.subscriptionMonitorMock.notifyDefaultSubscriptionChanged(phoneId);
317        waitABit();
318        if (ts.dcTrackerMock.getNumberOfLiveRequests() != 3) {
319            fail("test 10, LiveRequests != 3");
320        }
321        ts.die();
322    }
323}
324