Merge "TvInputHardware: Integration with audio framework changes"

This commit is contained in:
Wonsik Kim
2014-06-19 01:58:01 +00:00
committed by Android (Google) Code Review
6 changed files with 197 additions and 20 deletions

View File

@@ -2533,6 +2533,9 @@ public class AudioManager {
// class is not used by other parts of the framework, which instead use definitions and methods
// 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,

View File

@@ -225,6 +225,7 @@ public class AudioSystem
// 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;

View File

@@ -16,6 +16,7 @@
package android.media.tv;
import android.media.AudioManager;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
@@ -56,14 +57,11 @@ public final class TvInputHardwareInfo implements Parcelable {
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() {
@@ -74,6 +72,14 @@ public final class TvInputHardwareInfo implements Parcelable {
return mType;
}
public int getAudioType() {
return mAudioType;
}
public String getAudioAddress() {
return mAudioAddress;
}
// Parcelable
@Override
public int describeContents() {
@@ -84,10 +90,59 @@ public final class TvInputHardwareInfo implements Parcelable {
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;
}
}
}

View File

@@ -94,8 +94,7 @@ final class TvInputHal {
}
// 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() {
@@ -105,23 +104,21 @@ final class TvInputHal {
});
}
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);
}
});
}

View File

@@ -17,6 +17,11 @@
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;
@@ -48,11 +53,13 @@ class TvInputHardwareManager implements TvInputHal.Callback {
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();
@@ -258,12 +265,48 @@ class TvInputHardwareManager implements TvInputHal.Callback {
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;
}
}
@@ -288,6 +331,22 @@ class TvInputHardwareManager implements TvInputHal.Callback {
}
}
}
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;
}
}
@@ -299,7 +358,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
throw new IllegalStateException("Device already released.");
}
}
// TODO
// TODO: Use AudioGain?
}
@Override

View File

@@ -54,6 +54,17 @@ static struct {
jmethodID build;
} gTvStreamConfigBuilderClassInfo;
static struct {
jclass clazz;
jmethodID constructor;
jmethodID deviceId;
jmethodID type;
jmethodID audioType;
jmethodID audioAddress;
jmethodID build;
} gTvInputHardwareInfoBuilderClassInfo;
////////////////////////////////////////////////////////////////////////////////
class JTvInputHal {
@@ -209,7 +220,6 @@ const tv_stream_config_t* JTvInputHal::getStreamConfigs(int deviceId, int* numCo
return configs;
}
// static
void JTvInputHal::notify(
tv_input_device_t* dev, tv_input_event_t* event, void* data) {
@@ -232,11 +242,32 @@ void JTvInputHal::notify(
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) {
@@ -339,7 +370,8 @@ int register_android_server_tv_TvInputHal(JNIEnv* env) {
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(
@@ -382,6 +414,36 @@ int register_android_server_tv_TvInputHal(JNIEnv* env) {
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;
}