Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 123ec40f authored by Amy's avatar Amy Committed by shubang
Browse files

Refactor the Active Source updating logic in CEC devices.

ag/5108161

Move local Active Source to control service since each device
only needs one local Active Source. Easier to update.

But each device needs multiple mIsActiveSource for each device type
since only one of them should be the Active Source.

When Active Source can be handled only by one device type, like OneTouchPlay,
call setAndBroadcastActiveSourceFromOneDeviceType in service to update
all the device types.

When receiving broadcast messages, all of the device types can handle
Active Source updating in their own logic by calling
setAndBroadcastActiveSource in service.

Test: atest com.android.server.hdmi
Change-Id: I88ce68719ae02c7a847dabb6c558abdb6840b3fa
parent cd18d288
Loading
Loading
Loading
Loading
+3 −11
Original line number Diff line number Diff line
@@ -133,9 +133,6 @@ abstract class HdmiCecLocalDevice {
            return s.toString();
        }
    }
    // Logical address of the active source.
    @GuardedBy("mLock")
    protected final ActiveSource mActiveSource = new ActiveSource();

    // Active routing path. Physical address of the active source but not all the time, such as
    // when the new active source does not claim itself to be one. Note that we don't keep
@@ -867,9 +864,7 @@ abstract class HdmiCecLocalDevice {
    }

    ActiveSource getActiveSource() {
        synchronized (mLock) {
            return mActiveSource;
        }
        return mService.getActiveSource();
    }

    void setActiveSource(ActiveSource newActive) {
@@ -881,10 +876,7 @@ abstract class HdmiCecLocalDevice {
    }

    void setActiveSource(int logicalAddress, int physicalAddress) {
        synchronized (mLock) {
            mActiveSource.logicalAddress = logicalAddress;
            mActiveSource.physicalAddress = physicalAddress;
        }
        mService.setActiveSource(logicalAddress, physicalAddress);
        mService.setLastInputForMhl(Constants.INVALID_PORT_ID);
    }

@@ -1042,7 +1034,7 @@ abstract class HdmiCecLocalDevice {
        pw.println("mAddress: " + mAddress);
        pw.println("mPreferredAddress: " + mPreferredAddress);
        pw.println("mDeviceInfo: " + mDeviceInfo);
        pw.println("mActiveSource: " + mActiveSource);
        pw.println("mActiveSource: " + getActiveSource());
        pw.println(String.format("mActiveRoutingPath: 0x%04x", mActiveRoutingPath));
    }

+2 −6
Original line number Diff line number Diff line
@@ -676,12 +676,8 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
        }
        if (getLocalActivePort() == Constants.CEC_SWITCH_HOME && mService.isPlaybackDevice()) {
            routeToInputFromPortId(Constants.CEC_SWITCH_HOME);
            if (mService.playback() != null) {
                mService.playback().setAndBroadcastActiveSource(
                        message, mService.getPhysicalAddress());
            } else {
                setAndBroadcastActiveSource(message, mService.getPhysicalAddress());
            }
            mService.setAndBroadcastActiveSourceFromOneDeviceType(
                    message.getSource(), mService.getPhysicalAddress());
            return;
        }

+0 −49
Original line number Diff line number Diff line
@@ -48,8 +48,6 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
    private static final boolean SET_MENU_LANGUAGE =
            SystemProperties.getBoolean(Constants.PROPERTY_SET_MENU_LANGUAGE, false);

    private boolean mIsActiveSource = false;

    // Used to keep the device awake while it is the active source. For devices that
    // cannot wake up via CEC commands, this address the inconvenience of having to
    // turn them on. True by default, and can be disabled (i.e. device can go to sleep
