Skip to content

Commit

Permalink
add fd cache so that it won't show content provider permission denial…
Browse files Browse the repository at this point in the history
… after activity recreate
  • Loading branch information
cinit committed Dec 19, 2021
1 parent d4cec67 commit 4e52b18
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import cc.ioctl.nfcdevicehost.ipc.daemon.INciHostDaemon;
import cc.ioctl.nfcdevicehost.databinding.FragmentMainDumpBinding;
import cc.ioctl.nfcdevicehost.decoder.NxpHalV2EventTranslator;
import cc.ioctl.nfcdevicehost.util.SafUtils;
import cc.ioctl.nfcdevicehost.util.ThreadManager;

/**
Expand Down Expand Up @@ -134,10 +135,9 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
return null;
}
Uri uri = Uri.parse(uriPath);
final ContentResolver resolver = requireContext().getContentResolver();
ThreadManager.async(() -> {
try {
InputStream is = resolver.openInputStream(uri);
InputStream is = SafUtils.openInputStream(requireContext(), uri);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
Expand Down
70 changes: 70 additions & 0 deletions app/src/main/java/cc/ioctl/nfcdevicehost/util/SafUtils.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
package cc.ioctl.nfcdevicehost.util;

import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Objects;

import cc.ioctl.nfcdevicehost.activity.ShadowSafTransientActivity;
Expand Down Expand Up @@ -136,4 +146,64 @@ public void commit() {
}

}

private static final HashMap<String, ParcelFileDescriptor> sCachedFileDescriptors = new HashMap<>();

/**
* Open an input stream for the given uri. The result is cached.
* TODO: add a lifecycle callback to clear the cached fd when the activity is destroyed.
*
* @param context the activity or application context
* @param uri the uri of the file to be opened
* @return the input stream of the file
* @throws IOException if any error occurs
* @throws SecurityException if access denied by the content provider
*/
public static InputStream openInputStream(@NonNull Context context, @NonNull Uri uri)
throws IOException, SecurityException {
Objects.requireNonNull(context, "context");
Objects.requireNonNull(uri, "uri");
try {
ParcelFileDescriptor fd = context.getContentResolver().openFileDescriptor(uri, "r");
if (fd == null) {
throw new IOException("Failed to open " + uri + ", is the provider still running?");
}
ParcelFileDescriptor dup = fd.dup();
synchronized (sCachedFileDescriptors) {
ParcelFileDescriptor old = sCachedFileDescriptors.put(uri.toString(), dup);
if (old != null) {
old.close();
}
sCachedFileDescriptors.put(uri.toString(), dup);
}
// do not close the fd, it will be closed when the input stream is closed
return new FileInputStream(fd.getFileDescriptor());
} catch (SecurityException se) {
// the access is denied, maybe there is an activity recreation?
// try to open the input stream by a cached file descriptor
ParcelFileDescriptor dup = null;
synchronized (sCachedFileDescriptors) {
ParcelFileDescriptor cached = sCachedFileDescriptors.get(uri.toString());
if (cached != null) {
dup = cached.dup();
}
}
if (dup != null) {
FileDescriptor fd = dup.getFileDescriptor();
try {
// set the offset to 0
Os.lseek(fd, 0, OsConstants.SEEK_SET);
// do not close the fd, it will be closed when the input stream is closed
return new FileInputStream(fd);
} catch (ErrnoException e) {
dup.close();
throw new IOException("Failed to seek to the beginning of the file", e);
}
} else {
// we have no cached file descriptor, re-throw the exception
throw se;
}
}
}

}

0 comments on commit 4e52b18

Please sign in to comment.