Merge "TvInputHardware: Integration with audio framework changes"
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user