@@ -220,53 +218,6 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
        return super.handleUserControlPressed(message);
    }

    @Override
    @ServiceThreadOnly
    protected boolean handleSetStreamPath(HdmiCecMessage message) {
        assertRunOnServiceThread();
        int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
        // If current device is the target path, set to Active Source.
        // If the path is under the current device, should switch
        int port = getLocalPortFromPhysicalAddress(physicalAddress);
        if (port == 0) {
            setIsActiveSource(true);
            maySendActiveSource(message.getSource());
            wakeUpIfActiveSource();
        } else if (port > 0) {
            // Wake up the device if the power is in standby mode for routing
            if (mService.isPowerStandbyOrTransient()) {
                mService.wakeUp();
            }
            routeToPort(port);
        }
        return true;
    }

    // Samsung model we tested sends <Routing Change> and <Request Active Source>
    // in a row, and then changes the input to the internal source if there is no
    // <Active Source> in response. To handle this, we'll set ActiveSource aggressively.
    @Override
    @ServiceThreadOnly
    protected boolean handleRoutingChange(HdmiCecMessage message) {
        assertRunOnServiceThread();
        int newPath = HdmiUtils.twoBytesToInt(message.getParams(), 2);
        maySetActiveSource(newPath);
        return true;  // Broadcast message.
    }

    @Override
    @ServiceThreadOnly
    protected boolean handleRoutingInformation(HdmiCecMessage message) {
        assertRunOnServiceThread();
        int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
        maySetActiveSource(physicalAddress);
        return true;  // Broadcast message.
    }

    private void maySetActiveSource(int physicalAddress) {
        setIsActiveSource(physicalAddress == mService.getPhysicalAddress());
    }

    @Override
    protected void wakeUpIfActiveSource() {
        if (!mIsActiveSource) {
+7 −24
Original line number Diff line number Diff line
@@ -37,7 +37,8 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
    private static final String TAG = "HdmiCecLocalDeviceSource";

    // Indicate if current device is Active Source or not
    private boolean mIsActiveSource = false;
    @VisibleForTesting
    protected boolean mIsActiveSource = false;

    // Device has cec switch functionality or not.
    // Default is false.
@@ -113,7 +114,7 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
        int logicalAddress = message.getSource();
        int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
        ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
        if (!mActiveSource.equals(activeSource)) {
        if (!getActiveSource().equals(activeSource)) {
            setActiveSource(activeSource);
        }
        setIsActiveSource(physicalAddress == mService.getPhysicalAddress());
@@ -185,24 +186,13 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
        // do nothing
    }

    // Active source claiming needs to be handled in the parent class
    // since we decide who will be the active source when the device supports
    // Active source claiming needs to be handled in Service
    // since service can decide who will be the active source when the device supports
    // multiple device types in this method.
    // This method should only be called when the device can be the active source.
    protected void setAndBroadcastActiveSource(HdmiCecMessage message, int physicalAddress) {
        // If the device has both playback and audio system logical addresses,
        // playback will claim active source. Otherwise audio system will.
        HdmiCecLocalDevice deviceToBeActiveSource = mService.playback();
        if (deviceToBeActiveSource == null) {
            deviceToBeActiveSource = mService.audioSystem();
        }
        if (this == deviceToBeActiveSource) {
            ActiveSource activeSource = ActiveSource.of(mAddress, physicalAddress);
            setIsActiveSource(true);
            setActiveSource(activeSource);
            wakeUpIfActiveSource();
            maySendActiveSource(message.getSource());
        }
        mService.setAndBroadcastActiveSource(
                message, physicalAddress, getDeviceInfo().getDeviceType());
    }

    @ServiceThreadOnly
@@ -211,13 +201,6 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
        mIsActiveSource = on;
    }

    @ServiceThreadOnly
    // Check if current device is the Active Source
    boolean isActiveSource() {
        assertRunOnServiceThread();
        return mIsActiveSource;
    }

    protected void wakeUpIfActiveSource() {
        if (!mIsActiveSource) {
            return;
+7 −5
Original line number Diff line number Diff line
@@ -47,11 +47,13 @@ import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
import com.android.server.hdmi.HdmiControlService.SendMessageCallback;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -307,7 +309,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
    private void handleSelectInternalSource() {
        assertRunOnServiceThread();
        // Seq #18
        if (mService.isControlEnabled() && mActiveSource.logicalAddress != mAddress) {
        if (mService.isControlEnabled() && getActiveSource().logicalAddress != mAddress) {
            updateActiveSource(mAddress, mService.getPhysicalAddress());
            if (mSkipRoutingControl) {
                mSkipRoutingControl = false;
@@ -329,7 +331,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
    void updateActiveSource(ActiveSource newActive) {
        assertRunOnServiceThread();
        // Seq #14
        if (mActiveSource.equals(newActive)) {
        if (getActiveSource().equals(newActive)) {
            return;
        }
        setActiveSource(newActive);
@@ -402,7 +404,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
            invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS);
            return;
        }
        mActiveSource.invalidate();
        getActiveSource().invalidate();
        if (!mService.isControlEnabled()) {
            setActivePortId(portId);
            invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
@@ -518,7 +520,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
        } else {
            // No HDMI port to switch to was found. Notify the input change listers to
            // switch to the lastly shown internal input.
            mActiveSource.invalidate();
            getActiveSource().invalidate();
            setActivePath(Constants.INVALID_PHYSICAL_ADDRESS);
            mService.invokeInputChangeListener(HdmiDeviceInfo.INACTIVE_DEVICE);
        }
@@ -685,7 +687,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
        byte[] params = message.getParams();
        int currentPath = HdmiUtils.twoBytesToInt(params);
        if (HdmiUtils.isAffectingActiveRoutingPath(getActivePath(), currentPath)) {
            mActiveSource.invalidate();
            getActiveSource().invalidate();
            removeAction(RoutingControlAction.class);
            int newPath = HdmiUtils.twoBytesToInt(params, 2);
            addAndStartAction(new RoutingControlAction(this, newPath, true, null));
Loading