summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/java/android/media/AudioManager.java62
-rw-r--r--media/java/android/media/AudioPortEventHandler.java2
-rw-r--r--media/java/android/media/MediaCodec.java33
-rw-r--r--media/java/android/media/MediaPlayer.java21
-rw-r--r--media/java/android/media/midi/MidiDeviceInfo.java3
-rw-r--r--media/java/android/media/midi/MidiDeviceStatus.java3
-rw-r--r--media/jni/android_media_MediaCodec.cpp39
-rw-r--r--media/jni/android_media_MediaSync.h2
-rw-r--r--media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java34
9 files changed, 132 insertions, 67 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 19900d0..56f0400 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3402,7 +3402,17 @@ public class AudioManager {
* @hide
*/
public static int listAudioPorts(ArrayList<AudioPort> ports) {
- return updateAudioPortCache(ports, null);
+ return updateAudioPortCache(ports, null, null);
+ }
+
+ /**
+ * Returns a list of descriptors for all audio ports managed by the audio framework as
+ * it was before the last update calback.
+ * @param ports An AudioPort ArrayList where the list will be returned.
+ * @hide
+ */
+ public static int listPreviousAudioPorts(ArrayList<AudioPort> ports) {
+ return updateAudioPortCache(null, null, ports);
}
/**
@@ -3411,19 +3421,44 @@ public class AudioManager {
* @hide
*/
public static int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) {
+ if (devices == null) {
+ return ERROR_BAD_VALUE;
+ }
ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
- int status = updateAudioPortCache(ports, null);
+ int status = updateAudioPortCache(ports, null, null);
if (status == SUCCESS) {
- devices.clear();
- for (int i = 0; i < ports.size(); i++) {
- if (ports.get(i) instanceof AudioDevicePort) {
- devices.add((AudioDevicePort)ports.get(i));
- }
- }
+ filterDevicePorts(ports, devices);
+ }
+ return status;
+ }
+
+ /**
+ * Specialized version of listPreviousAudioPorts() listing only audio devices (AudioDevicePort)
+ * @see listPreviousAudioPorts(ArrayList<AudioPort>)
+ * @hide
+ */
+ public static int listPreviousAudioDevicePorts(ArrayList<AudioDevicePort> devices) {
+ if (devices == null) {
+ return ERROR_BAD_VALUE;
+ }
+ ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
+ int status = updateAudioPortCache(null, null, ports);
+ if (status == SUCCESS) {
+ filterDevicePorts(ports, devices);
}
return status;
}
+ private static void filterDevicePorts(ArrayList<AudioPort> ports,
+ ArrayList<AudioDevicePort> devices) {
+ devices.clear();
+ for (int i = 0; i < ports.size(); i++) {
+ if (ports.get(i) instanceof AudioDevicePort) {
+ devices.add((AudioDevicePort)ports.get(i));
+ }
+ }
+ }
+
/**
* Create a connection between two or more devices. The framework will reject the request if
* device types are not compatible or the implementation does not support the requested
@@ -3474,7 +3509,7 @@ public class AudioManager {
* @hide
*/
public static int listAudioPatches(ArrayList<AudioPatch> patches) {
- return updateAudioPortCache(null, patches);
+ return updateAudioPortCache(null, patches, null);
}
/**
@@ -3540,6 +3575,7 @@ public class AudioManager {
static final int AUDIOPORT_GENERATION_INIT = 0;
static Integer sAudioPortGeneration = new Integer(AUDIOPORT_GENERATION_INIT);
static ArrayList<AudioPort> sAudioPortsCached = new ArrayList<AudioPort>();
+ static ArrayList<AudioPort> sPreviousAudioPortsCached = new ArrayList<AudioPort>();
static ArrayList<AudioPatch> sAudioPatchesCached = new ArrayList<AudioPatch>();
static int resetAudioPortGeneration() {
@@ -3551,7 +3587,8 @@ public class AudioManager {
return generation;
}
- static int updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches) {
+ static int updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches,
+ ArrayList<AudioPort> previousPorts) {
synchronized (sAudioPortGeneration) {
if (sAudioPortGeneration == AUDIOPORT_GENERATION_INIT) {
@@ -3610,6 +3647,7 @@ public class AudioManager {
}
}
+ sPreviousAudioPortsCached = sAudioPortsCached;
sAudioPortsCached = newPorts;
sAudioPatchesCached = newPatches;
sAudioPortGeneration = portGeneration[0];
@@ -3622,6 +3660,10 @@ public class AudioManager {
patches.clear();
patches.addAll(sAudioPatchesCached);
}
+ if (previousPorts != null) {
+ previousPorts.clear();
+ previousPorts.addAll(sPreviousAudioPortsCached);
+ }
}
return SUCCESS;
}
diff --git a/media/java/android/media/AudioPortEventHandler.java b/media/java/android/media/AudioPortEventHandler.java
index c49e8c2..c152245 100644
--- a/media/java/android/media/AudioPortEventHandler.java
+++ b/media/java/android/media/AudioPortEventHandler.java
@@ -84,7 +84,7 @@ class AudioPortEventHandler {
ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
if (msg.what != AUDIOPORT_EVENT_SERVICE_DIED) {
- int status = AudioManager.updateAudioPortCache(ports, patches);
+ int status = AudioManager.updateAudioPortCache(ports, patches, null);
if (status != AudioManager.SUCCESS) {
return;
}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 6f7b583..72198b6 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -816,10 +816,9 @@ final public class MediaCodec {
* Thrown when an internal codec error occurs.
*/
public final static class CodecException extends IllegalStateException {
- CodecException(int errorCode, int actionCode, @Nullable String detailMessage, int reason) {
+ CodecException(int errorCode, int actionCode, @Nullable String detailMessage) {
super(detailMessage);
mErrorCode = errorCode;
- mReason = reason;
mActionCode = actionCode;
// TODO get this from codec
@@ -847,21 +846,7 @@ final public class MediaCodec {
}
/**
- * Retrieve the reason associated with a CodecException.
- * The reason could be one of {@link #REASON_HARDWARE} or {@link #REASON_RECLAIMED}.
- *
- */
- @ReasonCode
- public int getReason() {
- return mReason;
- }
-
- /**
- * Retrieve the error code associated with a CodecException.
- * This is opaque diagnostic information and may depend on
- * hardware or API level.
- *
- * @hide
+ * Retrieve the error code associated with a CodecException
*/
public int getErrorCode() {
return mErrorCode;
@@ -878,22 +863,21 @@ final public class MediaCodec {
}
/**
- * This indicates the exception is caused by the hardware.
+ * This indicates required resource was not able to be allocated.
*/
- public static final int REASON_HARDWARE = 0;
+ public static final int ERROR_INSUFFICIENT_RESOURCE = 1100;
/**
- * This indicates the exception is because the resource manager reclaimed
- * the media resource used by the codec.
+ * This indicates the resource manager reclaimed the media resource used by the codec.
* <p>
* With this exception, the codec must be released, as it has moved to terminal state.
*/
- public static final int REASON_RECLAIMED = 1;
+ public static final int ERROR_RECLAIMED = 1101;
/** @hide */
@IntDef({
- REASON_HARDWARE,
- REASON_RECLAIMED,
+ ERROR_INSUFFICIENT_RESOURCE,
+ ERROR_RECLAIMED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ReasonCode {}
@@ -904,7 +888,6 @@ final public class MediaCodec {
private final String mDiagnosticInfo;
private final int mErrorCode;
- private final int mReason;
private final int mActionCode;
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 2f42521..aaafa55 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2824,6 +2824,13 @@ public class MediaPlayer implements SubtitleController.Listener
mSubtitleController.selectDefaultTrack();
}
break;
+ case MEDIA_INFO_BUFFERING_START:
+ case MEDIA_INFO_BUFFERING_END:
+ TimeProvider timeProvider = mTimeProvider;
+ if (timeProvider != null) {
+ timeProvider.onBuffering(msg.arg1 == MEDIA_INFO_BUFFERING_START);
+ }
+ break;
}
if (mOnInfoListener != null) {
@@ -3362,6 +3369,7 @@ public class MediaPlayer implements SubtitleController.Listener
private MediaPlayer mPlayer;
private boolean mPaused = true;
private boolean mStopped = true;
+ private boolean mBuffering;
private long mLastReportedTime;
private long mTimeAdjustment;
// since we are expecting only a handful listeners per stream, there is
@@ -3455,12 +3463,22 @@ public class MediaPlayer implements SubtitleController.Listener
}
/** @hide */
+ public void onBuffering(boolean buffering) {
+ synchronized (this) {
+ if (DEBUG) Log.d(TAG, "onBuffering: " + buffering);
+ mBuffering = buffering;
+ scheduleNotification(REFRESH_AND_NOTIFY_TIME, 0 /* delay */);
+ }
+ }
+
+ /** @hide */
public void onStopped() {
synchronized(this) {
if (DEBUG) Log.d(TAG, "onStopped");
mPaused = true;
mStopped = true;
mSeeking = false;
+ mBuffering = false;
scheduleNotification(NOTIFY_STOP, 0 /* delay */);
}
}
@@ -3481,6 +3499,7 @@ public class MediaPlayer implements SubtitleController.Listener
synchronized(this) {
mStopped = false;
mSeeking = true;
+ mBuffering = false;
scheduleNotification(NOTIFY_SEEK, 0 /* delay */);
}
}
@@ -3683,7 +3702,7 @@ public class MediaPlayer implements SubtitleController.Listener
nanoTime >= mLastNanoTime + MAX_NS_WITHOUT_POSITION_CHECK) {
try {
mLastTimeUs = mPlayer.getCurrentPosition() * 1000L;
- mPaused = !mPlayer.isPlaying();
+ mPaused = !mPlayer.isPlaying() || mBuffering;
if (DEBUG) Log.v(TAG, (mPaused ? "paused" : "playing") + " at " + mLastTimeUs);
} catch (IllegalStateException e) {
if (mPausing) {
diff --git a/media/java/android/media/midi/MidiDeviceInfo.java b/media/java/android/media/midi/MidiDeviceInfo.java
index 35374ed..57607e9 100644
--- a/media/java/android/media/midi/MidiDeviceInfo.java
+++ b/media/java/android/media/midi/MidiDeviceInfo.java
@@ -298,6 +298,9 @@ public final class MidiDeviceInfo implements Parcelable {
@Override
public String toString() {
+ // This is a hack to force the mProperties Bundle to unparcel so we can
+ // print all the names and values.
+ mProperties.getString(PROPERTY_NAME);
return ("MidiDeviceInfo[mType=" + mType +
",mInputPortCount=" + mInputPortCount +
",mOutputPortCount=" + mOutputPortCount +
diff --git a/media/java/android/media/midi/MidiDeviceStatus.java b/media/java/android/media/midi/MidiDeviceStatus.java
index 7522dcf..d4abeff 100644
--- a/media/java/android/media/midi/MidiDeviceStatus.java
+++ b/media/java/android/media/midi/MidiDeviceStatus.java
@@ -89,10 +89,9 @@ public final class MidiDeviceStatus implements Parcelable {
@Override
public String toString() {
- StringBuilder builder = new StringBuilder(mDeviceInfo.toString());
int inputPortCount = mDeviceInfo.getInputPortCount();
int outputPortCount = mDeviceInfo.getOutputPortCount();
- builder.append(" mInputPortOpen=[");
+ StringBuilder builder = new StringBuilder("mInputPortOpen=[");
for (int i = 0; i < inputPortCount; i++) {
builder.append(mInputPortOpen[i]);
if (i < inputPortCount -1) {
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index f808c0d..31fb37c 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -70,10 +70,10 @@ static struct CodecActionCodes {
jint codecActionRecoverable;
} gCodecActionCodes;
-static struct ExceptionReason {
- jint reasonHardware;
- jint reasonReclaimed;
-} gExceptionReason;
+static struct CodecErrorCodes {
+ jint errorInsufficientResource;
+ jint errorReclaimed;
+} gCodecErrorCodes;
static struct {
jclass clazz;
@@ -600,7 +600,7 @@ static jthrowable createCodecException(
env, env->FindClass("android/media/MediaCodec$CodecException"));
CHECK(clazz.get() != NULL);
- const jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "(IILjava/lang/String;I)V");
+ const jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "(IILjava/lang/String;)V");
CHECK(ctor != NULL);
ScopedLocalRef<jstring> msgObj(
@@ -619,9 +619,19 @@ static jthrowable createCodecException(
break;
}
- int reason =
- (err == DEAD_OBJECT) ? gExceptionReason.reasonReclaimed : gExceptionReason.reasonHardware;
- return (jthrowable)env->NewObject(clazz.get(), ctor, err, actionCode, msgObj.get(), reason);
+ /* translate OS errors to Java API CodecException errorCodes */
+ switch (err) {
+ case NO_MEMORY:
+ err = gCodecErrorCodes.errorInsufficientResource;
+ break;
+ case DEAD_OBJECT:
+ err = gCodecErrorCodes.errorReclaimed;
+ break;
+ default: /* Other error codes go out as is. */
+ break;
+ }
+
+ return (jthrowable)env->NewObject(clazz.get(), ctor, err, actionCode, msgObj.get());
}
void JMediaCodec::handleCallback(const sp<AMessage> &msg) {
@@ -1636,14 +1646,14 @@ static void android_media_MediaCodec_native_init(JNIEnv *env) {
gCodecActionCodes.codecActionRecoverable =
env->GetStaticIntField(clazz.get(), field);
- field = env->GetStaticFieldID(clazz.get(), "REASON_HARDWARE", "I");
+ field = env->GetStaticFieldID(clazz.get(), "ERROR_INSUFFICIENT_RESOURCE", "I");
CHECK(field != NULL);
- gExceptionReason.reasonHardware =
+ gCodecErrorCodes.errorInsufficientResource =
env->GetStaticIntField(clazz.get(), field);
- field = env->GetStaticFieldID(clazz.get(), "REASON_RECLAIMED", "I");
+ field = env->GetStaticFieldID(clazz.get(), "ERROR_RECLAIMED", "I");
CHECK(field != NULL);
- gExceptionReason.reasonReclaimed =
+ gCodecErrorCodes.errorReclaimed =
env->GetStaticIntField(clazz.get(), field);
clazz.reset(env->FindClass("android/view/Surface"));
@@ -1693,6 +1703,11 @@ static void android_media_MediaCodec_native_setup(
String8::format("Failed to initialize %s, error %#x", tmp, err));
env->ReleaseStringUTFChars(name, tmp);
return;
+ } if (err == NO_MEMORY) {
+ throwCodecException(env, err, ACTION_CODE_TRANSIENT,
+ String8::format("Failed to initialize %s, error %#x", tmp, err));
+ env->ReleaseStringUTFChars(name, tmp);
+ return;
} else if (err != OK) {
// believed possible to try again
jniThrowException(env, "java/io/IOException",
diff --git a/media/jni/android_media_MediaSync.h b/media/jni/android_media_MediaSync.h
index b69af9c..22c77c7 100644
--- a/media/jni/android_media_MediaSync.h
+++ b/media/jni/android_media_MediaSync.h
@@ -26,7 +26,7 @@ namespace android {
struct AudioPlaybackRate;
class AudioTrack;
-struct IGraphicBufferProducer;
+class IGraphicBufferProducer;
struct MediaClock;
class MediaSync;
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
index 63a8da7..0ccbf6a 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
@@ -92,7 +92,6 @@ public final class BluetoothMidiDevice {
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from GATT server.");
- // FIXME synchronize?
close();
}
}
@@ -121,8 +120,8 @@ public final class BluetoothMidiDevice {
}
}
} else {
- Log.w(TAG, "onServicesDiscovered received: " + status);
- // FIXME - report error back to client?
+ Log.e(TAG, "onServicesDiscovered received: " + status);
+ close();
}
}
@@ -137,9 +136,12 @@ public final class BluetoothMidiDevice {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
CLIENT_CHARACTERISTIC_CONFIG);
- // FIXME null check
- descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
- mBluetoothGatt.writeDescriptor(descriptor);
+ if (descriptor != null) {
+ descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
+ mBluetoothGatt.writeDescriptor(descriptor);
+ } else {
+ Log.e(TAG, "No CLIENT_CHARACTERISTIC_CONFIG for device " + mBluetoothDevice);
+ }
}
@Override
@@ -244,16 +246,18 @@ public final class BluetoothMidiDevice {
}.start();
}
- void close() {
+ private void close() {
+ synchronized (mBluetoothDevice) {
mEventScheduler.close();
- if (mDeviceServer != null) {
- IoUtils.closeQuietly(mDeviceServer);
- mDeviceServer = null;
- mService.deviceClosed(mBluetoothDevice);
- }
- if (mBluetoothGatt != null) {
- mBluetoothGatt.close();
- mBluetoothGatt = null;
+ if (mDeviceServer != null) {
+ IoUtils.closeQuietly(mDeviceServer);
+ mDeviceServer = null;
+ mService.deviceClosed(mBluetoothDevice);
+ }
+ if (mBluetoothGatt != null) {
+ mBluetoothGatt.close();
+ mBluetoothGatt = null;
+ }
}
}