Change file access return types to ParcelFileDescriptor

FileInputStream works well with Java code, but for this usecase files may need to be passed onto JNI layer which requires access to fd-int and
FileInputStream or the underlying FileDescriptor type do not expose a
getter to the FD int which causes a lot of back and forth.

Changing to PFD and add checks alongside other validations in
system-server to ensure read only behaviour.

Test: cts in this topic added
Bug: 329656165
Change-Id: Ic5aa0d49e04afc74ff97833f3bbc5eab4790ef5b
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 0ab4772..ad74e18 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12956,15 +12956,15 @@
 
   @FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence") public abstract class OnDeviceSandboxedInferenceService extends android.app.Service {
     ctor public OnDeviceSandboxedInferenceService();
-    method public final void fetchFeatureFileInputStreamMap(@NonNull android.app.ondeviceintelligence.Feature, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,java.io.FileInputStream>>);
+    method public final void fetchFeatureFileDescriptorMap(@NonNull android.app.ondeviceintelligence.Feature, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,android.os.ParcelFileDescriptor>>);
     method @NonNull public java.util.concurrent.Executor getCallbackExecutor();
+    method public final void getReadOnlyFileDescriptor(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.os.ParcelFileDescriptor>) throws java.io.FileNotFoundException;
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method @NonNull public abstract void onProcessRequest(int, @NonNull android.app.ondeviceintelligence.Feature, @NonNull android.os.Bundle, int, @Nullable android.os.CancellationSignal, @Nullable android.app.ondeviceintelligence.ProcessingSignal, @NonNull android.app.ondeviceintelligence.ProcessingCallback);
     method @NonNull public abstract void onProcessRequestStreaming(int, @NonNull android.app.ondeviceintelligence.Feature, @NonNull android.os.Bundle, int, @Nullable android.os.CancellationSignal, @Nullable android.app.ondeviceintelligence.ProcessingSignal, @NonNull android.app.ondeviceintelligence.StreamingProcessingCallback);
     method @NonNull public abstract void onTokenInfoRequest(int, @NonNull android.app.ondeviceintelligence.Feature, @NonNull android.os.Bundle, @Nullable android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.app.ondeviceintelligence.TokenInfo,android.app.ondeviceintelligence.OnDeviceIntelligenceException>);
     method public abstract void onUpdateProcessingState(@NonNull android.os.Bundle, @NonNull android.os.OutcomeReceiver<android.os.PersistableBundle,android.app.ondeviceintelligence.OnDeviceIntelligenceException>);
     method public final java.io.FileInputStream openFileInput(@NonNull String) throws java.io.FileNotFoundException;
-    method public final void openFileInputAsync(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.io.FileInputStream>) throws java.io.FileNotFoundException;
     field public static final String SERVICE_INTERFACE = "android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService";
   }
 
diff --git a/core/java/android/service/ondeviceintelligence/OnDeviceSandboxedInferenceService.java b/core/java/android/service/ondeviceintelligence/OnDeviceSandboxedInferenceService.java
index d943c80..fc7a4c8 100644
--- a/core/java/android/service/ondeviceintelligence/OnDeviceSandboxedInferenceService.java
+++ b/core/java/android/service/ondeviceintelligence/OnDeviceSandboxedInferenceService.java
@@ -27,21 +27,21 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.app.Service;
-import android.app.ondeviceintelligence.OnDeviceIntelligenceException;
-import android.os.Bundle;
 import android.app.ondeviceintelligence.Feature;
 import android.app.ondeviceintelligence.IProcessingSignal;
 import android.app.ondeviceintelligence.IResponseCallback;
 import android.app.ondeviceintelligence.IStreamingResponseCallback;
 import android.app.ondeviceintelligence.ITokenInfoCallback;
+import android.app.ondeviceintelligence.OnDeviceIntelligenceException;
 import android.app.ondeviceintelligence.OnDeviceIntelligenceManager;
 import android.app.ondeviceintelligence.OnDeviceIntelligenceManager.InferenceParams;
