mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-26 11:51:10 +01:00
Share media from within Media Preview and share QR code image.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
package org.thoughtcrime.securesms.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.MemoryFile;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.ProxyFileDescriptorCallback;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.OsConstants;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Objects;
|
||||
|
||||
@RequiresApi(api = 26)
|
||||
final class MemoryFileDescriptorProxy {
|
||||
|
||||
private static final String TAG = Log.tag(MemoryFileDescriptorProxy.class);
|
||||
|
||||
public static ParcelFileDescriptor create(@NonNull Context context,
|
||||
@NonNull MemoryFile file)
|
||||
throws IOException
|
||||
{
|
||||
StorageManager storageManager = Objects.requireNonNull(context.getSystemService(StorageManager.class));
|
||||
HandlerThread thread = new HandlerThread("MemoryFile");
|
||||
|
||||
thread.start();
|
||||
Log.i(TAG, "Thread started");
|
||||
|
||||
Handler handler = new Handler(thread.getLooper());
|
||||
ProxyCallback proxyCallback = new ProxyCallback(file, () -> {
|
||||
if (thread.quitSafely()) {
|
||||
Log.i(TAG, "Thread quitSafely true");
|
||||
} else {
|
||||
Log.w(TAG, "Thread quitSafely false");
|
||||
}
|
||||
});
|
||||
|
||||
ParcelFileDescriptor parcelFileDescriptor = storageManager.openProxyFileDescriptor(ParcelFileDescriptor.MODE_READ_ONLY,
|
||||
proxyCallback,
|
||||
handler);
|
||||
|
||||
Log.i(TAG, "Created");
|
||||
return parcelFileDescriptor;
|
||||
}
|
||||
|
||||
private static final class ProxyCallback extends ProxyFileDescriptorCallback {
|
||||
|
||||
private final MemoryFile memoryFile;
|
||||
private final Runnable onClose;
|
||||
|
||||
ProxyCallback(@NonNull MemoryFile memoryFile, Runnable onClose) {
|
||||
this.memoryFile = memoryFile;
|
||||
this.onClose = onClose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long onGetSize() {
|
||||
return memoryFile.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onRead(long offset, int size, byte[] data) throws ErrnoException {
|
||||
try {
|
||||
InputStream inputStream = memoryFile.getInputStream();
|
||||
if(inputStream.skip(offset) != offset){
|
||||
throw new AssertionError();
|
||||
}
|
||||
return inputStream.read(data, 0, size);
|
||||
} catch (IOException e) {
|
||||
throw new ErrnoException("onRead", OsConstants.EBADF);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRelease() {
|
||||
Log.i(TAG, "onRelease()");
|
||||
memoryFile.close();
|
||||
onClose.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,50 @@
|
||||
package org.thoughtcrime.securesms.util;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Build;
|
||||
import android.os.MemoryFile;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class MemoryFileUtil {
|
||||
public final class MemoryFileUtil {
|
||||
|
||||
public static ParcelFileDescriptor getParcelFileDescriptor(MemoryFile file) throws IOException {
|
||||
private MemoryFileUtil() {}
|
||||
|
||||
public static ParcelFileDescriptor getParcelFileDescriptor(@NonNull MemoryFile file)
|
||||
throws IOException
|
||||
{
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
return MemoryFileDescriptorProxy.create(ApplicationDependencies.getApplication(), file);
|
||||
} else {
|
||||
return getParcelFileDescriptorLegacy(file);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("JavaReflectionMemberAccess")
|
||||
@SuppressLint("PrivateApi")
|
||||
public static ParcelFileDescriptor getParcelFileDescriptorLegacy(@NonNull MemoryFile file)
|
||||
throws IOException
|
||||
{
|
||||
try {
|
||||
Method method = MemoryFile.class.getDeclaredMethod("getFileDescriptor");
|
||||
FileDescriptor fileDescriptor = (FileDescriptor) method.invoke(file);
|
||||
|
||||
Field field = fileDescriptor.getClass().getDeclaredField("descriptor");
|
||||
Field field = fileDescriptor.getClass().getDeclaredField("descriptor");
|
||||
field.setAccessible(true);
|
||||
|
||||
int fd = field.getInt(fileDescriptor);
|
||||
|
||||
return ParcelFileDescriptor.adoptFd(fd);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IOException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IOException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new IOException(e);
|
||||
} catch (NoSuchFieldException e) {
|
||||
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | NoSuchFieldException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user