diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-27 15:38:40 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-27 15:38:40 -0700 |
commit | e1861133d51b9e6a6f658eb366630ad4f4d3ff8f (patch) | |
tree | 046aaac6d455ccd57d38f3a13df44ecd13ac0322 /media | |
parent | d91450e1169b3a57b3507fe86d947de05549f4ed (diff) | |
parent | 3f2fd987b230740e1b28ccb541d1181cb2187ae6 (diff) | |
download | frameworks_base-e1861133d51b9e6a6f658eb366630ad4f4d3ff8f.zip frameworks_base-e1861133d51b9e6a6f658eb366630ad4f4d3ff8f.tar.gz frameworks_base-e1861133d51b9e6a6f658eb366630ad4f4d3ff8f.tar.bz2 |
Merge commit 'korg/cupcake'
Conflicts:
core/java/android/webkit/WebView.java
core/java/android/widget/TwoLineListItem.java
preloaded-classes
Diffstat (limited to 'media')
27 files changed, 730 insertions, 301 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/AudioRecord.java b/media/java/android/media/AudioRecord.java index 0ef7760..a49bd67 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -165,27 +165,24 @@ public class AudioRecord */ private Object mRecordingStateLock = new Object(); /** - * The listener the AudioRecord notifies when a previously set marker is reached. - * @see #setMarkerReachedListener(OnMarkerReachedListener) + * The listener the AudioRecord notifies when the record position reaches a marker + * or for periodic updates during the progression of the record head. + * @see #setRecordPositionUpdateListener(OnRecordPositionUpdateListener) + * @see #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler) */ - private OnMarkerReachedListener mMarkerListener = null; + private OnRecordPositionUpdateListener mPositionListener = null; /** - * Lock to protect marker listener updates against event notifications + * Lock to protect position listener updates against event notifications */ - private final Object mMarkerListenerLock = new Object(); + private final Object mPositionListenerLock = new Object(); /** - * The listener the AudioRecord notifies periodically during recording. - * @see #setPeriodicNotificationListener(OnPeriodicNotificationListener) + * Handler for marker events coming from the native code */ - private OnPeriodicNotificationListener mPeriodicListener = null; + private NativeEventHandler mEventHandler = null; /** - * Lock to protect periodic listener updates against event notifications + * Looper associated with the thread that creates the AudioRecord instance */ - private final Object mPeriodicListenerLock = new Object(); - /** - * Handler for events coming from the native code - */ - private NativeEventHandler mNativeEventHandler = null; + private Looper mInitializationLooper = null; /** * Size of the native audio buffer. */ @@ -217,6 +214,11 @@ public class AudioRecord throws IllegalArgumentException { mState = STATE_UNINITIALIZED; mRecordingState = RECORDSTATE_STOPPED; + + // remember which looper is associated with the AudioRecord instanciation + if ((mInitializationLooper = Looper.myLooper()) == null) { + mInitializationLooper = Looper.getMainLooper(); + } audioParamCheck(audioSource, sampleRateInHz, channelConfig, audioFormat); @@ -319,21 +321,6 @@ public class AudioRecord } - // Convenience method for the creation of the native event handler - // It is called only when a non-null event listener is set. - // precondition: - // mNativeEventHandler is null - private void createNativeEventHandler() { - Looper looper; - if ((looper = Looper.myLooper()) != null) { - mNativeEventHandler = new NativeEventHandler(this, looper); - } else if ((looper = Looper.getMainLooper()) != null) { - mNativeEventHandler = new NativeEventHandler(this, looper); - } else { - mNativeEventHandler = null; - } - } - /** * Releases the native AudioRecord resources. @@ -433,7 +420,6 @@ public class AudioRecord } /** - * {@hide} * Returns the minimum buffer size required for the successful creation of an AudioRecord * object. * @param sampleRateInHz the sample rate expressed in Hertz. @@ -602,36 +588,40 @@ public class AudioRecord // Initialization / configuration //-------------------- /** - * Sets the listener the AudioRecord notifies when a previously set marker is reached. + * Sets the listener the AudioRecord notifies when a previously set marker is reached or + * for each periodic record head position update. * @param listener */ - public void setMarkerReachedListener(OnMarkerReachedListener listener) { - synchronized (mMarkerListenerLock) { - mMarkerListener = listener; - } - if ((listener != null) && (mNativeEventHandler == null)) { - createNativeEventHandler(); - } + public void setRecordPositionUpdateListener(OnRecordPositionUpdateListener listener) { + setRecordPositionUpdateListener(listener, null); } - - /** - * Sets the listener the AudioRecord notifies periodically during recording. - * @param listener - */ - public void setPeriodicNotificationListener(OnPeriodicNotificationListener listener) { - synchronized (mPeriodicListenerLock) { - mPeriodicListener = listener; - } - if ((listener != null) && (mNativeEventHandler == null)) { - createNativeEventHandler(); + + public void setRecordPositionUpdateListener(OnRecordPositionUpdateListener listener, + Handler handler) { + synchronized (mPositionListenerLock) { + + mPositionListener = listener; + + if (listener != null) { + if (handler != null) { + mEventHandler = new NativeEventHandler(this, handler.getLooper()); + } else { + // no given handler, use the looper the AudioRecord was created in + mEventHandler = new NativeEventHandler(this, mInitializationLooper); + } + } else { + mEventHandler = null; + } } + } /** - * Sets the marker position at which the listener, if set with - * {@link #setMarkerReachedListener(OnMarkerReachedListener)}, is called. + * Sets the marker position at which the listener is called, if set with + * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)} or + * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)}. * @param markerInFrames marker position expressed in frames * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, * {@link #ERROR_INVALID_OPERATION} @@ -642,8 +632,9 @@ public class AudioRecord /** - * Sets the period at which the listener, if set with - * {@link #setPositionNotificationPeriod(int)}, is called. + * Sets the period at which the listener is called, if set with + * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)} or + * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)}. * @param periodInFrames update period expressed in frames * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION} */ @@ -659,70 +650,65 @@ public class AudioRecord * Interface definition for a callback to be invoked when an AudioRecord has * reached a notification marker set by setNotificationMarkerPosition(). */ - public interface OnMarkerReachedListener { + public interface OnRecordPositionUpdateListener { /** * Called on the listener to notify it that the previously set marker has been reached * by the recording head. */ void onMarkerReached(AudioRecord recorder); - } - - - /** - * Interface definition for a callback to be invoked for each periodic AudioRecord - * update during recording. The update interval is set by setPositionNotificationPeriod(). - */ - public interface OnPeriodicNotificationListener { + /** - * Called on the listener to periodically notify it that the recording head has reached + * Called on the listener to periodically notify it that the record head has reached * a multiple of the notification period. */ void onPeriodicNotification(AudioRecord recorder); } + + //--------------------------------------------------------- // Inner classes //-------------------- + /** - * Helper class to handle the forwarding of native events to the appropriate listeners - */ - private class NativeEventHandler extends Handler - { - private AudioRecord mAudioRecord; - - public NativeEventHandler(AudioRecord ar, Looper looper) { + * Helper class to handle the forwarding of native events to the appropriate listener + * (potentially) handled in a different thread + */ + private class NativeEventHandler extends Handler { + + private final AudioRecord mAudioRecord; + + NativeEventHandler(AudioRecord recorder, Looper looper) { super(looper); - mAudioRecord = ar; + mAudioRecord = recorder; } - + @Override public void handleMessage(Message msg) { - if (mAudioRecord == null) { - return; + OnRecordPositionUpdateListener listener = null; + synchronized (mPositionListenerLock) { + listener = mAudioRecord.mPositionListener; } + switch(msg.what) { case NATIVE_EVENT_MARKER: - synchronized (mMarkerListenerLock) { - if (mAudioRecord.mMarkerListener != null) { - mAudioRecord.mMarkerListener.onMarkerReached(mAudioRecord); - } + if (listener != null) { + listener.onMarkerReached(mAudioRecord); } break; case NATIVE_EVENT_NEW_POS: - synchronized (mPeriodicListenerLock) { - if (mAudioRecord.mPeriodicListener != null) { - mAudioRecord.mPeriodicListener.onPeriodicNotification(mAudioRecord); - } + if (listener != null) { + listener.onPeriodicNotification(mAudioRecord); } break; default: Log.e(TAG, "[ android.media.AudioRecord.NativeEventHandler ] " + "Unknown event type: " + msg.what); - break; + break; } } - } + }; //--------------------------------------------------------- @@ -737,9 +723,10 @@ public class AudioRecord return; } - if (recorder.mNativeEventHandler != null) { - Message m = recorder.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj); - recorder.mNativeEventHandler.sendMessage(m); + if (recorder.mEventHandler != null) { + Message m = + recorder.mEventHandler.obtainMessage(what, arg1, arg2, obj); + recorder.mEventHandler.sendMessage(m); } } diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 83ede0d..2e3e460 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -21,6 +21,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.database.ContentObserver; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; import android.os.Binder; @@ -92,7 +93,8 @@ public class AudioService extends IAudioService.Stub { private AudioHandler mAudioHandler; /** @see VolumeStreamState */ private VolumeStreamState[] mStreamStates; - + private SettingsObserver mSettingsObserver; + private boolean mMicMute; private int mMode; private int[] mRoutes = new int[AudioSystem.NUM_MODES]; @@ -157,9 +159,6 @@ public class AudioService extends IAudioService.Stub { */ private int mRingerMode; - /** @see System#MODE_RINGER_STREAMS_AFFECTED */ - private int mRingerModeAffectedStreams; - /** @see System#MUTE_STREAMS_AFFECTED */ private int mMuteAffectedStreams; @@ -181,7 +180,8 @@ public class AudioService extends IAudioService.Stub { mContext = context; mContentResolver = context.getContentResolver(); mVolumePanel = new VolumePanel(context, this); - + mSettingsObserver = new SettingsObserver(); + createAudioSystemThread(); createStreamStates(); readPersistedSettings(); @@ -275,8 +275,6 @@ public class AudioService extends IAudioService.Stub { final ContentResolver cr = mContentResolver; mRingerMode = System.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL); - mRingerModeAffectedStreams = System.getInt(mContentResolver, - System.MODE_RINGER_STREAMS_AFFECTED, 1 << AudioSystem.STREAM_RING); mVibrateSetting = System.getInt(cr, System.VIBRATE_ON, 0); @@ -494,32 +492,36 @@ public class AudioService extends IAudioService.Stub { /** @see AudioManager#setRingerMode(int) */ public void setRingerMode(int ringerMode) { if (ringerMode != mRingerMode) { - mRingerMode = ringerMode; - - // Adjust volumes via posting message - int numStreamTypes = AudioSystem.getNumStreamTypes(); - if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) { - for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { - if (!isStreamAffectedByRingerMode(streamType)) continue; - // Bring back last audible volume - setStreamVolumeInt(streamType, mStreamStates[streamType].mLastAudibleIndex, - false); - } - } else { - for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { - if (!isStreamAffectedByRingerMode(streamType)) continue; - // Either silent or vibrate, either way volume is 0 - setStreamVolumeInt(streamType, 0, false); - } - } + setRingerModeInt(ringerMode); // Send sticky broadcast broadcastRingerMode(); + } + } - // Post a persist ringer mode msg - sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, SHARED_MSG, - SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); + private void setRingerModeInt(int ringerMode) { + mRingerMode = ringerMode; + + // Adjust volumes via posting message + int numStreamTypes = AudioSystem.getNumStreamTypes(); + if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) { + for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { + if (!isStreamAffectedByRingerMode(streamType)) continue; + // Bring back last audible volume + setStreamVolumeInt(streamType, mStreamStates[streamType].mLastAudibleIndex, + false); + } + } else { + for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { + if (!isStreamAffectedByRingerMode(streamType)) continue; + // Either silent or vibrate, either way volume is 0 + setStreamVolumeInt(streamType, 0, false); + } } + + // Post a persist ringer mode msg + sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, SHARED_MSG, + SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); } /** @see AudioManager#shouldVibrate(int) */ @@ -565,7 +567,6 @@ public class AudioService extends IAudioService.Stub { /** * @see #setVibrateSetting(int, int) - * @hide */ public static int getValueForVibrateSetting(int existingValue, int vibrateType, int vibrateSetting) { @@ -659,7 +660,6 @@ public class AudioService extends IAudioService.Stub { } /** @see AudioManager#playSoundEffect(int, float) */ - /* @hide FIXME: unhide before release */ public void playSoundEffectVolume(int effectType, float volume) { sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SHARED_MSG, SENDMSG_NOOP, effectType, (int) (volume * 1000), null, 0); @@ -783,7 +783,9 @@ public class AudioService extends IAudioService.Stub { } public boolean isStreamAffectedByRingerMode(int streamType) { - return (mRingerModeAffectedStreams & (1 << streamType)) != 0; + int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver, + Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); + return (ringerModeAffectedStreams & (1 << streamType)) != 0; } public boolean isStreamAffectedByMute(int streamType) { @@ -1233,4 +1235,25 @@ public class AudioService extends IAudioService.Stub { } } + private class SettingsObserver extends ContentObserver { + + SettingsObserver() { + super(new Handler()); + mContentResolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + + /* + * Ensure all stream types that should be affected by ringer mode + * are in the proper state. + */ + setRingerModeInt(getRingerMode()); + } + + } + } diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 316fa7a..4196ef3 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); @@ -414,7 +423,6 @@ public class AudioTrack } /** - * @hide * Returns the current playback rate in Hz. Note that this rate may differ from one set using * {@link #setPlaybackRate(int)} as the value effectively set is implementation-dependent. */ @@ -513,7 +521,6 @@ public class AudioTrack } /** - * {@hide} * Returns the minimum buffer size required for the successful creation of an AudioTrack * object to be created in the {@link #MODE_STREAM} mode. * @param sampleRateInHz the sample rate expressed in Hertz. @@ -902,11 +909,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..c9efac5 100644 --- a/media/java/android/media/JetPlayer.java +++ b/media/java/android/media/JetPlayer.java @@ -63,26 +63,33 @@ public class JetPlayer private static final int JET_EVENT_CHAN_SHIFT = 14; // shift to get MIDI channel to bit 0 private static final int JET_EVENT_TRACK_SHIFT = 18; // shift to get track ID to bit 0 private static final int JET_EVENT_SEG_SHIFT = 24; // shift to get segment ID to bit 0 + + // to keep in sync with values used in external/sonivox/arm-wt-22k/Android.mk + // Jet rendering audio parameters + private static final int JET_OUTPUT_RATE = 22050; // _SAMPLE_RATE_22050 in Android.mk + private static final int JET_OUTPUT_CHANNEL_CONFIG = + AudioFormat.CHANNEL_CONFIGURATION_STEREO; // NUM_OUTPUT_CHANNELS=2 in Android.mk //-------------------------------------------- // 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; @@ -101,8 +108,9 @@ public class JetPlayer // Constructor, finalize //------------------------ public static JetPlayer getJetPlayer() { - if (singletonRef == null) + if (singletonRef == null) { singletonRef = new JetPlayer(); + } return singletonRef; } @@ -115,10 +123,24 @@ public class JetPlayer private JetPlayer() { - - native_setup(new WeakReference<JetPlayer>(this), - JetPlayer.getMaxTracks(), - 1200); //TODO parametrize this (?) + + // remember which looper is associated with the JetPlayer instanciation + if ((mInitializationLooper = Looper.myLooper()) == null) { + mInitializationLooper = Looper.getMainLooper(); + } + + int buffSizeInBytes = AudioTrack.getMinBufferSize(JET_OUTPUT_RATE, + JET_OUTPUT_CHANNEL_CONFIG, AudioFormat.ENCODING_PCM_16BIT); + + if ((buffSizeInBytes != AudioTrack.ERROR) + && (buffSizeInBytes != AudioTrack.ERROR_BAD_VALUE)) { + + native_setup(new WeakReference<JetPlayer>(this), + JetPlayer.getMaxTracks(), + // bytes to frame conversion: sample format is ENCODING_PCM_16BIT, 2 channels + // 1200 == minimum buffer size in frames on generation 1 hardware + Math.max(1200, buffSizeInBytes / 4)); + } } @@ -132,18 +154,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 +245,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 +274,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 +300,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 +370,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 +397,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..19ab0ad 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; @@ -1131,8 +1131,6 @@ public class MediaPlayer /** * Interface definition of a callback to be invoked when the * video size is first known or updated - * FIXME: Unhide this API after approval - * @hide */ public interface OnVideoSizeChangedListener { @@ -1142,7 +1140,6 @@ public class MediaPlayer * @param mp the MediaPlayer associated with this callback * @param width the width of the video * @param height the height of the video - * @hide */ public void onVideoSizeChanged(MediaPlayer mp, int width, int height); } @@ -1151,12 +1148,11 @@ 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 - * @hide + * @param listener the callback that will be run */ - public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener l) + public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener) { - mOnVideoSizeChangedListener = l; + mOnVideoSizeChangedListener = listener; } private OnVideoSizeChangedListener mOnVideoSizeChangedListener; @@ -1178,7 +1174,7 @@ public class MediaPlayer /** The video is streamed and its container is not valid for progressive * playback i.e the video's index (e.g moov atom) is not at the start of the * file. - * @hide pending API council approval. Replace with @see tag after. + * @see android.media.MediaPlayer.OnErrorListener */ public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200; @@ -1226,14 +1222,12 @@ public class MediaPlayer */ /** Unspecified media player info. * @see android.media.MediaPlayer.OnInfoListener - * @hide pending API council approval. */ public static final int MEDIA_INFO_UNKNOWN = 1; /** The video is too complex for the decoder: it can't decode frames fast * enough. Possibly only the audio plays fine at this stage. * @see android.media.MediaPlayer.OnInfoListener - * @hide pending API council approval. */ public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; @@ -1241,20 +1235,17 @@ public class MediaPlayer * not interleaved at all, e.g has all the video samples first then all the * audio ones. Video is playing but a lot of disk seeks may be happening. * @see android.media.MediaPlayer.OnInfoListener - * @hide pending API council approval. */ public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; /** The media cannot be seeked (e.g live stream) * @see android.media.MediaPlayer.OnInfoListener - * @hide pending API council approval. */ public static final int MEDIA_INFO_NOT_SEEKABLE = 801; /** * Interface definition of a callback to be invoked to communicate some * info and/or warning about the media or its playback. - * @hide pending API council approval. */ public interface OnInfoListener { @@ -1282,7 +1273,6 @@ public class MediaPlayer * Register a callback to be invoked when an info/warning is available. * * @param listener the callback that will be run - * @hide pending API council approval. */ public void setOnInfoListener(OnInfoListener listener) { 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/jni/soundpool/NOTICE b/media/jni/soundpool/NOTICE new file mode 100644 index 0000000..c5b1efa --- /dev/null +++ b/media/jni/soundpool/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2005-2008, 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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 7594ff0..986f88e 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -200,6 +200,7 @@ status_t AudioRecord::set( // TODO: add audio hardware input latency here mLatency = (1000*mFrameCount) / mSampleRate; mMarkerPosition = 0; + mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; @@ -293,6 +294,9 @@ status_t AudioRecord::stop() if (android_atomic_and(~1, &mActive) == 1) { mAudioRecord->stop(); + // the record head position will reset to 0, so if a marker is set, we need + // to activate it again + mMarkerReached = false; if (t != 0) { t->requestExit(); } else { @@ -317,6 +321,7 @@ status_t AudioRecord::setMarkerPosition(uint32_t marker) if (mCbf == 0) return INVALID_OPERATION; mMarkerPosition = marker; + mMarkerReached = false; return NO_ERROR; } @@ -492,10 +497,10 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) size_t readSize; // Manage marker callback - if (mMarkerPosition > 0) { + if (!mMarkerReached && (mMarkerPosition > 0)) { if (mCblk->user >= mMarkerPosition) { mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); - mMarkerPosition = 0; + mMarkerReached = true; } } @@ -527,7 +532,14 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) readSize = audioBuffer.size; // Sanity check on returned size - if (ssize_t(readSize) <= 0) break; + if (ssize_t(readSize) <= 0) { + // The callback is done filling buffers + // Keep this thread going to handle timed events and + // still try to get more data in intervals of WAIT_PERIOD_MS + // but don't just loop and block the CPU, so wait + usleep(WAIT_PERIOD_MS*1000); + break; + } if (readSize > reqSize) readSize = reqSize; audioBuffer.size = readSize; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index d26b0c5..24f7281 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -259,6 +259,7 @@ status_t AudioTrack::set( mLatency = afLatency + (1000*mFrameCount) / mSampleRate; mLoopCount = 0; mMarkerPosition = 0; + mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; @@ -360,6 +361,9 @@ void AudioTrack::stop() // Cancel loops (If we are in the middle of a loop, playback // would not stop until loopCount reaches 0). setLoop(0, 0, 0); + // the playback head position will reset to 0, so if a marker is set, we need + // to activate it again + mMarkerReached = false; // Force flush if a shared buffer is used otherwise audioflinger // will not stop before end of buffer is reached. if (mSharedBuffer != 0) { @@ -385,14 +389,18 @@ bool AudioTrack::stopped() const void AudioTrack::flush() { LOGV("flush"); + + // clear playback marker and periodic update counter + mMarkerPosition = 0; + mMarkerReached = false; + mUpdatePeriod = 0; + 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 +451,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() @@ -510,6 +518,7 @@ status_t AudioTrack::setMarkerPosition(uint32_t marker) if (mCbf == 0) return INVALID_OPERATION; mMarkerPosition = marker; + mMarkerReached = false; return NO_ERROR; } @@ -757,10 +766,10 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) } // Manage marker callback - if(mMarkerPosition > 0) { + if (!mMarkerReached && (mMarkerPosition > 0)) { if (mCblk->server >= mMarkerPosition) { mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); - mMarkerPosition = 0; + mMarkerReached = true; } } diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp index 2c62104..586aacb 100644 --- a/media/libmedia/JetPlayer.cpp +++ b/media/libmedia/JetPlayer.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_NDEBUG 0 +//#define LOG_NDEBUG 0 #define LOG_TAG "JetPlayer-C" #include <utils/Log.h> @@ -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/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 6b40412..809316a 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -91,6 +91,7 @@ MediaPlayer::MediaPlayer() mLoop = false; mLeftVolume = mRightVolume = 1.0; mVideoWidth = mVideoHeight = 0; + mLockThreadId = 0; } void MediaPlayer::onFirstRef() @@ -223,16 +224,24 @@ status_t MediaPlayer::prepare() { LOGV("prepare"); Mutex::Autolock _l(mLock); - if (mPrepareSync) return -EALREADY; + mLockThreadId = getThreadId(); + if (mPrepareSync) { + mLockThreadId = 0; + return -EALREADY; + } mPrepareSync = true; status_t ret = prepareAsync_l(); - if (ret != NO_ERROR) return ret; + if (ret != NO_ERROR) { + mLockThreadId = 0; + return ret; + } if (mPrepareSync) { mSignal.wait(mLock); // wait for prepare done mPrepareSync = false; } LOGV("prepare complete - status=%d", mPrepareStatus); + mLockThreadId = 0; return mPrepareStatus; } @@ -407,8 +416,12 @@ status_t MediaPlayer::seekTo_l(int msec) status_t MediaPlayer::seekTo(int msec) { + mLockThreadId = getThreadId(); Mutex::Autolock _l(mLock); - return seekTo_l(msec); + status_t result = seekTo_l(msec); + mLockThreadId = 0; + + return result; } status_t MediaPlayer::reset() @@ -485,14 +498,24 @@ void MediaPlayer::notify(int msg, int ext1, int ext2) { LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); bool send = true; + bool locked = false; // TODO: In the future, we might be on the same thread if the app is // running in the same process as the media server. In that case, // this will deadlock. - mLock.lock(); + // + // The threadId hack below works around this for the care of prepare + // and seekTo within the same process. + // FIXME: Remember, this is a hack, it's not even a hack that is applied + // consistently for all use-cases, this needs to be revisited. + if (mLockThreadId != getThreadId()) { + mLock.lock(); + locked = true; + } + if (mPlayer == 0) { LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2); - mLock.unlock(); // release the lock when done. + if (locked) mLock.unlock(); // release the lock when done. return; } @@ -561,7 +584,7 @@ void MediaPlayer::notify(int msg, int ext1, int ext2) } sp<MediaPlayerListener> listener = mListener; - mLock.unlock(); + if (locked) mLock.unlock(); // this prevents re-entrant calls into client code if ((listener != 0) && send) { 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/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 95001c6..8ef0dc6 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -460,6 +460,7 @@ void MediaPlayerService::Client::disconnect() Mutex::Autolock l(mLock); p = mPlayer; } + mClient.clear(); mPlayer.clear(); // clear the notification to prevent callbacks to dead client diff --git a/media/sdutils/Android.mk b/media/sdutils/Android.mk index 2009b3c..dafb8a6 100644 --- a/media/sdutils/Android.mk +++ b/media/sdutils/Android.mk @@ -9,6 +9,7 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := libhardware_legacy libcutils libutils libc LOCAL_MODULE:= sdutil +LOCAL_MODULE_TAGS := debug include $(BUILD_EXECUTABLE) 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)); + } +} diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java index 4fa6735..61a8a29 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java @@ -22,8 +22,7 @@ import android.graphics.Bitmap; import java.io.FileOutputStream; import android.test.AndroidTestCase; import com.android.mediaframeworktest.MediaNames; -import android.test.suitebuilder.annotation.LargeTest; -import android.test.suitebuilder.annotation.Suppress; +import android.test.suitebuilder.annotation.*; /** * WARNING: @@ -35,7 +34,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { private static final String TAG = "MediaMetadataRetrieverTest"; // Test album art extraction. - @LargeTest + @MediumTest public static void testAlbumArt() throws Exception { Log.v(TAG, "testAlbumArt starts."); MediaMetadataRetriever retriever = new MediaMetadataRetriever(); @@ -109,7 +108,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // If the specified call order and valid media file is used, no exception // should be thrown. - @LargeTest + @MediumTest public static void testBasicNormalMethodCallSequence() throws Exception { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); @@ -136,7 +135,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // If setDataSource() has not been called, both captureFrame() and extractMetadata() must // return null. - @LargeTest + @MediumTest public static void testBasicAbnormalMethodCallSequence() { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); @@ -145,7 +144,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { } // Test setDataSource() - @LargeTest + @MediumTest public static void testSetDataSource() { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY); @@ -190,7 +189,7 @@ public class MediaMetadataRetrieverTest extends AndroidTestCase { // Due to the lack of permission to access hardware decoder, any calls // attempting to capture a frame will fail. These are commented out for now // until we find a solution to this access permission problem. - @LargeTest + @MediumTest public static void testIntendedUsage() { // By default, capture frame and retrieve metadata MediaMetadataRetriever retriever = new MediaMetadataRetriever(); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java index bde000b..134144d 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderPrepareStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; import java.io.IOException; @@ -59,7 +59,7 @@ public class MediaRecorderPrepareStateUnitTest extends AndroidTestCase implement } } - @LargeTest + @MediumTest public void testPrepare() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderResetStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderResetStateUnitTest.java index 80532c3..cae9e31 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderResetStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderResetStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderResetStateUnitTest extends AndroidTestCase implements recorder.reset(); } - @LargeTest + @MediumTest public void testReset() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioEncoderStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioEncoderStateUnitTest.java index e387a77..4b5a818 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioEncoderStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioEncoderStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderSetAudioEncoderStateUnitTest extends AndroidTestCase i recorder.setAudioEncoder(MediaRecorderStateUnitTestTemplate.AUDIO_ENCODER); } - @LargeTest + @MediumTest public void testSetAudioEncoder() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioSourceStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioSourceStateUnitTest.java index 60af54c..f8ab48cf 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioSourceStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetAudioSourceStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderSetAudioSourceStateUnitTest extends AndroidTestCase im recorder.setAudioSource(MediaRecorderStateUnitTestTemplate.AUDIO_SOURCE); } - @LargeTest + @MediumTest public void testSetAudioSource() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java index 37d97e9..712a758 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFileStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -51,7 +51,7 @@ public class MediaRecorderSetOutputFileStateUnitTest extends AndroidTestCase imp recorder.setOutputFile(MediaRecorderStateUnitTestTemplate.RECORD_OUTPUT_PATH); } - @LargeTest + @MediumTest public void testSetOutputFile() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFormatStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFormatStateUnitTest.java index a7ee2d4..cacdd87 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFormatStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderSetOutputFormatStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderSetOutputFormatStateUnitTest extends AndroidTestCase i recorder.setOutputFormat(MediaRecorderStateUnitTestTemplate.OUTPUT_FORMAT); } - @LargeTest + @MediumTest public void testSetOutputFormat() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStartStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStartStateUnitTest.java index 4af5967..d1232fc 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStartStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStartStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderStartStateUnitTest extends AndroidTestCase implements recorder.start(); } - @LargeTest + @MediumTest public void testStart() { mTestTemplate.runTestOnMethod(this); } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java index 5475900..8737595 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaRecorderStopStateUnitTest.java @@ -18,7 +18,7 @@ package com.android.mediaframeworktest.unit; import android.media.MediaRecorder; import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Suppress; /** @@ -54,7 +54,7 @@ public class MediaRecorderStopStateUnitTest extends AndroidTestCase implements M recorder.stop(); } - @LargeTest + @MediumTest public void testStop() { mTestTemplate.runTestOnMethod(this); } |