Home | History | Annotate | Download | only in archives
      1 /*
      2  * Copyright (C) 2016 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 
     17 package com.android.documentsui.archives;
     18 
     19 import com.android.documentsui.tests.R;
     20 
     21 import android.content.Context;
     22 import android.content.res.AssetFileDescriptor;
     23 import android.database.Cursor;
     24 import android.database.MatrixCursor;
     25 import android.database.MatrixCursor.RowBuilder;
     26 import android.net.Uri;
     27 import android.os.CancellationSignal;
     28 import android.os.ParcelFileDescriptor;
     29 import android.provider.DocumentsContract;
     30 import android.provider.DocumentsContract.Document;
     31 import android.provider.DocumentsContract.Root;
     32 import android.provider.DocumentsProvider;
     33 import android.webkit.MimeTypeMap;
     34 
     35 import libcore.io.IoUtils;
     36 
     37 import java.io.File;
     38 import java.io.FileNotFoundException;
     39 import java.util.HashMap;
     40 import java.util.Map;
     41 import java.util.concurrent.ExecutorService;
     42 import java.util.concurrent.Executors;
     43 
     44 
     45 public class ResourcesProvider extends DocumentsProvider {
     46     public static final String AUTHORITY = "com.android.documentsui.archives.resourcesprovider";
     47 
     48     private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
     49             Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID
     50     };
     51     private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
     52             Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME,
     53             Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
     54     };
     55 
     56     private static final Map<String, Integer> RESOURCES = new HashMap<>();
     57     static {
     58         RESOURCES.put("archive.zip", R.raw.archive);
     59         RESOURCES.put("empty_dirs.zip", R.raw.empty_dirs);
     60         RESOURCES.put("no_dirs.zip", R.raw.no_dirs);
     61         RESOURCES.put("broken.zip", R.raw.broken);
     62     }
     63 
     64     private ExecutorService mExecutor = null;
     65     private TestUtils mTestUtils = null;
     66 
     67     @Override
     68     public boolean onCreate() {
     69         mExecutor = Executors.newSingleThreadExecutor();
     70         mTestUtils = new TestUtils(getContext(), getContext(), mExecutor);
     71         return true;
     72     }
     73 
     74     @Override
     75     public Cursor queryRoots(String[] projection) throws FileNotFoundException {
     76         final MatrixCursor result = new MatrixCursor(projection != null ? projection
     77                 : DEFAULT_ROOT_PROJECTION);
     78         final RowBuilder row = result.newRow();
     79         row.add(Root.COLUMN_ROOT_ID, "root-id");
     80         row.add(Root.COLUMN_FLAGS, 0);
     81         row.add(Root.COLUMN_TITLE, "ResourcesProvider");
     82         row.add(Root.COLUMN_DOCUMENT_ID, "root-document-id");
     83         return result;
     84     }
     85 
     86     @Override
     87     public Cursor queryDocument(String documentId, String[] projection)
     88             throws FileNotFoundException {
     89         final MatrixCursor result = new MatrixCursor(projection != null ? projection
     90                 : DEFAULT_DOCUMENT_PROJECTION);
     91         if ("root-document-id".equals(documentId)) {
     92             final RowBuilder row = result.newRow();
     93             row.add(Document.COLUMN_DOCUMENT_ID, "root-document-id");
     94             row.add(Document.COLUMN_FLAGS, 0);
     95             row.add(Document.COLUMN_DISPLAY_NAME, "ResourcesProvider");
     96             row.add(Document.COLUMN_SIZE, 0);
     97             row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
     98             return result;
     99         }
    100 
    101         includeDocument(result, documentId);
    102         return result;
    103     }
    104 
    105     @Override
    106     public Cursor queryChildDocuments(
    107             String parentDocumentId, String[] projection, String sortOrder)
    108             throws FileNotFoundException {
    109         if (!"root-document-id".equals(parentDocumentId)) {
    110             throw new FileNotFoundException();
    111         }
    112 
    113         final MatrixCursor result = new MatrixCursor(projection != null ? projection
    114                 : DEFAULT_DOCUMENT_PROJECTION);
    115         for (String documentId : RESOURCES.keySet()) {
    116             includeDocument(result, documentId);
    117         }
    118         return result;
    119     }
    120 
    121     @Override
    122     public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
    123             throws FileNotFoundException {
    124         final Integer resourceId = RESOURCES.get(docId);
    125         if (resourceId == null) {
    126             throw new FileNotFoundException();
    127         }
    128         return mTestUtils.getSeekableDescriptor(resourceId);
    129     }
    130 
    131     void includeDocument(MatrixCursor result, String documentId) throws FileNotFoundException {
    132         final Integer resourceId = RESOURCES.get(documentId);
    133         if (resourceId == null) {
    134             throw new FileNotFoundException();
    135         }
    136 
    137         AssetFileDescriptor fd = null;
    138         try {
    139             fd = getContext().getResources().openRawResourceFd(resourceId);
    140             final RowBuilder row = result.newRow();
    141             row.add(Document.COLUMN_DOCUMENT_ID, documentId);
    142             row.add(Document.COLUMN_FLAGS, 0);
    143             row.add(Document.COLUMN_DISPLAY_NAME, documentId);
    144 
    145             final int lastDot = documentId.lastIndexOf('.');
    146             assert(lastDot > 0);
    147             final String extension = documentId.substring(lastDot + 1).toLowerCase();
    148             final String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    149 
    150             row.add(Document.COLUMN_MIME_TYPE, mimeType);
    151             row.add(Document.COLUMN_SIZE, fd.getLength());
    152         }
    153         finally {
    154             IoUtils.closeQuietly(fd);
    155         }
    156     }
    157 }
    158