Fix NativeDevice.doesFileExist for secondary user

Fixes: 160883794
Test: atest
android.media.cts.ExifInterfaceTest#testStandaloneDataForRead
To build unit test:
atest -b TradefedContentProviderTest
To run unit test:
tools/tradefederation/core/tradefed.sh && run host -n --class com.android.tradefed.device.contentprovider.ContentProviderHandlerTest

Merged-In: I5390d7f58c6bc0afbd2bafbf988ea7d71763571a
Change-Id: I5390d7f58c6bc0afbd2bafbf988ea7d71763571a
(cherry picked from commit e1d2db77ffefa06882213b3383c763093044a166)
(cherry picked from commit 3c89213b4517641a5e13db97a0535fe642806b4e)
diff --git a/device_build_interfaces/com/android/tradefed/device/contentprovider/ContentProviderHandler.java b/device_build_interfaces/com/android/tradefed/device/contentprovider/ContentProviderHandler.java
index 3e37f20..3163b52 100644
--- a/device_build_interfaces/com/android/tradefed/device/contentprovider/ContentProviderHandler.java
+++ b/device_build_interfaces/com/android/tradefed/device/contentprovider/ContentProviderHandler.java
@@ -244,6 +244,29 @@
         return false;
     }
 
+    /**
+     * Determines if the file or non-empty directory exists on the device.
+     *
+     * @param deviceFilePath The absolute file path on device to check for existence.
+     * @return True if file/directory exists, False otherwise. If directory is empty, it will return
+     *     False as well.
+     */
+    public boolean doesFileExist(String deviceFilePath) throws DeviceNotAvailableException {
+        String contentUri = createEscapedContentUri(deviceFilePath);
+        String queryContentCommand =
+                String.format(
+                        "content query --user %d --uri %s", mDevice.getCurrentUser(), contentUri);
+
+        String listCommandResult = mDevice.executeShellCommand(queryContentCommand);
+
+        if (NO_RESULTS_STRING.equals(listCommandResult.trim())) {
+            // No file found.
+            return false;
+        }
+
+        return true;
+    }
+
     /** Returns true if {@link CommandStatus} is successful and there is no error message. */
     private boolean isSuccessful(CommandResult result) {
         if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
diff --git a/src/com/android/tradefed/device/NativeDevice.java b/src/com/android/tradefed/device/NativeDevice.java
index 8c96162..91eb579 100644
--- a/src/com/android/tradefed/device/NativeDevice.java
+++ b/src/com/android/tradefed/device/NativeDevice.java
@@ -1284,6 +1284,15 @@
     /** {@inheritDoc} */
     @Override
     public boolean doesFileExist(String deviceFilePath) throws DeviceNotAvailableException {
+        if (deviceFilePath.startsWith(SD_CARD)) {
+            ContentProviderHandler handler = getContentProvider();
+            if (handler != null) {
+                CLog.d("Delegating check to ContentProvider doesFileExist(%s)", deviceFilePath);
+
+                return handler.doesFileExist(deviceFilePath);
+            }
+        }
+        CLog.d("Using 'ls' to check doesFileExist(%s)", deviceFilePath);
         String lsGrep = executeShellCommand(String.format("ls \"%s\"", deviceFilePath));
         return !lsGrep.contains("No such file or directory");
     }
diff --git a/tests/src/com/android/tradefed/device/contentprovider/ContentProviderHandlerTest.java b/tests/src/com/android/tradefed/device/contentprovider/ContentProviderHandlerTest.java
index b0da7d4..0570a59 100644
--- a/tests/src/com/android/tradefed/device/contentprovider/ContentProviderHandlerTest.java
+++ b/tests/src/com/android/tradefed/device/contentprovider/ContentProviderHandlerTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.util.CommandResult;
@@ -369,6 +370,36 @@
                 espacedUrl);
     }
 
+    /** Test {@link ContentProviderHandler#doesFileExist(String)}. */
+    @Test
+    public void testDoesFileExist() throws Exception {
+        String devicePath = "path/somewhere/file.txt";
+
+        when(mMockDevice.getCurrentUser()).thenReturn(99);
+        when(mMockDevice.executeShellCommand(
+                        "content query --user 99 --uri "
+                                + ContentProviderHandler.createEscapedContentUri(devicePath)))
+                .thenReturn("");
+
+        assertTrue(mProvider.doesFileExist(devicePath));
+    }
+
+    /**
+     * Test {@link ContentProviderHandler#doesFileExist(String)} returns false when 'adb shell
+     * content query' returns no results.
+     */
+    @Test
+    public void testDoesFileExist_NotExists() throws Exception {
+        String devicePath = "path/somewhere/";
+
+        when(mMockDevice.getCurrentUser()).thenReturn(99);
+        when(mMockDevice.executeShellCommand(
+                        "content query --user 99 --uri "
+                                + ContentProviderHandler.createEscapedContentUri(devicePath)))
+                .thenReturn("No result found.\n");
+        assertFalse(mProvider.doesFileExist(devicePath));
+    }
+
     @Test
     public void testParseQueryResultRow() {
         String row =