1 /* 2 * Copyright (C) 2013 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; 18 19 import static com.android.documentsui.base.DocumentInfo.getCursorString; 20 21 import android.content.ContentProviderClient; 22 import android.database.Cursor; 23 import android.os.FileUtils; 24 import android.provider.DocumentsContract; 25 import android.util.Log; 26 27 import com.android.documentsui.archives.ArchivesProvider; 28 import com.android.documentsui.base.DocumentInfo; 29 30 import java.util.HashSet; 31 import java.util.Set; 32 33 public class DirectoryResult implements AutoCloseable { 34 35 private static final String TAG = "DirectoryResult"; 36 37 public Exception exception; 38 public DocumentInfo doc; 39 ContentProviderClient client; 40 41 private Cursor mCursor; 42 private Set<String> mFileNames; 43 private String[] mModelIds; 44 45 @Override close()46 public void close() { 47 FileUtils.closeQuietly(mCursor); 48 if (client != null && doc.isInArchive()) { 49 ArchivesProvider.releaseArchive(client, doc.derivedUri); 50 } 51 FileUtils.closeQuietly(client); 52 client = null; 53 doc = null; 54 55 setCursor(null); 56 } 57 getCursor()58 public Cursor getCursor() { 59 return mCursor; 60 } 61 getModelIds()62 public String[] getModelIds() { 63 return mModelIds; 64 } 65 getFileNames()66 public Set<String> getFileNames() { 67 return mFileNames; 68 } 69 70 /** Update the cursor and populate cursor-related fields. */ setCursor(Cursor cursor)71 public void setCursor(Cursor cursor) { 72 mCursor = cursor; 73 74 if (mCursor == null) { 75 mFileNames = null; 76 mModelIds = null; 77 } else { 78 loadDataFromCursor(); 79 } 80 } 81 82 /** Populate cursor-related field. Must not be called from UI thread. */ loadDataFromCursor()83 private void loadDataFromCursor() { 84 ThreadHelper.assertNotOnMainThread(); 85 int cursorCount = mCursor.getCount(); 86 String[] modelIds = new String[cursorCount]; 87 Set<String> fileNames = new HashSet<>(); 88 try { 89 mCursor.moveToPosition(-1); 90 for (int pos = 0; pos < cursorCount; ++pos) { 91 if (!mCursor.moveToNext()) { 92 Log.e(TAG, "Fail to move cursor to next pos: " + pos); 93 return; 94 } 95 96 // Generates a Model ID for a cursor entry that refers to a document. The Model 97 // ID is a unique string that can be used to identify the document referred to by 98 // the cursor. Prefix the ids with the authority to avoid collisions. 99 modelIds[pos] = ModelId.build(mCursor); 100 fileNames.add( 101 getCursorString(mCursor, DocumentsContract.Document.COLUMN_DISPLAY_NAME)); 102 } 103 } catch (Exception e) { 104 Log.e(TAG, "Exception when moving cursor. Stale cursor?", e); 105 return; 106 } 107 108 // Model related data is only non-null when no error iterating through cursor. 109 mModelIds = modelIds; 110 mFileNames = fileNames; 111 } 112 } 113