HdmiControlService是提供发送和处理HDMI控制消息, HDMI-CEC和MHL控制命令的服务。
一 HdmiControlService启动
1. SystemServer在startOtherServices过程中会启动HdmiControlService
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
traceBeginAndSlog("StartHdmiControlService");
mSystemServiceManager.startService(HdmiControlService.class);
traceEnd();
}
SystemFeature 配置在frameworks/native/data/etc路径下,在pkms启动时会读取和解析这些xml文件,其中android.hardware.hdmi.cec.xml有这个feature。
<permissions>
<feature name="android.hardware.hdmi.cec" />
</permissions>
2.初始化
确认设备的类型,并且创建了一个Settings数据库的监听器。
static final String PROPERTY_DEVICE_TYPE = "ro.hdmi.device_type";这个是设备的hdmi类型,
对于机顶盒 (OTT) 等 HDMI 源设备,请采用如下设置:
PRODUCT_PROPERTY_OVERRIDES += ro.hdmi.device_type=4
对于平板电视等 HDMI 接收设备,请采用如下设置:
PRODUCT_PROPERTY_OVERRIDES += ro.hdmi.device_type=0
public class HdmiDeviceInfo implements Parcelable {
/** TV device type. */
public static final int DEVICE_TV = 0;
/** Recording device type. */
public static final int DEVICE_RECORDER = 1;
/** Device type reserved for future usage. */
public static final int DEVICE_RESERVED = 2;
/** Tuner device type. */
public static final int DEVICE_TUNER = 3;
/** Playback device type. */
public static final int DEVICE_PLAYBACK = 4;
/** Audio system device type. */
public static final int DEVICE_AUDIO_SYSTEM = 5;
/** @hide Pure CEC switch device type. */
public static final int DEVICE_PURE_CEC_SWITCH = 6;
/** @hide Video processor device type. */
public static final int DEVICE_VIDEO_PROCESSOR = 7;
// Value indicating the device is not an active source.
public static final int DEVICE_INACTIVE = -1;
public HdmiControlService(Context context) {
super(context);
mLocalDevices = getIntList(SystemProperties.get(Constants.PROPERTY_DEVICE_TYPE));
mSettingsObserver = new SettingsObserver(mHandler);
}
private class SettingsObserver extends ContentObserver {
public SettingsObserver(Handler handler) {
super(handler);
}
// onChange is set up to run in service thread.
@Override
public void onChange(boolean selfChange, Uri uri) {
String option = uri.getLastPathSegment();
boolean enabled = readBooleanSetting(option, true);
switch (option) {
case Global.HDMI_CONTROL_ENABLED:
setControlEnabled(enabled);
break;
case Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED:
if (isTvDeviceEnabled()) {
tv().setAutoWakeup(enabled);
}
setCecOption(OptionKey.WAKEUP, enabled);
break;
case Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED:
for (int type : mLocalDevices) {
HdmiCecLocalDevice localDevice = mCecController.getLocalDevice(type);
if (localDevice != null) {
localDevice.setAutoDeviceOff(enabled);
}
}
// No need to propagate to HAL.
break;
case Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED:
if (isTvDeviceEnabled()) {
tv().setSystemAudioControlFeatureEnabled(enabled);
}
break;
case Global.HDMI_SYSTEM_AUDIO_STATUS_ENABLED:
if (isTvDeviceEnabled()) {
tv().changeSystemAudioStatus(enabled);
}
break;
case Global.MHL_INPUT_SWITCHING_ENABLED:
setMhlInputChangeEnabled(enabled);
break;
case Global.MHL_POWER_CHARGE_ENABLED:
mMhlController.setOption(OPTION_MHL_POWER_CHARGE, toInt(enabled));
break;
}
}
}
3.onStart
public void onStart() {
mIoThread.start();
mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;
mProhibitMode = false;
mHdmiControlEnabled = readBooleanSetting(Global.HDMI_CONTROL_ENABLED, true);
mMhlInputChangeEnabled = readBooleanSetting(Global.MHL_INPUT_SWITCHING_ENABLED, true);
mCecController = HdmiCecController.create(this);
if (mCecController != null) {
if (mHdmiControlEnabled) {
initializeCec(INITIATED_BY_BOOT_UP);
}
} else {
Slog.i(TAG, "Device does not support HDMI-CEC.");
return;
}
mMhlController = HdmiMhlControllerStub.create(this);
if (!mMhlController.isReady()) {
Slog.i(TAG, "Device does not support MHL-control.");
}
mMhlDevices = Collections.emptyList();
initPortInfo();
mMessageValidator = new HdmiCecMessageValidator(this);
publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());
if (mCecController != null) {
// Register broadcast receiver for power state change.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SHUTDOWN);
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
getContext().registerReceiver(mHdmiControlBroadcastReceiver, filter);
// Register ContentObserver to monitor the settings change.
registerContentObserver();
}
mMhlController.setOp