Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cca31ebb authored by Tomasz Mikolajewski's avatar Tomasz Mikolajewski
Browse files

Add support to virtual and typed files in StubProvider.

Bug: 26147488
Change-Id: I40a75547ff16bb7d45f36843c29692268b4291b6
parent a416cd02
Loading
Loading
Loading
Loading
+103 −36
Original line number Original line Diff line number Diff line
@@ -44,9 +44,11 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map;


public class StubProvider extends DocumentsProvider {
public class StubProvider extends DocumentsProvider {
@@ -105,7 +107,13 @@ public class StubProvider extends DocumentsProvider {


        mRoots.clear();
        mRoots.clear();
        for (String rootId : rootIds) {
        for (String rootId : rootIds) {
            final RootInfo rootInfo = new RootInfo(rootId, getSize(rootId));
            // Make a subdir in the cache dir for each root.
            final File file = new File(getContext().getCacheDir(), rootId);
            if (file.mkdir()) {
                Log.i(TAG, "Created new root directory @ " + file.getPath());
            }
            final RootInfo rootInfo = new RootInfo(file, getSize(rootId));
            mStorage.put(rootInfo.document.documentId, rootInfo.document);
            mRoots.put(rootId, rootInfo);
            mRoots.put(rootId, rootInfo);
        }
        }
    }
    }
@@ -188,7 +196,7 @@ public class StubProvider extends DocumentsProvider {
                created = file.createNewFile();
                created = file.createNewFile();
            } catch (IOException e) {
            } catch (IOException e) {
                // We'll throw an FNF exception later :)
                // We'll throw an FNF exception later :)
                Log.e(TAG, "createnewFile operation failed for file: " + file, e);
                Log.e(TAG, "createNewFile operation failed for file: " + file, e);
            }
            }
            if (!created) {
            if (!created) {
                throw new FileNotFoundException(
                throw new FileNotFoundException(
@@ -197,7 +205,8 @@ public class StubProvider extends DocumentsProvider {
            Log.i(TAG, "Created new file: " + file);
            Log.i(TAG, "Created new file: " + file);
        }
        }


        final StubDocument document = new StubDocument(file, mimeType, parent);
        final StubDocument document = StubDocument.createRegularDocument(file, mimeType, parent);
        mStorage.put(document.documentId, document);
        Log.d(TAG, "Created document " + document.documentId);
        Log.d(TAG, "Created document " + document.documentId);
        notifyParentChanged(document.parentId);
        notifyParentChanged(document.parentId);
        getContext().getContentResolver().notifyChange(
        getContext().getContentResolver().notifyChange(
@@ -264,14 +273,18 @@ public class StubProvider extends DocumentsProvider {
    public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
    public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
            throws FileNotFoundException {
            throws FileNotFoundException {
        final StubDocument document = mStorage.get(docId);
        final StubDocument document = mStorage.get(docId);
        if (document == null || !document.file.isFile())
        if (document == null || !document.file.isFile()) {
            throw new FileNotFoundException();
            throw new FileNotFoundException();
        }
        if ((document.flags & Document.FLAG_VIRTUAL_DOCUMENT) != 0) {
            throw new IllegalStateException("Tried to open a virtual file.");
        }


        if ("r".equals(mode)) {
        if ("r".equals(mode)) {
            ParcelFileDescriptor pfd = ParcelFileDescriptor.open(document.file,
            final ParcelFileDescriptor pfd = ParcelFileDescriptor.open(document.file,
                        ParcelFileDescriptor.MODE_READ_ONLY);
                        ParcelFileDescriptor.MODE_READ_ONLY);
            if (docId.equals(mSimulateReadErrors)) {
            if (docId.equals(mSimulateReadErrors)) {
                pfd = new ParcelFileDescriptor(pfd) {
                return new ParcelFileDescriptor(pfd) {
                    @Override
                    @Override
                    public void checkError() throws IOException {
                    public void checkError() throws IOException {
                        throw new IOException("Test error");
                        throw new IOException("Test error");
@@ -298,6 +311,37 @@ public class StubProvider extends DocumentsProvider {
        throw new FileNotFoundException();
        throw new FileNotFoundException();
    }
    }


    @Override
    public AssetFileDescriptor openTypedDocument(
            String documentId, String mimeTypeFilter, Bundle opts, CancellationSignal signal)
            throws FileNotFoundException {
        final StubDocument document = mStorage.get(documentId);
        if (document == null || !document.file.isFile()) {
            throw new FileNotFoundException();
        }
        if ((document.flags & Document.FLAG_SUPPORTS_TYPED_DOCUMENT) == 0) {
            throw new IllegalStateException("Tried to open a non-typed document as typed.");
        }
        for (final String mimeType : document.streamTypes) {
            // Strict compare won't accept wildcards, but that's OK for tests, as DocumentsUI
            // doesn't use them for openTypedDocument.
            if (mimeType.equals(mimeTypeFilter)) {
                ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
                            document.file, ParcelFileDescriptor.MODE_READ_ONLY);
                if (!documentId.equals(mSimulateReadErrors)) {
                    pfd = new ParcelFileDescriptor(pfd) {
                        @Override
                        public void checkError() throws IOException {
                            throw new IOException("Test error");
                        }
                    };
                }
                return new AssetFileDescriptor(pfd, 0, document.file.length());
            }
        }
        throw new IllegalArgumentException("Invalid MIME type filter for openTypedDocument().");
    }

    private ParcelFileDescriptor startWrite(final StubDocument document)
    private ParcelFileDescriptor startWrite(final StubDocument document)
            throws FileNotFoundException {
            throws FileNotFoundException {
        ParcelFileDescriptor[] pipe;
        ParcelFileDescriptor[] pipe;
@@ -398,14 +442,7 @@ public class StubProvider extends DocumentsProvider {
        row.add(Document.COLUMN_DISPLAY_NAME, document.file.getName());
        row.add(Document.COLUMN_DISPLAY_NAME, document.file.getName());
        row.add(Document.COLUMN_SIZE, document.file.length());
        row.add(Document.COLUMN_SIZE, document.file.length());
        row.add(Document.COLUMN_MIME_TYPE, document.mimeType);
        row.add(Document.COLUMN_MIME_TYPE, document.mimeType);
        int flags = Document.FLAG_SUPPORTS_DELETE;
        row.add(Document.COLUMN_FLAGS, document.flags);
        // TODO: Add support for renaming.
        if (document.file.isDirectory()) {
            flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
        } else {
            flags |= Document.FLAG_SUPPORTS_WRITE;
        }
        row.add(Document.COLUMN_FLAGS, flags);
        row.add(Document.COLUMN_LAST_MODIFIED, document.file.lastModified());
        row.add(Document.COLUMN_LAST_MODIFIED, document.file.lastModified());
    }
    }


@@ -469,7 +506,8 @@ public class StubProvider extends DocumentsProvider {
            fout.write(content);
            fout.write(content);
            fout.close();
            fout.close();
        }
        }
        final StubDocument document = new StubDocument(file, mimeType, parent);
        final StubDocument document = StubDocument.createRegularDocument(file, mimeType, parent);
        mStorage.put(document.documentId, document);
        return DocumentsContract.buildDocumentUri(mAuthority,  document.documentId);
        return DocumentsContract.buildDocumentUri(mAuthority,  document.documentId);
    }
    }


@@ -489,21 +527,16 @@ public class StubProvider extends DocumentsProvider {
        return found.file;
        return found.file;
    }
    }


    final class RootInfo {
    final static class RootInfo {
        public final String name;
        public final String name;
        public final StubDocument document;
        public final StubDocument document;
        public long capacity;
        public long capacity;
        public long size;
        public long size;


        RootInfo(String name, long capacity) {
        RootInfo(File file, long capacity) {
            this.name = name;
            this.name = file.getName();
            this.capacity = 1024 * 1024;
            this.capacity = 1024 * 1024;
            // Make a subdir in the cache dir for each root.
            this.document = StubDocument.createRootDocument(file, this);
            File file = new File(getContext().getCacheDir(), name);
            if (file.mkdir()) {
                Log.i(TAG, "Created new root directory @ " + file.getPath());
            }
            this.document = new StubDocument(file, Document.MIME_TYPE_DIR, this);
            this.capacity = capacity;
            this.capacity = capacity;
            this.size = 0;
            this.size = 0;
        }
        }
@@ -513,38 +546,72 @@ public class StubProvider extends DocumentsProvider {
        }
        }
    }
    }


    final class StubDocument {
    final static class StubDocument {
        public final File file;
        public final File file;
        public final String mimeType;
        public final String documentId;
        public final String documentId;
        public final String mimeType;
        public final List<String> streamTypes;
        public final int flags;
        public final String parentId;
        public final String parentId;
        public final RootInfo rootInfo;
        public final RootInfo rootInfo;


        StubDocument(File file, String mimeType, StubDocument parent) {
        private StubDocument(
                 File file, String mimeType, List<String> streamTypes, int flags,
                 StubDocument parent) {
            this.file = file;
            this.file = file;
            this.mimeType = mimeType;
            this.documentId = getDocumentIdForFile(file);
            this.documentId = getDocumentIdForFile(file);
            this.mimeType = mimeType;
            this.streamTypes = streamTypes;
            this.flags = flags;
            this.parentId = parent.documentId;
            this.parentId = parent.documentId;
            this.rootInfo = parent.rootInfo;
            this.rootInfo = parent.rootInfo;
            mStorage.put(this.documentId, this);
        }
        }


        StubDocument(File file, String mimeType, RootInfo rootInfo) {
        private StubDocument(File file, RootInfo rootInfo) {
            this.file = file;
            this.file = file;
            this.mimeType = mimeType;
            this.documentId = getDocumentIdForFile(file);
            this.documentId = getDocumentIdForFile(file);
            this.mimeType = Document.MIME_TYPE_DIR;
            this.streamTypes = new ArrayList<String>();
            this.flags = Document.FLAG_DIR_SUPPORTS_CREATE;
            this.parentId = null;
            this.parentId = null;
            this.rootInfo = rootInfo;
            this.rootInfo = rootInfo;
            mStorage.put(this.documentId, this);
        }
        }

        public static StubDocument createRootDocument(File file, RootInfo rootInfo) {
            return new StubDocument(file, rootInfo);
        }

        public static StubDocument createRegularDocument(
                File file, String mimeType, StubDocument parent) {
            int flags = Document.FLAG_SUPPORTS_DELETE;
            if (file.isDirectory()) {
                flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
            } else {
                flags |= Document.FLAG_SUPPORTS_WRITE;
            }
            return new StubDocument(file, mimeType, new ArrayList<String>(), flags, parent);
        }

        public static StubDocument createVirtualDocument(
                File file, String mimeType, List<String> streamTypes, StubDocument parent) {
            int flags = Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_WRITE
                    | Document.FLAG_VIRTUAL_DOCUMENT;
            if (streamTypes.size() > 0) {
                flags |= Document.FLAG_SUPPORTS_TYPED_DOCUMENT;
            }
            return new StubDocument(file, mimeType, streamTypes, flags, parent);
        }

        @Override
        @Override
        public String toString() {
        public String toString() {
            return "StubDocument{"
            return "StubDocument{"
                    + "path:" + file.getPath()
                    + "path:" + file.getPath()
                    + ", mimeType:" + mimeType
                    + ", rootInfo:" + rootInfo
                    + ", documentId:" + documentId
                    + ", documentId:" + documentId
                    + ", mimeType:" + mimeType
                    + ", streamTypes:" + streamTypes.toString()
                    + ", flags:" + flags
                    + ", parentId:" + parentId
                    + ", parentId:" + parentId
                    + ", rootInfo:" + rootInfo
                    + "}";
                    + "}";
        }
        }
    }
    }