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

Commit 58514937 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Resized thumbnails; async; extend MatrixCursor." into klp-dev

parents f855a2ff 9d0843df
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -8052,6 +8052,7 @@ package android.database {
  public class MatrixCursor.RowBuilder {
    method public android.database.MatrixCursor.RowBuilder add(java.lang.Object);
    method public android.database.MatrixCursor.RowBuilder offer(java.lang.String, java.lang.Object);
  }
  public class MergeCursor extends android.database.AbstractCursor {
+36 −11
Original line number Diff line number Diff line
@@ -83,11 +83,10 @@ public class MatrixCursor extends AbstractCursor {
     *  row
     */
    public RowBuilder newRow() {
        rowCount++;
        int endIndex = rowCount * columnCount;
        final int row = rowCount++;
        final int endIndex = rowCount * columnCount;
        ensureCapacity(endIndex);
        int start = endIndex - columnCount;
        return new RowBuilder(start, endIndex);
        return new RowBuilder(row);
    }

    /**
@@ -180,18 +179,29 @@ public class MatrixCursor extends AbstractCursor {
    }

    /**
     * Builds a row, starting from the left-most column and adding one column
     * value at a time. Follows the same ordering as the column names specified
     * at cursor construction time.
     * Builds a row of values using either of these approaches:
     * <ul>
     * <li>Values can be added with explicit column ordering using
     * {@link #add(Object)}, which starts from the left-most column and adds one
     * column value at a time. This follows the same ordering as the column
     * names specified at cursor construction time.
     * <li>Column and value pairs can be offered for possible inclusion using
     * {@link #offer(String, Object)}. If the cursor includes the given column,
     * the value will be set for that column, otherwise the value is ignored.
     * This approach is useful when matching data to a custom projection.
     * </ul>
     * Undefined values are left as {@code null}.
     */
    public class RowBuilder {
        private final int row;
        private final int endIndex;

        private int index;
        private final int endIndex;

        RowBuilder(int index, int endIndex) {
            this.index = index;
            this.endIndex = endIndex;
        RowBuilder(int row) {
            this.row = row;
            this.index = row * columnCount;
            this.endIndex = index + columnCount;
        }

        /**
@@ -210,6 +220,21 @@ public class MatrixCursor extends AbstractCursor {
            data[index++] = columnValue;
            return this;
        }

        /**
         * Offer value for possible inclusion if this cursor defines the given
         * column. Columns not defined by the cursor are silently ignored.
         *
         * @return this builder to support chaining
         */
        public RowBuilder offer(String columnName, Object value) {
            for (int i = 0; i < columnNames.length; i++) {
                if (columnName.equals(columnNames[i])) {
                    data[(row * columnCount) + i] = value;
                }
            }
            return this;
        }
    }

    // AbstractCursor implementation.
+17 −5
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.google.android.collect.Lists;

import libcore.io.IoUtils;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
@@ -461,16 +462,27 @@ public final class DocumentsContract {
        final Bundle opts = new Bundle();
        opts.putParcelable(EXTRA_THUMBNAIL_SIZE, size);

        InputStream is = null;
        AssetFileDescriptor afd = null;
        try {
            is = new AssetFileDescriptor.AutoCloseInputStream(
                    resolver.openTypedAssetFileDescriptor(documentUri, "image/*", opts));
            return BitmapFactory.decodeStream(is);
            afd = resolver.openTypedAssetFileDescriptor(documentUri, "image/*", opts);

            final FileDescriptor fd = afd.getFileDescriptor();
            final BitmapFactory.Options bitmapOpts = new BitmapFactory.Options();

            bitmapOpts.inJustDecodeBounds = true;
            BitmapFactory.decodeFileDescriptor(fd, null, bitmapOpts);

            final int widthSample = bitmapOpts.outWidth / size.x;
            final int heightSample = bitmapOpts.outHeight / size.y;

            bitmapOpts.inJustDecodeBounds = false;
            bitmapOpts.inSampleSize = Math.min(widthSample, heightSample);
            return BitmapFactory.decodeFileDescriptor(fd, null, bitmapOpts);
        } catch (IOException e) {
            Log.w(TAG, "Failed to load thumbnail for " + documentUri + ": " + e);
            return null;
        } finally {
            IoUtils.closeQuietly(is);
            IoUtils.closeQuietly(afd);
        }
    }

+4 −2
Original line number Diff line number Diff line
@@ -19,8 +19,8 @@ package android.provider;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
@@ -532,7 +532,8 @@ public final class MediaStore {
        private static final Object sThumbBufLock = new Object();
        private static byte[] sThumbBuf;

        private static Bitmap getMiniThumbFromFile(Cursor c, Uri baseUri, ContentResolver cr, BitmapFactory.Options options) {
        private static Bitmap getMiniThumbFromFile(
                Cursor c, Uri baseUri, ContentResolver cr, BitmapFactory.Options options) {
            Bitmap bitmap = null;
            Uri thumbUri = null;
            try {
@@ -577,6 +578,7 @@ public final class MediaStore {
                if (c != null) c.close();
            }
        }

        /**
         * This method ensure thumbnails associated with origId are generated and decode the byte
         * stream from database (MICRO_KIND) or file (MINI_KIND).
+50 −0
Original line number Diff line number Diff line
@@ -128,6 +128,56 @@ public class MatrixCursorTest extends TestCase {
        } catch (IllegalArgumentException e) { /* expected */ }
    }

    public void testRowBuilderOffer() {
        MatrixCursor cursor = newMatrixCursor();

        cursor.newRow()
                .offer("float", 4.2f)
                .offer("string", "foobar")
                .offer("blob", new byte[] {(byte) 0xaa, (byte) 0x55})
                .offer("lolwat", "kittens");

        cursor.newRow();

        cursor.newRow()
                .offer("string", "zero")
                .offer("string", "one")
                .offer("string", "two")
                .offer("lolwat", "kittens");

        assertTrue(cursor.moveToFirst());
        assertEquals("foobar", cursor.getString(0));
        assertEquals(null, cursor.getString(1));
        assertEquals(0, cursor.getShort(1));
        assertEquals(0, cursor.getInt(2));
        assertEquals(0, cursor.getLong(3));
        assertEquals(4.2f, cursor.getFloat(4));
        assertEquals(0.0d, cursor.getDouble(5));
        MoreAsserts.assertEquals(new byte[] {(byte) 0xaa, (byte) 0x55}, cursor.getBlob(6));

        assertTrue(cursor.moveToNext());
        assertEquals(null, cursor.getString(0));
        assertEquals(0, cursor.getShort(1));
        assertEquals(0, cursor.getInt(2));
        assertEquals(0, cursor.getLong(3));
        assertEquals(0.0f, cursor.getFloat(4));
        assertEquals(0.0d, cursor.getDouble(5));
        assertEquals(null, cursor.getBlob(6));

        assertTrue(cursor.moveToNext());
        assertEquals("two", cursor.getString(0));
        assertEquals(0, cursor.getShort(1));
        assertEquals(0, cursor.getInt(2));
        assertEquals(0, cursor.getLong(3));
        assertEquals(0.0f, cursor.getFloat(4));
        assertEquals(0.0d, cursor.getDouble(5));
        assertEquals(null, cursor.getBlob(6));

        assertTrue(cursor.isLast());
        assertFalse(cursor.moveToNext());
        assertTrue(cursor.isAfterLast());
    }

    static class NonIterableArrayList<T> extends ArrayList<T> {

        NonIterableArrayList() {}
Loading