summaryrefslogtreecommitdiffstats
path: root/media/java
diff options
context:
space:
mode:
Diffstat (limited to 'media/java')
-rw-r--r--media/java/android/media/AudioManager.java144
-rw-r--r--media/java/android/media/AudioService.java20
-rw-r--r--media/java/android/media/IRemoteControlClient.aidl60
-rw-r--r--media/java/android/media/audiofx/AudioEffect.java15
-rw-r--r--media/java/android/media/audiofx/BassBoost.java13
-rw-r--r--media/java/android/media/audiofx/Equalizer.java15
-rw-r--r--media/java/android/media/audiofx/Virtualizer.java16
-rw-r--r--media/java/android/media/videoeditor/MediaArtistNativeHelper.java93
-rwxr-xr-xmedia/java/android/media/videoeditor/MediaImageItem.java26
-rwxr-xr-xmedia/java/android/media/videoeditor/MediaItem.java38
-rwxr-xr-xmedia/java/android/media/videoeditor/MediaVideoItem.java18
11 files changed, 320 insertions, 138 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 56a9933..7a92b35 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1743,7 +1743,13 @@ public class AudioManager {
/**
* @hide
- * @param eventReceiver
+ * Unregisters the remote control client that was providing information to display on the
+ * remotes.
+ * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
+ * that receives the media button intent, and associated with the remote control
+ * client.
+ * @see #registerRemoteControlClient(ComponentName)
+
*/
public void unregisterRemoteControlClient(ComponentName eventReceiver) {
if (eventReceiver == null) {
@@ -1783,27 +1789,152 @@ public class AudioManager {
* Definitions of constants to be used in {@link android.media.IRemoteControlClient}.
*/
public final class RemoteControlParameters {
+ /**
+ * Playback state of an IRemoteControlClient which is stopped.
+ *
+ * @see android.media.IRemoteControlClient#getPlaybackState()
+ */
public final static int PLAYSTATE_STOPPED = 1;
+ /**
+ * Playback state of an IRemoteControlClient which is paused.
+ *
+ * @see android.media.IRemoteControlClient#getPlaybackState()
+ */
public final static int PLAYSTATE_PAUSED = 2;
+ /**
+ * Playback state of an IRemoteControlClient which is playing media.
+ *
+ * @see android.media.IRemoteControlClient#getPlaybackState()
+ */
public final static int PLAYSTATE_PLAYING = 3;
+ /**
+ * Playback state of an IRemoteControlClient which is fast forwarding in the media
+ * it is currently playing.
+ *
+ * @see android.media.IRemoteControlClient#getPlaybackState()
+ */
public final static int PLAYSTATE_FAST_FORWARDING = 4;
+ /**
+ * Playback state of an IRemoteControlClient which is fast rewinding in the media
+ * it is currently playing.
+ *
+ * @see android.media.IRemoteControlClient#getPlaybackState()
+ */
public final static int PLAYSTATE_REWINDING = 5;
+ /**
+ * Playback state of an IRemoteControlClient which is skipping to the next
+ * logical chapter (such as a song in a playlist) in the media it is currently playing.
+ *
+ * @see android.media.IRemoteControlClient#getPlaybackState()
+ */
public final static int PLAYSTATE_SKIPPING_FORWARDS = 6;
+ /**
+ * Playback state of an IRemoteControlClient which is skipping back to the previous
+ * logical chapter (such as a song in a playlist) in the media it is currently playing.
+ *
+ * @see android.media.IRemoteControlClient#getPlaybackState()
+ */
public final static int PLAYSTATE_SKIPPING_BACKWARDS = 7;
+ /**
+ * Playback state of an IRemoteControlClient which is buffering data to play before it can
+ * start or resume playback.
+ *
+ * @see android.media.IRemoteControlClient#getPlaybackState()
+ */
public final static int PLAYSTATE_BUFFERING = 8;
+ /**
+ * Playback state of an IRemoteControlClient which cannot perform any playback related
+ * operation because of an internal error. Examples of such situations are no network
+ * connectivity when attempting to stream data from a server, or expired user credentials
+ * when trying to play subscription-based content.
+ *
+ * @see android.media.IRemoteControlClient#getPlaybackState()
+ */
+ public final static int PLAYSTATE_ERROR = 9;
+ /**
+ * Flag indicating an IRemoteControlClient makes use of the "previous" media key.
+ *
+ * @see android.media.IRemoteControlClient#getTransportControlFlags()
+ * @see android.view.KeyEvent#KEYCODE_MEDIA_PREVIOUS
+ */
public final static int FLAG_KEY_MEDIA_PREVIOUS = 1 << 0;
+ /**
+ * Flag indicating an IRemoteControlClient makes use of the "rewing" media key.
+ *
+ * @see android.media.IRemoteControlClient#getTransportControlFlags()
+ * @see android.view.KeyEvent#KEYCODE_MEDIA_REWIND
+ */
public final static int FLAG_KEY_MEDIA_REWIND = 1 << 1;
+ /**
+ * Flag indicating an IRemoteControlClient makes use of the "play" media key.
+ *
+ * @see android.media.IRemoteControlClient#getTransportControlFlags()
+ * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY
+ */
public final static int FLAG_KEY_MEDIA_PLAY = 1 << 2;
+ /**
+ * Flag indicating an IRemoteControlClient makes use of the "play/pause" media key.
+ *
+ * @see android.media.IRemoteControlClient#getTransportControlFlags()
+ * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE
+ */
public final static int FLAG_KEY_MEDIA_PLAY_PAUSE = 1 << 3;
+ /**
+ * Flag indicating an IRemoteControlClient makes use of the "pause" media key.
+ *
+ * @see android.media.IRemoteControlClient#getTransportControlFlags()
+ * @see android.view.KeyEvent#KEYCODE_MEDIA_PAUSE
+ */
public final static int FLAG_KEY_MEDIA_PAUSE = 1 << 4;
+ /**
+ * Flag indicating an IRemoteControlClient makes use of the "stop" media key.
+ *
+ * @see android.media.IRemoteControlClient#getTransportControlFlags()
+ * @see android.view.KeyEvent#KEYCODE_MEDIA_STOP
+ */
public final static int FLAG_KEY_MEDIA_STOP = 1 << 5;
+ /**
+ * Flag indicating an IRemoteControlClient makes use of the "fast forward" media key.
+ *
+ * @see android.media.IRemoteControlClient#getTransportControlFlags()
+ * @see android.view.KeyEvent#KEYCODE_MEDIA_FAST_FORWARD
+ */
public final static int FLAG_KEY_MEDIA_FAST_FORWARD = 1 << 6;
+ /**
+ * Flag indicating an IRemoteControlClient makes use of the "next" media key.
+ *
+ * @see android.media.IRemoteControlClient#getTransportControlFlags()
+ * @see android.view.KeyEvent#KEYCODE_MEDIA_NEXT
+ */
public final static int FLAG_KEY_MEDIA_NEXT = 1 << 7;
+ /**
+ * Flag used to signal that the metadata exposed by the IRemoteControlClient has changed.
+ *
+ * @see #notifyRemoteControlInformationChanged(ComponentName, int)
+ */
public final static int FLAG_INFORMATION_CHANGED_METADATA = 1 << 0;
+ /**
+ * Flag used to signal that the transport control buttons supported by the
+ * IRemoteControlClient have changed.
+ * This can for instance happen when playback is at the end of a playlist, and the "next"
+ * operation is not supported anymore.
+ *
+ * @see #notifyRemoteControlInformationChanged(ComponentName, int)
+ */
public final static int FLAG_INFORMATION_CHANGED_KEY_MEDIA = 1 << 1;
+ /**
+ * Flag used to signal that the playback state of the IRemoteControlClient has changed.
+ *
+ * @see #notifyRemoteControlInformationChanged(ComponentName, int)
+ */
public final static int FLAG_INFORMATION_CHANGED_PLAYSTATE = 1 << 2;
+ /**
+ * Flag used to signal that the album art for the IRemoteControlClient has changed.
+ *
+ * @see #notifyRemoteControlInformationChanged(ComponentName, int)
+ */
public final static int FLAG_INFORMATION_CHANGED_ALBUM_ART = 1 << 3;
}
@@ -1830,6 +1961,17 @@ public class AudioManager {
/**
* @hide
+ * The media button event receiver associated with the IRemoteControlClient.
+ * The {@link android.content.ComponentName} value of the event receiver can be retrieved with
+ * {@link android.content.ComponentName#unflattenFromString(String)}
+ *
+ * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION
+ */
+ public static final String EXTRA_REMOTE_CONTROL_EVENT_RECEIVER =
+ "android.media.EXTRA_REMOTE_CONTROL_EVENT_RECEIVER";
+
+ /**
+ * @hide
* The flags describing what information has changed in the current remote control client.
*
* @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 5951229..ff2e66b 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -17,6 +17,7 @@
package android.media;
import android.app.ActivityManagerNative;
+import android.app.KeyguardManager;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
@@ -309,6 +310,8 @@ public class AudioService extends IAudioService.Stub {
private static final int NOTIFICATION_VOLUME_DELAY_MS = 5000;
// previous volume adjustment direction received by checkForRingerModeChange()
private int mPrevVolDirection = AudioManager.ADJUST_SAME;
+ // Keyguard manager proxy
+ private KeyguardManager mKeyguardManager;
///////////////////////////////////////////////////////////////////////////
// Construction
@@ -492,8 +495,10 @@ public class AudioService extends IAudioService.Stub {
streamType = getActiveStreamType(suggestedStreamType);
}
- // Don't play sound on other streams
- if (streamType != AudioSystem.STREAM_RING && (flags & AudioManager.FLAG_PLAY_SOUND) != 0) {
+ // Play sounds on STREAM_RING only and if lock screen is not on.
+ if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
+ ((STREAM_VOLUME_ALIAS[streamType] != AudioSystem.STREAM_RING) ||
+ (mKeyguardManager != null && mKeyguardManager.isKeyguardLocked()))) {
flags &= ~AudioManager.FLAG_PLAY_SOUND;
}
@@ -2167,8 +2172,10 @@ public class AudioService extends IAudioService.Stub {
case MSG_RCDISPLAY_UPDATE:
synchronized(mCurrentRcLock) {
+ // msg.obj is guaranteed to be non null
+ RemoteControlStackEntry rcse = (RemoteControlStackEntry)msg.obj;
if ((mCurrentRcClient == null) ||
- (!mCurrentRcClient.equals((IRemoteControlClient)msg.obj))) {
+ (!mCurrentRcClient.equals(rcse.mRcClient))) {
// the remote control display owner has changed between the
// the message to update the display was sent, and the time it
// gets to be processed (now)
@@ -2183,6 +2190,9 @@ public class AudioService extends IAudioService.Stub {
rcClientIntent.putExtra(
AudioManager.EXTRA_REMOTE_CONTROL_CLIENT_INFO_CHANGED,
msg.arg1);
+ rcClientIntent.putExtra(
+ AudioManager.EXTRA_REMOTE_CONTROL_EVENT_RECEIVER,
+ rcse.mReceiverComponent.flattenToString());
rcClientIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcast(rcClientIntent);
}
@@ -2508,6 +2518,8 @@ public class AudioService extends IAudioService.Stub {
sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SHARED_MSG, SENDMSG_NOOP,
0, 0, null, 0);
+ mKeyguardManager =
+ (KeyguardManager)mContext.getSystemService(Context.KEYGUARD_SERVICE);
mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
resetBluetoothSco();
getBluetoothHeadset();
@@ -3131,7 +3143,7 @@ public class AudioService extends IAudioService.Stub {
mCurrentRcClient = rcse.mRcClient;
}
mAudioHandler.sendMessage( mAudioHandler.obtainMessage(MSG_RCDISPLAY_UPDATE,
- infoFlagsAboutToBeUsed /* arg1 */, 0, rcse.mRcClient /* obj */) );
+ infoFlagsAboutToBeUsed /* arg1 */, 0, rcse /* obj, != null */) );
}
/**
diff --git a/media/java/android/media/IRemoteControlClient.aidl b/media/java/android/media/IRemoteControlClient.aidl
index a49371c..76d178c 100644
--- a/media/java/android/media/IRemoteControlClient.aidl
+++ b/media/java/android/media/IRemoteControlClient.aidl
@@ -19,7 +19,12 @@ package android.media;
import android.graphics.Bitmap;
/**
- * {@hide}
+ * @hide
+ * Interface for an object that exposes information meant to be consumed by remote controls
+ * capable of displaying metadata, album art and media transport control buttons.
+ * Such a remote control client object is associated with a media button event receiver
+ * when registered through
+ * {@link AudioManager#registerRemoteControlClient(ComponentName, IRemoteControlClient)}.
*/
interface IRemoteControlClient
{
@@ -41,36 +46,49 @@ interface IRemoteControlClient
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE},
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_WRITER},
* {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}.
- * @return null if the given field is not supported, or the String matching the metadata field.
+ * @return null if the requested field is not supported, or the String matching the
+ * metadata field.
*/
String getMetadataString(int field);
/**
- * Returns the current playback state.
+ * Called by a remote control to retrieve the current playback state.
* @return one of the following values:
- * {@link android.media.AudioManager.RemoteControl#PLAYSTATE_STOPPED},
- * {@link android.media.AudioManager.RemoteControl#PLAYSTATE_PAUSED},
- * {@link android.media.AudioManager.RemoteControl#PLAYSTATE_PLAYING},
- * {@link android.media.AudioManager.RemoteControl#PLAYSTATE_FAST_FORWARDING},
- * {@link android.media.AudioManager.RemoteControl#PLAYSTATE_REWINDING},
- * {@link android.media.AudioManager.RemoteControl#PLAYSTATE_SKIPPING_FORWARDS},
- * {@link android.media.AudioManager.RemoteControl#PLAYSTATE_SKIPPING_BACKWARDS},
- * {@link android.media.AudioManager.RemoteControl#PLAYSTATE_BUFFERING}.
+ * {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_STOPPED},
+ * {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_PAUSED},
+ * {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_PLAYING},
+ * {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_FAST_FORWARDING},
+ * {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_REWINDING},
+ * {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_SKIPPING_FORWARDS},
+ * {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_SKIPPING_BACKWARDS},
+ * {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_BUFFERING},
+ * {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_ERROR}.
*/
int getPlaybackState();
/**
- * Returns the flags for the media transport control buttons this client supports.
- * @see {@link android.media.AudioManager.RemoteControl#FLAG_KEY_MEDIA_PREVIOUS},
- * {@link android.media.AudioManager.RemoteControl#FLAG_KEY_MEDIA_REWIND},
- * {@link android.media.AudioManager.RemoteControl#FLAG_KEY_MEDIA_PLAY},
- * {@link android.media.AudioManager.RemoteControl#FLAG_KEY_MEDIA_PLAY_PAUSE},
- * {@link android.media.AudioManager.RemoteControl#FLAG_KEY_MEDIA_PAUSE},
- * {@link android.media.AudioManager.RemoteControl#FLAG_KEY_MEDIA_STOP},
- * {@link android.media.AudioManager.RemoteControl#FLAG_KEY_MEDIA_FAST_FORWARD},
- * {@link android.media.AudioManager.RemoteControl#FLAG_KEY_MEDIA_NEXT}
+ * Called by a remote control to retrieve the flags for the media transport control buttons
+ * that this client supports.
+ * @see {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_PREVIOUS},
+ * {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_REWIND},
+ * {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_PLAY},
+ * {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_PLAY_PAUSE},
+ * {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_PAUSE},
+ * {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_STOP},
+ * {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_FAST_FORWARD},
+ * {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_NEXT}
*/
int getTransportControlFlags();
- Bitmap getAlbumArt(int width, int height);
+ /**
+ * Called by a remote control to retrieve the album art picture at the requested size.
+ * Note that returning a bitmap smaller than the maximum requested dimension is accepted
+ * and it will be scaled as needed, but exceeding the maximum dimensions may produce
+ * unspecified results, such as the image being cropped or simply not being displayed.
+ * @param maxWidth the maximum width of the requested bitmap expressed in pixels.
+ * @param maxHeight the maximum height of the requested bitmap expressed in pixels.
+ * @return the bitmap for the album art, or null if there isn't any.
+ * @see android.graphics.Bitmap
+ */
+ Bitmap getAlbumArt(int maxWidth, int maxHeight);
}
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 3ac0104..673f9f4 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -40,13 +40,11 @@ import java.util.UUID;
* <li> {@link android.media.audiofx.PresetReverb}</li>
* <li> {@link android.media.audiofx.EnvironmentalReverb}</li>
* </ul>
- * <p>If the audio effect is to be applied to a specific AudioTrack or MediaPlayer instance,
+ * <p>To apply the audio effect to a specific AudioTrack or MediaPlayer instance,
* the application must specify the audio session ID of that instance when creating the AudioEffect.
* (see {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions).
- * To apply an effect to the global audio output mix, session 0 must be specified when creating the
- * AudioEffect.
- * <p>Creating an effect on the output mix (audio session 0) requires permission
- * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
+ * <p>NOTE: attaching insert effects (equalizer, bass boost, virtualizer) to the global audio output
+ * mix by use of session 0 is deprecated.
* <p>Creating an AudioEffect object will create the corresponding effect engine in the audio
* framework if no instance of the same effect type exists in the specified audio session.
* If one exists, this instance will be used.
@@ -356,10 +354,9 @@ public class AudioEffect {
* how much the requesting application needs control of effect
* parameters. The normal priority is 0, above normal is a
* positive number, below normal a negative number.
- * @param audioSession system wide unique audio session identifier. If audioSession
- * is not 0, the effect will be attached to the MediaPlayer or
- * AudioTrack in the same audio session. Otherwise, the effect
- * will apply to the output mix.
+ * @param audioSession system wide unique audio session identifier.
+ * The effect will be attached to the MediaPlayer or AudioTrack in
+ * the same audio session.
*
* @throws java.lang.IllegalArgumentException
* @throws java.lang.UnsupportedOperationException
diff --git a/media/java/android/media/audiofx/BassBoost.java b/media/java/android/media/audiofx/BassBoost.java
index ca55f0f..91459ed 100644
--- a/media/java/android/media/audiofx/BassBoost.java
+++ b/media/java/android/media/audiofx/BassBoost.java
@@ -39,9 +39,7 @@ import java.util.StringTokenizer;
* for the SLBassBoostItf interface. Please refer to this specification for more details.
* <p>To attach the BassBoost to a particular AudioTrack or MediaPlayer, specify the audio session
* ID of this AudioTrack or MediaPlayer when constructing the BassBoost.
- * If the audio session ID 0 is specified, the BassBoost applies to the main audio output mix.
- * <p>Creating a BassBoost on the output mix (audio session 0) requires permission
- * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
+ * <p>NOTE: attaching a BassBoost to the global audio output mix by use of session 0 is deprecated.
* <p>See {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions.
* <p>See {@link android.media.audiofx.AudioEffect} class for more details on
* controlling audio effects.
@@ -89,9 +87,8 @@ public class BassBoost extends AudioEffect {
* engine. As the same engine can be shared by several applications, this parameter indicates
* how much the requesting application needs control of effect parameters. The normal priority
* is 0, above normal is a positive number, below normal a negative number.
- * @param audioSession system wide unique audio session identifier. If audioSession
- * is not 0, the BassBoost will be attached to the MediaPlayer or AudioTrack in the
- * same audio session. Otherwise, the BassBoost will apply to the output mix.
+ * @param audioSession system wide unique audio session identifier. The BassBoost will be
+ * attached to the MediaPlayer or AudioTrack in the same audio session.
*
* @throws java.lang.IllegalStateException
* @throws java.lang.IllegalArgumentException
@@ -103,6 +100,10 @@ public class BassBoost extends AudioEffect {
UnsupportedOperationException, RuntimeException {
super(EFFECT_TYPE_BASS_BOOST, EFFECT_TYPE_NULL, priority, audioSession);
+ if (audioSession == 0) {
+ Log.w(TAG, "WARNING: attaching a BassBoost to global output mix is deprecated!");
+ }
+
int[] value = new int[1];
checkStatus(getParameter(PARAM_STRENGTH_SUPPORTED, value));
mStrengthSupported = (value[0] != 0);
diff --git a/media/java/android/media/audiofx/Equalizer.java b/media/java/android/media/audiofx/Equalizer.java
index b3bafa9..7f38955 100644
--- a/media/java/android/media/audiofx/Equalizer.java
+++ b/media/java/android/media/audiofx/Equalizer.java
@@ -39,10 +39,8 @@ import java.util.StringTokenizer;
* mapping those defined by the OpenSL ES 1.0.1 Specification (http://www.khronos.org/opensles/)
* for the SLEqualizerItf interface. Please refer to this specification for more details.
* <p>To attach the Equalizer to a particular AudioTrack or MediaPlayer, specify the audio session
- * ID of this AudioTrack or MediaPlayer when constructing the Equalizer. If the audio session ID 0
- * is specified, the Equalizer applies to the main audio output mix.
- * <p>Creating an Equalizer on the output mix (audio session 0) requires permission
- * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
+ * ID of this AudioTrack or MediaPlayer when constructing the Equalizer.
+ * <p>NOTE: attaching an Equalizer to the global audio output mix by use of session 0 is deprecated.
* <p>See {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions.
* <p>See {@link android.media.audiofx.AudioEffect} class for more details on controlling audio
* effects.
@@ -134,9 +132,8 @@ public class Equalizer extends AudioEffect {
* engine. As the same engine can be shared by several applications, this parameter indicates
* how much the requesting application needs control of effect parameters. The normal priority
* is 0, above normal is a positive number, below normal a negative number.
- * @param audioSession system wide unique audio session identifier. If audioSession
- * is not 0, the Equalizer will be attached to the MediaPlayer or AudioTrack in the
- * same audio session. Otherwise, the Equalizer will apply to the output mix.
+ * @param audioSession system wide unique audio session identifier. The Equalizer will be
+ * attached to the MediaPlayer or AudioTrack in the same audio session.
*
* @throws java.lang.IllegalStateException
* @throws java.lang.IllegalArgumentException
@@ -148,6 +145,10 @@ public class Equalizer extends AudioEffect {
UnsupportedOperationException, RuntimeException {
super(EFFECT_TYPE_EQUALIZER, EFFECT_TYPE_NULL, priority, audioSession);
+ if (audioSession == 0) {
+ Log.w(TAG, "WARNING: attaching an Equalizer to global output mix is deprecated!");
+ }
+
getNumberOfBands();
mNumPresets = (int)getNumberOfPresets();
diff --git a/media/java/android/media/audiofx/Virtualizer.java b/media/java/android/media/audiofx/Virtualizer.java
index a682a45..68a7b88 100644
--- a/media/java/android/media/audiofx/Virtualizer.java
+++ b/media/java/android/media/audiofx/Virtualizer.java
@@ -40,10 +40,9 @@ import java.util.StringTokenizer;
* mapping those defined by the OpenSL ES 1.0.1 Specification (http://www.khronos.org/opensles/)
* for the SLVirtualizerItf interface. Please refer to this specification for more details.
* <p>To attach the Virtualizer to a particular AudioTrack or MediaPlayer, specify the audio session
- * ID of this AudioTrack or MediaPlayer when constructing the Virtualizer. If the audio session ID 0
- * is specified, the Virtualizer applies to the main audio output mix.
- * <p>Creating a Virtualizer on the output mix (audio session 0) requires permission
- * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
+ * ID of this AudioTrack or MediaPlayer when constructing the Virtualizer.
+ * <p>NOTE: attaching a Virtualizer to the global audio output mix by use of session 0 is
+ * deprecated.
* <p>See {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions.
* <p>See {@link android.media.audiofx.AudioEffect} class for more details on controlling
* audio effects.
@@ -90,9 +89,8 @@ public class Virtualizer extends AudioEffect {
* engine. As the same engine can be shared by several applications, this parameter indicates
* how much the requesting application needs control of effect parameters. The normal priority
* is 0, above normal is a positive number, below normal a negative number.
- * @param audioSession system wide unique audio session identifier. If audioSession
- * is not 0, the Virtualizer will be attached to the MediaPlayer or AudioTrack in the
- * same audio session. Otherwise, the Virtualizer will apply to the output mix.
+ * @param audioSession system wide unique audio session identifier. The Virtualizer will
+ * be attached to the MediaPlayer or AudioTrack in the same audio session.
*
* @throws java.lang.IllegalStateException
* @throws java.lang.IllegalArgumentException
@@ -104,6 +102,10 @@ public class Virtualizer extends AudioEffect {
UnsupportedOperationException, RuntimeException {
super(EFFECT_TYPE_VIRTUALIZER, EFFECT_TYPE_NULL, priority, audioSession);
+ if (audioSession == 0) {
+ Log.w(TAG, "WARNING: attaching a Virtualizer to global output mix is deprecated!");
+ }
+
int[] value = new int[1];
checkStatus(getParameter(PARAM_STRENGTH_SUPPORTED, value));
mStrengthSupported = (value[0] != 0);
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index 5bfdcdb..8caa04c 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -3781,72 +3781,62 @@ class MediaArtistNativeHelper {
* @param startMs The starting time in ms
* @param endMs The end time in ms
* @param thumbnailCount The number of frames to be extracted
+ * @param indices The indices of thumbnails wanted
+ * @param callback The callback used to pass back the bitmaps
* from startMs to endMs
*
* @return The frames as bitmaps in bitmap array
**/
- Bitmap[] getPixelsList(String filename, int width, int height, long startMs, long endMs,
- int thumbnailCount) {
- int[] rgb888 = null;
- int thumbnailSize = 0;
- Bitmap tempBitmap = null;
-
+ void getPixelsList(String filename, final int width, final int height,
+ long startMs, long endMs, int thumbnailCount, int[] indices,
+ final MediaItem.GetThumbnailListCallback callback) {
/* Make width and height as even */
final int newWidth = (width + 1) & 0xFFFFFFFE;
final int newHeight = (height + 1) & 0xFFFFFFFE;
- thumbnailSize = newWidth * newHeight * 4;
+ final int thumbnailSize = newWidth * newHeight;
/* Create a temp bitmap for resized thumbnails */
- if ((newWidth != width) || (newHeight != height)) {
- tempBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
- }
- int i = 0;
- int deltaTime = (int)(endMs - startMs) / thumbnailCount;
- Bitmap[] bitmaps = null;
-
- try {
- // This may result in out of Memory Error
- rgb888 = new int[thumbnailSize * thumbnailCount];
- bitmaps = new Bitmap[thumbnailCount];
- } catch (Throwable e) {
- // Allocating to new size with Fixed count
- try {
- rgb888 = new int[thumbnailSize * MAX_THUMBNAIL_PERMITTED];
- bitmaps = new Bitmap[MAX_THUMBNAIL_PERMITTED];
- thumbnailCount = MAX_THUMBNAIL_PERMITTED;
- } catch (Throwable ex) {
- throw new RuntimeException("Memory allocation fails, thumbnail count too large: "
- + thumbnailCount);
- }
- }
- IntBuffer tmpBuffer = IntBuffer.allocate(thumbnailSize);
- nativeGetPixelsList(filename, rgb888, newWidth, newHeight, deltaTime, thumbnailCount,
- startMs, endMs);
+ final Bitmap tempBitmap =
+ (newWidth != width || newHeight != height)
+ ? Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888)
+ : null;
+
+ final int[] rgb888 = new int[thumbnailSize];
+ final IntBuffer tmpBuffer = IntBuffer.allocate(thumbnailSize);
+ nativeGetPixelsList(filename, rgb888, newWidth, newHeight,
+ thumbnailCount, startMs, endMs, indices,
+ new NativeGetPixelsListCallback() {
+ public void onThumbnail(int index) {
+ Bitmap bitmap = Bitmap.createBitmap(
+ width, height, Bitmap.Config.ARGB_8888);
+ tmpBuffer.put(rgb888, 0, thumbnailSize);
+ tmpBuffer.rewind();
+
+ if ((newWidth == width) && (newHeight == height)) {
+ bitmap.copyPixelsFromBuffer(tmpBuffer);
+ } else {
+ /* Copy the out rgb buffer to temp bitmap */
+ tempBitmap.copyPixelsFromBuffer(tmpBuffer);
- for (; i < thumbnailCount; i++) {
- bitmaps[i] = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- tmpBuffer.put(rgb888, (i * thumbnailSize), thumbnailSize);
- tmpBuffer.rewind();
+ /* Create a canvas to resize */
+ final Canvas canvas = new Canvas(bitmap);
+ canvas.drawBitmap(tempBitmap,
+ new Rect(0, 0, newWidth, newHeight),
+ new Rect(0, 0, width, height), sResizePaint);
- if ((newWidth == width) && (newHeight == height)) {
- bitmaps[i].copyPixelsFromBuffer(tmpBuffer);
- } else {
- /* Copy the out rgb buffer to temp bitmap */
- tempBitmap.copyPixelsFromBuffer(tmpBuffer);
-
- /* Create a canvas to resize */
- final Canvas canvas = new Canvas(bitmaps[i]);
- canvas.drawBitmap(tempBitmap, new Rect(0, 0, newWidth, newHeight),
- new Rect(0, 0, width, height), sResizePaint);
- canvas.setBitmap(null);
+ canvas.setBitmap(null);
+ }
+ callback.onThumbnail(bitmap, index);
}
- }
+ });
if (tempBitmap != null) {
tempBitmap.recycle();
}
+ }
- return bitmaps;
+ interface NativeGetPixelsListCallback {
+ public void onThumbnail(int index);
}
/**
@@ -3957,8 +3947,9 @@ class MediaArtistNativeHelper {
private native int nativeGetPixels(String fileName, int[] pixelArray, int width, int height,
long timeMS);
- private native int nativeGetPixelsList(String fileName, int[] pixelArray, int width, int height,
- int timeMS, int nosofTN, long startTimeMs, long endTimeMs);
+ private native int nativeGetPixelsList(String fileName, int[] pixelArray,
+ int width, int height, int nosofTN, long startTimeMs, long endTimeMs,
+ int[] indices, NativeGetPixelsListCallback callback);
/**
* Releases the JNI and cleans up the core native module.. Should be called
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index f0cc1fe..4ca6fad 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -616,17 +616,18 @@ public class MediaImageItem extends MediaItem {
* {@inheritDoc}
*/
@Override
- public Bitmap[] getThumbnailList(int width, int height, long startMs, long endMs,
- int thumbnailCount) throws IOException {
+ public void getThumbnailList(int width, int height,
+ long startMs, long endMs,
+ int thumbnailCount,
+ int[] indices,
+ GetThumbnailListCallback callback)
+ throws IOException {
//KenBurns was not applied on this.
if (getGeneratedImageClip() == null) {
final Bitmap thumbnail = scaleImage(mFilename, width, height);
- final Bitmap[] thumbnailArray = new Bitmap[thumbnailCount];
- for (int i = 0; i < thumbnailCount; i++) {
- thumbnailArray[i] = thumbnail;
+ for (int i = 0; i < indices.length; i++) {
+ callback.onThumbnail(thumbnail, i);
}
-
- return thumbnailArray;
} else {
if (startMs > endMs) {
throw new IllegalArgumentException("Start time is greater than end time");
@@ -636,15 +637,8 @@ public class MediaImageItem extends MediaItem {
throw new IllegalArgumentException("End time is greater than file duration");
}
- if (startMs == endMs) {
- Bitmap[] bitmap = new Bitmap[1];
- bitmap[0] = mMANativeHelper.getPixels(getGeneratedImageClip(),
- width, height,startMs);
- return bitmap;
- }
-
- return mMANativeHelper.getPixelsList(getGeneratedImageClip(), width,
- height,startMs,endMs,thumbnailCount);
+ mMANativeHelper.getPixelsList(getGeneratedImageClip(), width,
+ height, startMs, endMs, thumbnailCount, indices, callback);
}
}
diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java
index 8c4841f..4e9ea75 100755
--- a/media/java/android/media/videoeditor/MediaItem.java
+++ b/media/java/android/media/videoeditor/MediaItem.java
@@ -564,15 +564,41 @@ public abstract class MediaItem {
* @param startMs The start of time range in milliseconds
* @param endMs The end of the time range in milliseconds
* @param thumbnailCount The thumbnail count
- *
- * @return The array of Bitmaps
+ * @param indices The indices of the thumbnails wanted
+ * @param callback The callback used to pass back the bitmaps
*
* @throws IOException if a file error occurs
*/
- public abstract Bitmap[] getThumbnailList(int width, int height,
- long startMs, long endMs,
- int thumbnailCount)
- throws IOException;
+ public abstract void getThumbnailList(int width, int height,
+ long startMs, long endMs,
+ int thumbnailCount,
+ int[] indices,
+ GetThumbnailListCallback callback)
+ throws IOException;
+
+ public interface GetThumbnailListCallback {
+ public void onThumbnail(Bitmap bitmap, int index);
+ }
+
+ // This is for compatibility, only used in tests.
+ public Bitmap[] getThumbnailList(int width, int height,
+ long startMs, long endMs,
+ int thumbnailCount)
+ throws IOException {
+ final Bitmap[] bitmaps = new Bitmap[thumbnailCount];
+ int[] indices = new int[thumbnailCount];
+ for (int i = 0; i < thumbnailCount; i++) {
+ indices[i] = i;
+ }
+ getThumbnailList(width, height, startMs, endMs,
+ thumbnailCount, indices, new GetThumbnailListCallback() {
+ public void onThumbnail(Bitmap bitmap, int index) {
+ bitmaps[index] = bitmap;
+ }
+ });
+
+ return bitmaps;
+ }
/*
* {@inheritDoc}
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index 6248651..0ac354b 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -293,8 +293,12 @@ public class MediaVideoItem extends MediaItem {
* {@inheritDoc}
*/
@Override
- public Bitmap[] getThumbnailList(int width, int height, long startMs,
- long endMs, int thumbnailCount) throws IOException {
+ public void getThumbnailList(int width, int height,
+ long startMs, long endMs,
+ int thumbnailCount,
+ int[] indices,
+ GetThumbnailListCallback callback)
+ throws IOException {
if (startMs > endMs) {
throw new IllegalArgumentException("Start time is greater than end time");
}
@@ -307,14 +311,8 @@ public class MediaVideoItem extends MediaItem {
throw new IllegalArgumentException("Invalid dimension");
}
- if (startMs == endMs) {
- final Bitmap[] bitmap = new Bitmap[1];
- bitmap[0] = mMANativeHelper.getPixels(super.getFilename(), width, height,startMs);
- return bitmap;
- }
-
- return mMANativeHelper.getPixelsList(super.getFilename(), width,
- height,startMs,endMs,thumbnailCount);
+ mMANativeHelper.getPixelsList(super.getFilename(), width,
+ height, startMs, endMs, thumbnailCount, indices, callback);
}
/*