Only add uid format to logcat command if available

Bug: 206135156
Test: atest hello_world_test
Test: m tradefed-all ;
      ./tools/tradefederation/core/javatests/run_tradefed_tests.sh \
      --class com.android.tradefed.device.NativeDeviceTest
Test: atest hello_world_test

Change-Id: I568da35097dc8f6f663e9c2c22c5de5c88bfc14c
diff --git a/javatests/com/android/tradefed/device/NativeDeviceTest.java b/javatests/com/android/tradefed/device/NativeDeviceTest.java
index ea072d0..506e755 100644
--- a/javatests/com/android/tradefed/device/NativeDeviceTest.java
+++ b/javatests/com/android/tradefed/device/NativeDeviceTest.java
@@ -3061,10 +3061,10 @@
 
     /**
      * Test that when a {@link NativeDevice#getLogcatSince(long)} is requested a matching logcat
-     * command is generated.
+     * command is generated on sdk version 23.
      */
     @Test
-    public void testGetLogcatSince() throws Exception {
+    public void testGetLogcatSinceOnSdk23() throws Exception {
         long date = 1512990942000L; // 2017-12-11 03:15:42.015
         setGetPropertyExpectation("ro.build.version.sdk", "23");
 
@@ -3076,6 +3076,27 @@
 
         verify(mMockIDevice)
                 .executeShellCommand(
+                        Mockito.eq(String.format("logcat -v threadtime -t '%s'", dateFormatted)),
+                        Mockito.any());
+    }
+
+    /**
+     * Test that when a {@link NativeDevice#getLogcatSince(long)} is requested a matching logcat
+     * command is generated on sdk version 24.
+     */
+    @Test
+    public void testGetLogcatSinceOnSdkOver24() throws Exception {
+        long date = 1512990942000L; // 2017-12-11 03:15:42.015
+        setGetPropertyExpectation("ro.build.version.sdk", "24");
+
+        SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm:ss.mmm");
+        String dateFormatted = format.format(new Date(date));
+
+        InputStreamSource res = mTestDevice.getLogcatSince(date);
+        StreamUtil.close(res);
+
+        verify(mMockIDevice)
+                .executeShellCommand(
                         Mockito.eq(
                                 String.format("logcat -v threadtime,uid -t '%s'", dateFormatted)),
                         Mockito.any());
diff --git a/javatests/com/android/tradefed/device/TestDeviceFuncTest.java b/javatests/com/android/tradefed/device/TestDeviceFuncTest.java
index a8abd0b..854af8e 100644
--- a/javatests/com/android/tradefed/device/TestDeviceFuncTest.java
+++ b/javatests/com/android/tradefed/device/TestDeviceFuncTest.java
@@ -850,7 +850,9 @@
     public void testLogcatCmd() throws DeviceNotAvailableException {
         CLog.i("testLogcatCmd");
         // Adding -d flag to dump the log and exit, to make this a non-blocking call
-        CommandResult result = mTestDevice.executeShellV2Command(LogcatReceiver.LOGCAT_CMD + " -d");
+        CommandResult result =
+                mTestDevice.executeShellV2Command(
+                        LogcatReceiver.getDefaultLogcatCmd(mTestDevice) + " -d");
         assertThat(result.getStatus()).isEqualTo(CommandStatus.SUCCESS);
     }
 
diff --git a/javatests/com/android/tradefed/device/cloud/ManagedRemoteDeviceTest.java b/javatests/com/android/tradefed/device/cloud/ManagedRemoteDeviceTest.java
index 38d7254..e9858a2 100644
--- a/javatests/com/android/tradefed/device/cloud/ManagedRemoteDeviceTest.java
+++ b/javatests/com/android/tradefed/device/cloud/ManagedRemoteDeviceTest.java
@@ -21,6 +21,7 @@
 
 import com.android.ddmlib.IDevice;
 import com.android.tradefed.config.GlobalConfiguration;
+import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.IDeviceMonitor;
 import com.android.tradefed.device.IDeviceStateMonitor;
 import com.android.tradefed.device.TestDeviceOptions;
@@ -57,7 +58,13 @@
         mStateMonitor = Mockito.mock(IDeviceStateMonitor.class);
         mDeviceMonitor = Mockito.mock(IDeviceMonitor.class);
         mMockLogger = Mockito.mock(ITestLogger.class);
-        mDevice = new ManagedRemoteDevice(mIDevice, mStateMonitor, mDeviceMonitor);
+        mDevice =
+                new ManagedRemoteDevice(mIDevice, mStateMonitor, mDeviceMonitor) {
+                    @Override
+                    public int getApiLevel() throws DeviceNotAvailableException {
+                        return 29;
+                    }
+                };
         mDevice.setTestLogger(mMockLogger);
     }
 
diff --git a/src/com/android/tradefed/device/LogcatReceiver.java b/src/com/android/tradefed/device/LogcatReceiver.java
index cfd93a9..8993b1c 100644
--- a/src/com/android/tradefed/device/LogcatReceiver.java
+++ b/src/com/android/tradefed/device/LogcatReceiver.java
@@ -15,6 +15,7 @@
  */
 package com.android.tradefed.device;
 
+import com.android.tradefed.log.LogUtil;
 import com.android.tradefed.result.InputStreamSource;
 
 import com.google.errorprone.annotations.MustBeClosed;
@@ -27,7 +28,6 @@
     private BackgroundDeviceAction mDeviceAction;
     private LargeOutputReceiver mReceiver;
 
-    static final String LOGCAT_CMD = "logcat -v threadtime,uid";
     private static final String LOGCAT_DESC = "logcat";
 
     /**
@@ -40,7 +40,6 @@
      */
     public LogcatReceiver(ITestDevice device, String logcatCmd,
             long maxFileSize, int logStartDelay) {
-
         mReceiver = new LargeOutputReceiver(LOGCAT_DESC, device.getSerialNumber(),
                 maxFileSize);
         // FIXME: remove mLogStartDelay. Currently delay starting logcat, as starting
@@ -56,7 +55,7 @@
      * @param logStartDelay the delay to wait after the device becomes online
      */
     public LogcatReceiver(ITestDevice device, long maxFileSize, int logStartDelay) {
-        this(device, LOGCAT_CMD, maxFileSize, logStartDelay);
+        this(device, getDefaultLogcatCmd(device), maxFileSize, logStartDelay);
     }
 
     @Override
@@ -92,4 +91,20 @@
     public void clear() {
         mReceiver.clear();
     }
+
+    /** Get the default logcat command, only append uid format if api level > 24. */
+    public static String getDefaultLogcatCmd(ITestDevice device) {
+        String logcatCmd = "logcat -v threadtime";
+        // Logcat format support UID started from api level 24.
+        try {
+            if (device.getApiLevel() >= 24) {
+                logcatCmd = logcatCmd + ",uid";
+            }
+        } catch (DeviceNotAvailableException e) {
+            LogUtil.CLog.e("Use logcat command without UID format due to: ");
+            LogUtil.CLog.e(e);
+        }
+
+        return logcatCmd;
+    }
 }
diff --git a/src/com/android/tradefed/device/NativeDevice.java b/src/com/android/tradefed/device/NativeDevice.java
index 6b93a2c..be2f346 100644
--- a/src/com/android/tradefed/device/NativeDevice.java
+++ b/src/com/android/tradefed/device/NativeDevice.java
@@ -2618,7 +2618,9 @@
                             "getLogcatSince",
                             getSerialNumber(),
                             getOptions().getMaxLogcatDataSize());
