Use "dpm force-security-logs" in security logging test.

This is to avoid relying on implementation details like
how big is batch notification level and how long is the
delay between log fetching.

Change-Id: Ic00da14ce214f4f6958d4fc098e573579f2853dd
Bug: 70886042
Test: cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t
  com.android.cts.devicepolicy.DeviceOwnerTest#testSecurityLoggingWithSingleUser
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
index bc4fe8d..17d52f7 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
@@ -16,6 +16,8 @@
 package com.android.cts.deviceowner;
 
 import android.app.admin.SecurityLog.SecurityEvent;
+import android.content.Context;
+import android.content.SharedPreferences;
 import android.os.Parcel;
 import android.support.test.InstrumentationRegistry;
 
@@ -24,7 +26,8 @@
 
 public class SecurityLoggingTest extends BaseDeviceOwnerTest {
     private static final String ARG_BATCH_NUMBER = "batchNumber";
-    private static final int BUFFER_ENTRIES_NOTIFICATION_LEVEL = 1024;
+    private static final String PREF_KEY_PREFIX = "batch-last-id-";
+    private static final String PREF_NAME = "batchIds";
 
     /**
      * Test: retrieving security logs can only be done if there's one user on the device or all
@@ -52,25 +55,30 @@
 
     /**
      * Test: retrieving security logs. This test has should be called when security logging is
-     * enabled and directly after reboot with device owner installed so that security logging
-     * actually takes place and fetching the logs isn't subject to rate limiting.
+     * enabled and a batch of events is available.
      */
-    public void testGetSecurityLogs() {
-        List<SecurityEvent> events = mDevicePolicyManager.retrieveSecurityLogs(getWho());
-        String param = InstrumentationRegistry.getArguments().getString(ARG_BATCH_NUMBER);
-        int batchNumber = param == null ? 0 : Integer.parseInt(param);
+    public void testGetSecurityLogs() throws Exception {
+        List<SecurityEvent> events = null;
+        // Retry once after seeping for 1 second, in case "dpm force-security-logs" hasn't taken
+        // effect just yet.
+        for (int i = 0; i < 2 && events == null; i++) {
+            events = mDevicePolicyManager.retrieveSecurityLogs(getWho());
+            if (events == null) Thread.sleep(1000);
+        }
+
+        final String param = InstrumentationRegistry.getArguments().getString(ARG_BATCH_NUMBER);
+        final int batchNumber = param == null ? 0 : Integer.parseInt(param);
         verifySecurityLogs(batchNumber, events);
     }
 
-    private static void verifySecurityLogs(int batchNumber, List<SecurityEvent> events) {
+    private void verifySecurityLogs(int batchNumber, List<SecurityEvent> events) {
         assertTrue("Unable to get events", events != null && events.size() > 0);
-        assertTrue(
-                "First id in batch " + events.get(0).getId() + " is too small for the batch number "
-                        + batchNumber,
-                events.get(0).getId() >= (BUFFER_ENTRIES_NOTIFICATION_LEVEL * batchNumber));
+
+        verifyContinuousIdsBetweenBatches(batchNumber, events);
+
         // We don't know much about the events, so just call public API methods.
         for (int i = 0; i < events.size(); i++) {
-            SecurityEvent event = events.get(i);
+            final SecurityEvent event = events.get(i);
 
             // Test id for monotonically increasing.
             if (i > 0) {
@@ -84,7 +92,7 @@
             p.setDataPosition(0);
 
             // Restore from parcel and check contents.
-            SecurityEvent restored = SecurityEvent.CREATOR.createFromParcel(p);
+            final SecurityEvent restored = SecurityEvent.CREATOR.createFromParcel(p);
             p.recycle();
 
             // For some events data is encapsulated into Object array.
@@ -107,6 +115,31 @@
     }
 
     /**
+     * Check that there are no gaps between ids in two consecutive batches. Shared preference is
+     * used to store these numbers between invocations.
+     */
+    private void verifyContinuousIdsBetweenBatches(int batchNumber, List<SecurityEvent> events) {
+        final SharedPreferences prefs =
+                mContext.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
+
+        final long firstId = events.get(0).getId();
+        if (batchNumber == 0) {
+            assertEquals("Event id wasn't reset.", 0L, firstId);
+        } else {
+            final String prevBatchLastIdKey = PREF_KEY_PREFIX + (batchNumber - 1);
+            assertTrue("Last event id from previous batch not found in shared prefs",
+                    prefs.contains(prevBatchLastIdKey));
+            final long prevBatchLastId = prefs.getLong(prevBatchLastIdKey, 0);
+            assertEquals("Event ids aren't consecutive between batches",
+                    firstId, prevBatchLastId + 1);
+        }
+
+        final String currBatchLastIdKey = PREF_KEY_PREFIX + batchNumber;
+        final long lastId = events.get(events.size() - 1).getId();
+        prefs.edit().putLong(currBatchLastIdKey, lastId).commit();
+    }
+
+    /**
      * Test: Test enabling security logging. This test should be executed after installing a device
      * owner so that we check that logging is not enabled by default. This test has a side effect:
      * security logging is enabled after its execution.
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 72795ad..f4db369 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -56,7 +56,7 @@
     private static final String TEST_APP_LOCATION = "/data/local/tmp/cts/packageinstaller/";
 
     private static final String ARG_SECURITY_LOGGING_BATCH_NUMBER = "batchNumber";
-    private static final int BUFFER_SECURITY_ENTRIES_NOTIFICATION_LEVEL = 1024;
+    private static final int SECURITY_EVENTS_BATCH_SIZE = 100;
 
     private static final String ARG_NETWORK_LOGGING_BATCH_COUNT = "batchCount";
 
@@ -471,23 +471,22 @@
         executeDeviceTestMethod(".SecurityLoggingTest", "testDisablingSecurityLogging");
 
         // Generate more than enough events for a batch of security events.
-        int batchSize = BUFFER_SECURITY_ENTRIES_NOTIFICATION_LEVEL + 100;
         try {
             executeDeviceTestMethod(".SecurityLoggingTest", "testEnablingSecurityLogging");
             // Reboot to ensure ro.device_owner is set to true in logd.
             rebootAndWaitUntilReady();
 
             // First batch: retrieve and verify the events.
-            runBatch(0, batchSize);
+            runBatch(0);
 
             // Verify event ids are consistent across a consecutive batch.
-            runBatch(1, batchSize);
+            runBatch(1);
 
             // Reboot the device, so the security event ids are reset.
             rebootAndWaitUntilReady();
 
             // First batch after reboot: retrieve and verify the events.
-            runBatch(0 /* batch number */, batchSize);
+            runBatch(0 /* batch number */);
 
             // Immediately attempting to fetch events again should fail.
             executeDeviceTestMethod(".SecurityLoggingTest",
@@ -498,16 +497,14 @@
         }
     }
 
-    private void runBatch(int batchNumber, int batchSize) throws Exception {
+    private void runBatch(int batchNumber) throws Exception {
         // Trigger security events of type TAG_ADB_SHELL_CMD.
-        for (int i = 0; i < batchSize; i++) {
-            getDevice().executeShellCommand("adb shell echo just_testing_" + i);
+        for (int i = 0; i < SECURITY_EVENTS_BATCH_SIZE; i++) {
+            getDevice().executeShellCommand("echo just_testing_" + i);
         }
 
-        // Sleep for ~1 minute so that SecurityLogMonitor fetches the security events. This is
-        // an implementation detail we shouldn't rely on but there is no other way to do it
-        // currently.
-        Thread.sleep(TimeUnit.SECONDS.toMillis(70));
+        // Force log batch.
+        getDevice().executeShellCommand("dpm force-security-logs");
 
         // Verify the contents of the batch.
         executeDeviceTestMethod(".SecurityLoggingTest", "testGetSecurityLogs",