1 /*
2  * Copyright (C) 2022 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.settings.safetycenter;
18 
19 import static android.safetycenter.SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES;
20 import static android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID;
21 import static android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCE_IDS;
22 import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED;
23 import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED;
24 import static com.google.common.truth.Truth.assertThat;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.Mockito.never;
27 import static org.mockito.Mockito.times;
28 import static org.mockito.Mockito.verify;
29 import static org.mockito.Mockito.when;
30 
31 import android.content.Context;
32 import android.content.Intent;
33 import android.os.Flags;
34 import android.platform.test.flag.junit.SetFlagsRule;
35 import android.safetycenter.SafetyEvent;
36 import android.safetycenter.SafetySourceData;
37 
38 import androidx.test.core.app.ApplicationProvider;
39 import androidx.test.ext.junit.runners.AndroidJUnit4;
40 
41 import com.android.internal.widget.LockPatternUtils;
42 import com.android.settings.privatespace.PrivateSpaceSafetySource;
43 import com.android.settings.testutils.FakeFeatureFactory;
44 
45 import org.junit.After;
46 import org.junit.Before;
47 import org.junit.Rule;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 import org.mockito.ArgumentCaptor;
51 import org.mockito.Mock;
52 import org.mockito.MockitoAnnotations;
53 
54 import java.util.Arrays;
55 import java.util.List;
56 
57 @RunWith(AndroidJUnit4.class)
58 public class SafetySourceBroadcastReceiverTest {
59 
60     private static final String REFRESH_BROADCAST_ID = "REFRESH_BROADCAST_ID";
61 
62     private Context mApplicationContext;
63 
64     @Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
65 
66     @Mock private LockPatternUtils mLockPatternUtils;
67     @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
68 
69     @Before
setUp()70     public void setUp() {
71         MockitoAnnotations.initMocks(this);
72         mApplicationContext = ApplicationProvider.getApplicationContext();
73         final FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
74         when(featureFactory.securityFeatureProvider.getLockPatternUtils(mApplicationContext))
75                 .thenReturn(mLockPatternUtils);
76         SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper;
77     }
78 
79     @After
tearDown()80     public void tearDown() {
81         SafetyCenterManagerWrapper.sInstance = null;
82     }
83 
84     @Test
onReceive_onRefresh_whenSafetyCenterIsDisabled_doesNotSetData()85     public void onReceive_onRefresh_whenSafetyCenterIsDisabled_doesNotSetData() {
86         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false);
87         Intent intent =
88                 new Intent()
89                         .setAction(ACTION_REFRESH_SAFETY_SOURCES)
90                         .putExtra(
91                                 EXTRA_REFRESH_SAFETY_SOURCE_IDS,
92                                 new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
93                         .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
94 
95         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
96 
97         verify(mSafetyCenterManagerWrapper, never())
98                 .setSafetySourceData(any(), any(), any(), any());
99     }
100 
101     @Test
onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoIntentAction_doesNotSetData()102     public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoIntentAction_doesNotSetData() {
103         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
104         Intent intent =
105                 new Intent()
106                         .putExtra(
107                                 EXTRA_REFRESH_SAFETY_SOURCE_IDS,
108                                 new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
109                         .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
110 
111         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
112 
113         verify(mSafetyCenterManagerWrapper, never())
114                 .setSafetySourceData(any(), any(), any(), any());
115     }
116 
117     @Test
onReceive_onRefresh_whenSafetyCenterIsEnabled_withNullSourceIds_doesNotSetData()118     public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNullSourceIds_doesNotSetData() {
119         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
120         Intent intent =
121                 new Intent()
122                         .setAction(ACTION_REFRESH_SAFETY_SOURCES)
123                         .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
124 
125         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
126 
127         verify(mSafetyCenterManagerWrapper, never())
128                 .setSafetySourceData(any(), any(), any(), any());
129     }
130 
131     @Test
onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoSourceIds_doesNotSetData()132     public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoSourceIds_doesNotSetData() {
133         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
134         Intent intent =
135                 new Intent()
136                         .setAction(ACTION_REFRESH_SAFETY_SOURCES)
137                         .putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, new String[] {})
138                         .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
139 
140         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
141 
142         verify(mSafetyCenterManagerWrapper, never())
143                 .setSafetySourceData(any(), any(), any(), any());
144     }
145 
146     @Test
onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoBroadcastId_doesNotSetData()147     public void onReceive_onRefresh_whenSafetyCenterIsEnabled_withNoBroadcastId_doesNotSetData() {
148         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
149         Intent intent =
150                 new Intent()
151                         .setAction(ACTION_REFRESH_SAFETY_SOURCES)
152                         .putExtra(
153                                 EXTRA_REFRESH_SAFETY_SOURCE_IDS,
154                                 new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID});
155 
156         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
157 
158         verify(mSafetyCenterManagerWrapper, never())
159                 .setSafetySourceData(any(), any(), any(), any());
160     }
161 
162     @Test
onReceive_onRefresh_setsRefreshEvent()163     public void onReceive_onRefresh_setsRefreshEvent() {
164         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
165         Intent intent =
166                 new Intent()
167                         .setAction(ACTION_REFRESH_SAFETY_SOURCES)
168                         .putExtra(
169                                 EXTRA_REFRESH_SAFETY_SOURCE_IDS,
170                                 new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
171                         .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
172 
173         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
174         ArgumentCaptor<SafetyEvent> captor = ArgumentCaptor.forClass(SafetyEvent.class);
175         verify(mSafetyCenterManagerWrapper, times(1))
176                 .setSafetySourceData(any(), any(), any(), captor.capture());
177 
178         assertThat(captor.getValue())
179                 .isEqualTo(
180                         new SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
181                                 .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
182                                 .build());
183     }
184 
185     @Test
onReceive_onRefresh_withLockscreenSourceId_setsLockscreenData()186     public void onReceive_onRefresh_withLockscreenSourceId_setsLockscreenData() {
187         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
188         Intent intent =
189                 new Intent()
190                         .setAction(ACTION_REFRESH_SAFETY_SOURCES)
191                         .putExtra(
192                                 EXTRA_REFRESH_SAFETY_SOURCE_IDS,
193                                 new String[] {LockScreenSafetySource.SAFETY_SOURCE_ID})
194                         .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
195 
196         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
197         ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
198         verify(mSafetyCenterManagerWrapper, times(1))
199                 .setSafetySourceData(any(), captor.capture(), any(), any());
200 
201         assertThat(captor.getValue()).isEqualTo(LockScreenSafetySource.SAFETY_SOURCE_ID);
202     }
203 
204     @Test
onReceive_onRefresh_withBiometricsSourceId_setsBiometricData()205     public void onReceive_onRefresh_withBiometricsSourceId_setsBiometricData() {
206         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
207         Intent intent =
208                 new Intent()
209                         .setAction(ACTION_REFRESH_SAFETY_SOURCES)
210                         .putExtra(
211                                 EXTRA_REFRESH_SAFETY_SOURCE_IDS,
212                                 new String[] {BiometricsSafetySource.SAFETY_SOURCE_ID})
213                         .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
214 
215         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
216         ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
217         verify(mSafetyCenterManagerWrapper, times(1))
218                 .setSafetySourceData(any(), captor.capture(), any(), any());
219 
220         assertThat(captor.getValue()).isEqualTo(BiometricsSafetySource.SAFETY_SOURCE_ID);
221     }
222 
223     /**
224      *  Tests that on receiving the refresh broadcast request with the PS source id, the PS data
225      * is set.
226      */
227     @Test
onReceive_onRefresh_withPrivateSpaceSourceId_setsPrivateSpaceData()228     public void onReceive_onRefresh_withPrivateSpaceSourceId_setsPrivateSpaceData() {
229         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
230         Intent intent =
231                 new Intent()
232                         .setAction(ACTION_REFRESH_SAFETY_SOURCES)
233                         .putExtra(
234                                 EXTRA_REFRESH_SAFETY_SOURCE_IDS,
235                                 new String[] {PrivateSpaceSafetySource.SAFETY_SOURCE_ID})
236                         .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
237 
238         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
239         ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
240         verify(mSafetyCenterManagerWrapper, times(1))
241                 .setSafetySourceData(any(), captor.capture(), any(), any());
242 
243         assertThat(captor.getValue()).isEqualTo(PrivateSpaceSafetySource.SAFETY_SOURCE_ID);
244     }
245 
246     /** Tests that the PS source sets null data when it's disabled. */
247     @Test
onReceive_onRefresh_withPrivateSpaceFeatureDisabled_setsNullData()248     public void onReceive_onRefresh_withPrivateSpaceFeatureDisabled_setsNullData() {
249         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
250         mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE,
251                 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES);
252 
253         Intent intent =
254                 new Intent()
255                         .setAction(ACTION_REFRESH_SAFETY_SOURCES)
256                         .putExtra(
257                                 EXTRA_REFRESH_SAFETY_SOURCE_IDS,
258                                 new String[] {PrivateSpaceSafetySource.SAFETY_SOURCE_ID})
259                         .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
260 
261         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
262         ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
263         verify(mSafetyCenterManagerWrapper, times(1))
264                 .setSafetySourceData(any(), any(), captor.capture(), any());
265 
266         assertThat(captor.getValue()).isEqualTo(null);
267     }
268 
269     @Test
onReceive_onBootCompleted_setsBootCompleteEvent()270     public void onReceive_onBootCompleted_setsBootCompleteEvent() {
271         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
272         Intent intent = new Intent().setAction(Intent.ACTION_BOOT_COMPLETED);
273 
274         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
275         ArgumentCaptor<SafetyEvent> captor = ArgumentCaptor.forClass(SafetyEvent.class);
276         verify(mSafetyCenterManagerWrapper, times(3))
277                 .setSafetySourceData(any(), any(), any(), captor.capture());
278 
279         SafetyEvent bootEvent = new SafetyEvent.Builder(SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build();
280         assertThat(captor.getAllValues())
281                 .containsExactlyElementsIn(Arrays.asList(bootEvent, bootEvent, bootEvent));
282     }
283 
284     @Test
onReceive_onBootCompleted_sendsAllSafetySourcesData()285     public void onReceive_onBootCompleted_sendsAllSafetySourcesData() {
286         when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
287         Intent intent = new Intent().setAction(Intent.ACTION_BOOT_COMPLETED);
288 
289         new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
290         ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
291         verify(mSafetyCenterManagerWrapper, times(3))
292                 .setSafetySourceData(any(), captor.capture(), any(), any());
293         List<String> safetySourceIdList = captor.getAllValues();
294 
295         assertThat(safetySourceIdList.stream().anyMatch(
296                 id -> id.equals(LockScreenSafetySource.SAFETY_SOURCE_ID))).isTrue();
297         assertThat(safetySourceIdList.stream().anyMatch(
298                 id -> id.equals(BiometricsSafetySource.SAFETY_SOURCE_ID))).isTrue();
299         assertThat(safetySourceIdList.stream().anyMatch(
300                 id -> id.equals(PrivateSpaceSafetySource.SAFETY_SOURCE_ID))).isTrue();
301     }
302 }
303