auto import from //branches/cupcake_rel/...@140373
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 077d016..f509fb5 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -160,7 +160,7 @@
16, // STREAM_MUSIC
8, // STREAM_ALARM
8, // STREAM_NOTIFICATION
- 15, // STREAM_BLUETOOTH_SCO
+ 16, // STREAM_BLUETOOTH_SCO
};
/** @hide Default volume index values for audio streams */
@@ -220,7 +220,7 @@
* By default this is on for the ring stream. If this flag is included,
* this behavior will be present regardless of the stream type being
* affected by the ringer mode.
- *
+ *
* @see #adjustVolume(int, int)
* @see #adjustStreamVolume(int, int, int)
*/
@@ -954,25 +954,21 @@
/**
* IME standard keypress sound
* @see #playSoundEffect(int)
- * @hide FIXME: Unhide before release
*/
public static final int FX_KEYPRESS_STANDARD = 5;
/**
* IME spacebar keypress sound
* @see #playSoundEffect(int)
- * @hide FIXME: Unhide before release
*/
public static final int FX_KEYPRESS_SPACEBAR = 6;
/**
* IME delete keypress sound
* @see #playSoundEffect(int)
- * @hide FIXME: Unhide before release
*/
public static final int FX_KEYPRESS_DELETE = 7;
/**
* IME return_keypress sound
* @see #playSoundEffect(int)
- * @hide FIXME: Unhide before release
*/
public static final int FX_KEYPRESS_RETURN = 8;
/**
@@ -988,11 +984,10 @@
* {@link #FX_FOCUS_NAVIGATION_DOWN},
* {@link #FX_FOCUS_NAVIGATION_LEFT},
* {@link #FX_FOCUS_NAVIGATION_RIGHT},
- * FIXME: include links before release
- * {link #FX_KEYPRESS_STANDARD},
- * {link #FX_KEYPRESS_SPACEBAR},
- * {link #FX_KEYPRESS_DELETE},
- * {link #FX_KEYPRESS_RETURN},
+ * {@link #FX_KEYPRESS_STANDARD},
+ * {@link #FX_KEYPRESS_SPACEBAR},
+ * {@link #FX_KEYPRESS_DELETE},
+ * {@link #FX_KEYPRESS_RETURN},
* NOTE: This version uses the UI settings to determine
* whether sounds are heard or not.
*/
@@ -1021,15 +1016,13 @@
* {@link #FX_FOCUS_NAVIGATION_DOWN},
* {@link #FX_FOCUS_NAVIGATION_LEFT},
* {@link #FX_FOCUS_NAVIGATION_RIGHT},
- * FIXME: include links before release
- * {link #FX_KEYPRESS_STANDARD},
- * {link #FX_KEYPRESS_SPACEBAR},
- * {link #FX_KEYPRESS_DELETE},
- * {link #FX_KEYPRESS_RETURN},
+ * {@link #FX_KEYPRESS_STANDARD},
+ * {@link #FX_KEYPRESS_SPACEBAR},
+ * {@link #FX_KEYPRESS_DELETE},
+ * {@link #FX_KEYPRESS_RETURN},
* @param volume Sound effect volume
* NOTE: This version is for applications that have their own
* settings panel for enabling and controlling volume.
- * @hide FIXME: Unhide before release
*/
public void playSoundEffect(int effectType, float volume) {
if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 316fa7a..d2bad93 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -171,6 +171,10 @@
*/
private NativeEventHandlerDelegate mEventHandlerDelegate = null;
/**
+ * Looper associated with the thread that creates the AudioTrack instance
+ */
+ private Looper mInitializationLooper = null;
+ /**
* The audio data sampling rate in Hz.
*/
private int mSampleRate = 22050;
@@ -248,6 +252,11 @@
int bufferSizeInBytes, int mode)
throws IllegalArgumentException {
mState = STATE_UNINITIALIZED;
+
+ // remember which looper is associated with the AudioTrack instanciation
+ if ((mInitializationLooper = Looper.myLooper()) == null) {
+ mInitializationLooper = Looper.getMainLooper();
+ }
audioParamCheck(streamType, sampleRateInHz, channelConfig, audioFormat, mode);
@@ -902,11 +911,10 @@
if (handler != null) {
looper = handler.getLooper();
} else {
- // no given handler, look for main looper
- if ((looper = Looper.myLooper()) == null) {
- looper = Looper.getMainLooper();
- }
+ // no given handler, use the looper the AudioTrack was created in
+ looper = mInitializationLooper;
}
+
// construct the event handler with this looper
if (looper != null) {
// implement the event handler delegate
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index 9de0eec..6539d84 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -68,21 +68,22 @@
//--------------------------------------------
// Member variables
//------------------------
- private EventHandler mNativeEventHandler = null;
+ /**
+ * Handler for jet events and status updates coming from the native code
+ */
+ private NativeEventHandler mEventHandler = null;
/**
- * Lock to protect status listener updates against status change notifications
+ * Looper associated with the thread that creates the AudioTrack instance
*/
- private final Object mStatusListenerLock = new Object();
+ private Looper mInitializationLooper = null;
/**
* Lock to protect the event listener updates against event notifications
*/
private final Object mEventListenerLock = new Object();
- private JetStatusUpdateListener mJetStatusUpdateListener = null;
-
- private JetEventListener mJetEventListener = null;
+ private OnJetEventListener mJetEventListener = null;
private static JetPlayer singletonRef;
@@ -115,6 +116,11 @@
private JetPlayer() {
+
+ // remember which looper is associated with the JetPlayer instanciation
+ if ((mInitializationLooper = Looper.myLooper()) == null) {
+ mInitializationLooper = Looper.getMainLooper();
+ }
native_setup(new WeakReference<JetPlayer>(this),
JetPlayer.getMaxTracks(),
@@ -132,18 +138,6 @@
}
- private void createNativeEventHandler() {
- Looper looper;
- if ((looper = Looper.myLooper()) != null) {
- mNativeEventHandler = new EventHandler(this, looper);
- } else if ((looper = Looper.getMainLooper()) != null) {
- mNativeEventHandler = new EventHandler(this, looper);
- } else {
- mNativeEventHandler = null;
- }
- }
-
-
//--------------------------------------------
// Getters
//------------------------
@@ -235,24 +229,27 @@
//---------------------------------------------------------
// Internal class to handle events posted from native code
//------------------------
- private class EventHandler extends Handler
+ private class NativeEventHandler extends Handler
{
private JetPlayer mJet;
- public EventHandler(JetPlayer jet, Looper looper) {
+ public NativeEventHandler(JetPlayer jet, Looper looper) {
super(looper);
mJet = jet;
}
@Override
public void handleMessage(Message msg) {
+ OnJetEventListener listener = null;
+ synchronized (mEventListenerLock) {
+ listener = mJet.mJetEventListener;
+ }
switch(msg.what) {
case JET_EVENT:
- synchronized (mEventListenerLock) {
- if (mJetEventListener != null) {
- // call the appropriate listener after decoding the event parameters
- // encoded in msg.arg1
- mJetEventListener.onJetEvent(
+ if (listener != null) {
+ // call the appropriate listener after decoding the event parameters
+ // encoded in msg.arg1
+ mJetEventListener.onJetEvent(
mJet,
(short)((msg.arg1 & JET_EVENT_SEG_MASK) >> JET_EVENT_SEG_SHIFT),
(byte) ((msg.arg1 & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT),
@@ -261,28 +258,21 @@
(byte)(((msg.arg1 & JET_EVENT_CHAN_MASK) >> JET_EVENT_CHAN_SHIFT) + 1),
(byte) ((msg.arg1 & JET_EVENT_CTRL_MASK) >> JET_EVENT_CTRL_SHIFT),
(byte) (msg.arg1 & JET_EVENT_VAL_MASK) );
- }
}
return;
case JET_USERID_UPDATE:
- synchronized (mStatusListenerLock) {
- if (mJetStatusUpdateListener != null) {
- mJetStatusUpdateListener.onJetUserIdUpdate(mJet, msg.arg1, msg.arg2);
- }
+ if (listener != null) {
+ listener.onJetUserIdUpdate(mJet, msg.arg1, msg.arg2);
}
return;
case JET_NUMQUEUEDSEGMENT_UPDATE:
- synchronized (mStatusListenerLock) {
- if (mJetStatusUpdateListener != null) {
- mJetStatusUpdateListener.onJetNumQueuedSegmentUpdate(mJet, msg.arg1);
- }
+ if (listener != null) {
+ listener.onJetNumQueuedSegmentUpdate(mJet, msg.arg1);
}
return;
case JET_PAUSE_UPDATE:
- synchronized (mStatusListenerLock) {
- if (mJetStatusUpdateListener != null)
- mJetStatusUpdateListener.onJetPauseUpdate(mJet, msg.arg1);
- }
+ if (listener != null)
+ listener.onJetPauseUpdate(mJet, msg.arg1);
return;
default:
@@ -294,22 +284,48 @@
//--------------------------------------------
- // Jet status update listener
+ // Jet event listener
//------------------------
- public void setStatusUpdateListener(JetStatusUpdateListener listener) {
- synchronized(mStatusListenerLock) {
- mJetStatusUpdateListener = listener;
- }
-
- if ((listener != null) && (mNativeEventHandler == null)) {
- createNativeEventHandler();
+ public void setEventListener(OnJetEventListener listener) {
+ setEventListener(listener, null);
+ }
+
+ public void setEventListener(OnJetEventListener listener, Handler handler) {
+ synchronized(mEventListenerLock) {
+
+ mJetEventListener = listener;
+
+ if (listener != null) {
+ if (handler != null) {
+ mEventHandler = new NativeEventHandler(this, handler.getLooper());
+ } else {
+ // no given handler, use the looper the AudioTrack was created in
+ mEventHandler = new NativeEventHandler(this, mInitializationLooper);
+ }
+ } else {
+ mEventHandler = null;
+ }
+
}
}
+
/**
- * Handles the notification when the JET status is updated.
+ * Handles the notification when the JET engine generates an event.
*/
- public interface JetStatusUpdateListener {
+ public interface OnJetEventListener {
+ /**
+ * Callback for when the JET engine generates a new event.
+ *
+ * @param player the JET player the event is coming from
+ * @param segment 8 bit unsigned value
+ * @param track 6 bit unsigned value
+ * @param channel 4 bit unsigned value
+ * @param controller 7 bit unsigned value
+ * @param value 7 bit unsigned value
+ */
+ void onJetEvent(JetPlayer player,
+ short segment, byte track, byte channel, byte controller, byte value);
/**
* Callback for when JET's currently playing segment userID is updated.
*
@@ -338,38 +354,6 @@
//--------------------------------------------
- // Jet event listener
- //------------------------
- public void setEventListener(JetEventListener listener) {
- synchronized(mEventListenerLock) {
- mJetEventListener = listener;
- }
-
- if ((listener != null) && (mNativeEventHandler == null)) {
- createNativeEventHandler();
- }
- }
-
- /**
- * Handles the notification when the JET engine generates an event.
- */
- public interface JetEventListener {
- /**
- * Callback for when the JET engine generates a new event.
- *
- * @param player the JET player the event is coming from
- * @param segment 8 bit unsigned value
- * @param track 6 bit unsigned value
- * @param channel 4 bit unsigned value
- * @param controller 7 bit unsigned value
- * @param value 7 bit unsigned value
- */
- void onJetEvent(JetPlayer player,
- short segment, byte track, byte channel, byte controller, byte value);
- }
-
-
- //--------------------------------------------
// Native methods
//------------------------
private native final boolean native_setup(Object Jet_this,
@@ -397,13 +381,15 @@
@SuppressWarnings("unused")
private static void postEventFromNative(Object jetplayer_ref,
int what, int arg1, int arg2) {
-
+ //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
JetPlayer jet = (JetPlayer)((WeakReference)jetplayer_ref).get();
- if( (jet!=null) && (jet.mNativeEventHandler!=null) ){
- Message m = jet.mNativeEventHandler.obtainMessage(what, arg1, arg2, null);
- jet.mNativeEventHandler.sendMessage(m);
+ if ((jet != null) && (jet.mEventHandler != null)) {
+ Message m =
+ jet.mEventHandler.obtainMessage(what, arg1, arg2, null);
+ jet.mEventHandler.sendMessage(m);
}
+
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 202d0ae..9668efa 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1036,11 +1036,11 @@
* Register a callback to be invoked when the media source is ready
* for playback.
*
- * @param l the callback that will be run
+ * @param listener the callback that will be run
*/
- public void setOnPreparedListener(OnPreparedListener l)
+ public void setOnPreparedListener(OnPreparedListener listener)
{
- mOnPreparedListener = l;
+ mOnPreparedListener = listener;
}
private OnPreparedListener mOnPreparedListener;
@@ -1063,11 +1063,11 @@
* Register a callback to be invoked when the end of a media source
* has been reached during playback.
*
- * @param l the callback that will be run
+ * @param listener the callback that will be run
*/
- public void setOnCompletionListener(OnCompletionListener l)
+ public void setOnCompletionListener(OnCompletionListener listener)
{
- mOnCompletionListener = l;
+ mOnCompletionListener = listener;
}
private OnCompletionListener mOnCompletionListener;
@@ -1092,11 +1092,11 @@
* Register a callback to be invoked when the status of a network
* stream's buffer has changed.
*
- * @param l the callback that will be run
+ * @param listener the callback that will be run.
*/
- public void setOnBufferingUpdateListener(OnBufferingUpdateListener l)
+ public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener)
{
- mOnBufferingUpdateListener = l;
+ mOnBufferingUpdateListener = listener;
}
private OnBufferingUpdateListener mOnBufferingUpdateListener;
@@ -1119,11 +1119,11 @@
* Register a callback to be invoked when a seek operation has been
* completed.
*
- * @param l the callback that will be run
+ * @param listener the callback that will be run
*/
- public void setOnSeekCompleteListener(OnSeekCompleteListener l)
+ public void setOnSeekCompleteListener(OnSeekCompleteListener listener)
{
- mOnSeekCompleteListener = l;
+ mOnSeekCompleteListener = listener;
}
private OnSeekCompleteListener mOnSeekCompleteListener;
@@ -1151,12 +1151,12 @@
* Register a callback to be invoked when the video size is
* known or updated.
*
- * @param l the callback that will be run
+ * @param listener the callback that will be run
* @hide
*/
- public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener l)
+ public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener)
{
- mOnVideoSizeChangedListener = l;
+ mOnVideoSizeChangedListener = listener;
}
private OnVideoSizeChangedListener mOnVideoSizeChangedListener;
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 1c08cba..676f241 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -259,6 +259,12 @@
/**
* Sets the maximum duration (in ms) of the recording session.
* Call this after setOutFormat() but before prepare().
+ * After recording reaches the specified duration, a notification
+ * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
+ * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
+ * and recording will be stopped. Stopping happens asynchronously, there
+ * is no guarantee that the recorder will have stopped by the time the
+ * listener is notified.
*
* @param max_duration_ms the maximum duration in ms (if zero or negative, disables the duration limit)
*
@@ -266,6 +272,21 @@
public native void setMaxDuration(int max_duration_ms) throws IllegalArgumentException;
/**
+ * Sets the maximum filesize (in bytes) of the recording session.
+ * Call this after setOutFormat() but before prepare().
+ * After recording reaches the specified filesize, a notification
+ * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
+ * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
+ * and recording will be stopped. Stopping happens asynchronously, there
+ * is no guarantee that the recorder will have stopped by the time the
+ * listener is notified.
+ *
+ * @param max_filesize_bytes the maximum filesize in bytes (if zero or negative, disables the limit)
+ *
+ */
+ public native void setMaxFileSize(long max_filesize_bytes) throws IllegalArgumentException;
+
+ /**
* Sets the audio encoder to be used for recording. If this method is not
* called, the output file will not contain an audio track. Call this after
* setOutputFormat() but before prepare().
@@ -441,6 +462,10 @@
* @see android.media.MediaRecorder.OnInfoListener
*/
public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800;
+ /** A maximum filesize had been setup and has now been reached.
+ * @see android.media.MediaRecorder.OnInfoListener
+ */
+ public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801;
/**
* Interface definition for a callback to be invoked when an error
@@ -455,6 +480,8 @@
* @param what the type of error that has occurred:
* <ul>
* <li>{@link #MEDIA_RECORDER_INFO_UNKNOWN}
+ * <li>{@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
+ * <li>{@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
* </ul>
* @param extra an extra code, specific to the error type
*/
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 1e508d2..209b09f 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -268,6 +268,19 @@
}
static void
+android_media_MediaRecorder_setMaxFileSize(
+ JNIEnv *env, jobject thiz, jlong max_filesize_bytes)
+{
+ LOGV("setMaxFileSize(%lld)", max_filesize_bytes);
+ sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+
+ char params[64];
+ sprintf(params, "max-filesize=%lld", max_filesize_bytes);
+
+ process_media_recorder_call(env, mr->setParameters(String8(params)), "java/lang/RuntimeException", "setMaxFileSize failed.");
+}
+
+static void
android_media_MediaRecorder_prepare(JNIEnv *env, jobject thiz)
{
LOGV("prepare");
@@ -370,6 +383,7 @@
{"setVideoSize", "(II)V", (void *)android_media_MediaRecorder_setVideoSize},
{"setVideoFrameRate", "(I)V", (void *)android_media_MediaRecorder_setVideoFrameRate},
{"setMaxDuration", "(I)V", (void *)android_media_MediaRecorder_setMaxDuration},
+ {"setMaxFileSize", "(J)V", (void *)android_media_MediaRecorder_setMaxFileSize},
{"_prepare", "()V", (void *)android_media_MediaRecorder_prepare},
{"getMaxAmplitude", "()I", (void *)android_media_MediaRecorder_native_getMaxAmplitude},
{"start", "()V", (void *)android_media_MediaRecorder_start},
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index d26b0c5..7537ddf 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -387,12 +387,10 @@
LOGV("flush");
if (!mActive) {
- mCblk->lock.lock();
mAudioTrack->flush();
// Release AudioTrack callback thread in case it was waiting for new buffers
// in AudioTrack::obtainBuffer()
mCblk->cv.signal();
- mCblk->lock.unlock();
}
}
@@ -443,7 +441,7 @@
if (rate > afSamplingRate*2) rate = afSamplingRate*2;
if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE;
- mCblk->sampleRate = rate;
+ mCblk->sampleRate = (uint16_t)rate;
}
uint32_t AudioTrack::getSampleRate()
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index 2c62104..77a9013 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -194,8 +194,15 @@
}
while (1) {
+
mMutex.lock(); // [[[[[[[[ LOCK ---------------------------------------
+ if (mEasData == NULL) {
+ mMutex.unlock();
+ LOGV("JetPlayer::render(): NULL EAS data, exiting render.");
+ goto threadExit;
+ }
+
// nothing to render, wait for client thread to wake us up
while (!mRender)
{
@@ -255,7 +262,10 @@
}//while (1)
threadExit:
- mAudioTrack->flush();
+ if (mAudioTrack) {
+ mAudioTrack->stop();
+ mAudioTrack->flush();
+ }
if (mAudioBuffer) {
delete [] mAudioBuffer;
mAudioBuffer = NULL;
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 23b3b9d..6b26faf 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -367,8 +367,9 @@
status_t ret = mMediaRecorder->setParameters(params);
if (OK != ret) {
LOGE("setParameters(%s) failed: %d", params.string(), ret);
- mCurrentState = MEDIA_RECORDER_ERROR;
- return ret;
+ // Do not change our current state to MEDIA_RECORDER_ERROR, failures
+ // of the only currently supported parameters, "max-duration" and
+ // "max-filesize" are _not_ fatal.
}
return ret;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
index 3c449c9..6edc2cc 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -16,12 +16,13 @@
package com.android.mediaframeworktest;
-import com.android.mediaframeworktest.functional.MediaPlayerApiTest;
-import com.android.mediaframeworktest.functional.SimTonesTest;
-import com.android.mediaframeworktest.functional.MediaMetadataTest;
import com.android.mediaframeworktest.functional.CameraTest;
-import com.android.mediaframeworktest.functional.MediaRecorderTest;
import com.android.mediaframeworktest.functional.MediaAudioTrackTest;
+import com.android.mediaframeworktest.functional.MediaMetadataTest;
+import com.android.mediaframeworktest.functional.MediaMimeTest;
+import com.android.mediaframeworktest.functional.MediaPlayerApiTest;
+import com.android.mediaframeworktest.functional.MediaRecorderTest;
+import com.android.mediaframeworktest.functional.SimTonesTest;
import junit.framework.TestSuite;
@@ -50,6 +51,7 @@
suite.addTestSuite(CameraTest.class);
suite.addTestSuite(MediaRecorderTest.class);
suite.addTestSuite(MediaAudioTrackTest.class);
+ suite.addTestSuite(MediaMimeTest.class);
return suite;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java
new file mode 100644
index 0000000..d2809c1
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+import java.io.File;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.util.Log;
+import com.android.mediaframeworktest.MediaFrameworkTest;
+
+/*
+ * System tests for the handling of mime type in the media framework.
+ *
+ * To run this test suite:
+ make frameworks/base/media/tests/MediaFrameworkTest
+ make mediaframeworktest
+
+ adb install -r out/target/product/dream/data/app/mediaframeworktest.apk
+
+ adb shell am instrument -e class \
+ com.android.mediaframeworktest.functional.MediaMimeTest \
+ -w com.android.mediaframeworktest/.MediaFrameworkTestRunner
+ *
+ */
+public class MediaMimeTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+ private final String TAG = "MediaMimeTest";
+ private Context mContext;
+ private final String MP3_FILE = "/sdcard/media_api/music/SHORTMP3.mp3";
+ private final String MEDIA_PLAYBACK_NAME = "com.android.music.MediaPlaybackActivity";
+
+ public MediaMimeTest() {
+ super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = getActivity();
+ // Checks you have all the test files on your SDCARD.
+ assertTrue(new File(MP3_FILE).exists());
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // ----------------------------------------------------------------------
+ // AUDIO mime type resolution tests.
+
+ @MediumTest
+ // Checks the MediaPlaybackActivity handles audio/mp3.
+ public void testCheckMediaPlaybackHandlesAudioMp3() throws Exception {
+ assertMediaPlaybackActivityHandles("audio/mp3");
+ }
+
+ @MediumTest
+ // Checks the MediaPlaybackActivity handles audio/*.
+ public void testCheckMediaPlaybackHandlesAudio() throws Exception {
+ assertMediaPlaybackActivityHandles("audio/*");
+ }
+
+ @MediumTest
+ // Checks the MediaPlaybackActivity handles application/itunes. Some servers
+ // set the Content-type header to application/iTunes (with capital T, but
+ // the download manager downcasts it) for their MP3 podcasts. This is non
+ // standard but we try to support it anyway.
+ // See bug 1401491
+ public void testCheckMediaPlaybackHandlesApplicationItunes() throws Exception {
+ assertMediaPlaybackActivityHandles("application/itunes");
+ }
+
+ @MediumTest
+ // Checks the activity resolver handling of mime types is case sensitive.
+ // See bug 1710534
+ public void testCheckActivityResolverMimeHandlingIsCaseSensitive() throws Exception {
+ assertNoActivityHandles("AUDIO/MP3"); // <--- look uppercase
+ }
+
+ @MediumTest
+ // Checks the activity resolver does not trims leading whitespaces when
+ // resolving mime types. Trailing whitespaces seems to be non
+ // significant.
+ // See bug 1710534
+ public void testCheckWhiteSpacesInMimeTypeHandling() throws Exception {
+ assertNoActivityHandles(" audio/mp3");
+ assertNoActivityHandles(" audio/mp3 ");
+ assertMediaPlaybackActivityHandles("audio/mp3 ");
+ }
+
+ // @return a ResolveInfo instance for the mime type or null if the type is
+ // not handled by any activity.
+ private ResolveInfo resolveMime(String mime) {
+ Intent viewIntent = new Intent(Intent.ACTION_VIEW);
+ Uri uri = Uri.fromParts("file", MP3_FILE, null);
+
+ viewIntent.setDataAndType(uri, mime);
+ return mContext.getPackageManager().resolveActivity(
+ viewIntent, PackageManager.MATCH_DEFAULT_ONLY);
+ }
+
+ // Helper method to check the media playback activity handles the given mime type.
+ // @param mime type to test for
+ private void assertMediaPlaybackActivityHandles(String mime) throws Exception {
+ ResolveInfo ri = resolveMime(mime);
+
+ assertNotNull(ri);
+ assertEquals(MEDIA_PLAYBACK_NAME, ri.activityInfo.name.toString());
+ }
+
+ // Helper method to check that NO activity handles the given mime type.
+ // @param mime type to test for
+ private void assertNoActivityHandles(String mime) throws Exception {
+ assertNull(resolveMime(mime));
+ }
+}