/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import android.hardware.hdmi.HdmiDeviceInfo; import android.util.Slog; import com.android.server.hdmi.HdmiControlService.DevicePollingCallback; import java.util.BitSet; import java.util.List; /** * Feature action that handles hot-plug detection mechanism. * Hot-plug event is initiated by timer after device discovery action. * *
Check all devices every 15 secs except for system audio.
* If system audio is on, check hot-plug for audio system every 5 secs.
* For other devices, keep 15 secs period.
*/
// Seq #3
final class HotplugDetectionAction extends HdmiCecFeatureAction {
private static final String TAG = "HotPlugDetectionAction";
private static final int POLLING_INTERVAL_MS = 5000;
private static final int TIMEOUT_COUNT = 3;
private static final int AVR_COUNT_MAX = 3;
// State in which waits for next polling
private static final int STATE_WAIT_FOR_NEXT_POLLING = 1;
// All addresses except for broadcast (unregistered address).
private static final int NUM_OF_ADDRESS = Constants.ADDR_SPECIFIC_USE
- Constants.ADDR_TV + 1;
private int mTimeoutCount = 0;
// Counter used to ensure the connection to AVR is stable. Occasional failure to get
// polling response from AVR despite its presence leads to unstable status flipping.
// This is a workaround to deal with it, by removing the device only if the removal
// is detected {@code AVR_COUNT_MAX} times in a row.
private int mAvrStatusCount = 0;
/**
* Constructor
*
* @param source {@link HdmiCecLocalDevice} instance
*/
HotplugDetectionAction(HdmiCecLocalDevice source) {
super(source);
}
@Override
boolean start() {
Slog.v(TAG, "Hot-plug dection started.");
mState = STATE_WAIT_FOR_NEXT_POLLING;
mTimeoutCount = 0;
// Start timer without polling.
// The first check for all devices will be initiated 15 seconds later.
addTimer(mState, POLLING_INTERVAL_MS);
return true;
}
@Override
boolean processCommand(HdmiCecMessage cmd) {
// No-op
return false;
}
@Override
void handleTimerEvent(int state) {
if (mState != state) {
return;
}
if (mState == STATE_WAIT_FOR_NEXT_POLLING) {
mTimeoutCount = (mTimeoutCount + 1) % TIMEOUT_COUNT;
pollDevices();
}
}
/**
* Start device polling immediately.
*/
void pollAllDevicesNow() {
// Clear existing timer to avoid overlapped execution
mActionTimer.clearTimerMessage();
mTimeoutCount = 0;
mState = STATE_WAIT_FOR_NEXT_POLLING;
pollAllDevices();
addTimer(mState, POLLING_INTERVAL_MS);
}
// This method is called every 5 seconds.
private void pollDevices() {
// All device check called every 15 seconds.
if (mTimeoutCount == 0) {
pollAllDevices();
} else {
if (tv().isSystemAudioActivated()) {
pollAudioSystem();
}
}
addTimer(mState, POLLING_INTERVAL_MS);
}
private void pollAllDevices() {
Slog.v(TAG, "Poll all devices.");
pollDevices(new DevicePollingCallback() {
@Override
public void onPollingFinished(List