Add openReceivedFile tests in BluetoothOppUtilityTest

Test: atest BluetoothOppUtilityTest
Tag: #refactor
Bug: 237467631
Change-Id: I79f098b61e95cc37a86da733483b9f8c87937bda
(cherry picked from commit 4ee8597de4c34d108d54a06d0e3d10108bc73677)
Merged-In: I79f098b61e95cc37a86da733483b9f8c87937bda
diff --git a/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java b/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java
index 33b67a7..855f1ff4 100644
--- a/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java
+++ b/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java
@@ -22,11 +22,13 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.obex.HeaderSet;
 
+import java.io.FileNotFoundException;
 import java.io.IOException;
 
 /**
@@ -102,6 +104,15 @@
     }
 
     /**
+     * Proxies {@link ContentResolver#openFileDescriptor(Uri, String)}.
+     */
+    public ParcelFileDescriptor contentResolverOpenFileDescriptor(ContentResolver contentResolver,
+            final Uri uri, final String mode) throws FileNotFoundException {
+        return contentResolver.openFileDescriptor(uri, mode);
+    }
+
+
+    /**
      * Proxies {@link HeaderSet#getHeader}.
      */
     public Object getHeader(HeaderSet headerSet, int headerId) throws IOException {
diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java
index f12c0b3..875cfcc 100644
--- a/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java
+++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java
@@ -239,7 +239,8 @@
             if (V) {
                 Log.d(TAG, "This uri will be deleted: " + uri);
             }
-            context.getContentResolver().delete(uri, null, null);
+            BluetoothMethodProxy.getInstance().contentResolverDelete(context.getContentResolver(),
+                    uri, null, null);
             return;
         }
 
