Loading services/contentcapture/java/com/android/server/contentprotection/ContentProtectionBlocklistManager.java 0 → 100644 +111 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.contentprotection; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.pm.PackageInfo; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import java.io.BufferedReader; import java.io.FileReader; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * Manages whether the content protection is enabled for an app using a blocklist. * * @hide */ class ContentProtectionBlocklistManager { private static final String TAG = "ContentProtectionBlocklistManager"; private static final String PACKAGE_NAME_BLOCKLIST_FILENAME = "/product/etc/res/raw/content_protection/package_name_blocklist.txt"; @NonNull private final ContentProtectionPackageManager mContentProtectionPackageManager; @Nullable private Set<String> mPackageNameBlocklist; protected ContentProtectionBlocklistManager( @NonNull ContentProtectionPackageManager contentProtectionPackageManager) { mContentProtectionPackageManager = contentProtectionPackageManager; } public boolean isAllowed(@NonNull String packageName) { if (mPackageNameBlocklist == null) { // List not loaded or failed to load, don't run on anything return false; } if (mPackageNameBlocklist.contains(packageName)) { return false; } PackageInfo packageInfo = mContentProtectionPackageManager.getPackageInfo(packageName); if (packageInfo == null) { return false; } if (!mContentProtectionPackageManager.hasRequestedInternetPermissions(packageInfo)) { return false; } if (mContentProtectionPackageManager.isSystemApp(packageInfo)) { return false; } if (mContentProtectionPackageManager.isUpdatedSystemApp(packageInfo)) { return false; } return true; } public void updateBlocklist(int blocklistSize) { Slog.i(TAG, "Blocklist size updating to: " + blocklistSize); mPackageNameBlocklist = readPackageNameBlocklist(blocklistSize); } @Nullable private Set<String> readPackageNameBlocklist(int blocklistSize) { if (blocklistSize <= 0) { // Explicitly requested an empty blocklist return Collections.emptySet(); } List<String> lines = readLinesFromRawFile(PACKAGE_NAME_BLOCKLIST_FILENAME); if (lines == null) { return null; } return lines.stream().limit(blocklistSize).collect(Collectors.toSet()); } @VisibleForTesting @Nullable protected List<String> readLinesFromRawFile(@NonNull String filename) { try (FileReader fileReader = new FileReader(filename); BufferedReader bufferedReader = new BufferedReader(fileReader)) { return bufferedReader .lines() .map(line -> line.trim()) .filter(line -> !line.isBlank()) .collect(Collectors.toList()); } catch (Exception ex) { Slog.e(TAG, "Failed to read: " + filename, ex); return null; } } } services/contentcapture/java/com/android/server/contentprotection/ContentProtectionPackageManager.java +4 −3 Original line number Diff line number Diff line Loading @@ -34,8 +34,9 @@ import java.util.Arrays; * * @hide */ final class ContentProtectionPackageManager { private static final String TAG = ContentProtectionPackageManager.class.getSimpleName(); public class ContentProtectionPackageManager { private static final String TAG = "ContentProtectionPackageManager"; private static final PackageInfoFlags PACKAGE_INFO_FLAGS = PackageInfoFlags.of(PackageManager.GET_PERMISSIONS); Loading @@ -51,7 +52,7 @@ final class ContentProtectionPackageManager { try { return mPackageManager.getPackageInfo(packageName, PACKAGE_INFO_FLAGS); } catch (NameNotFoundException ex) { Slog.w(TAG, "Package info not found: ", ex); Slog.w(TAG, "Package info not found for: " + packageName, ex); return null; } } Loading services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionBlocklistManagerTest.java 0 → 100644 +236 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.contentprotection; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.content.pm.PackageInfo; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; 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; import java.util.ArrayList; import java.util.List; /** * Test for {@link ContentProtectionBlocklistManager}. * * <p>Run with: {@code atest * FrameworksServicesTests: * com.android.server.contentprotection.ContentProtectionBlocklistManagerTest} */ @RunWith(AndroidJUnit4.class) @SmallTest public class ContentProtectionBlocklistManagerTest { private static final String FIRST_PACKAGE_NAME = "com.test.first.package.name"; private static final String SECOND_PACKAGE_NAME = "com.test.second.package.name"; private static final String UNLISTED_PACKAGE_NAME = "com.test.unlisted.package.name"; private static final String PACKAGE_NAME_BLOCKLIST_FILENAME = "/product/etc/res/raw/content_protection/package_name_blocklist.txt"; private static final PackageInfo PACKAGE_INFO = new PackageInfo(); private static final List<String> LINES = ImmutableList.of(FIRST_PACKAGE_NAME, SECOND_PACKAGE_NAME); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Mock private ContentProtectionPackageManager mMockContentProtectionPackageManager; private final List<String> mReadRawFiles = new ArrayList<>(); private ContentProtectionBlocklistManager mContentProtectionBlocklistManager; @Before public void setup() { mContentProtectionBlocklistManager = new TestContentProtectionBlocklistManager(); } @Test public void isAllowed_blocklistNotLoaded() { boolean actual = mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); assertThat(actual).isFalse(); assertThat(mReadRawFiles).isEmpty(); verifyZeroInteractions(mMockContentProtectionPackageManager); } @Test public void isAllowed_inBlocklist() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); boolean actual = mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); assertThat(actual).isFalse(); verifyZeroInteractions(mMockContentProtectionPackageManager); } @Test public void isAllowed_packageInfoNotFound() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME)) .thenReturn(null); boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME); assertThat(actual).isFalse(); verify(mMockContentProtectionPackageManager, never()) .hasRequestedInternetPermissions(any()); verify(mMockContentProtectionPackageManager, never()).isSystemApp(any()); verify(mMockContentProtectionPackageManager, never()).isUpdatedSystemApp(any()); } @Test public void isAllowed_notRequestedInternet() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME)) .thenReturn(PACKAGE_INFO); when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO)) .thenReturn(false); boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME); assertThat(actual).isFalse(); verify(mMockContentProtectionPackageManager, never()).isSystemApp(any()); verify(mMockContentProtectionPackageManager, never()).isUpdatedSystemApp(any()); } @Test public void isAllowed_systemApp() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME)) .thenReturn(PACKAGE_INFO); when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO)) .thenReturn(true); when(mMockContentProtectionPackageManager.isSystemApp(PACKAGE_INFO)).thenReturn(true); boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME); assertThat(actual).isFalse(); verify(mMockContentProtectionPackageManager, never()).isUpdatedSystemApp(any()); } @Test public void isAllowed_updatedSystemApp() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME)) .thenReturn(PACKAGE_INFO); when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO)) .thenReturn(true); when(mMockContentProtectionPackageManager.isSystemApp(PACKAGE_INFO)).thenReturn(true); when(mMockContentProtectionPackageManager.isUpdatedSystemApp(PACKAGE_INFO)) .thenReturn(true); boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME); assertThat(actual).isFalse(); } @Test public void isAllowed_allowed() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME)) .thenReturn(PACKAGE_INFO); when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO)) .thenReturn(true); when(mMockContentProtectionPackageManager.isSystemApp(PACKAGE_INFO)).thenReturn(false); when(mMockContentProtectionPackageManager.isUpdatedSystemApp(PACKAGE_INFO)) .thenReturn(false); boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME); assertThat(actual).isTrue(); } @Test public void updateBlocklist_negativeSize() { mContentProtectionBlocklistManager.updateBlocklist(/* blocklistSize= */ -1); assertThat(mReadRawFiles).isEmpty(); mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); verify(mMockContentProtectionPackageManager).getPackageInfo(FIRST_PACKAGE_NAME); } @Test public void updateBlocklist_zeroSize() { mContentProtectionBlocklistManager.updateBlocklist(/* blocklistSize= */ 0); assertThat(mReadRawFiles).isEmpty(); mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); verify(mMockContentProtectionPackageManager).getPackageInfo(FIRST_PACKAGE_NAME); } @Test public void updateBlocklist_positiveSize_belowTotal() { mContentProtectionBlocklistManager.updateBlocklist(/* blocklistSize= */ 1); assertThat(mReadRawFiles).containsExactly(PACKAGE_NAME_BLOCKLIST_FILENAME); mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); mContentProtectionBlocklistManager.isAllowed(SECOND_PACKAGE_NAME); verify(mMockContentProtectionPackageManager, never()).getPackageInfo(FIRST_PACKAGE_NAME); verify(mMockContentProtectionPackageManager).getPackageInfo(SECOND_PACKAGE_NAME); } @Test public void updateBlocklist_positiveSize_aboveTotal() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size() + 1); assertThat(mReadRawFiles).containsExactly(PACKAGE_NAME_BLOCKLIST_FILENAME); mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); mContentProtectionBlocklistManager.isAllowed(SECOND_PACKAGE_NAME); verify(mMockContentProtectionPackageManager, never()).getPackageInfo(FIRST_PACKAGE_NAME); verify(mMockContentProtectionPackageManager, never()).getPackageInfo(SECOND_PACKAGE_NAME); } private final class TestContentProtectionBlocklistManager extends ContentProtectionBlocklistManager { TestContentProtectionBlocklistManager() { super(mMockContentProtectionPackageManager); } @Override protected List<String> readLinesFromRawFile(@NonNull String filename) { mReadRawFiles.add(filename); return LINES; } } } Loading
services/contentcapture/java/com/android/server/contentprotection/ContentProtectionBlocklistManager.java 0 → 100644 +111 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.contentprotection; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.pm.PackageInfo; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import java.io.BufferedReader; import java.io.FileReader; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * Manages whether the content protection is enabled for an app using a blocklist. * * @hide */ class ContentProtectionBlocklistManager { private static final String TAG = "ContentProtectionBlocklistManager"; private static final String PACKAGE_NAME_BLOCKLIST_FILENAME = "/product/etc/res/raw/content_protection/package_name_blocklist.txt"; @NonNull private final ContentProtectionPackageManager mContentProtectionPackageManager; @Nullable private Set<String> mPackageNameBlocklist; protected ContentProtectionBlocklistManager( @NonNull ContentProtectionPackageManager contentProtectionPackageManager) { mContentProtectionPackageManager = contentProtectionPackageManager; } public boolean isAllowed(@NonNull String packageName) { if (mPackageNameBlocklist == null) { // List not loaded or failed to load, don't run on anything return false; } if (mPackageNameBlocklist.contains(packageName)) { return false; } PackageInfo packageInfo = mContentProtectionPackageManager.getPackageInfo(packageName); if (packageInfo == null) { return false; } if (!mContentProtectionPackageManager.hasRequestedInternetPermissions(packageInfo)) { return false; } if (mContentProtectionPackageManager.isSystemApp(packageInfo)) { return false; } if (mContentProtectionPackageManager.isUpdatedSystemApp(packageInfo)) { return false; } return true; } public void updateBlocklist(int blocklistSize) { Slog.i(TAG, "Blocklist size updating to: " + blocklistSize); mPackageNameBlocklist = readPackageNameBlocklist(blocklistSize); } @Nullable private Set<String> readPackageNameBlocklist(int blocklistSize) { if (blocklistSize <= 0) { // Explicitly requested an empty blocklist return Collections.emptySet(); } List<String> lines = readLinesFromRawFile(PACKAGE_NAME_BLOCKLIST_FILENAME); if (lines == null) { return null; } return lines.stream().limit(blocklistSize).collect(Collectors.toSet()); } @VisibleForTesting @Nullable protected List<String> readLinesFromRawFile(@NonNull String filename) { try (FileReader fileReader = new FileReader(filename); BufferedReader bufferedReader = new BufferedReader(fileReader)) { return bufferedReader .lines() .map(line -> line.trim()) .filter(line -> !line.isBlank()) .collect(Collectors.toList()); } catch (Exception ex) { Slog.e(TAG, "Failed to read: " + filename, ex); return null; } } }
services/contentcapture/java/com/android/server/contentprotection/ContentProtectionPackageManager.java +4 −3 Original line number Diff line number Diff line Loading @@ -34,8 +34,9 @@ import java.util.Arrays; * * @hide */ final class ContentProtectionPackageManager { private static final String TAG = ContentProtectionPackageManager.class.getSimpleName(); public class ContentProtectionPackageManager { private static final String TAG = "ContentProtectionPackageManager"; private static final PackageInfoFlags PACKAGE_INFO_FLAGS = PackageInfoFlags.of(PackageManager.GET_PERMISSIONS); Loading @@ -51,7 +52,7 @@ final class ContentProtectionPackageManager { try { return mPackageManager.getPackageInfo(packageName, PACKAGE_INFO_FLAGS); } catch (NameNotFoundException ex) { Slog.w(TAG, "Package info not found: ", ex); Slog.w(TAG, "Package info not found for: " + packageName, ex); return null; } } Loading
services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionBlocklistManagerTest.java 0 → 100644 +236 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.contentprotection; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.content.pm.PackageInfo; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; 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; import java.util.ArrayList; import java.util.List; /** * Test for {@link ContentProtectionBlocklistManager}. * * <p>Run with: {@code atest * FrameworksServicesTests: * com.android.server.contentprotection.ContentProtectionBlocklistManagerTest} */ @RunWith(AndroidJUnit4.class) @SmallTest public class ContentProtectionBlocklistManagerTest { private static final String FIRST_PACKAGE_NAME = "com.test.first.package.name"; private static final String SECOND_PACKAGE_NAME = "com.test.second.package.name"; private static final String UNLISTED_PACKAGE_NAME = "com.test.unlisted.package.name"; private static final String PACKAGE_NAME_BLOCKLIST_FILENAME = "/product/etc/res/raw/content_protection/package_name_blocklist.txt"; private static final PackageInfo PACKAGE_INFO = new PackageInfo(); private static final List<String> LINES = ImmutableList.of(FIRST_PACKAGE_NAME, SECOND_PACKAGE_NAME); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Mock private ContentProtectionPackageManager mMockContentProtectionPackageManager; private final List<String> mReadRawFiles = new ArrayList<>(); private ContentProtectionBlocklistManager mContentProtectionBlocklistManager; @Before public void setup() { mContentProtectionBlocklistManager = new TestContentProtectionBlocklistManager(); } @Test public void isAllowed_blocklistNotLoaded() { boolean actual = mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); assertThat(actual).isFalse(); assertThat(mReadRawFiles).isEmpty(); verifyZeroInteractions(mMockContentProtectionPackageManager); } @Test public void isAllowed_inBlocklist() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); boolean actual = mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); assertThat(actual).isFalse(); verifyZeroInteractions(mMockContentProtectionPackageManager); } @Test public void isAllowed_packageInfoNotFound() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME)) .thenReturn(null); boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME); assertThat(actual).isFalse(); verify(mMockContentProtectionPackageManager, never()) .hasRequestedInternetPermissions(any()); verify(mMockContentProtectionPackageManager, never()).isSystemApp(any()); verify(mMockContentProtectionPackageManager, never()).isUpdatedSystemApp(any()); } @Test public void isAllowed_notRequestedInternet() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME)) .thenReturn(PACKAGE_INFO); when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO)) .thenReturn(false); boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME); assertThat(actual).isFalse(); verify(mMockContentProtectionPackageManager, never()).isSystemApp(any()); verify(mMockContentProtectionPackageManager, never()).isUpdatedSystemApp(any()); } @Test public void isAllowed_systemApp() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME)) .thenReturn(PACKAGE_INFO); when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO)) .thenReturn(true); when(mMockContentProtectionPackageManager.isSystemApp(PACKAGE_INFO)).thenReturn(true); boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME); assertThat(actual).isFalse(); verify(mMockContentProtectionPackageManager, never()).isUpdatedSystemApp(any()); } @Test public void isAllowed_updatedSystemApp() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME)) .thenReturn(PACKAGE_INFO); when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO)) .thenReturn(true); when(mMockContentProtectionPackageManager.isSystemApp(PACKAGE_INFO)).thenReturn(true); when(mMockContentProtectionPackageManager.isUpdatedSystemApp(PACKAGE_INFO)) .thenReturn(true); boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME); assertThat(actual).isFalse(); } @Test public void isAllowed_allowed() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size()); when(mMockContentProtectionPackageManager.getPackageInfo(UNLISTED_PACKAGE_NAME)) .thenReturn(PACKAGE_INFO); when(mMockContentProtectionPackageManager.hasRequestedInternetPermissions(PACKAGE_INFO)) .thenReturn(true); when(mMockContentProtectionPackageManager.isSystemApp(PACKAGE_INFO)).thenReturn(false); when(mMockContentProtectionPackageManager.isUpdatedSystemApp(PACKAGE_INFO)) .thenReturn(false); boolean actual = mContentProtectionBlocklistManager.isAllowed(UNLISTED_PACKAGE_NAME); assertThat(actual).isTrue(); } @Test public void updateBlocklist_negativeSize() { mContentProtectionBlocklistManager.updateBlocklist(/* blocklistSize= */ -1); assertThat(mReadRawFiles).isEmpty(); mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); verify(mMockContentProtectionPackageManager).getPackageInfo(FIRST_PACKAGE_NAME); } @Test public void updateBlocklist_zeroSize() { mContentProtectionBlocklistManager.updateBlocklist(/* blocklistSize= */ 0); assertThat(mReadRawFiles).isEmpty(); mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); verify(mMockContentProtectionPackageManager).getPackageInfo(FIRST_PACKAGE_NAME); } @Test public void updateBlocklist_positiveSize_belowTotal() { mContentProtectionBlocklistManager.updateBlocklist(/* blocklistSize= */ 1); assertThat(mReadRawFiles).containsExactly(PACKAGE_NAME_BLOCKLIST_FILENAME); mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); mContentProtectionBlocklistManager.isAllowed(SECOND_PACKAGE_NAME); verify(mMockContentProtectionPackageManager, never()).getPackageInfo(FIRST_PACKAGE_NAME); verify(mMockContentProtectionPackageManager).getPackageInfo(SECOND_PACKAGE_NAME); } @Test public void updateBlocklist_positiveSize_aboveTotal() { mContentProtectionBlocklistManager.updateBlocklist(LINES.size() + 1); assertThat(mReadRawFiles).containsExactly(PACKAGE_NAME_BLOCKLIST_FILENAME); mContentProtectionBlocklistManager.isAllowed(FIRST_PACKAGE_NAME); mContentProtectionBlocklistManager.isAllowed(SECOND_PACKAGE_NAME); verify(mMockContentProtectionPackageManager, never()).getPackageInfo(FIRST_PACKAGE_NAME); verify(mMockContentProtectionPackageManager, never()).getPackageInfo(SECOND_PACKAGE_NAME); } private final class TestContentProtectionBlocklistManager extends ContentProtectionBlocklistManager { TestContentProtectionBlocklistManager() { super(mMockContentProtectionPackageManager); } @Override protected List<String> readLinesFromRawFile(@NonNull String filename) { mReadRawFiles.add(filename); return LINES; } } }