diff options
Diffstat (limited to 'media/java/android')
| -rw-r--r-- | media/java/android/media/AmrInputStream.java | 1 | ||||
| -rw-r--r-- | media/java/android/media/AudioManager.java | 3 | ||||
| -rw-r--r-- | media/java/android/media/AudioService.java | 89 | ||||
| -rw-r--r-- | media/java/android/media/AudioSystem.java | 88 | ||||
| -rw-r--r-- | media/java/android/media/MediaFile.java | 6 | ||||
| -rw-r--r-- | media/java/android/media/MediaMetadataRetriever.java | 57 | ||||
| -rw-r--r-- | media/java/android/media/MediaPlayer.java | 203 | ||||
| -rw-r--r-- | media/java/android/media/MediaRecorder.java | 117 | ||||
| -rw-r--r-- | media/java/android/media/MediaScanner.java | 16 | ||||
| -rw-r--r-- | media/java/android/media/MediaScannerConnection.java | 13 | ||||
| -rw-r--r-- | media/java/android/media/ResampleInputStream.java | 1 | ||||
| -rw-r--r-- | media/java/android/media/audiofx/AudioEffect.java | 116 |
12 files changed, 557 insertions, 153 deletions
diff --git a/media/java/android/media/AmrInputStream.java b/media/java/android/media/AmrInputStream.java index d40ca5a..bc68472 100644 --- a/media/java/android/media/AmrInputStream.java +++ b/media/java/android/media/AmrInputStream.java @@ -16,7 +16,6 @@ package android.media; -import android.util.Config; import android.util.Log; import java.io.InputStream; diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index cc2ffa0..e1daede 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -50,8 +50,7 @@ public class AudioManager { private long mVolumeKeyUpTime; private int mVolumeControlStream = -1; private static String TAG = "AudioManager"; - private static boolean DEBUG = false; - private static boolean localLOGV = DEBUG || android.util.Config.LOGV; + private static boolean localLOGV = false; /** * Broadcast intent, a hint for applications that audio is about to become diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 9d0cba3..504cfde 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -111,6 +111,7 @@ public class AudioService extends IAudioService.Stub { private static final int MSG_BTA2DP_DOCK_TIMEOUT = 8; private static final int MSG_LOAD_SOUND_EFFECTS = 9; private static final int MSG_SET_FORCE_USE = 10; + private static final int MSG_PERSIST_MEDIABUTTONRECEIVER = 11; private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000; @@ -355,6 +356,12 @@ public class AudioService extends IAudioService.Stub { intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED); context.registerReceiver(mReceiver, intentFilter); + // Register for package removal intent broadcasts for media button receiver persistence + IntentFilter pkgFilter = new IntentFilter(); + pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); + pkgFilter.addDataScheme("package"); + context.registerReceiver(mReceiver, pkgFilter); + // Register for media button intent broadcasts. intentFilter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON); intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); @@ -444,6 +451,9 @@ public class AudioService extends IAudioService.Stub { // Broadcast vibrate settings broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION); + + // Restore the default media button receiver from the system settings + restoreMediaButtonReceiver(); } private void setStreamVolumeIndex(int stream, int index) { @@ -1912,6 +1922,11 @@ public class AudioService extends IAudioService.Stub { } } + private void persistMediaButtonReceiver(ComponentName receiver) { + Settings.System.putString(mContentResolver, Settings.System.MEDIA_BUTTON_RECEIVER, + receiver == null ? "" : receiver.flattenToString()); + } + private void cleanupPlayer(MediaPlayer mp) { if (mp != null) { try { @@ -2022,6 +2037,10 @@ public class AudioService extends IAudioService.Stub { case MSG_SET_FORCE_USE: setForceUse(msg.arg1, msg.arg2); break; + + case MSG_PERSIST_MEDIABUTTONRECEIVER: + persistMediaButtonReceiver( (ComponentName) msg.obj ); + break; } } } @@ -2354,6 +2373,14 @@ public class AudioService extends IAudioService.Stub { newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, AudioManager.SCO_AUDIO_STATE_DISCONNECTED); mContext.sendStickyBroadcast(newIntent); + } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) { + if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { + // a package is being removed, not replaced + String packageName = intent.getData().getSchemeSpecificPart(); + if (packageName != null) { + removeMediaButtonReceiverForPackage(packageName); + } + } } } } @@ -2469,7 +2496,7 @@ public class AudioService extends IAudioService.Stub { if(fse.mClientId.equals(clientToRemove)) { Log.i(TAG, " AudioFocus abandonAudioFocus(): removing entry for " + fse.mClientId); - mFocusStack.remove(fse); + stackIterator.remove(); } } } @@ -2489,7 +2516,7 @@ public class AudioService extends IAudioService.Stub { if(fse.mSourceRef.equals(cb)) { Log.i(TAG, " AudioFocus abandonAudioFocus(): removing entry for " + fse.mClientId); - mFocusStack.remove(fse); + stackIterator.remove(); } } if (isTopOfStackForClientToRemove) { @@ -2701,6 +2728,56 @@ public class AudioService extends IAudioService.Stub { /** * Helper function: + * Remove any entry in the remote control stack that has the same package name as packageName + * Pre-condition: packageName != null + */ + private void removeMediaButtonReceiverForPackage(String packageName) { + synchronized(mRCStack) { + if (mRCStack.empty()) { + return; + } else { + RemoteControlStackEntry oldTop = mRCStack.peek(); + Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); + // iterate over the stack entries + while(stackIterator.hasNext()) { + RemoteControlStackEntry rcse = (RemoteControlStackEntry)stackIterator.next(); + if (packageName.equalsIgnoreCase(rcse.mReceiverComponent.getPackageName())) { + // a stack entry is from the package being removed, remove it from the stack + stackIterator.remove(); + } + } + if (mRCStack.empty()) { + // no saved media button receiver + mAudioHandler.sendMessage( + mAudioHandler.obtainMessage(MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, + null)); + return; + } else if (oldTop != mRCStack.peek()) { + // the top of the stack has changed, save it in the system settings + // by posting a message to persist it + mAudioHandler.sendMessage( + mAudioHandler.obtainMessage(MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, + mRCStack.peek().mReceiverComponent)); + } + } + } + } + + /** + * Helper function: + * Restore remote control receiver from the system settings + */ + private void restoreMediaButtonReceiver() { + String receiverName = Settings.System.getString(mContentResolver, + Settings.System.MEDIA_BUTTON_RECEIVER); + if ((null != receiverName) && !receiverName.isEmpty()) { + ComponentName receiverComponentName = ComponentName.unflattenFromString(receiverName); + registerMediaButtonEventReceiver(receiverComponentName); + } + } + + /** + * Helper function: * Set the new remote control receiver at the top of the RC focus stack */ private void pushMediaButtonReceiver(ComponentName newReceiver) { @@ -2712,11 +2789,15 @@ public class AudioService extends IAudioService.Stub { while(stackIterator.hasNext()) { RemoteControlStackEntry rcse = (RemoteControlStackEntry)stackIterator.next(); if(rcse.mReceiverComponent.equals(newReceiver)) { - mRCStack.remove(rcse); + stackIterator.remove(); break; } } mRCStack.push(new RemoteControlStackEntry(newReceiver)); + + // post message to persist the default media button receiver + mAudioHandler.sendMessage( mAudioHandler.obtainMessage( + MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, newReceiver/*obj*/) ); } /** @@ -2728,7 +2809,7 @@ public class AudioService extends IAudioService.Stub { while(stackIterator.hasNext()) { RemoteControlStackEntry rcse = (RemoteControlStackEntry)stackIterator.next(); if(rcse.mReceiverComponent.equals(newReceiver)) { - mRCStack.remove(rcse); + stackIterator.remove(); break; } } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 2492d47..95d93b2 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -64,44 +64,20 @@ public class AudioSystem /* * Sets the microphone mute on or off. * - * param on set <var>true</var> to mute the microphone; + * @param on set <var>true</var> to mute the microphone; * <var>false</var> to turn mute off - * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR + * @return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR */ public static native int muteMicrophone(boolean on); /* * Checks whether the microphone mute is on or off. * - * return true if microphone is muted, false if it's not + * @return true if microphone is muted, false if it's not */ public static native boolean isMicrophoneMuted(); - /* - * Sets the audio mode. - * - * param mode the requested audio mode (NORMAL, RINGTONE, or IN_CALL). - * Informs the HAL about the current audio state so that - * it can route the audio appropriately. - * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR - */ - /** @deprecated use {@link #setPhoneState(int)} */ - public static int setMode(int mode) { - return AUDIO_STATUS_ERROR; - } - /* - * Returns the current audio mode. - * - * return the current audio mode (NORMAL, RINGTONE, or IN_CALL). - * Returns the current current audio state from the HAL. - * - */ - /** @deprecated Do not use. */ - public static int getMode() { - return MODE_INVALID; - } - - /* modes for setPhoneState */ + /* modes for setPhoneState, must match AudioSystem.h audio_mode */ public static final int MODE_INVALID = -2; public static final int MODE_CURRENT = -1; public static final int MODE_NORMAL = 0; @@ -111,7 +87,7 @@ public class AudioSystem public static final int NUM_MODES = 4; - /* Routing bits for setRouting/getRouting API */ + /* Routing bits for the former setRouting/getRouting API */ /** @deprecated */ @Deprecated public static final int ROUTE_EARPIECE = (1 << 0); /** @deprecated */ @@ -128,33 +104,6 @@ public class AudioSystem @Deprecated public static final int ROUTE_ALL = 0xFFFFFFFF; /* - * Sets the audio routing for a specified mode - * - * param mode audio mode to change route. E.g., MODE_RINGTONE. - * param routes bit vector of routes requested, created from one or - * more of ROUTE_xxx types. Set bits indicate that route should be on - * param mask bit vector of routes to change, created from one or more of - * ROUTE_xxx types. Unset bits indicate the route should be left unchanged - * return command completion status see AUDIO_STATUS_OK, see AUDIO_STATUS_ERROR - */ - /** @deprecated use {@link #setDeviceConnectionState(int,int,String)} */ - public static int setRouting(int mode, int routes, int mask) { - return AUDIO_STATUS_ERROR; - } - - /* - * Returns the current audio routing bit vector for a specified mode. - * - * param mode audio mode to change route (e.g., MODE_RINGTONE) - * return an audio route bit vector that can be compared with ROUTE_xxx - * bits - */ - /** @deprecated use {@link #getDeviceConnectionState(int,String)} */ - public static int getRouting(int mode) { - return 0; - } - - /* * Checks whether the specified stream type is active. * * return true if any track playing on this stream is active. @@ -163,7 +112,7 @@ public class AudioSystem /* * Sets a group generic audio configuration parameters. The use of these parameters - * are platform dependant, see libaudio + * are platform dependent, see libaudio * * param keyValuePairs list of parameters key value pairs in the form: * key1=value1;key2=value2;... @@ -172,7 +121,7 @@ public class AudioSystem /* * Gets a group generic audio configuration parameters. The use of these parameters - * are platform dependant, see libaudio + * are platform dependent, see libaudio * * param keys list of parameters * return value: list of parameters key value pairs in the form: @@ -180,15 +129,7 @@ public class AudioSystem */ public static native String getParameters(String keys); - /* - private final static String TAG = "audio"; - - private void log(String msg) { - Log.d(TAG, "[AudioSystem] " + msg); - } - */ - - // These match the enum in libs/android_runtime/android_media_AudioSystem.cpp + // These match the enum AudioError in frameworks/base/core/jni/android_media_AudioSystem.cpp /* Command sucessful or Media server restarted. see ErrorCallback */ public static final int AUDIO_STATUS_OK = 0; /* Command failed or unspecified audio error. see ErrorCallback */ @@ -215,7 +156,7 @@ public class AudioSystem /* * Registers a callback to be invoked when an error occurs. - * param cb the callback to run + * @param cb the callback to run */ public static void setErrorCallback(ErrorCallback cb) { @@ -272,16 +213,17 @@ public class AudioSystem public static final int DEVICE_IN_AUX_DIGITAL = 0x800000; public static final int DEVICE_IN_DEFAULT = 0x80000000; - // device states + // device states, must match AudioSystem::device_connection_state public static final int DEVICE_STATE_UNAVAILABLE = 0; public static final int DEVICE_STATE_AVAILABLE = 1; + private static final int NUM_DEVICE_STATES = 1; - // phone state + // phone state, match audio_mode??? public static final int PHONE_STATE_OFFCALL = 0; public static final int PHONE_STATE_RINGING = 1; public static final int PHONE_STATE_INCALL = 2; - // config for setForceUse + // device categories config for setForceUse, must match AudioSystem::forced_config public static final int FORCE_NONE = 0; public static final int FORCE_SPEAKER = 1; public static final int FORCE_HEADPHONES = 2; @@ -292,13 +234,15 @@ public class AudioSystem public static final int FORCE_BT_DESK_DOCK = 7; public static final int FORCE_ANALOG_DOCK = 8; public static final int FORCE_DIGITAL_DOCK = 9; + private static final int NUM_FORCE_CONFIG = 10; public static final int FORCE_DEFAULT = FORCE_NONE; - // usage for serForceUse + // usage for setForceUse, must match AudioSystem::force_use public static final int FOR_COMMUNICATION = 0; public static final int FOR_MEDIA = 1; public static final int FOR_RECORD = 2; public static final int FOR_DOCK = 3; + private static final int NUM_FORCE_USE = 4; public static native int setDeviceConnectionState(int device, int state, String device_address); public static native int getDeviceConnectionState(int device, String device_address); diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index a027bc6..a54cf28 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -66,8 +66,9 @@ public class MediaFile { public static final int FILE_TYPE_ASF = 26; public static final int FILE_TYPE_MKV = 27; public static final int FILE_TYPE_MP2TS = 28; + public static final int FILE_TYPE_AVI = 29; private static final int FIRST_VIDEO_FILE_TYPE = FILE_TYPE_MP4; - private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_MP2TS; + private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_AVI; // Image file types public static final int FILE_TYPE_JPEG = 31; @@ -175,6 +176,7 @@ public class MediaFile { addFileType("OGG", FILE_TYPE_OGG, "application/ogg", MtpConstants.FORMAT_OGG); addFileType("OGA", FILE_TYPE_OGG, "application/ogg", MtpConstants.FORMAT_OGG); addFileType("AAC", FILE_TYPE_AAC, "audio/aac", MtpConstants.FORMAT_AAC); + addFileType("AAC", FILE_TYPE_AAC, "audio/aac-adts", MtpConstants.FORMAT_AAC); addFileType("MKA", FILE_TYPE_MKA, "audio/x-matroska"); addFileType("MID", FILE_TYPE_MID, "audio/midi"); @@ -185,6 +187,7 @@ public class MediaFile { addFileType("IMY", FILE_TYPE_IMY, "audio/imelody"); addFileType("RTX", FILE_TYPE_MID, "audio/midi"); addFileType("OTA", FILE_TYPE_MID, "audio/midi"); + addFileType("MXMF", FILE_TYPE_MID, "audio/midi"); addFileType("MPEG", FILE_TYPE_MP4, "video/mpeg", MtpConstants.FORMAT_MPEG); addFileType("MPG", FILE_TYPE_MP4, "video/mpeg", MtpConstants.FORMAT_MPEG); @@ -197,6 +200,7 @@ public class MediaFile { addFileType("MKV", FILE_TYPE_MKV, "video/x-matroska"); addFileType("WEBM", FILE_TYPE_MKV, "video/x-matroska"); addFileType("TS", FILE_TYPE_MP2TS, "video/mp2ts"); + addFileType("AVI", FILE_TYPE_AVI, "video/avi"); if (isWMVEnabled()) { addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv", MtpConstants.FORMAT_WMV); diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java index 77e939e..02d6b66 100644 --- a/media/java/android/media/MediaMetadataRetriever.java +++ b/media/java/android/media/MediaMetadataRetriever.java @@ -26,6 +26,8 @@ import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Map; + /** * MediaMetadataRetriever class provides a unified interface for retrieving * frame and meta data from an input media file. @@ -56,7 +58,33 @@ public class MediaMetadataRetriever * @throws IllegalArgumentException If the path is invalid. */ public native void setDataSource(String path) throws IllegalArgumentException; - + + /** + * Sets the data source (URI) to use. Call this + * method before the rest of the methods in this class. This method may be + * time-consuming. + * + * @param uri The URI of the input media. + * @param headers the headers to be sent together with the request for the data + * @throws IllegalArgumentException If the URI is invalid. + */ + public void setDataSource(String uri, Map<String, String> headers) + throws IllegalArgumentException { + int i = 0; + String[] keys = new String[headers.size()]; + String[] values = new String[headers.size()]; + for (Map.Entry<String, String> entry: headers.entrySet()) { + keys[i] = entry.getKey(); + values[i] = entry.getValue(); + ++i; + } + _setDataSource(uri, keys, values); + } + + private native void _setDataSource( + String uri, String[] keys, String[] values) + throws IllegalArgumentException; + /** * Sets the data source (FileDescriptor) to use. It is the caller's * responsibility to close the file descriptor. It is safe to do so as soon @@ -398,5 +426,32 @@ public class MediaMetadataRetriever * The metadata key to retrieve the music album compilation status. */ public static final int METADATA_KEY_COMPILATION = 15; + /** + * If this key exists the media contains audio content. + */ + public static final int METADATA_KEY_HAS_AUDIO = 16; + /** + * If this key exists the media contains video content. + */ + public static final int METADATA_KEY_HAS_VIDEO = 17; + /** + * If the media contains video, this key retrieves its width. + */ + public static final int METADATA_KEY_VIDEO_WIDTH = 18; + /** + * If the media contains video, this key retrieves its height. + */ + public static final int METADATA_KEY_VIDEO_HEIGHT = 19; + /** + * This key retrieves the average bitrate (in bits/sec), if available. + */ + public static final int METADATA_KEY_BITRATE = 20; + /** + * This key retrieves the language code of text tracks, if available. + * If multiple text tracks present, the return value will look like: + * "eng:chi" + * @hide + */ + public static final int METADATA_KEY_TIMED_TEXT_LANGUAGES = 21; // Add more here... } diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 8b29ea8..84f588e 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -623,6 +623,11 @@ public class MediaPlayer * being played. Note that if a SurfaceTexture is used, the value * set via setScreenOnWhilePlaying has no effect. * + * The timestamps provided by {@link SurfaceTexture#getTimestamp()} for a + * SurfaceTexture set as the video sink have an unspecified zero point, + * and cannot be directly compared between different media sources or different + * instances of the same media source, or across multiple runs of the same + * program. * @hide */ public void setTexture(SurfaceTexture st) { @@ -740,7 +745,6 @@ public class MediaPlayer * @param uri the Content URI of the data you want to play * @param headers the headers to be sent together with the request for the data * @throws IllegalStateException if it is called in an invalid state - * @hide pending API council */ public void setDataSource(Context context, Uri uri, Map<String, String> headers) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { @@ -795,8 +799,29 @@ public class MediaPlayer * @throws IllegalStateException if it is called in an invalid state * @hide pending API council */ - public native void setDataSource(String path, Map<String, String> headers) - throws IOException, IllegalArgumentException, IllegalStateException; + public void setDataSource(String path, Map<String, String> headers) + throws IOException, IllegalArgumentException, IllegalStateException + { + String[] keys = null; + String[] values = null; + + if (headers != null) { + keys = new String[headers.size()]; + values = new String[headers.size()]; + + int i = 0; + for (Map.Entry<String, String> entry: headers.entrySet()) { + keys[i] = entry.getKey(); + values[i] = entry.getValue(); + ++i; + } + } + _setDataSource(path, keys, values); + } + + private native void _setDataSource( + String path, String[] keys, String[] values) + throws IOException, IllegalArgumentException, IllegalStateException; /** * Sets the data source (FileDescriptor) to use. It is the caller's responsibility @@ -1115,6 +1140,7 @@ public class MediaPlayer mOnErrorListener = null; mOnInfoListener = null; mOnVideoSizeChangedListener = null; + mOnTimedTextListener = null; _release(); } @@ -1222,6 +1248,93 @@ public class MediaPlayer */ public native void attachAuxEffect(int effectId); + /* Do not change these values without updating their counterparts + * in include/media/mediaplayer.h! + */ + /** + * Key used in setParameter method. + * Indicates the index of the timed text track to be enabled/disabled + */ + private static final int KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000; + + /** + * Sets the parameter indicated by key. + * @param key key indicates the parameter to be set. + * @param value value of the parameter to be set. + * @return true if the parameter is set successfully, false otherwise + * {@hide} + */ + public native boolean setParameter(int key, Parcel value); + + /** + * Sets the parameter indicated by key. + * @param key key indicates the parameter to be set. + * @param value value of the parameter to be set. + * @return true if the parameter is set successfully, false otherwise + * {@hide} + */ + public boolean setParameter(int key, String value) { + Parcel p = Parcel.obtain(); + p.writeString(value); + return setParameter(key, p); + } + + /** + * Sets the parameter indicated by key. + * @param key key indicates the parameter to be set. + * @param value value of the parameter to be set. + * @return true if the parameter is set successfully, false otherwise + * {@hide} + */ + public boolean setParameter(int key, int value) { + Parcel p = Parcel.obtain(); + p.writeInt(value); + return setParameter(key, p); + } + + /** + * Gets the value of the parameter indicated by key. + * @param key key indicates the parameter to get. + * @param reply value of the parameter to get. + */ + private native void getParameter(int key, Parcel reply); + + /** + * Gets the value of the parameter indicated by key. + * @param key key indicates the parameter to get. + * @return value of the parameter. + * {@hide} + */ + public Parcel getParcelParameter(int key) { + Parcel p = Parcel.obtain(); + getParameter(key, p); + return p; + } + + /** + * Gets the value of the parameter indicated by key. + * @param key key indicates the parameter to get. + * @return value of the parameter. + * {@hide} + */ + public String getStringParameter(int key) { + Parcel p = Parcel.obtain(); + getParameter(key, p); + return p.readString(); + } + + /** + * Gets the value of the parameter indicated by key. + * @param key key indicates the parameter to get. + * @return value of the parameter. + * {@hide} + */ + public int getIntParameter(int key) { + Parcel p = Parcel.obtain(); + getParameter(key, p); + return p.readInt(); + } + /** * Sets the send level of the player to the attached auxiliary effect * {@see #attachAuxEffect(int)}. The level value range is 0 to 1.0. @@ -1277,6 +1390,36 @@ public class MediaPlayer private native final void native_finalize(); /** + * @param index The index of the text track to be turned on. + * @return true if the text track is enabled successfully. + * {@hide} + */ + public boolean enableTimedTextTrackIndex(int index) { + if (index < 0) { + return false; + } + return setParameter(KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX, index); + } + + /** + * Enables the first timed text track if any. + * @return true if the text track is enabled successfully + * {@hide} + */ + public boolean enableTimedText() { + return enableTimedTextTrackIndex(0); + } + + /** + * Disables timed text display. + * @return true if the text track is disabled successfully. + * {@hide} + */ + public boolean disableTimedText() { + return setParameter(KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX, -1); + } + + /** * @param reply Parcel with audio/video duration info for battery tracking usage * @return The status code. @@ -1296,6 +1439,7 @@ public class MediaPlayer private static final int MEDIA_BUFFERING_UPDATE = 3; private static final int MEDIA_SEEK_COMPLETE = 4; private static final int MEDIA_SET_VIDEO_SIZE = 5; + private static final int MEDIA_TIMED_TEXT = 99; private static final int MEDIA_ERROR = 100; private static final int MEDIA_INFO = 200; @@ -1364,6 +1508,11 @@ public class MediaPlayer } // No real default action so far. return; + case MEDIA_TIMED_TEXT: + if (mOnTimedTextListener != null) { + mOnTimedTextListener.onTimedText(mMediaPlayer, (String)msg.obj); + } + return; case MEDIA_NOP: // interface test message - ignore break; @@ -1457,11 +1606,16 @@ public class MediaPlayer public interface OnBufferingUpdateListener { /** - * Called to update status in buffering a media stream. + * Called to update status in buffering a media stream received through + * progressive HTTP download. The received buffering percentage + * indicates how much of the content has been buffered or played. + * For example a buffering update of 80 percent when half the content + * has already been played indicates that the next 30 percent of the + * content to play has been buffered. * * @param mp the MediaPlayer the update pertains to - * @param percent the percentage (0-100) of the buffer - * that has been filled thus far + * @param percent the percentage (0-100) of the content + * that has been buffered or played thus far */ void onBufferingUpdate(MediaPlayer mp, int percent); } @@ -1535,6 +1689,39 @@ public class MediaPlayer private OnVideoSizeChangedListener mOnVideoSizeChangedListener; + /** + * Interface definition of a callback to be invoked when a + * timed text is available for display. + * {@hide} + */ + public interface OnTimedTextListener + { + /** + * Called to indicate the video size + * + * @param mp the MediaPlayer associated with this callback + * @param text the timed text sample which contains the + * text needed to be displayed. + * {@hide} + */ + public void onTimedText(MediaPlayer mp, String text); + } + + /** + * Register a callback to be invoked when a timed text is available + * for display. + * + * @param listener the callback that will be run + * {@hide} + */ + public void setOnTimedTextListener(OnTimedTextListener listener) + { + mOnTimedTextListener = listener; + } + + private OnTimedTextListener mOnTimedTextListener; + + /* Do not change these values without updating their counterparts * in include/media/mediaplayer.h! */ @@ -1611,10 +1798,12 @@ public class MediaPlayer /** MediaPlayer is temporarily pausing playback internally in order to * buffer more data. + * @see android.media.MediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_BUFFERING_START = 701; /** MediaPlayer is resuming playback after filling buffers. + * @see android.media.MediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_BUFFERING_END = 702; @@ -1649,6 +1838,8 @@ public class MediaPlayer * <ul> * <li>{@link #MEDIA_INFO_UNKNOWN} * <li>{@link #MEDIA_INFO_VIDEO_TRACK_LAGGING} + * <li>{@link #MEDIA_INFO_BUFFERING_START} + * <li>{@link #MEDIA_INFO_BUFFERING_END} * <li>{@link #MEDIA_INFO_BAD_INTERLEAVING} * <li>{@link #MEDIA_INFO_NOT_SEEKABLE} * <li>{@link #MEDIA_INFO_METADATA_UPDATE} diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index edefb22..38202f2 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -347,6 +347,39 @@ public class MediaRecorder } /** + * Set and store the geodata (latitude and longitude) in the output file. + * This method should be called before prepare(). The geodata is + * stored in udta box if the output format is OutputFormat.THREE_GPP + * or OutputFormat.MPEG_4, and is ignored for other output formats. + * The geodata is stored according to ISO-6709 standard. + * + * @param latitude latitude in degrees. Its value must be in the + * range [-90, 90]. + * @param longitude longitude in degrees. Its value must be in the + * range [-180, 180]. + * + * @throws IllegalArgumentException if the given latitude or + * longitude is out of range. + * + */ + public void setLocation(float latitude, float longitude) { + int latitudex10000 = (int) (latitude * 10000 + 0.5); + int longitudex10000 = (int) (longitude * 10000 + 0.5); + + if (latitudex10000 > 900000 || latitudex10000 < -900000) { + String msg = "Latitude: " + latitude + " out of range."; + throw new IllegalArgumentException(msg); + } + if (longitudex10000 > 1800000 || longitudex10000 < -1800000) { + String msg = "Longitude: " + longitude + " out of range"; + throw new IllegalArgumentException(msg); + } + + setParameter("param-geotag-latitude=" + latitudex10000); + setParameter("param-geotag-longitude=" + longitudex10000); + } + + /** * Sets the format of the output file produced during recording. Call this * after setAudioSource()/setVideoSource() but before prepare(). * @@ -767,6 +800,75 @@ public class MediaRecorder */ public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801; + /** informational events for individual tracks, for testing purpose. + * The track informational event usually contains two parts in the ext1 + * arg of the onInfo() callback: bit 31-28 contains the track id; and + * the rest of the 28 bits contains the informational event defined here. + * For example, ext1 = (1 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the + * track id is 1 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE; + * while ext1 = (0 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the track + * id is 0 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE. The + * application should extract the track id and the type of informational + * event from ext1, accordingly. + * + * FIXME: + * Please update the comment for onInfo also when these + * events are unhidden so that application knows how to extract the track + * id and the informational event type from onInfo callback. + * + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INFO_LIST_START = 1000; + /** Signal the completion of the track for the recording session. + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS = 1000; + /** Indicate the recording progress in time (ms) during recording. + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME = 1001; + /** Indicate the track type: 0 for Audio and 1 for Video. + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INFO_TYPE = 1002; + /** Provide the track duration information. + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INFO_DURATION_MS = 1003; + /** Provide the max chunk duration in time (ms) for the given track. + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS = 1004; + /** Provide the total number of recordd frames. + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES = 1005; + /** Provide the max spacing between neighboring chunks for the given track. + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS = 1006; + /** Provide the elapsed time measuring from the start of the recording + * till the first output frame of the given track is received, excluding + * any intentional start time offset of a recording session for the + * purpose of eliminating the recording sound in the recorded file. + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS = 1007; + /** Provide the start time difference (delay) betweeen this track and + * the start of the movie. + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS = 1008; + /** Provide the total number of data (in kilo-bytes) encoded. + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES = 1009; + /** + * {@hide} + */ + public static final int MEDIA_RECORDER_TRACK_INFO_LIST_END = 2000; + + /** * Interface definition for a callback to be invoked when an error * occurs while recording. @@ -811,8 +913,17 @@ public class MediaRecorder /* Do not change these values without updating their counterparts * in include/media/mediarecorder.h! */ - private static final int MEDIA_RECORDER_EVENT_ERROR = 1; - private static final int MEDIA_RECORDER_EVENT_INFO = 2; + private static final int MEDIA_RECORDER_EVENT_LIST_START = 1; + private static final int MEDIA_RECORDER_EVENT_ERROR = 1; + private static final int MEDIA_RECORDER_EVENT_INFO = 2; + private static final int MEDIA_RECORDER_EVENT_LIST_END = 99; + + /* Events related to individual tracks */ + private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_START = 100; + private static final int MEDIA_RECORDER_TRACK_EVENT_ERROR = 100; + private static final int MEDIA_RECORDER_TRACK_EVENT_INFO = 101; + private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_END = 1000; + @Override public void handleMessage(Message msg) { @@ -822,12 +933,14 @@ public class MediaRecorder } switch(msg.what) { case MEDIA_RECORDER_EVENT_ERROR: + case MEDIA_RECORDER_TRACK_EVENT_ERROR: if (mOnErrorListener != null) mOnErrorListener.onError(mMediaRecorder, msg.arg1, msg.arg2); return; case MEDIA_RECORDER_EVENT_INFO: + case MEDIA_RECORDER_TRACK_EVENT_INFO: if (mOnInfoListener != null) mOnInfoListener.onInfo(mMediaRecorder, msg.arg1, msg.arg2); diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index 55b0045..790eaa3 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -46,7 +46,6 @@ import android.sax.Element; import android.sax.ElementListener; import android.sax.RootElement; import android.text.TextUtils; -import android.util.Config; import android.util.Log; import android.util.Xml; @@ -1052,7 +1051,7 @@ public class MediaScanner } for (String fileToDelete : existingFiles) { - if (Config.LOGV) + if (false) Log.v(TAG, "fileToDelete is " + fileToDelete); try { (new File(fileToDelete)).delete(); @@ -1169,7 +1168,7 @@ public class MediaScanner postscan(directories); long end = System.currentTimeMillis(); - if (Config.LOGD) { + if (false) { Log.d(TAG, " prescan time: " + (prescan - start) + "ms\n"); Log.d(TAG, " scan time: " + (scan - prescan) + "ms\n"); Log.d(TAG, "postscan time: " + (end - scan) + "ms\n"); @@ -1604,6 +1603,17 @@ public class MediaScanner private static native final void native_init(); private native final void native_setup(); private native final void native_finalize(); + + /** + * Releases resouces associated with this MediaScanner object. + * It is considered good practice to call this method when + * one is done using the MediaScanner object. After this method + * is called, the MediaScanner object can no longer be used. + */ + public void release() { + native_finalize(); + } + @Override protected void finalize() { mContext.getContentResolver().releaseProvider(mMediaProvider); diff --git a/media/java/android/media/MediaScannerConnection.java b/media/java/android/media/MediaScannerConnection.java index 503b5f4..969da39 100644 --- a/media/java/android/media/MediaScannerConnection.java +++ b/media/java/android/media/MediaScannerConnection.java @@ -25,7 +25,6 @@ import android.media.IMediaScannerService; import android.net.Uri; import android.os.IBinder; import android.os.RemoteException; -import android.util.Config; import android.util.Log; @@ -126,13 +125,13 @@ public class MediaScannerConnection implements ServiceConnection { public void disconnect() { synchronized (this) { if (mConnected) { - if (Config.LOGV) { + if (false) { Log.v(TAG, "Disconnecting from Media Scanner"); } try { mContext.unbindService(this); } catch (IllegalArgumentException ex) { - if (Config.LOGV) { + if (false) { Log.v(TAG, "disconnect failed: " + ex); } } @@ -164,12 +163,12 @@ public class MediaScannerConnection implements ServiceConnection { throw new IllegalStateException("not connected to MediaScannerService"); } try { - if (Config.LOGV) { + if (false) { Log.v(TAG, "Scanning file " + path); } mService.requestScanFile(path, mimeType, mListener); } catch (RemoteException e) { - if (Config.LOGD) { + if (false) { Log.d(TAG, "Failed to scan file " + path); } } @@ -240,7 +239,7 @@ public class MediaScannerConnection implements ServiceConnection { * Part of the ServiceConnection interface. Do not call. */ public void onServiceConnected(ComponentName className, IBinder service) { - if (Config.LOGV) { + if (false) { Log.v(TAG, "Connected to Media Scanner"); } synchronized (this) { @@ -255,7 +254,7 @@ public class MediaScannerConnection implements ServiceConnection { * Part of the ServiceConnection interface. Do not call. */ public void onServiceDisconnected(ComponentName className) { - if (Config.LOGV) { + if (false) { Log.v(TAG, "Disconnected from Media Scanner"); } synchronized (this) { diff --git a/media/java/android/media/ResampleInputStream.java b/media/java/android/media/ResampleInputStream.java index e26eae5..b025e25 100644 --- a/media/java/android/media/ResampleInputStream.java +++ b/media/java/android/media/ResampleInputStream.java @@ -16,7 +16,6 @@ package android.media; -import android.util.Config; import android.util.Log; import java.io.InputStream; diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java index d3e9a49..39c6d3e 100644 --- a/media/java/android/media/audiofx/AudioEffect.java +++ b/media/java/android/media/audiofx/AudioEffect.java @@ -573,27 +573,16 @@ public class AudioEffect { * * @param param the identifier of the parameter to set * @param value the new value for the specified parameter - * @return {@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE}, - * {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or - * {@link #ERROR_DEAD_OBJECT} in case of failure When called, value.length - * indicates the maximum size of the returned parameters value. When - * returning, value.length is updated with the actual size of the - * returned value. + * @return the number of meaningful bytes in value array in case of success or + * {@link #ERROR_BAD_VALUE}, {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} + * or {@link #ERROR_DEAD_OBJECT} in case of failure. * @throws IllegalStateException * @hide */ public int getParameter(byte[] param, byte[] value) throws IllegalStateException { checkState("getParameter()"); - int[] vSize = new int[1]; - vSize[0] = value.length; - int status = native_getParameter(param.length, param, vSize, value); - if (value.length > vSize[0]) { - byte[] resizedValue = new byte[vSize[0]]; - System.arraycopy(value, 0, resizedValue, 0, vSize[0]); - value = resizedValue; - } - return status; + return native_getParameter(param.length, param, value.length, value); } /** @@ -615,6 +604,7 @@ public class AudioEffect { * array of 1 or 2 integers * * @see #getParameter(byte[], byte[]) + * In case of success, returns the number of meaningful integers in value array. * @hide */ public int getParameter(int param, int[] value) @@ -628,9 +618,14 @@ public class AudioEffect { int status = getParameter(p, v); - value[0] = byteArrayToInt(v); - if (v.length > 4) { - value[1] = byteArrayToInt(v, 4); + if (status == 4 || status == 8) { + value[0] = byteArrayToInt(v); + if (status == 8) { + value[1] = byteArrayToInt(v, 4); + } + status /= 4; + } else { + status = ERROR; } return status; } @@ -640,6 +635,7 @@ public class AudioEffect { * array of 1 or 2 short integers * * @see #getParameter(byte[], byte[]) + * In case of success, returns the number of meaningful short integers in value array. * @hide */ public int getParameter(int param, short[] value) @@ -653,9 +649,14 @@ public class AudioEffect { int status = getParameter(p, v); - value[0] = byteArrayToShort(v); - if (v.length > 2) { - value[1] = byteArrayToShort(v, 2); + if (status == 2 || status == 4) { + value[0] = byteArrayToShort(v); + if (status == 4) { + value[1] = byteArrayToShort(v, 2); + } + status /= 2; + } else { + status = ERROR; } return status; } @@ -665,6 +666,7 @@ public class AudioEffect { * the value is also an array of 1 or 2 integers * * @see #getParameter(byte[], byte[]) + * In case of success, the returns the number of meaningful integers in value array. * @hide */ public int getParameter(int[] param, int[] value) @@ -681,9 +683,14 @@ public class AudioEffect { int status = getParameter(p, v); - value[0] = byteArrayToInt(v); - if (v.length > 4) { - value[1] = byteArrayToInt(v, 4); + if (status == 4 || status == 8) { + value[0] = byteArrayToInt(v); + if (status == 8) { + value[1] = byteArrayToInt(v, 4); + } + status /= 4; + } else { + status = ERROR; } return status; } @@ -693,6 +700,7 @@ public class AudioEffect { * the value is an array of 1 or 2 short integers * * @see #getParameter(byte[], byte[]) + * In case of success, returns the number of meaningful short integers in value array. * @hide */ public int getParameter(int[] param, short[] value) @@ -709,9 +717,14 @@ public class AudioEffect { int status = getParameter(p, v); - value[0] = byteArrayToShort(v); - if (v.length > 2) { - value[1] = byteArrayToShort(v, 2); + if (status == 2 || status == 4) { + value[0] = byteArrayToShort(v); + if (status == 4) { + value[1] = byteArrayToShort(v, 2); + } + status /= 2; + } else { + status = ERROR; } return status; } @@ -740,24 +753,14 @@ public class AudioEffect { /** * Send a command to the effect engine. This method is intended to send * proprietary commands to a particular effect implementation. - * + * In case of success, returns the number of meaningful bytes in reply array. + * In case of failure, the returned value is negative and implementation specific. * @hide */ public int command(int cmdCode, byte[] command, byte[] reply) throws IllegalStateException { checkState("command()"); - int[] replySize = new int[1]; - replySize[0] = reply.length; - - int status = native_command(cmdCode, command.length, command, - replySize, reply); - - if (reply.length > replySize[0]) { - byte[] resizedReply = new byte[replySize[0]]; - System.arraycopy(reply, 0, resizedReply, 0, replySize[0]); - reply = resizedReply; - } - return status; + return native_command(cmdCode, command.length, command, reply.length, reply); } // -------------------------------------------------------------------------- @@ -1145,10 +1148,10 @@ public class AudioEffect { int vsize, byte[] value); private native final int native_getParameter(int psize, byte[] param, - int[] vsize, byte[] value); + int vsize, byte[] value); private native final int native_command(int cmdCode, int cmdSize, - byte[] cmdData, int[] repSize, byte[] repData); + byte[] cmdData, int repSize, byte[] repData); private static native Object[] native_query_effects(); @@ -1172,23 +1175,30 @@ public class AudioEffect { * @hide */ public void checkStatus(int status) { - switch (status) { - case AudioEffect.SUCCESS: - break; - case AudioEffect.ERROR_BAD_VALUE: - throw (new IllegalArgumentException( - "AudioEffect: bad parameter value")); - case AudioEffect.ERROR_INVALID_OPERATION: - throw (new UnsupportedOperationException( - "AudioEffect: invalid parameter operation")); - default: - throw (new RuntimeException("AudioEffect: set/get parameter error")); + if (isError(status)) { + switch (status) { + case AudioEffect.ERROR_BAD_VALUE: + throw (new IllegalArgumentException( + "AudioEffect: bad parameter value")); + case AudioEffect.ERROR_INVALID_OPERATION: + throw (new UnsupportedOperationException( + "AudioEffect: invalid parameter operation")); + default: + throw (new RuntimeException("AudioEffect: set/get parameter error")); + } } } /** * @hide */ + public static boolean isError(int status) { + return (status < 0); + } + + /** + * @hide + */ public int byteArrayToInt(byte[] valueBuf) { return byteArrayToInt(valueBuf, 0); |
