1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.provider.tests;
18
19import android.database.Cursor;
20import android.database.MatrixCursor.RowBuilder;
21import android.database.MatrixCursor;
22import android.net.Uri;
23import android.os.Bundle;
24import android.os.CancellationSignal;
25import android.os.ParcelFileDescriptor;
26import android.provider.DocumentsContract.Document;
27import android.provider.DocumentsContract;
28import android.provider.DocumentsProvider;
29import android.support.provider.DocumentArchiveHelper;
30import android.util.Log;
31
32import java.io.FileNotFoundException;
33import java.io.File;
34import java.io.IOException;
35
36/**
37 * Stub provider for testing support for archives.
38 */
39public class StubProvider extends DocumentsProvider {
40    public static final String AUTHORITY = "android.support.provider.tests.mystubprovider";
41    public static final String DOCUMENT_ID = "document-id";
42    public static final String FILE_DOCUMENT_ID = "document-id:dir1/cherries.txt";
43    public static final Uri NOTIFY_URI = DocumentsContract.buildRootsUri(AUTHORITY);
44
45    private static final String TAG = "StubProvider";
46    private static final String[] DEFAULT_PROJECTION = new String[] {
47            Document.COLUMN_DOCUMENT_ID, Document.COLUMN_DISPLAY_NAME, Document.COLUMN_SIZE,
48            Document.COLUMN_MIME_TYPE, Document.COLUMN_FLAGS,
49            DocumentArchiveHelper.COLUMN_LOCAL_FILE_PATH
50    };
51
52    public File file;
53    public DocumentArchiveHelper archiveHelper;
54    public boolean simulatedDelete = false;
55
56    @Override
57    public Bundle call(String method, String args, Bundle extras) {
58        switch (method) {
59            case "reset":
60                simulatedDelete = false;
61                getContext().getContentResolver().notifyChange(NOTIFY_URI, null);
62                return null;
63            case "delete":
64                simulatedDelete = true;
65                getContext().getContentResolver().notifyChange(NOTIFY_URI, null);
66                return null;
67            default:
68                return super.call(method, args, extras);
69        }
70    }
71
72    @Override
73    public boolean onCreate() {
74        try {
75            archiveHelper = new DocumentArchiveHelper(this, ':');
76            file = TestUtils.createFileFromResource(getContext(), R.raw.archive);
77            return true;
78        } catch (IOException e) {
79            Log.e(TAG, "Failed to initialize StubProvider.");
80            return false;
81        }
82    }
83
84    @Override
85    public ParcelFileDescriptor openDocument(
86            String documentId, String mode, CancellationSignal signal)
87            throws FileNotFoundException {
88        if (archiveHelper.isArchivedDocument(documentId)) {
89            return archiveHelper.openDocument(documentId, mode, signal);
90        }
91
92        throw new UnsupportedOperationException();
93    }
94
95    @Override
96    public Cursor queryChildDocuments(
97            String parentDocumentId, String[] projection, String sortOrder)
98            throws FileNotFoundException {
99        if (archiveHelper.isArchivedDocument(parentDocumentId) ||
100                archiveHelper.isSupportedArchiveType(getDocumentType(parentDocumentId))) {
101            return archiveHelper.queryChildDocuments(parentDocumentId, projection, sortOrder);
102        }
103
104        throw new UnsupportedOperationException();
105    }
106
107    @Override
108    public Cursor queryDocument(String documentId, String[] projection)
109            throws FileNotFoundException {
110        if (archiveHelper.isArchivedDocument(documentId)) {
111            return archiveHelper.queryDocument(documentId, projection);
112        }
113
114        if (DOCUMENT_ID.equals(documentId)) {
115            if (simulatedDelete) {
116                throw new FileNotFoundException();
117            }
118
119            final MatrixCursor result = new MatrixCursor(
120                    projection != null ? projection : DEFAULT_PROJECTION);
121            result.setNotificationUri(getContext().getContentResolver(), NOTIFY_URI);
122            final RowBuilder row = result.newRow();
123            row.add(Document.COLUMN_DOCUMENT_ID, DOCUMENT_ID);
124            row.add(Document.COLUMN_DISPLAY_NAME, file.getName());
125            row.add(Document.COLUMN_SIZE, file.length());
126            row.add(Document.COLUMN_MIME_TYPE, "application/zip");
127            final int flags = archiveHelper.isSupportedArchiveType("application/zip")
128                    ? Document.FLAG_ARCHIVE : 0;
129            row.add(Document.COLUMN_FLAGS, flags);
130            row.add(DocumentArchiveHelper.COLUMN_LOCAL_FILE_PATH, file.getPath());
131            return result;
132        }
133
134        throw new FileNotFoundException();
135    }
136
137    @Override
138    public Cursor queryRoots(String[] projection) throws FileNotFoundException {
139        throw new UnsupportedOperationException();
140    }
141
142    @Override
143    public String getDocumentType(String documentId) throws FileNotFoundException {
144        if (archiveHelper.isArchivedDocument(documentId)) {
145            return archiveHelper.getDocumentType(documentId);
146        }
147
148        if (DOCUMENT_ID.equals(documentId)) {
149            return "application/zip";
150        }
151
152        throw new UnsupportedOperationException();
153    }
154}
155