-import android.app.ondeviceintelligence.ProcessingSignal;
 import android.app.ondeviceintelligence.ProcessingCallback;
+import android.app.ondeviceintelligence.ProcessingSignal;
 import android.app.ondeviceintelligence.StreamingProcessingCallback;
 import android.app.ondeviceintelligence.TokenInfo;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.HandlerExecutor;
@@ -292,15 +292,15 @@
 
     /**
      * Provides read-only access to the internal app storage via the
-     * {@link OnDeviceIntelligenceService}. This is an asynchronous implementation for
+     * {@link OnDeviceIntelligenceService}. This is an asynchronous alternative for
      * {@link #openFileInput(String)}.
      *
      * @param fileName       File name relative to the {@link Context#getFilesDir()}.
-     * @param resultConsumer Consumer to populate the corresponding file stream in.
+     * @param resultConsumer Consumer to populate the corresponding file descriptor in.
      */
-    public final void openFileInputAsync(@NonNull String fileName,
+    public final void getReadOnlyFileDescriptor(@NonNull String fileName,
             @NonNull @CallbackExecutor Executor executor,
-            @NonNull Consumer<FileInputStream> resultConsumer) throws FileNotFoundException {
+            @NonNull Consumer<ParcelFileDescriptor> resultConsumer) throws FileNotFoundException {
         AndroidFuture<ParcelFileDescriptor> future = new AndroidFuture<>();
         try {
             mRemoteStorageService.getReadOnlyFileDescriptor(fileName, future);
@@ -314,7 +314,7 @@
                 executor.execute(() -> resultConsumer.accept(null));
             } else {
                 executor.execute(
-                        () -> resultConsumer.accept(new FileInputStream(pfd.getFileDescriptor())));
+                        () -> resultConsumer.accept(pfd));
             }
         }, executor);
     }
@@ -328,12 +328,12 @@
      * @param resultConsumer Consumer to receive a map of filePath to the corresponding file input
      *                       stream.
      */
-    public final void fetchFeatureFileInputStreamMap(@NonNull Feature feature,
+    public final void fetchFeatureFileDescriptorMap(@NonNull Feature feature,
             @NonNull @CallbackExecutor Executor executor,
-            @NonNull Consumer<Map<String, FileInputStream>> resultConsumer) {
+            @NonNull Consumer<Map<String, ParcelFileDescriptor>> resultConsumer) {
         try {
             mRemoteStorageService.getReadOnlyFeatureFileDescriptorMap(feature,
-                    wrapResultReceiverAsReadOnly(resultConsumer, executor));
+                    wrapAsRemoteCallback(resultConsumer, executor));
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
@@ -359,22 +359,18 @@
     }
 
 
-    private RemoteCallback wrapResultReceiverAsReadOnly(
-            @NonNull Consumer<Map<String, FileInputStream>> resultConsumer,
+    private RemoteCallback wrapAsRemoteCallback(
+            @NonNull Consumer<Map<String, ParcelFileDescriptor>> resultConsumer,
             @NonNull Executor executor) {
         return new RemoteCallback(result -> {
             if (result == null) {
                 executor.execute(() -> resultConsumer.accept(new HashMap<>()));
             } else {
-                Map<String, FileInputStream> bundleMap = new HashMap<>();
-                result.keySet().forEach(key -> {
-                    ParcelFileDescriptor pfd = result.getParcelable(key,
-                            ParcelFileDescriptor.class);
-                    if (pfd != null) {
-                        bundleMap.put(key, new FileInputStream(pfd.getFileDescriptor()));
-                    }
-                });
-                executor.execute(() -> resultConsumer.accept(bundleMap));
+                Map<String, ParcelFileDescriptor> pfdMap = new HashMap<>();
+                result.keySet().forEach(key ->
+                        pfdMap.put(key, result.getParcelable(key,
+                                ParcelFileDescriptor.class)));
+                executor.execute(() -> resultConsumer.accept(pfdMap));
             }
         });
     }