/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.contentcapture;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.service.contentcapture.ContentCaptureServiceInfo;
import android.view.contentcapture.ContentCaptureEvent;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.server.LocalServices;
import com.android.server.contentprotection.ContentProtectionBlocklistManager;
import com.android.server.contentprotection.ContentProtectionConsentManager;
import com.android.server.contentprotection.RemoteContentProtectionService;
import com.android.server.pm.UserManagerInternal;
import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
/**
* Test for {@link ContentCaptureManagerService}.
*
*
Run with: {@code atest
* FrameworksServicesTests:com.android.server.contentcapture.ContentCaptureManagerServiceTest}
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
@SuppressWarnings("GuardedBy") // Service not really running, no need to expose locks
public class ContentCaptureManagerServiceTest {
private static final int USER_ID = 1234;
private static final String PACKAGE_NAME = "com.test.package";
private static final ComponentName COMPONENT_NAME =
new ComponentName(PACKAGE_NAME, "TestClass");
private static final ContentCaptureEvent EVENT =
new ContentCaptureEvent(/* sessionId= */ 100, /* type= */ 200);
private static final ParceledListSlice PARCELED_EVENTS =
new ParceledListSlice<>(ImmutableList.of(EVENT));
private static final Context sContext = ApplicationProvider.getApplicationContext();
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock private UserManagerInternal mMockUserManagerInternal;
@Mock private ContentProtectionBlocklistManager mMockContentProtectionBlocklistManager;
@Mock private ContentCaptureServiceInfo mMockContentCaptureServiceInfo;
@Mock private RemoteContentProtectionService mMockRemoteContentProtectionService;
@Mock private ContentProtectionConsentManager mMockContentProtectionConsentManager;
private boolean mDevCfgEnableContentProtectionReceiver;
private int mContentProtectionBlocklistManagersCreated;
private int mContentProtectionServiceInfosCreated;
private int mRemoteContentProtectionServicesCreated;
private int mContentProtectionConsentManagersCreated;
private String mConfigDefaultContentProtectionService = COMPONENT_NAME.flattenToString();
private boolean mContentProtectionServiceInfoConstructorShouldThrow;
private ContentCaptureManagerService mContentCaptureManagerService;
@Before
public void setup() {
when(mMockUserManagerInternal.getUserInfos()).thenReturn(new UserInfo[0]);
LocalServices.removeServiceForTest(UserManagerInternal.class);
LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
mContentCaptureManagerService = new TestContentCaptureManagerService();
}
@Test
public void constructor_contentProtection_flagDisabled_noManagers() {
assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0);
assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
assertThat(mContentProtectionConsentManagersCreated).isEqualTo(0);
verifyZeroInteractions(mMockContentProtectionBlocklistManager);
verifyZeroInteractions(mMockContentProtectionConsentManager);
}
@Test
public void constructor_contentProtection_componentNameNull_noManagers() {
mConfigDefaultContentProtectionService = null;
mContentCaptureManagerService = new TestContentCaptureManagerService();
assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0);
assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
assertThat(mContentProtectionConsentManagersCreated).isEqualTo(0);
verifyZeroInteractions(mMockContentProtectionBlocklistManager);
verifyZeroInteractions(mMockContentProtectionConsentManager);
}
@Test
public void constructor_contentProtection_componentNameBlank_noManagers() {
mConfigDefaultContentProtectionService = " ";
mContentCaptureManagerService = new TestContentCaptureManagerService();
assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0);
assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
assertThat(mContentProtectionConsentManagersCreated).isEqualTo(0);
verifyZeroInteractions(mMockContentProtectionBlocklistManager);
verifyZeroInteractions(mMockContentProtectionConsentManager);
}
@Test
public void constructor_contentProtection_enabled_createsManagers() {
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(1);
assertThat(mContentProtectionConsentManagersCreated).isEqualTo(1);
assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
verify(mMockContentProtectionBlocklistManager).updateBlocklist(anyInt());
verifyZeroInteractions(mMockContentProtectionConsentManager);
}
@Test
public void setFineTuneParamsFromDeviceConfig_doesNotUpdateContentProtectionBlocklist() {
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
mContentCaptureManagerService.mDevCfgContentProtectionAppsBlocklistSize += 100;
verify(mMockContentProtectionBlocklistManager).updateBlocklist(anyInt());
mContentCaptureManagerService.setFineTuneParamsFromDeviceConfig();
verifyNoMoreInteractions(mMockContentProtectionBlocklistManager);
}
@Test
public void getOptions_contentCaptureDisabled_contentProtectionDisabled() {
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
ContentCaptureOptions actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
USER_ID, PACKAGE_NAME);
assertThat(actual).isNull();
verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID);
verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
}
@Test
public void getOptions_contentCaptureDisabled_contentProtectionEnabled() {
when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
ContentCaptureOptions actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
USER_ID, PACKAGE_NAME);
assertThat(actual).isNotNull();
assertThat(actual.enableReceiver).isFalse();
assertThat(actual.contentProtectionOptions).isNotNull();
assertThat(actual.contentProtectionOptions.enableReceiver).isTrue();
assertThat(actual.whitelistedComponents).isNull();
}
@Test
public void getOptions_contentCaptureEnabled_contentProtectionDisabled() {
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
USER_ID, ImmutableList.of(PACKAGE_NAME), /* components= */ null);
ContentCaptureOptions actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
USER_ID, PACKAGE_NAME);
assertThat(actual).isNotNull();
assertThat(actual.enableReceiver).isTrue();
assertThat(actual.contentProtectionOptions).isNotNull();
assertThat(actual.contentProtectionOptions.enableReceiver).isFalse();
assertThat(actual.whitelistedComponents).isNull();
verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID);
verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
}
@Test
public void getOptions_contentCaptureEnabled_contentProtectionEnabled() {
when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
USER_ID, ImmutableList.of(PACKAGE_NAME), /* components= */ null);
ContentCaptureOptions actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.getOptions(
USER_ID, PACKAGE_NAME);
assertThat(actual).isNotNull();
assertThat(actual.enableReceiver).isTrue();
assertThat(actual.contentProtectionOptions).isNotNull();
assertThat(actual.contentProtectionOptions.enableReceiver).isTrue();
assertThat(actual.whitelistedComponents).isNull();
}
@Test
public void isWhitelisted_packageName_contentCaptureDisabled_contentProtectionNotGranted() {
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
boolean actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
USER_ID, PACKAGE_NAME);
assertThat(actual).isFalse();
verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID);
verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
}
@Test
public void isWhitelisted_packageName_contentCaptureDisabled_contentProtectionDisabled() {
when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
boolean actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
USER_ID, PACKAGE_NAME);
assertThat(actual).isFalse();
verify(mMockContentProtectionBlocklistManager).isAllowed(PACKAGE_NAME);
}
@Test
public void isWhitelisted_packageName_contentCaptureDisabled_contentProtectionEnabled() {
when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
boolean actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
USER_ID, PACKAGE_NAME);
assertThat(actual).isTrue();
}
@Test
public void isWhitelisted_packageName_contentCaptureEnabled_contentProtectionNotChecked() {
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
USER_ID, ImmutableList.of(PACKAGE_NAME), /* components= */ null);
boolean actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
USER_ID, PACKAGE_NAME);
assertThat(actual).isTrue();
verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt());
verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
}
@Test
public void isWhitelisted_componentName_contentCaptureDisabled_contentProtectionNotGranted() {
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
boolean actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
USER_ID, COMPONENT_NAME);
assertThat(actual).isFalse();
verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID);
verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
}
@Test
public void isWhitelisted_componentName_contentCaptureDisabled_contentProtectionDisabled() {
when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
boolean actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
USER_ID, COMPONENT_NAME);
assertThat(actual).isFalse();
verify(mMockContentProtectionBlocklistManager).isAllowed(PACKAGE_NAME);
}
@Test
public void isWhitelisted_componentName_contentCaptureDisabled_contentProtectionEnabled() {
when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true);
when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true);
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
boolean actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
USER_ID, COMPONENT_NAME);
assertThat(actual).isTrue();
}
@Test
public void isWhitelisted_componentName_contentCaptureEnabled_contentProtectionNotChecked() {
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist(
USER_ID, /* packageNames= */ null, ImmutableList.of(COMPONENT_NAME));
boolean actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
USER_ID, COMPONENT_NAME);
assertThat(actual).isTrue();
verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt());
verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
}
@Test
public void isContentProtectionReceiverEnabled_withoutManagers() {
boolean actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
USER_ID, PACKAGE_NAME);
assertThat(actual).isFalse();
verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt());
verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
}
@Test
public void isContentProtectionReceiverEnabled_disabledWithFlag() {
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
mContentCaptureManagerService.mDevCfgEnableContentProtectionReceiver = false;
boolean actual =
mContentCaptureManagerService.mGlobalContentCaptureOptions.isWhitelisted(
USER_ID, PACKAGE_NAME);
assertThat(actual).isFalse();
verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt());
verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString());
}
@Test
public void onLoginDetected_disabledAfterConstructor() {
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
mContentCaptureManagerService.mDevCfgEnableContentProtectionReceiver = false;
mContentCaptureManagerService
.getContentCaptureManagerServiceStub()
.onLoginDetected(PARCELED_EVENTS);
assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0);
assertThat(mRemoteContentProtectionServicesCreated).isEqualTo(0);
verifyZeroInteractions(mMockRemoteContentProtectionService);
}
@Test
public void onLoginDetected_invalidPermissions() {
mDevCfgEnableContentProtectionReceiver = true;
mContentProtectionServiceInfoConstructorShouldThrow = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
mContentCaptureManagerService
.getContentCaptureManagerServiceStub()
.onLoginDetected(PARCELED_EVENTS);
assertThat(mContentProtectionServiceInfosCreated).isEqualTo(1);
assertThat(mRemoteContentProtectionServicesCreated).isEqualTo(0);
verifyZeroInteractions(mMockRemoteContentProtectionService);
}
@Test
public void onLoginDetected_enabled() {
mDevCfgEnableContentProtectionReceiver = true;
mContentCaptureManagerService = new TestContentCaptureManagerService();
mContentCaptureManagerService
.getContentCaptureManagerServiceStub()
.onLoginDetected(PARCELED_EVENTS);
assertThat(mContentProtectionServiceInfosCreated).isEqualTo(1);
assertThat(mRemoteContentProtectionServicesCreated).isEqualTo(1);
verify(mMockRemoteContentProtectionService).onLoginDetected(PARCELED_EVENTS);
}
private class TestContentCaptureManagerService extends ContentCaptureManagerService {
TestContentCaptureManagerService() {
super(sContext);
this.mDevCfgEnableContentProtectionReceiver =
ContentCaptureManagerServiceTest.this.mDevCfgEnableContentProtectionReceiver;
}
@Override
protected boolean getEnableContentProtectionReceiverLocked() {
return ContentCaptureManagerServiceTest.this.mDevCfgEnableContentProtectionReceiver;
}
@Override
protected ContentProtectionBlocklistManager createContentProtectionBlocklistManager() {
mContentProtectionBlocklistManagersCreated++;
return mMockContentProtectionBlocklistManager;
}
@Override
protected String getContentProtectionServiceFlatComponentName() {
return mConfigDefaultContentProtectionService;
}
@Override
protected ContentCaptureServiceInfo createContentProtectionServiceInfo(
@NonNull ComponentName componentName) throws PackageManager.NameNotFoundException {
mContentProtectionServiceInfosCreated++;
if (mContentProtectionServiceInfoConstructorShouldThrow) {
throw new RuntimeException("TEST RUNTIME EXCEPTION");
}
return mMockContentCaptureServiceInfo;
}
@Override
protected RemoteContentProtectionService createRemoteContentProtectionService(
@NonNull ComponentName componentName) {
mRemoteContentProtectionServicesCreated++;
return mMockRemoteContentProtectionService;
}
@Override
protected ContentProtectionConsentManager createContentProtectionConsentManager() {
mContentProtectionConsentManagersCreated++;
return mMockContentProtectionConsentManager;
}
}
}