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 */
16package com.android.internal.telephony;
17
18import static com.android.internal.telephony.TelephonyIntents.ACTION_CARRIER_SIGNAL_PCO_VALUE;
19import static com.android.internal.telephony.TelephonyIntents
20        .ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED;
21import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
22
23import static org.junit.Assert.assertEquals;
24import static org.mockito.ArgumentMatchers.anyLong;
25import static org.mockito.Matchers.any;
26import static org.mockito.Matchers.anyInt;
27import static org.mockito.Matchers.argThat;
28import static org.mockito.Mockito.doReturn;
29import static org.mockito.Mockito.times;
30import static org.mockito.Mockito.verify;
31
32import android.content.Intent;
33import android.content.pm.ResolveInfo;
34import android.os.HandlerThread;
35import android.os.Message;
36import android.os.PersistableBundle;
37import android.telephony.CarrierConfigManager;
38import android.test.suitebuilder.annotation.SmallTest;
39
40import org.junit.After;
41import org.junit.Before;
42import org.junit.Test;
43import org.mockito.ArgumentCaptor;
44import org.mockito.Mock;
45
46import java.util.ArrayList;
47import java.util.Arrays;
48import java.util.Objects;
49
50public class CarrierSignalAgentTest extends TelephonyTest {
51
52    private CarrierSignalAgent mCarrierSignalAgentUT;
53    private PersistableBundle mBundle;
54    private CarrierSignalAgentHandler mCarrierSignalAgentHandler;
55    private static final String PCO_RECEIVER = "pak/PCO_RECEIVER";
56    private static final String DC_ERROR_RECEIVER = "pak/DC_ERROR_RECEIVER";
57    @Mock
58    ResolveInfo mResolveInfo;
59
60    private class CarrierSignalAgentHandler extends HandlerThread {
61
62        private CarrierSignalAgentHandler(String name) {
63            super(name);
64        }
65
66        @Override
67        public void onLooperPrepared() {
68            mCarrierSignalAgentUT = new CarrierSignalAgent(mPhone);
69            setReady(true);
70        }
71    }
72
73    @Before
74    public void setUp() throws Exception {
75        logd("CarrierSignalAgentTest +Setup!");
76        super.setUp(getClass().getSimpleName());
77        mBundle = mContextFixture.getCarrierConfigBundle();
78        mCarrierSignalAgentHandler = new CarrierSignalAgentHandler(getClass().getSimpleName());
79        mCarrierSignalAgentHandler.start();
80        waitUntilReady();
81        logd("CarrierSignalAgentTest -Setup!");
82    }
83
84    @After
85    public void tearDown() throws Exception {
86        mCarrierSignalAgentHandler.quit();
87        super.tearDown();
88    }
89
90    @Test
91    @SmallTest
92    public void testNotifyManifestReceivers() throws Exception {
93        // Broadcast count
94        int count = 0;
95        Intent intent = new Intent(ACTION_CARRIER_SIGNAL_PCO_VALUE);
96        mBundle.putStringArray(
97                CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
98                new String[]{PCO_RECEIVER + ":" + ACTION_CARRIER_SIGNAL_PCO_VALUE,
99                        DC_ERROR_RECEIVER + ":" + ACTION_CARRIER_SIGNAL_PCO_VALUE
100                });
101
102        // Verify no broadcast has been sent without carrier config
103        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(intent);
104        ArgumentCaptor<Intent> mCaptorIntent = ArgumentCaptor.forClass(Intent.class);
105        verify(mContext, times(count)).sendBroadcast(mCaptorIntent.capture());
106
107        // Trigger carrier config reloading
108        mContext.sendBroadcast(new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
109        waitForMs(50);
110        count++;
111
112        // Verify no broadcast has been sent due to no manifest receivers
113        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(intent);
114        verify(mContext, times(count)).sendBroadcast(mCaptorIntent.capture());
115
116        // Verify broadcast has been sent to two different registered manifest receivers
117        doReturn(new ArrayList<>(Arrays.asList(mResolveInfo)))
118                .when(mPackageManager).queryBroadcastReceivers((Intent) any(), anyInt());
119        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(intent);
120        count += 2;
121        mCaptorIntent = ArgumentCaptor.forClass(Intent.class);
122        verify(mContext, times(count)).sendBroadcast(mCaptorIntent.capture());
123
124        logd(mCaptorIntent.getAllValues().toString());
125        Intent capturedIntent = mCaptorIntent.getAllValues().get(1);
126        assertEquals(ACTION_CARRIER_SIGNAL_PCO_VALUE, capturedIntent.getAction());
127        assertEquals(DC_ERROR_RECEIVER, capturedIntent.getComponent().flattenToString());
128
129        capturedIntent = mCaptorIntent.getAllValues().get(2);
130        assertEquals(ACTION_CARRIER_SIGNAL_PCO_VALUE, capturedIntent.getAction());
131        assertEquals(PCO_RECEIVER, capturedIntent.getComponent().flattenToString());
132    }
133
134    @Test
135    @SmallTest
136    public void testNotifyRuntimeReceivers() throws Exception {
137        // Broadcast count
138        int count = 0;
139        Intent intent = new Intent(ACTION_CARRIER_SIGNAL_PCO_VALUE);
140        mBundle.putStringArray(
141                CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
142                new String[]{PCO_RECEIVER + ":" + ACTION_CARRIER_SIGNAL_PCO_VALUE});
143
144        // Verify no broadcast without carrier configs
145        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(intent);
146        ArgumentCaptor<Intent> mCaptorIntent = ArgumentCaptor.forClass(Intent.class);
147        verify(mContext, times(count)).sendBroadcast(mCaptorIntent.capture());
148
149        // Trigger carrier config reloading
150        mContext.sendBroadcast(new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
151        waitForMs(50);
152        count++;
153
154        // Verify broadcast has been sent to registered components
155        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(intent);
156        verify(mContext, times(++count)).sendBroadcast(mCaptorIntent.capture());
157        assertEquals(ACTION_CARRIER_SIGNAL_PCO_VALUE,
158                mCaptorIntent.getValue().getAction());
159        assertEquals(PCO_RECEIVER, mCaptorIntent.getValue().getComponent().flattenToString());
160
161        // Verify no broadcast has been sent to manifest receivers (bad config)
162        doReturn(new ArrayList<>(Arrays.asList(mResolveInfo)))
163                .when(mPackageManager).queryBroadcastReceivers((Intent) any(), anyInt());
164        mCaptorIntent = ArgumentCaptor.forClass(Intent.class);
165        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(intent);
166        verify(mContext, times(count)).sendBroadcast(mCaptorIntent.capture());
167    }
168
169    @Test
170    @SmallTest
171    public void testNotify() {
172        // Broadcast count
173        int count = 0;
174        mBundle.putStringArray(
175                CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
176                new String[]{ PCO_RECEIVER + ":" + ACTION_CARRIER_SIGNAL_PCO_VALUE });
177        mBundle.putStringArray(
178                CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
179                new String[]{ PCO_RECEIVER + ":"
180                        + ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED });
181        // Only wake signal is declared in the manifest
182        doReturn(new ArrayList<>(Arrays.asList(mResolveInfo)))
183                .when(mPackageManager).queryBroadcastReceivers(
184                argThat(o -> Objects.equals(o.getAction(), ACTION_CARRIER_SIGNAL_PCO_VALUE)),
185                anyInt());
186
187        mContext.sendBroadcast(new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
188        count++;
189        waitForMs(50);
190
191        // Wake signal for PAK_PCO_RECEIVER
192        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(
193                new Intent(ACTION_CARRIER_SIGNAL_PCO_VALUE));
194        ArgumentCaptor<Intent> mCaptorIntent = ArgumentCaptor.forClass(Intent.class);
195        verify(mContext, times(++count)).sendBroadcast(mCaptorIntent.capture());
196        assertEquals(ACTION_CARRIER_SIGNAL_PCO_VALUE, mCaptorIntent.getValue().getAction());
197        assertEquals(PCO_RECEIVER, mCaptorIntent.getValue().getComponent().flattenToString());
198
199        // No wake signal for PAK_PCO_RECEIVER
200        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(
201                new Intent(ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED));
202        mCaptorIntent = ArgumentCaptor.forClass(Intent.class);
203        verify(mContext, times(++count)).sendBroadcast(mCaptorIntent.capture());
204        assertEquals(ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED,
205                mCaptorIntent.getValue().getAction());
206        assertEquals(PCO_RECEIVER, mCaptorIntent.getValue().getComponent().flattenToString());
207
208        // Both wake and no-wake signals are declared in the manifest
209        doReturn(new ArrayList<>(Arrays.asList(mResolveInfo)))
210                .when(mPackageManager).queryBroadcastReceivers((Intent) any(), anyInt());
211        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(
212                new Intent(ACTION_CARRIER_SIGNAL_PCO_VALUE));
213        mCaptorIntent = ArgumentCaptor.forClass(Intent.class);
214        verify(mContext, times(++count)).sendBroadcast(mCaptorIntent.capture());
215        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(
216                new Intent(ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED));
217        mCaptorIntent = ArgumentCaptor.forClass(Intent.class);
218        verify(mContext, times(count)).sendBroadcast(mCaptorIntent.capture());
219
220        // Neither wake nor no-wake signals are declared in the manifest
221        doReturn(new ArrayList<>()).when(mPackageManager).queryBroadcastReceivers((Intent) any(),
222                anyInt());
223        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(
224                new Intent(ACTION_CARRIER_SIGNAL_PCO_VALUE));
225        mCaptorIntent = ArgumentCaptor.forClass(Intent.class);
226        verify(mContext, times(count)).sendBroadcast(mCaptorIntent.capture());
227        mCarrierSignalAgentUT.notifyCarrierSignalReceivers(
228                new Intent(ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED));
229        mCaptorIntent = ArgumentCaptor.forClass(Intent.class);
230        verify(mContext, times(++count)).sendBroadcast(mCaptorIntent.capture());
231    }
232
233
234    @Test
235    @SmallTest
236    public void testCarrierConfigChange() {
237        // default config value
238        mBundle.putStringArray(
239                CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
240                new String[]{ PCO_RECEIVER + ":" + ACTION_CARRIER_SIGNAL_PCO_VALUE + ","
241                        + ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED });
242        mContext.sendBroadcast(new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
243        waitForMs(50);
244        // verify no reset action on initial config load
245        verify(mCarrierActionAgent, times(0)).sendMessageAtTime(any(Message.class), anyLong());
246
247        // new carrier config with different receiver intent order
248        mBundle.putStringArray(
249                CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
250                new String[]{ PCO_RECEIVER + ":" + ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
251                        + "," + ACTION_CARRIER_SIGNAL_PCO_VALUE});
252        mContext.sendBroadcast(new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
253        waitForMs(50);
254        // verify no reset action for the same config (different order)
255        verify(mCarrierActionAgent, times(0)).sendMessageAtTime(any(Message.class), anyLong());
256
257        // new different config value
258        mBundle.putStringArray(
259                CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
260                new String[]{ DC_ERROR_RECEIVER + ":" + ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
261                        + "," + ACTION_CARRIER_SIGNAL_PCO_VALUE});
262        mContext.sendBroadcast(new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
263        waitForMs(50);
264        // verify there is no reset action
265        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
266        verify(mCarrierActionAgent, times(1))
267                .sendMessageAtTime(messageArgumentCaptor.capture(), anyLong());
268        assertEquals(CarrierActionAgent.CARRIER_ACTION_RESET,
269                messageArgumentCaptor.getValue().what);
270    }
271}
272