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

Commit da3785ae authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 7624

* changes:
  Impl. of the metadata getters.
parents eb7a869a cb2e00ee
Loading
Loading
Loading
Loading
+77 −31
Original line number Diff line number Diff line
@@ -20,10 +20,12 @@ import android.graphics.Bitmap;
import android.os.Parcel;
import android.util.Log;

import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Set;
import java.util.HashMap;
import java.util.Set;
import java.util.TimeZone;


/**
@@ -104,13 +106,18 @@ public class Metadata

    public static final int STRING_VAL     = 1;
    public static final int INTEGER_VAL    = 2;
    public static final int LONG_VAL = 3;
    public static final int DOUBLE_VAL = 4;
    public static final int TIMED_TEXT_VAL = 5;
    private static final int LAST_TYPE = 5;
    public static final int BOOLEAN_VAL    = 3;
    public static final int LONG_VAL       = 4;
    public static final int DOUBLE_VAL     = 5;
    public static final int TIMED_TEXT_VAL = 6;
    public static final int DATE_VAL       = 7;
    public static final int BYTE_ARRAY_VAL = 8;
    // FIXME: misses a type for shared heap is missing (MemoryFile).
    // FIXME: misses a type for bitmaps.
    private static final int LAST_TYPE = 8;

    private static final String TAG = "media.Metadata";
    private static final int kMetaHeaderSize = 8;  // 8 bytes for the size + the marker
    private static final int kMetaHeaderSize = 8;  //  size + marker
    private static final int kMetaMarker = 0x4d455441;  // 'M' 'E' 'T' 'A'
    private static final int kRecordHeaderSize = 12; // size + id + type

@@ -122,21 +129,28 @@ public class Metadata
    // Used to look up if a key was present too.
    // Key: Metadata ID
    // Value: Offset of the metadata type field in the record.
    private final HashMap<Integer, Integer> mKeyToPosMap = new HashMap<Integer, Integer>();
    private final HashMap<Integer, Integer> mKeyToPosMap =
            new HashMap<Integer, Integer>();

    /**
     * Helper class to hold a pair (time, text). Can be used to implement caption.
     * Helper class to hold a triple (time, duration, text). Can be used to
     * implement caption.
     */
    public class TimedText {
        private Date mTime;
        private int mDuration;  // millisec
        private String mText;
        public TimedText(final Date time, final String text) {

        public TimedText(Date time, int duration, String text) {
            mTime = time;
            mDuration = duration;
            mText = text;
        }

        public String toString() {
            StringBuilder res = new StringBuilder(80);
            res.append(mTime).append(":").append(mText);
            res.append(mTime).append("-").append(mDuration)
                    .append(":").append(mText);
            return res.toString();
        }
    }
@@ -300,44 +314,64 @@ public class Metadata
        return mKeyToPosMap.containsKey(metadataId);
    }

    // Accessors
    // Accessors.
    // Caller must make sure the key is present using the {@code has}
    // method otherwise a RuntimeException will occur.

    public String getString(final int key) {
        // FIXME: Implement.
        return new String();
        checkType(key, STRING_VAL);
        return mParcel.readString();
    }

    public int getInt(final int key) {
        // FIXME: Implement.
        return 0;
        checkType(key, INTEGER_VAL);
        return mParcel.readInt();
    }

    public boolean getBoolean(final int key) {
        checkType(key, BOOLEAN_VAL);
        return mParcel.readInt() == 1;
    }

    public long getLong(final int key) {
        // FIXME: Implement.
        return 0;
        checkType(key, LONG_VAL);
        return mParcel.readLong();
    }

    public double getDouble(final int key) {
        // FIXME: Implement.
        return 0.0;
        checkType(key, DOUBLE_VAL);
        return mParcel.readDouble();
    }

    public byte[] getByteArray(final int key) {
        return new byte[0];
    }

    public Bitmap getBitmap(final int key) {
        // FIXME: Implement.
        return null;
        checkType(key, BYTE_ARRAY_VAL);
        return mParcel.createByteArray();
    }

    public Date getDate(final int key) {
        // FIXME: Implement.
        return new Date();
        checkType(key, DATE_VAL);
        final long timeSinceEpoch = mParcel.readLong();
        final String timeZone = mParcel.readString();

        if (timeZone.length() == 0) {
            return new Date(timeSinceEpoch);
        } else {
            TimeZone tz = TimeZone.getTimeZone(timeZone);
            Calendar cal = Calendar.getInstance(tz);

            cal.setTimeInMillis(timeSinceEpoch);
            return cal.getTime();
        }
    }

    public TimedText getTimedText(final int key) {
        // FIXME: Implement.
        return new TimedText(new Date(0), "<missing>");
        checkType(key, TIMED_TEXT_VAL);
        final Date startTime = new Date(mParcel.readLong());  // epoch
        final int duration = mParcel.readInt();  // millisec

        return new TimedText(startTime,
                             duration,
                             mParcel.readString());
    }

    // @return the last available system metadata id. Ids are
