MonitoringCertTask no longer relies on software.device_admin
Added a test to validate that it still works the way it should before
and after the change.
Bug: 33258404
Bug: 35196414
Fix: 35129745
Test: runtest -x services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
Test: also manual, instructions:
Test: (1) Disable software.device_admin from tablet_core_hardware, rebuild.
Test: (2) Install CA cert. Notification should appear.
Test: (3) Reboot. Notification should still be there.
Change-Id: Id992725c1844a2fffbde4d8acaba531e99f853ad
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 6fb65d5..a186b59 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -21,6 +21,8 @@
import android.Manifest.permission;
import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
@@ -32,6 +34,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
import android.graphics.Color;
import android.net.IIpConnectivityMetrics;
@@ -52,10 +55,13 @@
import android.util.Pair;
import com.android.internal.R;
+import com.android.internal.util.ParcelableString;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.UserRestrictionsUtils;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -76,13 +82,16 @@
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -1193,6 +1202,53 @@
return uid;
}
+ public void testCertificateDisclosure() throws Exception {
+ final int userId = DpmMockContext.CALLER_USER_HANDLE;
+ final UserHandle user = UserHandle.of(userId);
+
+ mContext.applicationInfo = new ApplicationInfo();
+ mContext.callerPermissions.add(permission.MANAGE_USERS);
+ mContext.packageName = "com.android.frameworks.servicestests";
+ mContext.userContexts.put(user, mContext);
+ when(mContext.resources.getColor(anyInt(), anyObject())).thenReturn(Color.WHITE);
+
+ ParceledListSlice<ParcelableString> oneCert = asSlice(new String[] {"1"});
+ ParceledListSlice<ParcelableString> fourCerts = asSlice(new String[] {"1", "2", "3", "4"});
+
+ final String TEST_STRING = "Test for exactly 2 certs out of 4";
+ doReturn(TEST_STRING).when(mContext.resources).getQuantityText(anyInt(), eq(2));
+
+ // Given that we have exactly one certificate installed,
+ when(mContext.keyChainConnection.getService().getUserCaAliases()).thenReturn(oneCert);
+ // when that certificate is approved,
+ dpms.approveCaCert(oneCert.getList().get(0).string, userId, true);
+ // a notification should not be shown.
+ verify(mContext.notificationManager, timeout(1000))
+ .cancelAsUser(anyString(), anyInt(), eq(user));
+
+ // Given that we have four certificates installed,
+ when(mContext.keyChainConnection.getService().getUserCaAliases()).thenReturn(fourCerts);
+ // when two of them are approved (one of them approved twice hence no action),
+ dpms.approveCaCert(fourCerts.getList().get(0).string, userId, true);
+ dpms.approveCaCert(fourCerts.getList().get(1).string, userId, true);
+ // a notification should be shown saying that there are two certificates left to approve.
+ verify(mContext.notificationManager, timeout(1000))
+ .notifyAsUser(anyString(), anyInt(), argThat(
+ new BaseMatcher<Notification>() {
+ @Override
+ public boolean matches(Object item) {
+ final Notification noti = (Notification) item;
+ return TEST_STRING.equals(
+ noti.extras.getString(Notification.EXTRA_TITLE));
+ }
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(
+ "Notification{title=\"" + TEST_STRING + "\"}");
+ }
+ }), eq(user));
+ }
+
/**
* Simple test for delegate set/get and general delegation. Tests verifying that delegated
* privileges can acually be exercised by a delegate are not covered here.
@@ -3734,4 +3790,20 @@
assertTrue(dpm.setProfileOwner(admin, null, userId));
mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
}
+
+ /**
+ * Convert String[] to ParceledListSlice<ParcelableString>.
+ * <p>
+ * TODO: This shouldn't be necessary. If ParcelableString does need to exist, it also needs
+ * a real constructor.
+ */
+ private static ParceledListSlice<ParcelableString> asSlice(String[] s) {
+ List<ParcelableString> list = new ArrayList<>(s.length);
+ for (int i = 0; i < s.length; i++) {
+ ParcelableString item = new ParcelableString();
+ item.string = s[i];
+ list.add(i, item);
+ }
+ return new ParceledListSlice<ParcelableString>(list);
+ }
}