diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-18 17:39:46 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-18 17:39:46 -0700 |
commit | 105925376f8d0f6b318c9938c7b83ef7fef094da (patch) | |
tree | 3b19ee2bd8704cb9c6a0da7e42dec6759183de6d /media | |
parent | ba87e3e6c985e7175152993b5efcc7dd2f0e1c93 (diff) | |
download | frameworks_base-105925376f8d0f6b318c9938c7b83ef7fef094da.zip frameworks_base-105925376f8d0f6b318c9938c7b83ef7fef094da.tar.gz frameworks_base-105925376f8d0f6b318c9938c7b83ef7fef094da.tar.bz2 |
auto import from //branches/cupcake_rel/...@140373
Diffstat (limited to 'media')
-rw-r--r-- | media/java/android/media/AudioManager.java | 27 | ||||
-rw-r--r-- | media/java/android/media/AudioTrack.java | 16 | ||||
-rw-r--r-- | media/java/android/media/JetPlayer.java | 154 | ||||
-rw-r--r-- | media/java/android/media/MediaPlayer.java | 30 | ||||
-rw-r--r-- | media/java/android/media/MediaRecorder.java | 27 | ||||
-rw-r--r-- | media/jni/android_media_MediaRecorder.cpp | 14 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 4 | ||||
-rw-r--r-- | media/libmedia/JetPlayer.cpp | 12 | ||||
-rw-r--r-- | media/libmedia/mediarecorder.cpp | 5 | ||||
-rwxr-xr-x | media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java | 10 | ||||
-rw-r--r-- | media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java | 139 |
11 files changed, 308 insertions, 130 deletions
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 @@ public class AudioManager { 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 @@ public class AudioManager { * 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 @@ public class AudioManager { /** * 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 @@ public class AudioManager { * {@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 @@ public class AudioManager { * {@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 @@ public class AudioTrack */ 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 @@ public class AudioTrack 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 @@ public class AudioTrack 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 @@ public class JetPlayer //-------------------------------------------- // 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 @@ public class JetPlayer 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 @@ public class JetPlayer } - 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 @@ public class JetPlayer //--------------------------------------------------------- // 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 @@ public class JetPlayer (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 @@ public class JetPlayer //-------------------------------------------- - // 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 @@ public class JetPlayer //-------------------------------------------- - // 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 @@ public class JetPlayer @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 @@ public class MediaPlayer * 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 @@ public class MediaPlayer * 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 @@ public class MediaPlayer * 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 @@ public class MediaPlayer * 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 @@ public class MediaPlayer * 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 @@ public class MediaRecorder /** * 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 class MediaRecorder 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 @@ public class MediaRecorder * @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 @@ public class MediaRecorder * @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 @@ android_media_MediaRecorder_setMaxDuration(JNIEnv *env, jobject thiz, jint max_d } 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 @@ static JNINativeMethod gMethods[] = { {"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 @@ void AudioTrack::flush() 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 @@ void AudioTrack::setSampleRate(int rate) 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 @@ int JetPlayer::render() { } 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 @@ int JetPlayer::render() { }//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 MediaRecorder::setParameters(const String8& params) { 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 @@ public class MediaFrameworkTestRunner extends InstrumentationTestRunner { 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)); + } +} |