-            String command = String.format("%s -t '%s'", LogcatReceiver.LOGCAT_CMD, dateFormatted);
+            String command =
+                    String.format(
+                            "%s -t '%s'", LogcatReceiver.getDefaultLogcatCmd(this), dateFormatted);
             getIDevice().executeShellCommand(command, largeReceiver);
             return largeReceiver.getData();
         } catch (IOException|AdbCommandRejectedException|
@@ -2651,7 +2653,7 @@
             // add -d parameter to make this a non blocking call
             getIDevice()
                     .executeShellCommand(
-                            LogcatReceiver.LOGCAT_CMD + " -d",
+                            LogcatReceiver.getDefaultLogcatCmd(this) + " -d",
                             largeReceiver,
                             LOGCAT_DUMP_TIMEOUT,
                             TimeUnit.MILLISECONDS);
@@ -2693,9 +2695,11 @@
         if (logcatOptions == null) {
             return new LogcatReceiver(this, mOptions.getMaxLogcatDataSize(), mLogStartDelay);
         } else {
-            return new LogcatReceiver(this,
-                    String.format("%s %s", LogcatReceiver.LOGCAT_CMD, logcatOptions),
-                    mOptions.getMaxLogcatDataSize(), mLogStartDelay);
+            return new LogcatReceiver(
+                    this,
+                    String.format("%s %s", LogcatReceiver.getDefaultLogcatCmd(this), logcatOptions),
+                    mOptions.getMaxLogcatDataSize(),
+                    mLogStartDelay);
         }
     }