1 /*
2  * Copyright (C) 2013 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.server.contentcapture;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.anyInt;
22 import static org.mockito.ArgumentMatchers.anyString;
23 import static org.mockito.Mockito.never;
24 import static org.mockito.Mockito.verify;
25 import static org.mockito.Mockito.verifyNoMoreInteractions;
26 import static org.mockito.Mockito.verifyZeroInteractions;
27 import static org.mockito.Mockito.when;
28 
29 import android.annotation.NonNull;
30 import android.content.ComponentName;
31 import android.content.ContentCaptureOptions;
32 import android.content.Context;
33 import android.content.pm.PackageManager;
34 import android.content.pm.ParceledListSlice;
35 import android.content.pm.UserInfo;
36 import android.service.contentcapture.ContentCaptureServiceInfo;
37 import android.view.contentcapture.ContentCaptureEvent;
38 
39 import androidx.test.core.app.ApplicationProvider;
40 import androidx.test.ext.junit.runners.AndroidJUnit4;
41 import androidx.test.filters.SmallTest;
42 
43 import com.android.server.LocalServices;
44 import com.android.server.contentprotection.ContentProtectionBlocklistManager;
45 import com.android.server.contentprotection.ContentProtectionConsentManager;
46 import com.android.server.contentprotection.RemoteContentProtectionService;
47 import com.android.server.pm.UserManagerInternal;
48 
49 import com.google.common.collect.ImmutableList;
50 
51 import org.junit.Before;
52 import org.junit.Rule;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 import org.mockito.Mock;
56 import org.mockito.junit.MockitoJUnit;
57 import org.mockito.junit.MockitoRule;
58 
59 /**
60  * Test for {@link ContentCaptureManagerService}.
61  *
62  * <p>Run with: {@code atest
63  * FrameworksServicesTests:com.android.server.contentcapture.ContentCaptureManagerServiceTest}
64  */
65 @RunWith(AndroidJUnit4.class)
66 @SmallTest
67 @SuppressWarnings("GuardedBy") // Service not really running, no need to expose locks
68 public class ContentCaptureManagerServiceTest {
69 
70     private static final int USER_ID = 1234;
71 
72     private static final String PACKAGE_NAME = "com.test.package";
73 
74     private static final ComponentName COMPONENT_NAME =
75             new ComponentName(PACKAGE_NAME, "TestClass");
76 
77     private static final ContentCaptureEvent EVENT =
78             new ContentCaptureEvent(/* sessionId= */ 100, /* type= */ 200);
79 
80     private static final ParceledListSlice<ContentCaptureEvent> PARCELED_EVENTS =
81             new ParceledListSlice<>(ImmutableList.of(EVENT));
82 
83     private static final Context sContext = ApplicationProvider.getApplicationContext();
84 
85     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
86 
87     @Mock private UserManagerInternal mMockUserManagerInternal;
88 
89     @Mock private ContentProtectionBlocklistManager mMockContentProtectionBlocklistManager;
90 
91     @Mock private ContentCaptureServiceInfo mMockContentCaptureServiceInfo;
92 
93     @Mock private RemoteContentProtectionService mMockRemoteContentProtectionService;
94 
95     @Mock private ContentProtectionConsentManager mMockContentProtectionConsentManager;
96 
97     private boolean mDevCfgEnableContentProtectionReceiver;
98 
99     private int mContentProtectionBlocklistManagersCreated;
100 
101     private int mContentProtectionServiceInfosCreated;
102 
103     private int mRemoteContentProtectionServicesCreated;
104 
105     private int mContentProtectionConsentManagersCreated;
106 
107     private String mConfigDefaultContentProtectionService = COMPONENT_NAME.flattenToString();
108 
109     private boolean mContentProtectionServiceInfoConstructorShouldThrow;
110 
111     private ContentCaptureManagerService mContentCaptureManagerService;
112 
113     @Before
setup()114     public void setup() {
115         when(mMockUserManagerInternal.getUserInfos()).thenReturn(new UserInfo[0]);
116         LocalServices.removeServiceForTest(UserManagerInternal.class);
117         LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
118         mContentCaptureManagerService = new TestContentCaptureManagerService();
119     }
120 
121     @Test
constructor_contentProtection_flagDisabled_noManagers()122     public void constructor_contentProtection_flagDisabled_noManagers() {
123         assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0);
124         assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
125         assertThat(mContentProtectionConsentManagersCreated).isEqualTo(0);
126         verifyZeroInteractions(mMockContentProtectionBlocklistManager);
127         verifyZeroInteractions(mMockContentProtectionConsentManager);
128     }
129 
130     @Test
constructor_contentProtection_componentNameNull_noManagers()131     public void constructor_contentProtection_componentNameNull_noManagers() {
132         mConfigDefaultContentProtectionService = null;
133 
134         mContentCaptureManagerService = new TestContentCaptureManagerService();
135 
136         assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0);
137         assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
138         assertThat(mContentProtectionConsentManagersCreated).isEqualTo(0);
139         verifyZeroInteractions(mMockContentProtectionBlocklistManager);
140         verifyZeroInteractions(mMockContentProtectionConsentManager);
141     }
142 
143     @Test
constructor_contentProtection_componentNameBlank_noManagers()144     public void constructor_contentProtection_componentNameBlank_noManagers() {
145         mConfigDefaultContentProtectionService = "   ";
146 
147         mContentCaptureManagerService = new TestContentCaptureManagerService();
148 
149         assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0);
150         assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
151         assertThat(mContentProtectionConsentManagersCreated).isEqualTo(0);
152         verifyZeroInteractions(mMockContentProtectionBlocklistManager);
153         verifyZeroInteractions(mMockContentProtectionConsentManager);
154     }
155 
156     @Test
constructor_contentProtection_enabled_createsManagers()157     public void constructor_contentProtection_enabled_createsManagers() {
158         mDevCfgEnableContentProtectionReceiver = true;
159 
160         mContentCaptureManagerService = new TestContentCaptureManagerService();
161 
162         assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(1);
163         assertThat(mContentProtectionConsentManagersCreated).isEqualTo(1);
164         assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
165         verify(mMockContentProtectionBlocklistManager).updateBlocklist(anyInt());
166         verifyZeroInteractions(mMockContentProtectionConsentManager);
167     }
168 
169     @Test
setFineTuneParamsFromDeviceConfig_doesNotUpdateContentProtectionBlocklist()170     public void setFineTuneParamsFromDeviceConfig_doesNotUpdateContentProtectionBlocklist() {
171         mDevCfgEnableContentProtectionReceiver = true;
172         mContentCaptureManagerService = new TestContentCaptureManagerService();
173         mContentCaptureManagerService.mDevCfgContentProtectionAppsBlocklistSize += 100;
174         verify(mMockContentProtectionBlocklistManager).updateBlocklist(anyInt());
175 
176         mContentCaptureManagerService.setFineTuneParamsFromDeviceConfig();
177 
178         verifyNoMoreInteractions(mMockContentProtectionBlocklistManager);
179     }
180 
181     @Test
getOptions_contentCaptureDisabled_contentProtectionDisabled()182     public void getOptions_contentCaptureDisabled_contentProtectionDisabled() {
183         mDevCfgEnableContentProtectionReceiver = true;
184         mContentCaptureManagerService = new TestContentCaptureManagerService();
185 
186         ContentCaptureOptions actual =
187                 mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
188                         USER_ID, PACKAGE_NAME);
189 
190         assertThat(actual).isNull();
191         verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID);
192         verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
193     }
194 
195     @Test
getOptions_contentCaptureDisabled_contentProtectionEnabled()196     public void getOptions_contentCaptureDisabled_contentProtectionEnabled() {
197         when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
198         when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
199         mDevCfgEnableContentProtectionReceiver = true;
200         mContentCaptureManagerService = new TestContentCaptureManagerService();
201 
202         ContentCaptureOptions actual =
203                 mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
204                         USER_ID, PACKAGE_NAME);
205 
206         assertThat(actual).isNotNull();
207         assertThat(actual.enableReceiver).isFalse();
208         assertThat(actual.contentProtectionOptions).isNotNull();
209         assertThat(actual.contentProtectionOptions.enableReceiver).isTrue();
210         assertThat(actual.whitelistedComponents).isNull();
211     }
212 
213     @Test
getOptions_contentCaptureEnabled_contentProtectionDisabled()214     public void getOptions_contentCaptureEnabled_contentProtectionDisabled() {
215         mDevCfgEnableContentProtectionReceiver = true;
216         mContentCaptureManagerService = new TestContentCaptureManagerService();
217         mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
218                 USER_ID, ImmutableList.of(PACKAGE_NAME), /* components= */ null);
219 
220         ContentCaptureOptions actual =
221                 mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
222                         USER_ID, PACKAGE_NAME);
223 
224         assertThat(actual).isNotNull();
225         assertThat(actual.enableReceiver).isTrue();
226         assertThat(actual.contentProtectionOptions).isNotNull();
227         assertThat(actual.contentProtectionOptions.enableReceiver).isFalse();
228         assertThat(actual.whitelistedComponents).isNull();
229         verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID);
230         verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
231     }
232 
233     @Test
getOptions_contentCaptureEnabled_contentProtectionEnabled()234     public void getOptions_contentCaptureEnabled_contentProtectionEnabled() {
235         when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
236         when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
237         mDevCfgEnableContentProtectionReceiver = true;
238         mContentCaptureManagerService = new TestContentCaptureManagerService();
239         mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
240                 USER_ID, ImmutableList.of(PACKAGE_NAME), /* components= */ null);
241 
242         ContentCaptureOptions actual =
243                 mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
244                         USER_ID, PACKAGE_NAME);
245 
246         assertThat(actual).isNotNull();
247         assertThat(actual.enableReceiver).isTrue();
248         assertThat(actual.contentProtectionOptions).isNotNull();
249         assertThat(actual.contentProtectionOptions.enableReceiver).isTrue();
250         assertThat(actual.whitelistedComponents).isNull();
251     }
252 
253     @Test
isWhitelisted_packageName_contentCaptureDisabled_contentProtectionNotGranted()254     public void isWhitelisted_packageName_contentCaptureDisabled_contentProtectionNotGranted() {
255         mDevCfgEnableContentProtectionReceiver = true;
256         mContentCaptureManagerService = new TestContentCaptureManagerService();
257 
258         boolean actual =
259                 mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
260                         USER_ID, PACKAGE_NAME);
261 
262         assertThat(actual).isFalse();
263         verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID);
264         verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
265     }
266 
267     @Test
isWhitelisted_packageName_contentCaptureDisabled_contentProtectionDisabled()268     public void isWhitelisted_packageName_contentCaptureDisabled_contentProtectionDisabled() {
269         when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
270         mDevCfgEnableContentProtectionReceiver = true;
271         mContentCaptureManagerService = new TestContentCaptureManagerService();
272 
273         boolean actual =
274                 mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
275                         USER_ID, PACKAGE_NAME);
276 
277         assertThat(actual).isFalse();
278         verify(mMockContentProtectionBlocklistManager).isAllowed(PACKAGE_NAME);
279     }
280 
281     @Test
isWhitelisted_packageName_contentCaptureDisabled_contentProtectionEnabled()282     public void isWhitelisted_packageName_contentCaptureDisabled_contentProtectionEnabled() {
283         when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
284         when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
285         mDevCfgEnableContentProtectionReceiver = true;
286         mContentCaptureManagerService = new TestContentCaptureManagerService();
287 
288         boolean actual =
289                 mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
290                         USER_ID, PACKAGE_NAME);
291 
292         assertThat(actual).isTrue();
293     }
294 
295     @Test
isWhitelisted_packageName_contentCaptureEnabled_contentProtectionNotChecked()296     public void isWhitelisted_packageName_contentCaptureEnabled_contentProtectionNotChecked() {
297         mDevCfgEnableContentProtectionReceiver = true;
298         mContentCaptureManagerService = new TestContentCaptureManagerService();
299         mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
300                 USER_ID, ImmutableList.of(PACKAGE_NAME), /* components= */ null);
301 
302         boolean actual =
303                 mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
304                         USER_ID, PACKAGE_NAME);
305 
306         assertThat(actual).isTrue();
307         verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt());
308         verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
309     }
310 
311     @Test
isWhitelisted_componentName_contentCaptureDisabled_contentProtectionNotGranted()312     public void isWhitelisted_componentName_contentCaptureDisabled_contentProtectionNotGranted() {
313         mDevCfgEnableContentProtectionReceiver = true;
314         mContentCaptureManagerService = new TestContentCaptureManagerService();
315 
316         boolean actual =
317                 mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
318                         USER_ID, COMPONENT_NAME);
319 
320         assertThat(actual).isFalse();
321         verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID);
322         verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
323     }
324 
325     @Test
isWhitelisted_componentName_contentCaptureDisabled_contentProtectionDisabled()326     public void isWhitelisted_componentName_contentCaptureDisabled_contentProtectionDisabled() {
327         when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
328         mDevCfgEnableContentProtectionReceiver = true;
329         mContentCaptureManagerService = new TestContentCaptureManagerService();
330 
331         boolean actual =
332                 mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
333                         USER_ID, COMPONENT_NAME);
334 
335         assertThat(actual).isFalse();
336         verify(mMockContentProtectionBlocklistManager).isAllowed(PACKAGE_NAME);
337     }
338 
339     @Test
isWhitelisted_componentName_contentCaptureDisabled_contentProtectionEnabled()340     public void isWhitelisted_componentName_contentCaptureDisabled_contentProtectionEnabled() {
341         when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
342         when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
343         mDevCfgEnableContentProtectionReceiver = true;
344         mContentCaptureManagerService = new TestContentCaptureManagerService();
345 
346         boolean actual =
347                 mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
348                         USER_ID, COMPONENT_NAME);
349 
350         assertThat(actual).isTrue();
351     }
352 
353     @Test
isWhitelisted_componentName_contentCaptureEnabled_contentProtectionNotChecked()354     public void isWhitelisted_componentName_contentCaptureEnabled_contentProtectionNotChecked() {
355         mDevCfgEnableContentProtectionReceiver = true;
356         mContentCaptureManagerService = new TestContentCaptureManagerService();
357         mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
358                 USER_ID, /* packageNames= */ null, ImmutableList.of(COMPONENT_NAME));
359 
360         boolean actual =
361                 mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
362                         USER_ID, COMPONENT_NAME);
363 
364         assertThat(actual).isTrue();
365         verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt());
366         verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
367     }
368 
369     @Test
isContentProtectionReceiverEnabled_withoutManagers()370     public void isContentProtectionReceiverEnabled_withoutManagers() {
371         boolean actual =
372                 mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
373                         USER_ID, PACKAGE_NAME);
374 
375         assertThat(actual).isFalse();
376         verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt());
377         verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
378     }
379 
380     @Test
isContentProtectionReceiverEnabled_disabledWithFlag()381     public void isContentProtectionReceiverEnabled_disabledWithFlag() {
382         mDevCfgEnableContentProtectionReceiver = true;
383         mContentCaptureManagerService = new TestContentCaptureManagerService();
384         mContentCaptureManagerService.mDevCfgEnableContentProtectionReceiver = false;
385 
386         boolean actual =
387                 mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
388                         USER_ID, PACKAGE_NAME);
389 
390         assertThat(actual).isFalse();
391         verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt());
392         verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
393     }
394 
395     @Test
onLoginDetected_disabledAfterConstructor()396     public void onLoginDetected_disabledAfterConstructor() {
397         mDevCfgEnableContentProtectionReceiver = true;
398         mContentCaptureManagerService = new TestContentCaptureManagerService();
399         mContentCaptureManagerService.mDevCfgEnableContentProtectionReceiver = false;
400 
401         mContentCaptureManagerService
402                 .getContentCaptureManagerServiceStub()
403                 .onLoginDetected(PARCELED_EVENTS);
404 
405         assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
406         assertThat(mRemoteContentProtectionServicesCreated).isEqualTo(0);
407         verifyZeroInteractions(mMockRemoteContentProtectionService);
408     }
409 
410     @Test
onLoginDetected_invalidPermissions()411     public void onLoginDetected_invalidPermissions() {
412         mDevCfgEnableContentProtectionReceiver = true;
413         mContentProtectionServiceInfoConstructorShouldThrow = true;
414         mContentCaptureManagerService = new TestContentCaptureManagerService();
415 
416         mContentCaptureManagerService
417                 .getContentCaptureManagerServiceStub()
418                 .onLoginDetected(PARCELED_EVENTS);
419 
420         assertThat(mContentProtectionServiceInfosCreated).isEqualTo(1);
421         assertThat(mRemoteContentProtectionServicesCreated).isEqualTo(0);
422         verifyZeroInteractions(mMockRemoteContentProtectionService);
423     }
424 
425     @Test
onLoginDetected_enabled()426     public void onLoginDetected_enabled() {
427         mDevCfgEnableContentProtectionReceiver = true;
428         mContentCaptureManagerService = new TestContentCaptureManagerService();
429 
430         mContentCaptureManagerService
431                 .getContentCaptureManagerServiceStub()
432                 .onLoginDetected(PARCELED_EVENTS);
433 
434         assertThat(mContentProtectionServiceInfosCreated).isEqualTo(1);
435         assertThat(mRemoteContentProtectionServicesCreated).isEqualTo(1);
436         verify(mMockRemoteContentProtectionService).onLoginDetected(PARCELED_EVENTS);
437     }
438 
439     private class TestContentCaptureManagerService extends ContentCaptureManagerService {
440 
TestContentCaptureManagerService()441         TestContentCaptureManagerService() {
442             super(sContext);
443             this.mDevCfgEnableContentProtectionReceiver =
444                     ContentCaptureManagerServiceTest.this.mDevCfgEnableContentProtectionReceiver;
445         }
446 
447         @Override
getEnableContentProtectionReceiverLocked()448         protected boolean getEnableContentProtectionReceiverLocked() {
449             return ContentCaptureManagerServiceTest.this.mDevCfgEnableContentProtectionReceiver;
450         }
451 
452         @Override
createContentProtectionBlocklistManager()453         protected ContentProtectionBlocklistManager createContentProtectionBlocklistManager() {
454             mContentProtectionBlocklistManagersCreated++;
455             return mMockContentProtectionBlocklistManager;
456         }
457 
458         @Override
getContentProtectionServiceFlatComponentName()459         protected String getContentProtectionServiceFlatComponentName() {
460             return mConfigDefaultContentProtectionService;
461         }
462 
463         @Override
createContentProtectionServiceInfo( @onNull ComponentName componentName)464         protected ContentCaptureServiceInfo createContentProtectionServiceInfo(
465                 @NonNull ComponentName componentName) throws PackageManager.NameNotFoundException {
466             mContentProtectionServiceInfosCreated++;
467             if (mContentProtectionServiceInfoConstructorShouldThrow) {
468                 throw new RuntimeException("TEST RUNTIME EXCEPTION");
469             }
470             return mMockContentCaptureServiceInfo;
471         }
472 
473         @Override
createRemoteContentProtectionService( @onNull ComponentName componentName)474         protected RemoteContentProtectionService createRemoteContentProtectionService(
475                 @NonNull ComponentName componentName) {
476             mRemoteContentProtectionServicesCreated++;
477             return mMockRemoteContentProtectionService;
478         }
479 
480         @Override
createContentProtectionConsentManager()481         protected ContentProtectionConsentManager createContentProtectionConsentManager() {
482             mContentProtectionConsentManagersCreated++;
483             return mMockContentProtectionConsentManager;
484         }
485     }
486 }
487