hw-security / de.cotech.hw.util.fdutil

Package de.cotech.hw.util.fdutil


Name Summary

open class ParcelFileDescriptorUtil

Utility class for loading streamed data into a seekable ParcelFileDescriptor.

This covers the use case of passing streaming data via an ACTION_SEND or similar Intent, without caching to a file. This is especially useful for encrypted files, e.g. from a de.cotech.hw.util.stream.DecryptingFileInputStream.

Unlike ParcelFileDescriptors obtained from a ParcelFileDescriptor#createPipe(), this method returns a seekable ParcelFileDescriptor. In practice, virtually all receivers of Intents with streamed data require seekable file descriptors. android.content.ContentProvider

ParcelFileDescriptor openFile(Uri uri, String mode) {
      try {
          File file = database.getEncryptedFilenameForUri(uri);
          int plaintextLength = getPlaintextLengthForUri(uri);
          return parcelFileDescriptorCompat.loadToParcelFileDescriptor(file, plaintextLength);
      } catch (e: IOException) {
          throw new FileNotFoundException(e.getMessage());

Internally, this uses one of two mechanisms:

  • On Android O (sdk 26) or higher, it uses a android.os.ProxyFileDescriptorCallback backed by a reference-counted android.os.MemoryFile.
  • On earlier Android versions, it falls back to a mechanism based on ephemeral file descriptors. To this end, it creates a file on storage that is deleted immediately after opening a couple of file descriptors. These file descriptors are cached and used for any subsequent access. Note that this method does not keep data strictly in-memory, but it’s as close as we could get.

Note: in our tests, the technique of extracting the internal file descriptor of a MemoryFile using reflection did not actually yield a seekable ParcelFileDescriptor that worked as intended.