@@ -360,4 +394,16 @@ public class Metadata
        }
        return true;
    }

    // Check the type of the data match what is expected.
    private void checkType(final int key, final int expectedType) {
        final int pos = mKeyToPosMap.get(key);

        mParcel.setDataPosition(pos);

        final int type = mParcel.readInt();
        if (type != expectedType) {
            throw new IllegalStateException("Wrong type " + expectedType + " but got " + type);
        }
    }
}
+222 −10
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@ import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;

import java.util.Calendar;
import java.util.Date;

/*
 * Check the Java layer that parses serialized metadata in Parcel
 * works as expected.
@@ -89,16 +92,6 @@ public class MediaPlayerMetadataParserTest extends AndroidTestCase {
        mParcel.writeInt(kMarker);
    }

    // Insert a string record at the current position.
    private void writeStringRecord(int metadataId, String val) {
        final int start = mParcel.dataPosition();
        mParcel.writeInt(-1);  // Placeholder for the length
        mParcel.writeInt(metadataId);
        mParcel.writeInt(Metadata.STRING_VAL);
        mParcel.writeString(val);
        adjustSize(start);
    }

    // ----------------------------------------------------------------------
    // START OF THE TESTS

@@ -133,7 +126,9 @@ public class MediaPlayerMetadataParserTest extends AndroidTestCase {
        assertParse();
    }

    // ----------------------------------------------------------------------
    // RECORDS
    // ----------------------------------------------------------------------

    // A record header should be at least 12 bytes long
    @SmallTest
@@ -223,4 +218,221 @@ public class MediaPlayerMetadataParserTest extends AndroidTestCase {
        assertFalse(mMetadata.has(Metadata.GENRE));
        assertFalse(mMetadata.has(Metadata.firstCustomId()));
    }

    // ----------------------------------------------------------------------
    // GETTERS
    // ----------------------------------------------------------------------

    // getString
    @SmallTest
    public void testGetString() throws Exception {
        writeStringRecord(Metadata.TITLE, "a title");
        writeStringRecord(Metadata.GENRE, "comedy");
        adjustSize();
        assertParse();

        assertEquals("a title", mMetadata.getString(Metadata.TITLE));
        assertEquals("comedy", mMetadata.getString(Metadata.GENRE));
    }

    // get an empty string.
    @SmallTest
    public void testGetEmptyString() throws Exception {
        writeStringRecord(Metadata.TITLE, "");
        adjustSize();
        assertParse();

        assertEquals("", mMetadata.getString(Metadata.TITLE));
    }

    // get a string when a NULL value was in the parcel
    @SmallTest
    public void testGetNullString() throws Exception {
        writeStringRecord(Metadata.TITLE, null);
        adjustSize();
        assertParse();

        assertEquals(null, mMetadata.getString(Metadata.TITLE));
    }

    // get a string when an integer is actually present
    @SmallTest
    public void testWrongType() throws Exception {
        writeIntRecord(Metadata.DURATION, 5);
        adjustSize();
        assertParse();

        try {
            mMetadata.getString(Metadata.DURATION);
        } catch (IllegalStateException ise) {
            return;
        }
        fail("Exception was not thrown");
    }

    // getInt
    @SmallTest
    public void testGetInt() throws Exception {
        writeIntRecord(Metadata.CD_TRACK_NUM, 1);
        adjustSize();
        assertParse();

        assertEquals(1, mMetadata.getInt(Metadata.CD_TRACK_NUM));
    }

    // getBoolean
    @SmallTest
    public void testGetBoolean() throws Exception {
        writeBooleanRecord(Metadata.DRM_CRIPPLED, true);
        adjustSize();
        assertParse();

        assertEquals(true, mMetadata.getBoolean(Metadata.DRM_CRIPPLED));
    }

    // getLong
    @SmallTest
    public void testGetLong() throws Exception {
        writeLongRecord(Metadata.DURATION, 1L);
        adjustSize();
        assertParse();

        assertEquals(1L, mMetadata.getLong(Metadata.DURATION));
    }

    // getDouble
    @SmallTest
    public void testGetDouble() throws Exception {
        writeDoubleRecord(Metadata.VIDEO_FRAME_RATE, 29.97);
        adjustSize();
        assertParse();

        assertEquals(29.97, mMetadata.getDouble(Metadata.VIDEO_FRAME_RATE));
    }

    // getByteArray
    @SmallTest
    public void testGetByteArray() throws Exception {
        byte data[] = new byte[]{1,2,3,4,5};

        writeByteArrayRecord(Metadata.ALBUM_ART, data);
        adjustSize();
        assertParse();

        byte res[] = mMetadata.getByteArray(Metadata.ALBUM_ART);
        for (int i = 0; i < data.length; ++i) {
            assertEquals(data[i], res[i]);
        }
    }

    // getDate
    @SmallTest
    public void testGetDate() throws Exception {
        writeDateRecord(Metadata.DATE, 0, "PST");
        adjustSize();
        assertParse();

        assertEquals(new Date(0), mMetadata.getDate(Metadata.DATE));
    }

    // getTimedText
    @SmallTest
    public void testGetTimedText() throws Exception {
        Date now = Calendar.getInstance().getTime();
        writeTimedTextRecord(Metadata.CAPTION, now.getTime(),
                             10, "Some caption");
        adjustSize();
        assertParse();

        Metadata.TimedText caption = mMetadata.getTimedText(Metadata.CAPTION);
        assertEquals("" + now + "-" + 10 + ":Some caption", caption.toString());
    }

    // ----------------------------------------------------------------------
    // HELPERS TO APPEND RECORDS
    // ----------------------------------------------------------------------

    // Insert a string record at the current position.
    private void writeStringRecord(int metadataId, String val) {
        final int start = mParcel.dataPosition();
        mParcel.writeInt(-1);  // Placeholder for the length
        mParcel.writeInt(metadataId);
        mParcel.writeInt(Metadata.STRING_VAL);
        mParcel.writeString(val);
        adjustSize(start);
    }

    // Insert an int record at the current position.
    private void writeIntRecord(int metadataId, int val) {
        final int start = mParcel.dataPosition();
        mParcel.writeInt(-1);  // Placeholder for the length
        mParcel.writeInt(metadataId);
        mParcel.writeInt(Metadata.INTEGER_VAL);
        mParcel.writeInt(val);
        adjustSize(start);
    }

    // Insert a boolean record at the current position.
    private void writeBooleanRecord(int metadataId, boolean val) {
        final int start = mParcel.dataPosition();
        mParcel.writeInt(-1);  // Placeholder for the length
        mParcel.writeInt(metadataId);
        mParcel.writeInt(Metadata.BOOLEAN_VAL);
        mParcel.writeInt(val ? 1 : 0);
        adjustSize(start);
    }

    // Insert a Long record at the current position.
    private void writeLongRecord(int metadataId, long val) {
        final int start = mParcel.dataPosition();
        mParcel.writeInt(-1);  // Placeholder for the length
        mParcel.writeInt(metadataId);
        mParcel.writeInt(Metadata.LONG_VAL);
        mParcel.writeLong(val);
        adjustSize(start);
    }

    // Insert a Double record at the current position.
    private void writeDoubleRecord(int metadataId, double val) {
        final int start = mParcel.dataPosition();
        mParcel.writeInt(-1);  // Placeholder for the length
        mParcel.writeInt(metadataId);
        mParcel.writeInt(Metadata.DOUBLE_VAL);
        mParcel.writeDouble(val);
        adjustSize(start);
    }

    // Insert a ByteArray record at the current position.
    private void writeByteArrayRecord(int metadataId, byte[] val) {
        final int start = mParcel.dataPosition();
        mParcel.writeInt(-1);  // Placeholder for the length
        mParcel.writeInt(metadataId);
        mParcel.writeInt(Metadata.BYTE_ARRAY_VAL);
        mParcel.writeByteArray(val);
        adjustSize(start);
    }

    // Insert a Date record at the current position.
    private void writeDateRecord(int metadataId, long time, String tz) {
        final int start = mParcel.dataPosition();
        mParcel.writeInt(-1);  // Placeholder for the length
        mParcel.writeInt(metadataId);
        mParcel.writeInt(Metadata.DATE_VAL);
        mParcel.writeLong(time);
        mParcel.writeString(tz);
        adjustSize(start);
    }

    // Insert a TimedText record at the current position.
    private void writeTimedTextRecord(int metadataId, long begin,
                                      int duration, String text) {
        final int start = mParcel.dataPosition();
        mParcel.writeInt(-1);  // Placeholder for the length
        mParcel.writeInt(metadataId);
        mParcel.writeInt(Metadata.TIMED_TEXT_VAL);
        mParcel.writeLong(begin);
        mParcel.writeInt(duration);
        mParcel.writeString(text);
        adjustSize(start);
    }
}