diff options
9 files changed, 135 insertions, 721 deletions
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java index 42b3e38b544f..57011e879454 100644 --- a/core/java/android/view/contentcapture/ContentCaptureManager.java +++ b/core/java/android/view/contentcapture/ContentCaptureManager.java @@ -364,14 +364,6 @@ public final class ContentCaptureManager { "enable_content_protection_receiver"; /** - * Sets the size of the app blocklist for the content protection flow. - * - * @hide - */ - public static final String DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE = - "content_protection_apps_blocklist_size"; - - /** * Sets the size of the in-memory ring buffer for the content protection flow. * * @hide @@ -440,8 +432,6 @@ public final class ContentCaptureManager { /** @hide */ public static final boolean DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER = false; /** @hide */ - public static final int DEFAULT_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE = 5000; - /** @hide */ public static final int DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE = 150; /** @hide */ public static final List<List<String>> DEFAULT_CONTENT_PROTECTION_REQUIRED_GROUPS = diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java index 65975e44ee2a..76ebdf4d4c1c 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java @@ -103,9 +103,8 @@ import com.android.internal.os.BackgroundThread; import com.android.internal.os.IResultReceiver; import com.android.internal.util.DumpUtils; import com.android.server.LocalServices; -import com.android.server.contentprotection.ContentProtectionBlocklistManager; +import com.android.server.contentprotection.ContentProtectionAllowlistManager; import com.android.server.contentprotection.ContentProtectionConsentManager; -import com.android.server.contentprotection.ContentProtectionPackageManager; import com.android.server.contentprotection.RemoteContentProtectionService; import com.android.server.infra.AbstractMasterSystemService; import com.android.server.infra.FrameworkResourcesServiceNameResolver; @@ -207,9 +206,6 @@ public class ContentCaptureManagerService extends boolean mDevCfgEnableContentProtectionReceiver; @GuardedBy("mLock") - int mDevCfgContentProtectionAppsBlocklistSize; - - @GuardedBy("mLock") int mDevCfgContentProtectionBufferSize; @GuardedBy("mLock") @@ -237,7 +233,7 @@ public class ContentCaptureManagerService extends @Nullable private final ComponentName mContentProtectionServiceComponentName; - @Nullable private final ContentProtectionBlocklistManager mContentProtectionBlocklistManager; + @Nullable private final ContentProtectionAllowlistManager mContentProtectionAllowlistManager; @Nullable private final ContentProtectionConsentManager mContentProtectionConsentManager; @@ -287,17 +283,15 @@ public class ContentCaptureManagerService extends if (getEnableContentProtectionReceiverLocked()) { mContentProtectionServiceComponentName = getContentProtectionServiceComponentName(); if (mContentProtectionServiceComponentName != null) { - mContentProtectionBlocklistManager = createContentProtectionBlocklistManager(); - mContentProtectionBlocklistManager.updateBlocklist( - mDevCfgContentProtectionAppsBlocklistSize); + mContentProtectionAllowlistManager = createContentProtectionAllowlistManager(); mContentProtectionConsentManager = createContentProtectionConsentManager(); } else { - mContentProtectionBlocklistManager = null; + mContentProtectionAllowlistManager = null; mContentProtectionConsentManager = null; } } else { mContentProtectionServiceComponentName = null; - mContentProtectionBlocklistManager = null; + mContentProtectionAllowlistManager = null; mContentProtectionConsentManager = null; } } @@ -445,8 +439,6 @@ public class ContentCaptureManagerService extends case ContentCaptureManager .DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER: case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE: - case ContentCaptureManager - .DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE: case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_REQUIRED_GROUPS_CONFIG: case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_CONFIG: case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_THRESHOLD: @@ -502,14 +494,6 @@ public class ContentCaptureManagerService extends ContentCaptureManager .DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER, ContentCaptureManager.DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER); - mDevCfgContentProtectionAppsBlocklistSize = - DeviceConfig.getInt( - DeviceConfig.NAMESPACE_CONTENT_CAPTURE, - ContentCaptureManager - .DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE, - ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE); - // mContentProtectionBlocklistManager.updateBlocklist not called on purpose here to keep - // it immutable at this point mDevCfgContentProtectionBufferSize = DeviceConfig.getInt( DeviceConfig.NAMESPACE_CONTENT_CAPTURE, @@ -542,7 +526,7 @@ public class ContentCaptureManagerService extends + mDevCfgMaxBufferSize + ", idleFlush=" + mDevCfgIdleFlushingFrequencyMs - + ", textFluxh=" + + ", textFlush=" + mDevCfgTextChangeFlushingFrequencyMs + ", logHistory=" + mDevCfgLogHistorySize @@ -552,8 +536,6 @@ public class ContentCaptureManagerService extends + mDevCfgDisableFlushForViewTreeAppearing + ", enableContentProtectionReceiver=" + mDevCfgEnableContentProtectionReceiver - + ", contentProtectionAppsBlocklistSize=" - + mDevCfgContentProtectionAppsBlocklistSize + ", contentProtectionBufferSize=" + mDevCfgContentProtectionBufferSize + ", contentProtectionRequiredGroupsConfig=" @@ -844,9 +826,6 @@ public class ContentCaptureManagerService extends pw.print("enableContentProtectionReceiver: "); pw.println(mDevCfgEnableContentProtectionReceiver); pw.print(prefix2); - pw.print("contentProtectionAppsBlocklistSize: "); - pw.println(mDevCfgContentProtectionAppsBlocklistSize); - pw.print(prefix2); pw.print("contentProtectionBufferSize: "); pw.println(mDevCfgContentProtectionBufferSize); pw.print(prefix2); @@ -877,9 +856,8 @@ public class ContentCaptureManagerService extends /** @hide */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) @NonNull - protected ContentProtectionBlocklistManager createContentProtectionBlocklistManager() { - return new ContentProtectionBlocklistManager( - new ContentProtectionPackageManager(getContext())); + protected ContentProtectionAllowlistManager createContentProtectionAllowlistManager() { + return new ContentProtectionAllowlistManager(); } /** @hide */ @@ -1429,7 +1407,7 @@ public class ContentCaptureManagerService extends private boolean isContentProtectionReceiverEnabled( @UserIdInt int userId, @NonNull String packageName) { if (mContentProtectionServiceComponentName == null - || mContentProtectionBlocklistManager == null + || mContentProtectionAllowlistManager == null || mContentProtectionConsentManager == null) { return false; } @@ -1443,7 +1421,7 @@ public class ContentCaptureManagerService extends } } return mContentProtectionConsentManager.isConsentGranted(userId) - && mContentProtectionBlocklistManager.isAllowed(packageName); + && mContentProtectionAllowlistManager.isAllowed(packageName); } } diff --git a/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionAllowlistManager.java b/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionAllowlistManager.java new file mode 100644 index 000000000000..59af5263fa9e --- /dev/null +++ b/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionAllowlistManager.java @@ -0,0 +1,38 @@ +/* + * 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.util.Slog; + +/** + * Manages whether the content protection is enabled for an app using a allowlist. + * + * @hide + */ +public class ContentProtectionAllowlistManager { + + private static final String TAG = "ContentProtectionAllowlistManager"; + + public ContentProtectionAllowlistManager() {} + + /** Returns true if the package is allowed. */ + public boolean isAllowed(@NonNull String packageName) { + Slog.v(TAG, packageName); + return false; + } +} diff --git a/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionBlocklistManager.java b/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionBlocklistManager.java deleted file mode 100644 index a0fd28b3f279..000000000000 --- a/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionBlocklistManager.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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 - */ -public 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; - - public 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; - } - } -} diff --git a/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionPackageManager.java b/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionPackageManager.java deleted file mode 100644 index 4ebac07ec3ea..000000000000 --- a/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionPackageManager.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.Manifest; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PackageManager.PackageInfoFlags; -import android.util.Slog; - -import java.util.Arrays; - -/** - * Basic package manager for content protection using content capture. - * - * @hide - */ -public class ContentProtectionPackageManager { - - private static final String TAG = "ContentProtectionPackageManager"; - - private static final PackageInfoFlags PACKAGE_INFO_FLAGS = - PackageInfoFlags.of(PackageManager.GET_PERMISSIONS); - - @NonNull private final PackageManager mPackageManager; - - public ContentProtectionPackageManager(@NonNull Context context) { - mPackageManager = context.getPackageManager(); - } - - @Nullable - public PackageInfo getPackageInfo(@NonNull String packageName) { - try { - return mPackageManager.getPackageInfo(packageName, PACKAGE_INFO_FLAGS); - } catch (NameNotFoundException ex) { - Slog.w(TAG, "Package info not found for: " + packageName, ex); - return null; - } - } - - public boolean isSystemApp(@NonNull PackageInfo packageInfo) { - return packageInfo.applicationInfo != null && isSystemApp(packageInfo.applicationInfo); - } - - private boolean isSystemApp(@NonNull ApplicationInfo applicationInfo) { - return (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; - } - - public boolean isUpdatedSystemApp(@NonNull PackageInfo packageInfo) { - return packageInfo.applicationInfo != null - && isUpdatedSystemApp(packageInfo.applicationInfo); - } - - private boolean isUpdatedSystemApp(@NonNull ApplicationInfo applicationInfo) { - return (applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; - } - - public boolean hasRequestedInternetPermissions(@NonNull PackageInfo packageInfo) { - return packageInfo.requestedPermissions != null - && Arrays.asList(packageInfo.requestedPermissions) - .contains(Manifest.permission.INTERNET); - } -} diff --git a/services/tests/servicestests/src/com/android/server/contentcapture/ContentCaptureManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/contentcapture/ContentCaptureManagerServiceTest.java index 5cc84b197e03..78bf9b0bc828 100644 --- a/services/tests/servicestests/src/com/android/server/contentcapture/ContentCaptureManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/contentcapture/ContentCaptureManagerServiceTest.java @@ -24,7 +24,6 @@ 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; @@ -44,7 +43,7 @@ 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.ContentProtectionAllowlistManager; import com.android.server.contentprotection.ContentProtectionConsentManager; import com.android.server.contentprotection.RemoteContentProtectionService; import com.android.server.pm.UserManagerInternal; @@ -94,7 +93,7 @@ public class ContentCaptureManagerServiceTest { @Mock private UserManagerInternal mMockUserManagerInternal; - @Mock private ContentProtectionBlocklistManager mMockContentProtectionBlocklistManager; + @Mock private ContentProtectionAllowlistManager mMockContentProtectionAllowlistManager; @Mock private ContentCaptureServiceInfo mMockContentCaptureServiceInfo; @@ -108,7 +107,7 @@ public class ContentCaptureManagerServiceTest { private List<List<String>> mDevCfgContentProtectionOptionalGroups = Collections.emptyList(); - private int mContentProtectionBlocklistManagersCreated; + private int mContentProtectionAllowlistManagersCreated; private int mContentProtectionServiceInfosCreated; @@ -132,10 +131,10 @@ public class ContentCaptureManagerServiceTest { @Test public void constructor_contentProtection_flagDisabled_noManagers() { - assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0); + assertThat(mContentProtectionAllowlistManagersCreated).isEqualTo(0); assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0); assertThat(mContentProtectionConsentManagersCreated).isEqualTo(0); - verifyZeroInteractions(mMockContentProtectionBlocklistManager); + verifyZeroInteractions(mMockContentProtectionAllowlistManager); verifyZeroInteractions(mMockContentProtectionConsentManager); } @@ -145,10 +144,10 @@ public class ContentCaptureManagerServiceTest { mContentCaptureManagerService = new TestContentCaptureManagerService(); - assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0); + assertThat(mContentProtectionAllowlistManagersCreated).isEqualTo(0); assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0); assertThat(mContentProtectionConsentManagersCreated).isEqualTo(0); - verifyZeroInteractions(mMockContentProtectionBlocklistManager); + verifyZeroInteractions(mMockContentProtectionAllowlistManager); verifyZeroInteractions(mMockContentProtectionConsentManager); } @@ -158,10 +157,10 @@ public class ContentCaptureManagerServiceTest { mContentCaptureManagerService = new TestContentCaptureManagerService(); - assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(0); + assertThat(mContentProtectionAllowlistManagersCreated).isEqualTo(0); assertThat(mContentProtectionServiceInfosCreated).isEqualTo(0); assertThat(mContentProtectionConsentManagersCreated).isEqualTo(0); - verifyZeroInteractions(mMockContentProtectionBlocklistManager); + verifyZeroInteractions(mMockContentProtectionAllowlistManager); verifyZeroInteractions(mMockContentProtectionConsentManager); } @@ -171,26 +170,13 @@ public class ContentCaptureManagerServiceTest { mContentCaptureManagerService = new TestContentCaptureManagerService(); - assertThat(mContentProtectionBlocklistManagersCreated).isEqualTo(1); + assertThat(mContentProtectionAllowlistManagersCreated).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(); @@ -201,13 +187,13 @@ public class ContentCaptureManagerServiceTest { assertThat(actual).isNull(); verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID); - verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString()); + verify(mMockContentProtectionAllowlistManager, never()).isAllowed(anyString()); } @Test public void getOptions_contentCaptureDisabled_contentProtectionEnabled() { when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true); - when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true); + when(mMockContentProtectionAllowlistManager.isAllowed(PACKAGE_NAME)).thenReturn(true); mDevCfgEnableContentProtectionReceiver = true; mContentCaptureManagerService = new TestContentCaptureManagerService(); @@ -239,13 +225,13 @@ public class ContentCaptureManagerServiceTest { assertThat(actual.contentProtectionOptions.enableReceiver).isFalse(); assertThat(actual.whitelistedComponents).isNull(); verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID); - verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString()); + verify(mMockContentProtectionAllowlistManager, never()).isAllowed(anyString()); } @Test public void getOptions_contentCaptureEnabled_contentProtectionEnabled() { when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true); - when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true); + when(mMockContentProtectionAllowlistManager.isAllowed(PACKAGE_NAME)).thenReturn(true); mDevCfgEnableContentProtectionReceiver = true; mContentCaptureManagerService = new TestContentCaptureManagerService(); mContentCaptureManagerService.mGlobalContentCaptureOptions.setWhitelist( @@ -273,7 +259,7 @@ public class ContentCaptureManagerServiceTest { assertThat(actual).isFalse(); verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID); - verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString()); + verify(mMockContentProtectionAllowlistManager, never()).isAllowed(anyString()); } @Test @@ -287,13 +273,13 @@ public class ContentCaptureManagerServiceTest { USER_ID, PACKAGE_NAME); assertThat(actual).isFalse(); - verify(mMockContentProtectionBlocklistManager).isAllowed(PACKAGE_NAME); + verify(mMockContentProtectionAllowlistManager).isAllowed(PACKAGE_NAME); } @Test public void isWhitelisted_packageName_contentCaptureDisabled_contentProtectionEnabled() { when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true); - when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true); + when(mMockContentProtectionAllowlistManager.isAllowed(PACKAGE_NAME)).thenReturn(true); mDevCfgEnableContentProtectionReceiver = true; mContentCaptureManagerService = new TestContentCaptureManagerService(); @@ -317,7 +303,7 @@ public class ContentCaptureManagerServiceTest { assertThat(actual).isTrue(); verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt()); - verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString()); + verify(mMockContentProtectionAllowlistManager, never()).isAllowed(anyString()); } @Test @@ -331,7 +317,7 @@ public class ContentCaptureManagerServiceTest { assertThat(actual).isFalse(); verify(mMockContentProtectionConsentManager).isConsentGranted(USER_ID); - verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString()); + verify(mMockContentProtectionAllowlistManager, never()).isAllowed(anyString()); } @Test @@ -345,13 +331,13 @@ public class ContentCaptureManagerServiceTest { USER_ID, COMPONENT_NAME); assertThat(actual).isFalse(); - verify(mMockContentProtectionBlocklistManager).isAllowed(PACKAGE_NAME); + verify(mMockContentProtectionAllowlistManager).isAllowed(PACKAGE_NAME); } @Test public void isWhitelisted_componentName_contentCaptureDisabled_contentProtectionEnabled() { when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true); - when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true); + when(mMockContentProtectionAllowlistManager.isAllowed(PACKAGE_NAME)).thenReturn(true); mDevCfgEnableContentProtectionReceiver = true; mContentCaptureManagerService = new TestContentCaptureManagerService(); @@ -375,13 +361,13 @@ public class ContentCaptureManagerServiceTest { assertThat(actual).isTrue(); verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt()); - verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString()); + verify(mMockContentProtectionAllowlistManager, never()).isAllowed(anyString()); } @Test public void isContentProtectionReceiverEnabled_true() { when(mMockContentProtectionConsentManager.isConsentGranted(USER_ID)).thenReturn(true); - when(mMockContentProtectionBlocklistManager.isAllowed(PACKAGE_NAME)).thenReturn(true); + when(mMockContentProtectionAllowlistManager.isAllowed(PACKAGE_NAME)).thenReturn(true); mDevCfgEnableContentProtectionReceiver = true; mContentCaptureManagerService = new TestContentCaptureManagerService(); @@ -400,7 +386,7 @@ public class ContentCaptureManagerServiceTest { assertThat(actual).isFalse(); verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt()); - verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString()); + verify(mMockContentProtectionAllowlistManager, never()).isAllowed(anyString()); } @Test @@ -415,7 +401,7 @@ public class ContentCaptureManagerServiceTest { assertThat(actual).isFalse(); verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt()); - verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString()); + verify(mMockContentProtectionAllowlistManager, never()).isAllowed(anyString()); } @Test @@ -431,7 +417,7 @@ public class ContentCaptureManagerServiceTest { assertThat(actual).isFalse(); verify(mMockContentProtectionConsentManager, never()).isConsentGranted(anyInt()); - verify(mMockContentProtectionBlocklistManager, never()).isAllowed(anyString()); + verify(mMockContentProtectionAllowlistManager, never()).isAllowed(anyString()); } @Test @@ -572,9 +558,9 @@ public class ContentCaptureManagerServiceTest { } @Override - protected ContentProtectionBlocklistManager createContentProtectionBlocklistManager() { - mContentProtectionBlocklistManagersCreated++; - return mMockContentProtectionBlocklistManager; + protected ContentProtectionAllowlistManager createContentProtectionAllowlistManager() { + mContentProtectionAllowlistManagersCreated++; + return mMockContentProtectionAllowlistManager; } @Override diff --git a/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionAllowlistManagerTest.java b/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionAllowlistManagerTest.java new file mode 100644 index 000000000000..6767a85035fe --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionAllowlistManagerTest.java @@ -0,0 +1,58 @@ +/* + * 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 androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +/** + * Test for {@link ContentProtectionAllowlistManager}. + * + * <p>Run with: {@code atest FrameworksServicesTests: + * com.android.server.contentprotection.ContentProtectionAllowlistManagerTest} + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class ContentProtectionAllowlistManagerTest { + + private static final String PACKAGE_NAME = "com.test.package.name"; + + @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + + private ContentProtectionAllowlistManager mContentProtectionAllowlistManager; + + @Before + public void setup() { + mContentProtectionAllowlistManager = new ContentProtectionAllowlistManager(); + } + + @Test + public void isAllowed() { + boolean actual = mContentProtectionAllowlistManager.isAllowed(PACKAGE_NAME); + + assertThat(actual).isFalse(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionBlocklistManagerTest.java b/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionBlocklistManagerTest.java deleted file mode 100644 index ba9956a63dca..000000000000 --- a/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionBlocklistManagerTest.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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; - } - } -} diff --git a/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionPackageManagerTest.java b/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionPackageManagerTest.java deleted file mode 100644 index 7d45ea4ce39a..000000000000 --- a/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionPackageManagerTest.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -import android.Manifest.permission; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PackageManager.PackageInfoFlags; -import android.testing.TestableContext; - -import androidx.test.core.app.ApplicationProvider; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -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 ContentProtectionPackageManager}. - * - * <p>Run with: {@code atest - * FrameworksServicesTests:com.android.server.contentprotection.ContentProtectionPackageManagerTest} - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class ContentProtectionPackageManagerTest { - private static final String PACKAGE_NAME = "PACKAGE_NAME"; - - private static final PackageInfo EMPTY_PACKAGE_INFO = new PackageInfo(); - - private static final PackageInfo SYSTEM_APP_PACKAGE_INFO = createSystemAppPackageInfo(); - - private static final PackageInfo UPDATED_SYSTEM_APP_PACKAGE_INFO = - createUpdatedSystemAppPackageInfo(); - - @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); - - @Rule - public final TestableContext mContext = - new TestableContext(ApplicationProvider.getApplicationContext()); - - @Mock private PackageManager mMockPackageManager; - - private ContentProtectionPackageManager mContentProtectionPackageManager; - - @Before - public void setup() { - mContext.setMockPackageManager(mMockPackageManager); - mContentProtectionPackageManager = new ContentProtectionPackageManager(mContext); - } - - @Test - public void getPackageInfo_found() throws Exception { - PackageInfo expected = createPackageInfo(/* flags= */ 0); - when(mMockPackageManager.getPackageInfo(eq(PACKAGE_NAME), any(PackageInfoFlags.class))) - .thenReturn(expected); - - PackageInfo actual = mContentProtectionPackageManager.getPackageInfo(PACKAGE_NAME); - - assertThat(actual).isEqualTo(expected); - } - - @Test - public void getPackageInfo_notFound() throws Exception { - when(mMockPackageManager.getPackageInfo(eq(PACKAGE_NAME), any(PackageInfoFlags.class))) - .thenThrow(new NameNotFoundException()); - - PackageInfo actual = mContentProtectionPackageManager.getPackageInfo(PACKAGE_NAME); - - assertThat(actual).isNull(); - } - - @Test - public void getPackageInfo_null() { - PackageInfo actual = mContentProtectionPackageManager.getPackageInfo(PACKAGE_NAME); - - assertThat(actual).isNull(); - } - - @Test - public void isSystemApp_true() { - boolean actual = mContentProtectionPackageManager.isSystemApp(SYSTEM_APP_PACKAGE_INFO); - - assertThat(actual).isTrue(); - } - - @Test - public void isSystemApp_false() { - boolean actual = - mContentProtectionPackageManager.isSystemApp(UPDATED_SYSTEM_APP_PACKAGE_INFO); - - assertThat(actual).isFalse(); - } - - @Test - public void isSystemApp_noApplicationInfo() { - boolean actual = mContentProtectionPackageManager.isSystemApp(EMPTY_PACKAGE_INFO); - - assertThat(actual).isFalse(); - } - - @Test - public void isUpdatedSystemApp_true() { - boolean actual = - mContentProtectionPackageManager.isUpdatedSystemApp( - UPDATED_SYSTEM_APP_PACKAGE_INFO); - - assertThat(actual).isTrue(); - } - - @Test - public void isUpdatedSystemApp_false() { - boolean actual = - mContentProtectionPackageManager.isUpdatedSystemApp(SYSTEM_APP_PACKAGE_INFO); - - assertThat(actual).isFalse(); - } - - @Test - public void isUpdatedSystemApp_noApplicationInfo() { - boolean actual = mContentProtectionPackageManager.isUpdatedSystemApp(EMPTY_PACKAGE_INFO); - - assertThat(actual).isFalse(); - } - - @Test - public void hasRequestedInternetPermissions_true() { - PackageInfo packageInfo = createPackageInfo(new String[] {permission.INTERNET}); - - boolean actual = - mContentProtectionPackageManager.hasRequestedInternetPermissions(packageInfo); - - assertThat(actual).isTrue(); - } - - @Test - public void hasRequestedInternetPermissions_false() { - PackageInfo packageInfo = createPackageInfo(new String[] {permission.ACCESS_FINE_LOCATION}); - - boolean actual = - mContentProtectionPackageManager.hasRequestedInternetPermissions(packageInfo); - - assertThat(actual).isFalse(); - } - - @Test - public void hasRequestedInternetPermissions_noRequestedPermissions() { - boolean actual = - mContentProtectionPackageManager.hasRequestedInternetPermissions( - EMPTY_PACKAGE_INFO); - - assertThat(actual).isFalse(); - } - - private static PackageInfo createSystemAppPackageInfo() { - return createPackageInfo(ApplicationInfo.FLAG_SYSTEM); - } - - private static PackageInfo createUpdatedSystemAppPackageInfo() { - return createPackageInfo(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP); - } - - private static PackageInfo createPackageInfo(int flags) { - return createPackageInfo(flags, /* requestedPermissions= */ new String[0]); - } - - private static PackageInfo createPackageInfo(String[] requestedPermissions) { - return createPackageInfo(/* flags= */ 0, requestedPermissions); - } - - private static PackageInfo createPackageInfo(int flags, String[] requestedPermissions) { - PackageInfo packageInfo = new PackageInfo(); - packageInfo.packageName = PACKAGE_NAME; - packageInfo.applicationInfo = new ApplicationInfo(); - packageInfo.applicationInfo.packageName = PACKAGE_NAME; - packageInfo.applicationInfo.flags = flags; - packageInfo.requestedPermissions = requestedPermissions; - return packageInfo; - } -} |