Handle TODO in SystemAudioActionFromTv.
- Added onFinishedCallback to handle the deferred starting of FeatureAction.
Bug: 15843078, Bug: 15841546
Change-Id: I6cb5fba91d6115e8bb02c38601a72ed315c22e2f
diff --git a/services/core/java/com/android/server/hdmi/FeatureAction.java b/services/core/java/com/android/server/hdmi/FeatureAction.java
index 7d15f4c..b7b2f90 100644
--- a/services/core/java/com/android/server/hdmi/FeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/FeatureAction.java
@@ -18,11 +18,13 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.util.Pair;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.hdmi.HdmiControlService.DevicePollingCallback;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -59,6 +61,8 @@
// Timer that manages timeout events.
protected ActionTimer mActionTimer;
+ private ArrayList<Pair<FeatureAction, Runnable>> mOnFinishedCallbacks;
+
FeatureAction(HdmiCecLocalDevice source) {
mSource = source;
mService = mSource.getService();
@@ -220,8 +224,22 @@
* Finish up the action. Reset the state, and remove itself from the action queue.
*/
protected void finish() {
+ finish(true);
+ }
+
+ void finish(boolean removeSelf) {
clear();
- removeAction(this);
+ if (removeSelf) {
+ removeAction(this);
+ }
+ if (mOnFinishedCallbacks != null) {
+ for (Pair<FeatureAction, Runnable> actionCallbackPair: mOnFinishedCallbacks) {
+ if (actionCallbackPair.first.mState != STATE_NONE) {
+ actionCallbackPair.second.run();
+ }
+ }
+ mOnFinishedCallbacks = null;
+ }
}
protected final HdmiCecLocalDevice localDevice() {
@@ -244,10 +262,17 @@
return mSource.getDeviceInfo().getPhysicalAddress();
}
- protected void sendUserControlPressedAndReleased(int targetAddress, int uiCommand) {
+ protected final void sendUserControlPressedAndReleased(int targetAddress, int uiCommand) {
sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(
getSourceAddress(), targetAddress, uiCommand));
sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(
getSourceAddress(), targetAddress));
}
+
+ protected final void addOnFinishedCallback(FeatureAction action, Runnable runnable) {
+ if (mOnFinishedCallbacks == null) {
+ mOnFinishedCallbacks = new ArrayList<>();
+ }
+ mOnFinishedCallbacks.add(Pair.create(action, runnable));
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 3937ce1..7515242 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -65,7 +65,7 @@
// Note that access to this collection should happen in service thread.
private final LinkedList<FeatureAction> mActions = new LinkedList<>();
- private Handler mHandler = new Handler () {
+ private final Handler mHandler = new Handler () {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -482,6 +482,7 @@
@ServiceThreadOnly
void removeAction(final FeatureAction action) {
assertRunOnServiceThread();
+ action.finish(false);
mActions.remove(action);
checkIfPendingActionsCleared();
}
@@ -502,8 +503,8 @@
while (iter.hasNext()) {
FeatureAction action = iter.next();
if (action != exception && action.getClass().equals(clazz)) {
- action.clear();
- mActions.remove(action);
+ action.finish(false);
+ iter.remove();
}
}
checkIfPendingActionsCleared();
@@ -637,7 +638,7 @@
Iterator<FeatureAction> iter = mActions.iterator();
while (iter.hasNext()) {
FeatureAction action = iter.next();
- action.finish();
+ action.finish(false);
iter.remove();
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 923b87d..8840c62 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -536,10 +536,17 @@
}
@ServiceThreadOnly
+ // Seq #32
void changeSystemAudioMode(boolean enabled, IHdmiControlCallback callback) {
assertRunOnServiceThread();
+ if (!mService.isControlEnabled() || hasAction(DeviceDiscoveryAction.class)) {
+ setSystemAudioMode(false, true);
+ invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
+ return;
+ }
HdmiCecDeviceInfo avr = getAvrDeviceInfo();
if (avr == null) {
+ setSystemAudioMode(false, true);
invokeCallback(callback, HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
return;
}
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index 185de59..6204c16 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -219,7 +219,7 @@
return;
}
- // Should ave only one Device Select Action
+ // Should have only one Device Select Action
DeviceSelectAction action = actions.get(0);
if (action.getTargetAddress() == address) {
removeAction(DeviceSelectAction.class);
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
index 86895cc..4be036a 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
@@ -23,14 +23,20 @@
import android.os.RemoteException;
import android.util.Slog;
+import java.util.List;
+
/**
* Base feature action class for SystemAudioActionFromTv and SystemAudioActionFromAvr.
*/
abstract class SystemAudioAction extends FeatureAction {
private static final String TAG = "SystemAudioAction";
+ // Transient state to differentiate with STATE_NONE where the on-finished callback
+ // will not be called.
+ private static final int STATE_CHECK_ROUTING_IN_PRGRESS = 1;
+
// State in which waits for <SetSystemAudioMode>.
- private static final int STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE = 1;
+ private static final int STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE = 2;
private static final int MAX_SEND_RETRY_COUNT = 2;
@@ -65,7 +71,25 @@
mCallback = callback;
}
+ // Seq #27
protected void sendSystemAudioModeRequest() {
+ mState = STATE_CHECK_ROUTING_IN_PRGRESS;
+ List<RoutingControlAction> routingActions = getActions(RoutingControlAction.class);
+ if (!routingActions.isEmpty()) {
+ // Should have only one Routing Control Action
+ RoutingControlAction routingAction = routingActions.get(0);
+ routingAction.addOnFinishedCallback(this, new Runnable() {
+ @Override
+ public void run() {
+ sendSystemAudioModeRequestInternal();
+ }
+ });
+ return;
+ }
+ sendSystemAudioModeRequestInternal();
+ }
+
+ private void sendSystemAudioModeRequestInternal() {
int avrPhysicalAddress = tv().getAvrDeviceInfo().getPhysicalAddress();
HdmiCecMessage command = HdmiCecMessageBuilder.buildSystemAudioModeRequest(
getSourceAddress(),
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
index a565077..77783b7 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
@@ -23,7 +23,7 @@
/**
* Feature action that handles System Audio initiated by AVR devices.
*/
-// # Seq 33
+// Seq #33
final class SystemAudioActionFromAvr extends SystemAudioAction {
/**
* Constructor
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java b/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java
index 2146c4e..cb3588c 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java
@@ -24,6 +24,7 @@
* Feature action that handles System Audio initiated by TV devices.
*/
final class SystemAudioActionFromTv extends SystemAudioAction {
+
/**
* Constructor
*
@@ -41,9 +42,6 @@
@Override
boolean start() {
- // TODO: Check HDMI-CEC is enabled.
- // TODO: Move to the waiting state if currently a routing change is in progress.
-
removeSystemAudioActionInProgress();
sendSystemAudioModeRequest();
return true;
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
index 80954d4..d03634e 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
@@ -21,6 +21,7 @@
/**
* Action to initiate system audio once AVR is detected on Device discovery action.
*/
+// Seq #27
final class SystemAudioAutoInitiationAction extends FeatureAction {
private final int mAvrAddress;