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

Commit 5510a153 authored by Gloria Wang's avatar Gloria Wang Committed by Android (Google) Code Review
Browse files

Merge "- Public part of the Metadata API. - Modify the media framework test for Metadata."

parents 52da3a43 1e1b13e6
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -10433,6 +10433,16 @@ package android.media {
    method public abstract void onScanCompleted(java.lang.String, android.net.Uri);
  }
  public class Metadata {
    method public boolean getBoolean(int);
    method public boolean has(int);
    method public java.util.Set<java.lang.Integer> keySet();
    field public static final int PAUSE_AVAILABLE = 1; // 0x1
    field public static final int SEEK_AVAILABLE = 4; // 0x4
    field public static final int SEEK_BACKWARD_AVAILABLE = 2; // 0x2
    field public static final int SEEK_FORWARD_AVAILABLE = 3; // 0x3
  }
  public class Ringtone {
    method public int getStreamType();
    method public java.lang.String getTitle(android.content.Context);
+35 −36
Original line number Diff line number Diff line
@@ -51,47 +51,46 @@ class Metadata {

    static const Type kAny = 0;

    // Playback capabilities.
    static const Type kPauseAvailable        = 1; // Boolean
    static const Type kSeekBackwardAvailable = 2; // Boolean
    static const Type kSeekForwardAvailable  = 3; // Boolean
    static const Type kSeekAvailable         = 4; // Boolean

    // Keep in sync with android/media/Metadata.java
    static const Type kTitle = 1;           // String
    static const Type kComment = 2;         // String
    static const Type kCopyright = 3;       // String
    static const Type kAlbum = 4;           // String
    static const Type kArtist = 5;          // String
    static const Type kAuthor = 6;          // String
    static const Type kComposer = 7;        // String
    static const Type kGenre = 8;           // String
    static const Type kDate = 9;            // Date
    static const Type kDuration = 10;       // Integer(millisec)
    static const Type kCdTrackNum = 11;     // Integer 1-based
    static const Type kCdTrackMax = 12;     // Integer
    static const Type kRating = 13;         // String
    static const Type kAlbumArt = 14;       // byte[]
    static const Type kVideoFrame = 15;     // Bitmap
    static const Type kCaption = 16;        // TimedText

    static const Type kBitRate = 17;       // Integer, Aggregate rate of
    static const Type kTitle                 = 5; // String
    static const Type kComment               = 6; // String
    static const Type kCopyright             = 7; // String
    static const Type kAlbum                 = 8; // String
    static const Type kArtist                = 9; // String
    static const Type kAuthor                = 10; // String
    static const Type kComposer              = 11; // String
    static const Type kGenre                 = 12; // String
    static const Type kDate                  = 13; // Date
    static const Type kDuration              = 14; // Integer(millisec)
    static const Type kCdTrackNum            = 15; // Integer 1-based
    static const Type kCdTrackMax            = 16; // Integer
    static const Type kRating                = 17; // String
    static const Type kAlbumArt              = 18; // byte[]
    static const Type kVideoFrame            = 19; // Bitmap

    static const Type kBitRate               = 20; // Integer, Aggregate rate of
    // all the streams in bps.

    static const Type kAudioBitRate = 18; // Integer, bps
    static const Type kVideoBitRate = 19; // Integer, bps
    static const Type kAudioSampleRate = 20; // Integer, Hz
    static const Type kVideoframeRate = 21;  // Integer, Hz
    static const Type kAudioBitRate          = 21; // Integer, bps
    static const Type kVideoBitRate          = 22; // Integer, bps
    static const Type kAudioSampleRate       = 23; // Integer, Hz
    static const Type kVideoframeRate        = 24; // Integer, Hz

    // See RFC2046 and RFC4281.
    static const Type kMimeType = 22;      // String
    static const Type kAudioCodec = 23;    // String
    static const Type kVideoCodec = 24;    // String

    static const Type kVideoHeight = 25;   // Integer
    static const Type kVideoWidth = 26;    // Integer
    static const Type kNumTracks = 27;     // Integer
    static const Type kDrmCrippled = 28;   // Boolean

    // Playback capabilities.
    static const Type kPauseAvailable = 29;        // Boolean
    static const Type kSeekBackwardAvailable = 30; // Boolean
    static const Type kSeekForwardAvailable = 31;  // Boolean
    static const Type kSeekAvailable = 32;         // Boolean
    static const Type kMimeType              = 25; // String
    static const Type kAudioCodec            = 26; // String
    static const Type kVideoCodec            = 27; // String

    static const Type kVideoHeight           = 28; // Integer
    static const Type kVideoWidth            = 29; // Integer
    static const Type kNumTracks             = 30; // Integer
    static const Type kDrmCrippled           = 31; // Boolean

    // @param p[inout] The parcel to append the metadata records
    // to. The global metadata header should have been set already.
+211 −87
Original line number Diff line number Diff line
@@ -32,17 +32,13 @@ import java.util.TimeZone;
   Class to hold the media's metadata.  Metadata are used
   for human consumption and can be embedded in the media (e.g
   shoutcast) or available from an external source. The source can be
   local (e.g thumbnail stored in the DB) or remote (e.g caption
   server).
   local (e.g thumbnail stored in the DB) or remote.

   Metadata is like a Bundle. It is sparse and each key can occur at
   most once. The key is an integer and the value is the actual metadata.

   The caller is expected to know the type of the metadata and call
   the right get* method to fetch its value.

   // FIXME: unhide.
   {@hide}
 */
public class Metadata
{
@@ -59,69 +55,190 @@ public class Metadata
    // client to make the data purge-able once it is done with it.
    //

    /**
     * {@hide}
     */
    public static final int ANY = 0;  // Never used for metadata returned, only for filtering.
                                      // Keep in sync with kAny in MediaPlayerService.cpp

    // Playback capabilities.
    /**
     * Indicate whether the media can be paused
     */
    public static final int PAUSE_AVAILABLE         = 1; // Boolean
    /**
     * Indicate whether the media can be backward seeked
     */
    public static final int SEEK_BACKWARD_AVAILABLE = 2; // Boolean
    /**
     * Indicate whether the media can be forward seeked
     */
    public static final int SEEK_FORWARD_AVAILABLE  = 3; // Boolean
    /**
     * Indicate whether the media can be seeked
     */
    public static final int SEEK_AVAILABLE          = 4; // Boolean

    // TODO: Should we use numbers compatible with the metadata retriever?
    public static final int TITLE = 1;           // String
    public static final int COMMENT = 2;         // String
    public static final int COPYRIGHT = 3;       // String
    public static final int ALBUM = 4;           // String
    public static final int ARTIST = 5;          // String
    public static final int AUTHOR = 6;          // String
    public static final int COMPOSER = 7;        // String
    public static final int GENRE = 8;           // String
    public static final int DATE = 9;            // Date
    public static final int DURATION = 10;       // Integer(millisec)
    public static final int CD_TRACK_NUM = 11;   // Integer 1-based
    public static final int CD_TRACK_MAX = 12;   // Integer
    public static final int RATING = 13;         // String
    public static final int ALBUM_ART = 14;      // byte[]
    public static final int VIDEO_FRAME = 15;    // Bitmap
    public static final int CAPTION = 16;        // TimedText

    public static final int BIT_RATE = 17;       // Integer, Aggregate rate of
    /**
     * {@hide}
     */
    public static final int TITLE                   = 5; // String
    /**
     * {@hide}
     */
    public static final int COMMENT                 = 6; // String
    /**
     * {@hide}
     */
    public static final int COPYRIGHT               = 7; // String
    /**
     * {@hide}
     */
    public static final int ALBUM                   = 8; // String
    /**
     * {@hide}
     */
    public static final int ARTIST                  = 9; // String
    /**
     * {@hide}
     */
    public static final int AUTHOR                  = 10; // String
    /**
     * {@hide}
     */
    public static final int COMPOSER                = 11; // String
    /**
     * {@hide}
     */
    public static final int GENRE                   = 12; // String
    /**
     * {@hide}
     */
    public static final int DATE                    = 13; // Date
    /**
     * {@hide}
     */
    public static final int DURATION                = 14; // Integer(millisec)
    /**
     * {@hide}
     */
    public static final int CD_TRACK_NUM            = 15; // Integer 1-based
    /**
     * {@hide}
     */
    public static final int CD_TRACK_MAX            = 16; // Integer
    /**
     * {@hide}
     */
    public static final int RATING                  = 17; // String
    /**
     * {@hide}
     */
    public static final int ALBUM_ART               = 18; // byte[]
    /**
     * {@hide}
     */
    public static final int VIDEO_FRAME             = 19; // Bitmap

    /**
     * {@hide}
     */
    public static final int BIT_RATE                = 20; // Integer, Aggregate rate of
                                                          // all the streams in bps.

    public static final int AUDIO_BIT_RATE = 18; // Integer, bps
    public static final int VIDEO_BIT_RATE = 19; // Integer, bps
    public static final int AUDIO_SAMPLE_RATE = 20; // Integer, Hz
    public static final int VIDEO_FRAME_RATE = 21;  // Integer, Hz
    /**
     * {@hide}
     */
    public static final int AUDIO_BIT_RATE          = 21; // Integer, bps
    /**
     * {@hide}
     */
    public static final int VIDEO_BIT_RATE          = 22; // Integer, bps
    /**
     * {@hide}
     */
    public static final int AUDIO_SAMPLE_RATE       = 23; // Integer, Hz
    /**
     * {@hide}
     */
    public static final int VIDEO_FRAME_RATE        = 24; // Integer, Hz

    // See RFC2046 and RFC4281.
    public static final int MIME_TYPE = 22;      // String
    public static final int AUDIO_CODEC = 23;    // String
    public static final int VIDEO_CODEC = 24;    // String

    public static final int VIDEO_HEIGHT = 25;   // Integer
    public static final int VIDEO_WIDTH = 26;    // Integer
    public static final int NUM_TRACKS = 27;     // Integer
    public static final int DRM_CRIPPLED = 28;   // Boolean
    /**
     * {@hide}
     */
    public static final int MIME_TYPE               = 25; // String
    /**
     * {@hide}
     */
    public static final int AUDIO_CODEC             = 26; // String
    /**
     * {@hide}
     */
    public static final int VIDEO_CODEC             = 27; // String

    // Playback capabilities.
    public static final int PAUSE_AVAILABLE = 29;         // Boolean
    public static final int SEEK_BACKWARD_AVAILABLE = 30; // Boolean
    public static final int SEEK_FORWARD_AVAILABLE = 31;  // Boolean
    public static final int SEEK_AVAILABLE = 32;          // Boolean
    /**
     * {@hide}
     */
    public static final int VIDEO_HEIGHT            = 28; // Integer
    /**
     * {@hide}
     */
    public static final int VIDEO_WIDTH             = 29; // Integer
    /**
     * {@hide}
     */
    public static final int NUM_TRACKS              = 30; // Integer
    /**
     * {@hide}
     */
    public static final int DRM_CRIPPLED            = 31; // Boolean

    private static final int LAST_SYSTEM = 32;
    private static final int LAST_SYSTEM = 31;
    private static final int FIRST_CUSTOM = 8192;

    // Shorthands to set the MediaPlayer's metadata filter.
    /**
     * {@hide}
     */
    public static final Set<Integer> MATCH_NONE = Collections.EMPTY_SET;
    /**
     * {@hide}
     */
    public static final Set<Integer> MATCH_ALL = Collections.singleton(ANY);

    /**
     * {@hide}
     */
    public static final int STRING_VAL     = 1;
    /**
     * {@hide}
     */
    public static final int INTEGER_VAL    = 2;
    /**
     * {@hide}
     */
    public static final int BOOLEAN_VAL    = 3;
    /**
     * {@hide}
     */
    public static final int LONG_VAL       = 4;
    /**
     * {@hide}
     */
    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;
    /**
     * {@hide}
     */
    public static final int DATE_VAL       = 6;
    /**
     * {@hide}
     */
    public static final int BYTE_ARRAY_VAL = 7;
    // 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 int LAST_TYPE = 7;

    private static final String TAG = "media.Metadata";
    private static final int kInt32Size = 4;
@@ -142,28 +259,8 @@ public class Metadata
            new HashMap<Integer, Integer>();

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

        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(mDuration)
                    .append(":").append(mText);
            return res.toString();
        }
    }

    public Metadata() { }

    /**
@@ -273,6 +370,7 @@ public class Metadata
     *               should not modify the parcel after this call (and
     *               not call recycle on it.)
     * @return false if an error occurred.
     * {@hide}
     */
    public boolean parse(Parcel parcel) {
        if (parcel.dataAvail() < kMetaHeaderSize) {
@@ -328,36 +426,59 @@ public class Metadata
    // Caller must make sure the key is present using the {@code has}
    // method otherwise a RuntimeException will occur.

    /**
     * {@hide}
     */
    public String getString(final int key) {
        checkType(key, STRING_VAL);
        return mParcel.readString();
    }

    /**
     * {@hide}
     */
    public int getInt(final int key) {
        checkType(key, INTEGER_VAL);
        return mParcel.readInt();
    }

    /**
     * Get the boolean value indicated by key
     */
    public boolean getBoolean(final int key) {
        checkType(key, BOOLEAN_VAL);
        return mParcel.readInt() == 1;
    }

    /**
     * {@hide}
     */
    public long getLong(final int key) {
        checkType(key, LONG_VAL);
        checkType(key, LONG_VAL);    /**
     * {@hide}
     */
        return mParcel.readLong();
    }

    /**
     * {@hide}
     */
    public double getDouble(final int key) {
        checkType(key, DOUBLE_VAL);
        return mParcel.readDouble();
    }

    /**
     * {@hide}
     */
    public byte[] getByteArray(final int key) {
        checkType(key, BYTE_ARRAY_VAL);
        return mParcel.createByteArray();
    }

    /**
     * {@hide}
     */
    public Date getDate(final int key) {
        checkType(key, DATE_VAL);
        final long timeSinceEpoch = mParcel.readLong();
@@ -374,29 +495,30 @@ public class Metadata
        }
    }

    public TimedText getTimedText(final int key) {
        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
    // 1-indexed.
    /**
     * @return the last available system metadata id. Ids are
     *         1-indexed.
     * {@hide}
     */
    public static int lastSytemId() { return LAST_SYSTEM; }

    // @return the first available cutom metadata id.
    /**
     * @return the first available cutom metadata id.
     * {@hide}
     */
    public static int firstCustomId() { return FIRST_CUSTOM; }

    // @return the last value of known type. Types are 1-indexed.
    /**
     * @return the last value of known type. Types are 1-indexed.
     * {@hide}
     */
    public static int lastType() { return LAST_TYPE; }

    // Check val is either a system id or a custom one.
    // @param val Metadata key to test.
    // @return true if it is in a valid range.
    /**
     * Check val is either a system id or a custom one.
     * @param val Metadata key to test.
     * @return true if it is in a valid range.
     **/
    private boolean checkMetadataId(final int val) {
        if (val <= ANY || (LAST_SYSTEM < val && val < FIRST_CUSTOM)) {
            Log.e(TAG, "Invalid metadata ID " + val);
@@ -405,7 +527,9 @@ public class Metadata
        return true;
    }

    // Check the type of the data match what is expected.
    /**
     * 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);

+1 −2
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ namespace {
// All these constants below must be kept in sync with Metadata.java.
enum MetadataId {
    FIRST_SYSTEM_ID = 1,
    LAST_SYSTEM_ID = 32,
    LAST_SYSTEM_ID = 31,
    FIRST_CUSTOM_ID = 8192
};

@@ -43,7 +43,6 @@ enum Types {
    BOOLEAN_VAL,
    LONG_VAL,
    DOUBLE_VAL,
    TIMED_TEXT_VAL,
    DATE_VAL,
    BYTE_ARRAY_VAL,
};
+8 −28
Original line number Diff line number Diff line
@@ -277,11 +277,17 @@ public class MediaPlayerMetadataParserTest extends AndroidTestCase {
    // getBoolean
    @SmallTest
    public void testGetBoolean() throws Exception {
        writeBooleanRecord(Metadata.DRM_CRIPPLED, true);
        writeBooleanRecord(Metadata.PAUSE_AVAILABLE, true);
        writeBooleanRecord(Metadata.SEEK_AVAILABLE, true);
        writeBooleanRecord(Metadata.SEEK_BACKWARD_AVAILABLE, true);
        writeBooleanRecord(Metadata.SEEK_FORWARD_AVAILABLE, true);
        adjustSize();
        assertParse();

        assertEquals(true, mMetadata.getBoolean(Metadata.DRM_CRIPPLED));
        assertEquals(true, mMetadata.getBoolean(Metadata.PAUSE_AVAILABLE));
        assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_AVAILABLE));
        assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE));
        assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE));
    }

    // getLong
@@ -329,19 +335,6 @@ public class MediaPlayerMetadataParserTest extends AndroidTestCase {
        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
    // ----------------------------------------------------------------------
@@ -416,17 +409,4 @@ public class MediaPlayerMetadataParserTest extends AndroidTestCase {
        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);
    }
}