@@ -278,7 +279,8 @@
         String readOnlyMode = "r";
         ParcelFileDescriptor pfd = null;
         try {
-            pfd = resolver.openFileDescriptor(uri, readOnlyMode);
+            pfd = BluetoothMethodProxy.getInstance()
+                    .contentResolverOpenFileDescriptor(resolver, uri, readOnlyMode);
             return true;
         } catch (IOException e) {
             e.printStackTrace();
diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java
index 9703245..8dbe945 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java
@@ -19,13 +19,21 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.net.Uri;
 
@@ -41,8 +49,10 @@
 import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
 
+import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
 public class BluetoothOppUtilityTest {
@@ -124,6 +134,99 @@
     }
 
     @Test
+    public void openReceivedFile_fileNotExist() {
+        Uri contentResolverUri = Uri.parse("content://com.android.bluetooth.opp/btopp/0123");
+        Uri fileUri = Uri.parse("content:///tmp/randomFileName.txt");
+
+        Context spiedContext = spy(new ContextWrapper(mContext));
+
+        doReturn(mCursor).when(mCallProxy).contentResolverQuery(any(),
+                eq(contentResolverUri), any(), eq(null),
+                eq(null), eq(null));
+
+        doReturn(true).when(mCursor).moveToFirst();
+        doReturn(fileUri.toString()).when(mCursor).getString(anyInt());
+
+        BluetoothOppUtility.openReceivedFile(spiedContext, "randomFileName.txt",
+                "text/plain", 0L, contentResolverUri);
+
+        verify(spiedContext).startActivity(argThat(argument
+                -> Objects.equals(argument.getComponent().getClassName(),
+                BluetoothOppBtErrorActivity.class.getName())
+        ));
+    }
+
+    @Test
+    public void openReceivedFile_fileExist_HandlingApplicationExist() throws FileNotFoundException {
+        Uri contentResolverUri = Uri.parse("content://com.android.bluetooth.opp/btopp/0123");
+        Uri fileUri = Uri.parse("content:///tmp/randomFileName.txt");
+
+        Context spiedContext = spy(new ContextWrapper(mContext));
+        // Control BluetoothOppUtility#fileExists flow
+        doReturn(mCursor).when(mCallProxy).contentResolverQuery(any(),
+                eq(contentResolverUri), any(), eq(null),
+                eq(null), eq(null));
+
+        doReturn(true).when(mCursor).moveToFirst();
+        doReturn(fileUri.toString()).when(mCursor).getString(anyInt());
+
+        doReturn(0).when(mCallProxy).contentResolverDelete(any(), any(), any(), any());
+        doReturn(null).when(mCallProxy).contentResolverOpenFileDescriptor(any(),
+                eq(fileUri), any());
+
+        // Control BluetoothOppUtility#isRecognizedFileType flow
+        PackageManager mockManager = mock(PackageManager.class);
+        doReturn(mockManager).when(spiedContext).getPackageManager();
+        doReturn(List.of(new ResolveInfo())).when(mockManager).queryIntentActivities(any(),
+                anyInt());
+
+        BluetoothOppUtility.openReceivedFile(spiedContext, "randomFileName.txt",
+                "text/plain", 0L, contentResolverUri);
+
+        verify(spiedContext).startActivity(argThat(argument
+                        -> Objects.equals(
+                        argument.getData(), Uri.parse("content:///tmp/randomFileName.txt")
+                ) && Objects.equals(argument.getAction(), Intent.ACTION_VIEW)
+        ));
+    }
+
+    @Test
+    public void openReceivedFile_fileExist_HandlingApplicationNotExist()
+            throws FileNotFoundException {
+
+        Uri contentResolverUri = Uri.parse("content://com.android.bluetooth.opp/btopp/0123");
+        Uri fileUri = Uri.parse("content:///tmp/randomFileName.txt");
+
+        Context spiedContext = spy(new ContextWrapper(mContext));
+        // Control BluetoothOppUtility#fileExists flow
+        doReturn(mCursor).when(mCallProxy).contentResolverQuery(any(),
+                eq(contentResolverUri), any(), eq(null),
+                eq(null), eq(null));
+
+        doReturn(true).when(mCursor).moveToFirst();
+        doReturn(fileUri.toString()).when(mCursor).getString(anyInt());
+
+
+        doReturn(0).when(mCallProxy).contentResolverDelete(any(), any(), any(), any());
+        doReturn(null).when(mCallProxy).contentResolverOpenFileDescriptor(any(),
+                eq(fileUri), any());
+
+        // Control BluetoothOppUtility#isRecognizedFileType flow
+        PackageManager mockManager = mock(PackageManager.class);
+        doReturn(mockManager).when(spiedContext).getPackageManager();
+        doReturn(List.of()).when(mockManager).queryIntentActivities(any(), anyInt());
+
+        BluetoothOppUtility.openReceivedFile(spiedContext, "randomFileName.txt",
+                "text/plain", 0L, contentResolverUri);
+
+        verify(spiedContext).startActivity(
+                argThat(argument -> argument.getComponent().getClassName().equals(
+                        BluetoothOppBtErrorActivity.class.getName())
+                ));
+    }
+
+
+    @Test
     public void fillRecord_filledAllProperties() {
         int idValue = 1234;
         int directionValue = BluetoothShare.DIRECTION_OUTBOUND;
@@ -137,16 +240,16 @@
         String fileTypeValue = "text/plain";
 
         List<CursorMockData> cursorMockDataList = List.of(
-            new CursorMockData(BluetoothShare._ID, 0, idValue),
-            new CursorMockData(BluetoothShare.STATUS, 1, statusValue),
-            new CursorMockData(BluetoothShare.DIRECTION, 2, directionValue),
-            new CursorMockData(BluetoothShare.TOTAL_BYTES, 3, totalBytesValue),
-            new CursorMockData(BluetoothShare.CURRENT_BYTES, 4, currentBytesValue),
-            new CursorMockData(BluetoothShare.TIMESTAMP, 5, timestampValue),
-            new CursorMockData(BluetoothShare.DESTINATION, 6, destinationValue),
-            new CursorMockData(BluetoothShare._DATA, 7, null),
-            new CursorMockData(BluetoothShare.FILENAME_HINT, 8, null),
-            new CursorMockData(BluetoothShare.MIMETYPE, 9, fileTypeValue)
+                new CursorMockData(BluetoothShare._ID, 0, idValue),
+                new CursorMockData(BluetoothShare.STATUS, 1, statusValue),
+                new CursorMockData(BluetoothShare.DIRECTION, 2, directionValue),
+                new CursorMockData(BluetoothShare.TOTAL_BYTES, 3, totalBytesValue),
+                new CursorMockData(BluetoothShare.CURRENT_BYTES, 4, currentBytesValue),
+                new CursorMockData(BluetoothShare.TIMESTAMP, 5, timestampValue),
+                new CursorMockData(BluetoothShare.DESTINATION, 6, destinationValue),
+                new CursorMockData(BluetoothShare._DATA, 7, null),
+                new CursorMockData(BluetoothShare.FILENAME_HINT, 8, null),
+                new CursorMockData(BluetoothShare.MIMETYPE, 9, fileTypeValue)
         );
 
         BluetoothOppTestUtils.setUpMockCursor(mCursor, cursorMockDataList);