// from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService.
/** @hide
+ * The audio device code for representing "no device." */
+ public static final int DEVICE_NONE = AudioSystem.DEVICE_NONE;
+ /** @hide
* The audio output device code for the small speaker at the front of the device used
* when placing calls. Does not refer to an in-ear headphone without attached microphone,
* such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a
// audio device definitions: must be kept in sync with values in system/core/audio.h
//
+ public static final int DEVICE_NONE = 0x0;
// reserved bits
public static final int DEVICE_BIT_IN = 0x80000000;
public static final int DEVICE_BIT_DEFAULT = 0x40000000;
package android.media.tv;
+import android.media.AudioManager;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
private int mDeviceId;
private int mType;
- // TODO: Add audio port & audio address for audio service.
+ private int mAudioType;
+ private String mAudioAddress;
// TODO: Add HDMI handle for HDMI service.
- public TvInputHardwareInfo() { }
-
- public TvInputHardwareInfo(int deviceId, int type) {
- mDeviceId = deviceId;
- mType = type;
+ private TvInputHardwareInfo() {
}
public int getDeviceId() {
return mType;
}
+ public int getAudioType() {
+ return mAudioType;
+ }
+
+ public String getAudioAddress() {
+ return mAudioAddress;
+ }
+
// Parcelable
@Override
public int describeContents() {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mDeviceId);
dest.writeInt(mType);
+ dest.writeInt(mAudioType);
+ dest.writeString(mAudioAddress);
}
public void readFromParcel(Parcel source) {
mDeviceId = source.readInt();
mType = source.readInt();
+ mAudioType = source.readInt();
+ mAudioAddress = source.readString();
+ }
+
+ public static final class Builder {
+ private Integer mDeviceId = null;
+ private Integer mType = null;
+ private int mAudioType = AudioManager.DEVICE_NONE;
+ private String mAudioAddress = "";
+
+ public Builder() {
+ }
+
+ public Builder deviceId(int deviceId) {
+ mDeviceId = deviceId;
+ return this;
+ }
+
+ public Builder type(int type) {
+ mType = type;
+ return this;
+ }
+
+ public Builder audioType(int audioType) {
+ mAudioType = audioType;
+ return this;
+ }
+
+ public Builder audioAddress(String audioAddress) {
+ mAudioAddress = audioAddress;
+ return this;
+ }
+
+ public TvInputHardwareInfo build() {
+ if (mDeviceId == null || mType == null) {
+ throw new UnsupportedOperationException();
+ }
+
+ TvInputHardwareInfo info = new TvInputHardwareInfo();
+ info.mDeviceId = mDeviceId;
+ info.mType = mType;
+ info.mAudioType = mAudioType;
+ if (info.mAudioType != AudioManager.DEVICE_NONE) {
+ info.mAudioAddress = mAudioAddress;
+ }
+ return info;
+ }
}
}
}
// Called from native
- private void deviceAvailableFromNative(int deviceId, int type) {
- final TvInputHardwareInfo info = new TvInputHardwareInfo(deviceId, type);
+ private void deviceAvailableFromNative(final TvInputHardwareInfo info) {
mHandler.post(new Runnable() {
@Override
public void run() {
});
}
- private void deviceUnavailableFromNative(int deviceId) {
- final int id = deviceId;
+ private void deviceUnavailableFromNative(final int deviceId) {
mHandler.post(new Runnable() {
@Override
public void run() {
- mCallback.onDeviceUnavailable(id);
+ mCallback.onDeviceUnavailable(deviceId);
}
});
}
- private void streamConfigsChangedFromNative(int deviceId) {
- final int id = deviceId;
+ private void streamConfigsChangedFromNative(final int deviceId) {
mHandler.post(new Runnable() {
@Override
public void run() {
- retrieveStreamConfigs(id);
- mCallback.onStreamConfigurationChanged(id, mStreamConfigs);
+ retrieveStreamConfigs(deviceId);
+ mCallback.onStreamConfigurationChanged(deviceId, mStreamConfigs);
}
});
}
package com.android.server.tv;
import android.content.Context;
+import android.media.AudioDevicePort;
+import android.media.AudioManager;
+import android.media.AudioPatch;
+import android.media.AudioPort;
+import android.media.AudioPortConfig;
import android.media.tv.ITvInputHardware;
import android.media.tv.ITvInputHardwareCallback;
import android.media.tv.TvInputHardwareInfo;
private final List<TvInputHardwareInfo> mInfoList = new ArrayList<TvInputHardwareInfo>();
private final Context mContext;
private final Set<Integer> mActiveHdmiSources = new HashSet<Integer>();
+ private final AudioManager mAudioManager;
private final Object mLock = new Object();
public TvInputHardwareManager(Context context) {
mContext = context;
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
// TODO(hdmi): mHdmiManager = mContext.getSystemService(...);
// TODO(hdmi): mHdmiClient = mHdmiManager.getTvClient();
mHal.init();
private boolean mReleased = false;
private final Object mImplLock = new Object();
+ private final AudioDevicePort mAudioSource;
+ private final AudioDevicePort mAudioSink;
+ private AudioPatch mAudioPatch = null;
+
public TvInputHardwareImpl(TvInputHardwareInfo info) {
mInfo = info;
+ AudioDevicePort audioSource = null;
+ AudioDevicePort audioSink = null;
+ if (mInfo.getAudioType() != AudioManager.DEVICE_NONE) {
+ ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>();
+ if (mAudioManager.listAudioDevicePorts(devicePorts) == AudioManager.SUCCESS) {
+ // Find source
+ for (AudioPort port : devicePorts) {
+ AudioDevicePort devicePort = (AudioDevicePort) port;
+ if (devicePort.type() == mInfo.getAudioType() &&
+ devicePort.address().equals(mInfo.getAudioAddress())) {
+ audioSource = devicePort;
+ break;
+ }
+ }
+ // Find sink
+ // TODO: App may want to specify sink device?
+ int sinkDevices = mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC);
+ for (AudioPort port : devicePorts) {
+ AudioDevicePort devicePort = (AudioDevicePort) port;
+ if (devicePort.type() == sinkDevices) {
+ audioSink = devicePort;
+ break;
+ }
+ }
+ }
+ }
+ mAudioSource = audioSource;
+ mAudioSink = audioSink;
}
public void release() {
synchronized (mImplLock) {
+ if (mAudioPatch != null) {
+ mAudioManager.releaseAudioPatch(mAudioPatch);
+ mAudioPatch = null;
+ }
mReleased = true;
}
}
}
}
}
+ if (mAudioSource != null && mAudioSink != null) {
+ if (surface != null) {
+ AudioPortConfig sourceConfig = mAudioSource.activeConfig();
+ AudioPortConfig sinkConfig = mAudioSink.activeConfig();
+ AudioPatch[] audioPatchArray = new AudioPatch[] { mAudioPatch };
+ // TODO: build config if activeConfig() == null
+ mAudioManager.createAudioPatch(
+ audioPatchArray,
+ new AudioPortConfig[] { sourceConfig },
+ new AudioPortConfig[] { sinkConfig });
+ mAudioPatch = audioPatchArray[0];
+ } else {
+ mAudioManager.releaseAudioPatch(mAudioPatch);
+ mAudioPatch = null;
+ }
+ }
return mHal.setSurface(mInfo.getDeviceId(), surface, config) == TvInputHal.SUCCESS;
}
}
throw new IllegalStateException("Device already released.");
}
}
- // TODO
+ // TODO: Use AudioGain?
}
@Override
jmethodID build;
} gTvStreamConfigBuilderClassInfo;
+static struct {
+ jclass clazz;
+
+ jmethodID constructor;
+ jmethodID deviceId;
+ jmethodID type;
+ jmethodID audioType;
+ jmethodID audioAddress;
+ jmethodID build;
+} gTvInputHardwareInfoBuilderClassInfo;
+
////////////////////////////////////////////////////////////////////////////////
class JTvInputHal {
return configs;
}
-
// static
void JTvInputHal::notify(
tv_input_device_t* dev, tv_input_event_t* event, void* data) {
void JTvInputHal::onDeviceAvailable(const tv_input_device_info_t& info) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
mConnections.add(info.device_id, Connection());
+
+ jobject builder = env->NewObject(
+ gTvInputHardwareInfoBuilderClassInfo.clazz,
+ gTvInputHardwareInfoBuilderClassInfo.constructor);
+ env->CallObjectMethod(
+ builder, gTvInputHardwareInfoBuilderClassInfo.deviceId, info.device_id);
+ env->CallObjectMethod(
+ builder, gTvInputHardwareInfoBuilderClassInfo.type, info.type);
+ env->CallObjectMethod(
+ builder, gTvInputHardwareInfoBuilderClassInfo.audioType, info.audio_type);
+ if (info.audio_type != AUDIO_DEVICE_NONE) {
+ jstring audioAddress = env->NewStringUTF(info.audio_address);
+ env->CallObjectMethod(
+ builder, gTvInputHardwareInfoBuilderClassInfo.audioAddress, audioAddress);
+ env->DeleteLocalRef(audioAddress);
+ }
+
+ jobject infoObject = env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.build);
+
env->CallVoidMethod(
mThiz,
gTvInputHalClassInfo.deviceAvailable,
- info.device_id,
- info.type);
+ infoObject);
+
+ env->DeleteLocalRef(builder);
+ env->DeleteLocalRef(infoObject);
}
void JTvInputHal::onDeviceUnavailable(int deviceId) {
FIND_CLASS(clazz, "com/android/server/tv/TvInputHal");
GET_METHOD_ID(
- gTvInputHalClassInfo.deviceAvailable, clazz, "deviceAvailableFromNative", "(II)V");
+ gTvInputHalClassInfo.deviceAvailable, clazz,
+ "deviceAvailableFromNative", "(Landroid/media/tv/TvInputHardwareInfo;)V");
GET_METHOD_ID(
gTvInputHalClassInfo.deviceUnavailable, clazz, "deviceUnavailableFromNative", "(I)V");
GET_METHOD_ID(
gTvStreamConfigBuilderClassInfo.clazz,
"build", "()Landroid/media/tv/TvStreamConfig;");
+ FIND_CLASS(gTvInputHardwareInfoBuilderClassInfo.clazz,
+ "android/media/tv/TvInputHardwareInfo$Builder");
+ gTvInputHardwareInfoBuilderClassInfo.clazz =
+ jclass(env->NewGlobalRef(gTvInputHardwareInfoBuilderClassInfo.clazz));
+
+ GET_METHOD_ID(
+ gTvInputHardwareInfoBuilderClassInfo.constructor,
+ gTvInputHardwareInfoBuilderClassInfo.clazz,
+ "<init>", "()V");
+ GET_METHOD_ID(
+ gTvInputHardwareInfoBuilderClassInfo.deviceId,
+ gTvInputHardwareInfoBuilderClassInfo.clazz,
+ "deviceId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;");
+ GET_METHOD_ID(
+ gTvInputHardwareInfoBuilderClassInfo.type,
+ gTvInputHardwareInfoBuilderClassInfo.clazz,
+ "type", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;");
+ GET_METHOD_ID(
+ gTvInputHardwareInfoBuilderClassInfo.audioType,
+ gTvInputHardwareInfoBuilderClassInfo.clazz,
+ "audioType", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;");
+ GET_METHOD_ID(
+ gTvInputHardwareInfoBuilderClassInfo.audioAddress,
+ gTvInputHardwareInfoBuilderClassInfo.clazz,
+ "audioAddress", "(Ljava/lang/String;)Landroid/media/tv/TvInputHardwareInfo$Builder;");
+ GET_METHOD_ID(
+ gTvInputHardwareInfoBuilderClassInfo.build,
+ gTvInputHardwareInfoBuilderClassInfo.clazz,
+ "build", "()Landroid/media/tv/TvInputHardwareInfo;");
+
return 0;
}