Move getImageSource to UniFile interface, and remove UniRandomAccessFile, it's a suck design

This commit is contained in:
tarsin committed 2023-02-27 17:24:04 +08:00
1 parent c4a3f06b51
commit 24ccf60870
10 files changed
+54 -479

No files matched your search

@@ -302,25 +302,7 @@ class SpiderDen(private val mGalleryInfo: GalleryInfo) {
file = findImageFile(dir, index)
}
}
if (file is RawFile) {
val source = ImageDecoder.createSource(file.mFile)
return object : CloseableSource {
override val source: ImageDecoder.Source
get() = source
override fun close() {}
}
}
if (file != null) {
val source = ImageDecoder.createSource(contentResolver, file.uri)
return object : CloseableSource {
override val source: ImageDecoder.Source
get() = source
override fun close() {}
}
}
return null
return file?.imageSource
}
companion object {
@@ -19,10 +19,13 @@ package com.hippo.unifile;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.graphics.ImageDecoder;
import android.net.Uri;
import androidx.annotation.NonNull;
import com.hippo.image.Image;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -117,4 +120,20 @@ final class Contracts {
throw new IOException("Can't open InputStream", e);
}
}
@NonNull
static Image.CloseableSource getImageSource(Context context, Uri uri) {
var source = ImageDecoder.createSource(context.getContentResolver(), uri);
return new Image.CloseableSource() {
@NonNull
@Override
public ImageDecoder.Source getSource() {
return source;
}
@Override
public void close() {
}
};
}
}
@@ -1,228 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.unifile;
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.IntDef;
import androidx.annotation.NonNull;
import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
class FileDescriptorRandomAccessFile implements UniRandomAccessFile {
public static final int FLUSH_NONE = 0;
public static final int FLUSH_FSYNC = 1;
public static final int FLUSH_FDATASYNC = 2;
private final ParcelFileDescriptor pfd;
private final FileDescriptor fd;
private final int flushAfterWrite;
private final Object closeLock = new Object();
private volatile boolean closed = false;
private FileDescriptorRandomAccessFile(ParcelFileDescriptor pfd, FileDescriptor fd, String mode) {
this.pfd = pfd;
this.fd = fd;
switch (mode) {
case "rws":
flushAfterWrite = FLUSH_FSYNC;
break;
case "rwd":
flushAfterWrite = FLUSH_FDATASYNC;
break;
default:
flushAfterWrite = FLUSH_NONE;
break;
}
}
@NonNull
static FileDescriptorRandomAccessFile create(Context context, Uri uri, String mode) throws IOException {
// Get FileDescriptor
ParcelFileDescriptor pfd;
try {
pfd = context.getContentResolver().openFileDescriptor(uri, mode);
} catch (Throwable e) {
Utils.throwIfFatal(e);
throw new IOException("Can't get ParcelFileDescriptor", e);
}
if (pfd == null) {
throw new IOException("Can't get ParcelFileDescriptor");
}
FileDescriptor fd;
try {
fd = pfd.getFileDescriptor();
} catch (SecurityException e) {
pfd.close();
throw new IOException("Can't get FileDescriptor", e);
}
if (fd == null) {
pfd.close();
throw new IOException("Can't get FileDescriptor");
}
return new FileDescriptorRandomAccessFile(pfd, fd, mode);
}
private void maybeSync() {
if (flushAfterWrite == FLUSH_FSYNC) {
try {
fd.sync();
} catch (IOException e) {
// Ignored
}
} else if (flushAfterWrite == FLUSH_FDATASYNC) {
try {
Os.fdatasync(fd);
} catch (ErrnoException e) {
// Ignored
}
}
}
@Override
public void close() throws IOException {
synchronized (closeLock) {
if (closed) {
return;
}
closed = true;
}
pfd.close();
try {
Os.close(fd);
} catch (ErrnoException e) {
throw new IOException("An ErrnoException occurs", e);
}
}
@Override
public long getFilePointer() throws IOException {
try {
return Os.lseek(fd, 0L, OsConstants.SEEK_CUR);
} catch (ErrnoException e) {
throw new IOException("An ErrnoException occurs", e);
}
}
@Override
public void seek(long pos) throws IOException {
if (pos < 0) {
throw new IOException("offset < 0: " + pos);
} else {
try {
Os.lseek(fd, pos, OsConstants.SEEK_SET);
} catch (ErrnoException e) {
throw new IOException("An ErrnoException occurs", e);
}
}
}
@Override
public int skipBytes(int n) throws IOException {
long pos;
long len;
long newpos;
if (n <= 0) {
return 0;
}
pos = getFilePointer();
len = length();
newpos = pos + n;
if (newpos > len) {
newpos = len;
}
seek(newpos);
/* return the actual number of bytes skipped */
return (int) (newpos - pos);
}
@Override
public long length() throws IOException {
try {
return Os.fstat(fd).st_size;
} catch (ErrnoException e) {
throw new IOException("An ErrnoException occurs", e);
}
}
@Override
public void setLength(long newLength) throws IOException {
if (newLength < 0) {
throw new IllegalArgumentException("newLength < 0");
}
try {
Os.ftruncate(fd, newLength);
} catch (ErrnoException e) {
throw new IOException("An ErrnoException occurs", e);
}
long filePointer = getFilePointer();
if (filePointer > newLength) {
seek(newLength);
}
maybeSync();
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
try {
return Os.read(fd, b, off, len);
} catch (ErrnoException e) {
throw new IOException("An ErrnoException occurs", e);
}
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
try {
Os.write(fd, b, off, len);
} catch (ErrnoException e) {
throw new IOException("An ErrnoException occurs", e);
}
maybeSync();
}
@IntDef({FLUSH_NONE, FLUSH_FSYNC, FLUSH_FDATASYNC})
@Retention(RetentionPolicy.SOURCE)
public @interface FlushMode {
}
}
@@ -21,6 +21,8 @@ import android.net.Uri;
import androidx.annotation.NonNull;
import com.hippo.image.Image;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -187,7 +189,7 @@ class MediaFile extends UniFile {
@NonNull
@Override
public UniRandomAccessFile createRandomAccessFile(String mode) throws IOException {
return FileDescriptorRandomAccessFile.create(mContext, mUri, mode);
public Image.CloseableSource getImageSource() {
return Contracts.getImageSource(mContext, mUri);
}
}
@@ -16,20 +16,21 @@
package com.hippo.unifile;
import android.graphics.ImageDecoder;
import android.net.Uri;
import android.util.Log;
import android.webkit.MimeTypeMap;
import androidx.annotation.NonNull;
import com.hippo.image.Image;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
public class RawFile extends UniFile {
@@ -264,9 +265,21 @@ public class RawFile extends UniFile {
return new FileInputStream(mFile);
}
@Override
@NonNull
public UniRandomAccessFile createRandomAccessFile(String mode) throws FileNotFoundException {
return new RawRandomAccessFile(new RandomAccessFile(mFile, mode));
@Override
public Image.CloseableSource getImageSource() {
var src = ImageDecoder.createSource(mFile);
return new Image.CloseableSource() {
@NonNull
@Override
public ImageDecoder.Source getSource() {
return src;
}
@Override
public void close() {
}
};
}
}
@@ -1,83 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.unifile;
/*
* Created by Hippo on 8/15/2016.
*/
import java.io.IOException;
import java.io.RandomAccessFile;
class RawRandomAccessFile implements UniRandomAccessFile {
private final RandomAccessFile mFile;
RawRandomAccessFile(RandomAccessFile file) {
mFile = file;
}
@Override
public void close() throws IOException {
mFile.close();
}
@Override
public long getFilePointer() throws IOException {
return mFile.getFilePointer();
}
@Override
public void seek(long pos) throws IOException {
mFile.seek(pos);
}
@Override
public int skipBytes(int n) throws IOException {
return mFile.skipBytes(n);
}
@Override
public long length() throws IOException {
return mFile.length();
}
@Override
public void setLength(long newLength) throws IOException {
mFile.setLength(newLength);
}
@Override
public int read(byte[] b) throws IOException {
return mFile.read(b);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return mFile.read(b, off, len);
}
@Override
public void write(byte[] b) throws IOException {
mFile.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
mFile.write(b, off, len);
}
}
@@ -21,6 +21,8 @@ import android.net.Uri;
import androidx.annotation.NonNull;
import com.hippo.image.Image;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -168,11 +170,7 @@ class SingleDocumentFile extends UniFile {
@NonNull
@Override
public UniRandomAccessFile createRandomAccessFile(String mode) throws IOException {
// Check file
if (!ensureFile()) {
throw new IOException("Can't make sure it is file");
}
return FileDescriptorRandomAccessFile.create(mContext, mUri, mode);
public Image.CloseableSource getImageSource() {
return Contracts.getImageSource(mContext, mUri);
}
}
@@ -24,6 +24,8 @@ import android.webkit.MimeTypeMap;
import androidx.annotation.NonNull;
import com.hippo.image.Image;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -267,12 +269,7 @@ class TreeDocumentFile extends UniFile {
@NonNull
@Override
public UniRandomAccessFile createRandomAccessFile(String mode) throws IOException {
// Check file
if (!ensureFile()) {
throw new IOException("Can't make sure it is file");
}
return FileDescriptorRandomAccessFile.create(mContext, mUri, mode);
public Image.CloseableSource getImageSource() {
return Contracts.getImageSource(mContext, mUri);
}
}
@@ -25,6 +25,8 @@ import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.hippo.image.Image;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -440,13 +442,7 @@ public abstract class UniFile {
@NonNull
public abstract InputStream openInputStream() throws IOException;
/**
* Get a random access stuff of the UniFile
*
* @param mode "r" or "rw"
* @return the random access stuff
* @throws IOException
*/
@NonNull
public abstract UniRandomAccessFile createRandomAccessFile(String mode) throws IOException;
public abstract Image.CloseableSource getImageSource();
}
@@ -1,121 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.unifile;
/*
* Created by Hippo on 8/15/2016.
*/
import java.io.IOException;
/**
* The UniRandomAccessFile is designed to emulate RandomAccessFile interface for UniFile
*/
public interface UniRandomAccessFile {
/**
* Closes this UniRandomAccessFile and releases any resources associated with it.
* A closed UniRandomAccessFile cannot perform any operations.
*
* @throws IOException
*/
void close() throws IOException;
/**
* Returns the current offset in this file.
*
* @throws IOException
*/
long getFilePointer() throws IOException;
/**
* Move current location pointer to the new offset.
*
* @param pos the offset position, measured in bytes from the beginning
* @throws IOException
*/
void seek(long pos) throws IOException;
/**
* Attempts to skip over n bytes of input discarding the skipped bytes.
*
* @param n the number of bytes to be skipped
* @return the actual number of bytes skipped
* @throws IOException
*/
int skipBytes(int n) throws IOException;
/**
* Returns the length of this file.
*
* @throws IOException
*/
long length() throws IOException;
/**
* Sets the length of this file.
*
* @param newLength the desired length of the file
* @throws IOException
*/
void setLength(long newLength) throws IOException;
/**
* Reads b.length bytes from this file into the byte array,
* starting at the current file pointer.
*
* @param b the buffer into which the data is read
* @return the total number of bytes read into the buffer, or
* {@code -1} if there is no more data because the end of
* the file has been reached.
* @throws IOException if an I/O error occurs
*/
int read(byte[] b) throws IOException;
/**
* Reads exactly len bytes from this file into the byte array,
* starting at the current file pointer.
*
* @param b the buffer into which the data is read
* @param off the start offset of the data
* @param len the number of bytes to read
* @return the total number of bytes read into the buffer, or
* {@code -1} if there is no more data because the end of
* the file has been reached.
* @throws IOException
*/
int read(byte[] b, int off, int len) throws IOException;
/**
* Writes b.length bytes from the specified byte array to this file,
* starting at the current file pointer.
*
* @param b the data
* @throws IOException
*/
void write(byte[] b) throws IOException;
/**
* Writes len bytes from the specified byte array starting at offset off to this file.
*
* @param b the data
* @param off the start offset in the data
* @param len the number of bytes to write
* @throws IOException
*/
void write(byte[] b, int off, int len) throws IOException;
}