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

Commit 1f9d07fd authored by Amy Zhang's avatar Amy Zhang Committed by Android (Google) Code Review
Browse files

Merge "Cache OTP callback if the device is still under address allocation"

parents f9f98bc4 f5a866e9
Loading
Loading
Loading
Loading
+23 −6
Original line number Original line Diff line number Diff line
@@ -310,6 +310,11 @@ public class HdmiControlService extends SystemService {
    // Invoke once new local device is ready.
    // Invoke once new local device is ready.
    private IHdmiControlCallback mDisplayStatusCallback = null;
    private IHdmiControlCallback mDisplayStatusCallback = null;


    @Nullable
    // Save callback when the device is still under logcial address allocation
    // Invoke once new local device is ready.
    private IHdmiControlCallback mOtpCallbackPendingAddressAllocation = null;

    @Nullable
    @Nullable
    private HdmiCecController mCecController;
    private HdmiCecController mCecController;


@@ -785,17 +790,21 @@ public class HdmiControlService extends SystemService {
                    // Address allocation completed for all devices. Notify each device.
                    // Address allocation completed for all devices. Notify each device.
                    if (allocatingDevices.size() == ++finished[0]) {
                    if (allocatingDevices.size() == ++finished[0]) {
                        mAddressAllocated = true;
                        mAddressAllocated = true;
                        // Reinvoke the saved display status callback once the local device is ready.
                        if (mDisplayStatusCallback != null) {
                            queryDisplayStatus(mDisplayStatusCallback);
                            mDisplayStatusCallback = null;
                        }
                        if (initiatedBy != INITIATED_BY_HOTPLUG) {
                        if (initiatedBy != INITIATED_BY_HOTPLUG) {
                            // In case of the hotplug we don't call onInitializeCecComplete()
                            // In case of the hotplug we don't call onInitializeCecComplete()
                            // since we reallocate the logical address only.
                            // since we reallocate the logical address only.
                            onInitializeCecComplete(initiatedBy);
                            onInitializeCecComplete(initiatedBy);
                        }
                        }
                        notifyAddressAllocated(allocatedDevices, initiatedBy);
                        notifyAddressAllocated(allocatedDevices, initiatedBy);
                        // Reinvoke the saved display status callback once the local device is ready.
                        if (mDisplayStatusCallback != null) {
                            queryDisplayStatus(mDisplayStatusCallback);
                            mDisplayStatusCallback = null;
                        }
                        if (mOtpCallbackPendingAddressAllocation != null) {
                            oneTouchPlay(mOtpCallbackPendingAddressAllocation);
                            mOtpCallbackPendingAddressAllocation = null;
                        }
                        mCecMessageBuffer.processMessages();
                        mCecMessageBuffer.processMessages();
                    }
                    }
                }
                }
@@ -2246,8 +2255,16 @@ public class HdmiControlService extends SystemService {
    }
    }


    @ServiceThreadOnly
    @ServiceThreadOnly
    private void oneTouchPlay(final IHdmiControlCallback callback) {
    @VisibleForTesting
    protected void oneTouchPlay(final IHdmiControlCallback callback) {
        assertRunOnServiceThread();
        assertRunOnServiceThread();
        if (!mAddressAllocated) {
            mOtpCallbackPendingAddressAllocation = callback;
            Slog.d(TAG, "Local device is under address allocation. "
                        + "Save OTP callback for later process.");
            return;
        }

        HdmiCecLocalDeviceSource source = playback();
        HdmiCecLocalDeviceSource source = playback();
        if (source == null) {
        if (source == null) {
            source = audioSystem();
            source = audioSystem();
+1 −1
Original line number Original line Diff line number Diff line
@@ -77,7 +77,6 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction {
        sendCommand(HdmiCecMessageBuilder.buildTextViewOn(getSourceAddress(), mTargetAddress));
        sendCommand(HdmiCecMessageBuilder.buildTextViewOn(getSourceAddress(), mTargetAddress));
        broadcastActiveSource();
        broadcastActiveSource();
        queryDevicePowerStatus();
        queryDevicePowerStatus();
        mState = STATE_WAITING_FOR_REPORT_POWER_STATUS;
        addTimer(mState, HdmiConfig.TIMEOUT_MS);
        addTimer(mState, HdmiConfig.TIMEOUT_MS);
        return true;
        return true;
    }
    }
@@ -99,6 +98,7 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction {
    }
    }


    private void queryDevicePowerStatus() {
    private void queryDevicePowerStatus() {
        mState = STATE_WAITING_FOR_REPORT_POWER_STATUS;
        sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(),
        sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(),
                mTargetAddress));
                mTargetAddress));
    }
    }
+212 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2019 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 static android.os.SystemClock.sleep;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;

import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiControlCallback;
import android.os.Looper;
import android.os.SystemProperties;
import android.os.test.TestLooper;
import android.util.Slog;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;

import java.util.ArrayList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link HdmiControlServiceBinderAPITest} class.
 */
@SmallTest
@RunWith(JUnit4.class)
public class HdmiControlServiceBinderAPITest {

    private class HdmiCecLocalDeviceMyDevice extends HdmiCecLocalDevice {

        private boolean mCanGoToStandby;
        private boolean mIsStandby;
        private boolean mIsDisabled;

        protected HdmiCecLocalDeviceMyDevice(HdmiControlService service, int deviceType) {
            super(service, deviceType);
        }

        @Override
        protected void onAddressAllocated(int logicalAddress, int reason) {
        }

        @Override
        protected int getPreferredAddress() {
            return 0;
        }

        @Override
        protected void setPreferredAddress(int addr) {
        }

        @Override
        protected boolean canGoToStandby() {
            return mCanGoToStandby;
        }

        @Override
        protected void disableDevice(
            boolean initiatedByCec, final PendingActionClearedCallback originalCallback) {
            mIsDisabled = true;
            originalCallback.onCleared(this);
        }

        @Override
        protected void onStandby(boolean initiatedByCec, int standbyAction) {
            mIsStandby = true;
        }

        protected boolean isStandby() {
            return mIsStandby;
        }

        protected boolean isDisabled() {
            return mIsDisabled;
        }

        protected void setCanGoToStandby(boolean canGoToStandby) {
            mCanGoToStandby = canGoToStandby;
        }
    }

    private static final String TAG = "HdmiControlServiceBinderAPITest";
    private HdmiControlService mHdmiControlService;
    private HdmiCecController mHdmiCecController;
    private HdmiCecLocalDevicePlayback mPlaybackDevice;
    private FakeNativeWrapper mNativeWrapper;
    private Looper mMyLooper;
    private TestLooper mTestLooper = new TestLooper();
    private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
    private HdmiPortInfo[] mHdmiPortInfo;
    private int mResult;
    private int mPowerStatus;

    @Before
    public void SetUp() {
        mHdmiControlService =
            new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
                @Override
                void sendCecCommand(HdmiCecMessage command) {
                    switch (command.getOpcode()) {
                        case Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS:
                            HdmiCecMessage message =
                                HdmiCecMessageBuilder.buildReportPowerStatus(
                                    Constants.ADDR_TV,
                                    Constants.ADDR_PLAYBACK_1,
                                    HdmiControlManager.POWER_STATUS_ON);
                            handleCecCommand(message);
                            break;
                        default:
                            return;
                    }
                }

                @Override
                boolean isPowerStandby() {
                    return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY;
                }
            };
        mMyLooper = mTestLooper.getLooper();

        mPlaybackDevice = new HdmiCecLocalDevicePlayback(mHdmiControlService) {
            @Override
            void setIsActiveSource(boolean on) {
                mIsActiveSource = on;
            }

            @Override
            protected void wakeUpIfActiveSource() {}

            @Override
            protected void setPreferredAddress(int addr) {}

            @Override
            protected int getPreferredAddress() {
                return Constants.ADDR_PLAYBACK_1;
            }
        };
        mPlaybackDevice.init();

        mHdmiControlService.setIoLooper(mMyLooper);

        mNativeWrapper = new FakeNativeWrapper();
        mHdmiCecController =
            HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
        mHdmiControlService.setCecController(mHdmiCecController);
        mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
        mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));

        mLocalDevices.add(mPlaybackDevice);
        mHdmiPortInfo = new HdmiPortInfo[1];
        mHdmiPortInfo[0] =
            new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, 0x2100, true, false, false);
        mNativeWrapper.setPortInfo(mHdmiPortInfo);
        mHdmiControlService.initPortInfo();
        mResult = -1;
        mPowerStatus = HdmiControlManager.POWER_STATUS_ON;

        mTestLooper.dispatchAll();
    }

    @Test
    public void oneTouchPlay_addressNotAllocated() {
        assertThat(mHdmiControlService.isAddressAllocated()).isFalse();
        mHdmiControlService.oneTouchPlay(new IHdmiControlCallback.Stub() {
            @Override
            public void onComplete(int result) {
                mResult = result;
            }
        });
        assertEquals(mResult, -1);
        assertThat(mPlaybackDevice.mIsActiveSource).isFalse();

        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
        mTestLooper.dispatchAll();
        assertThat(mHdmiControlService.isAddressAllocated()).isTrue();
        assertEquals(mResult, HdmiControlManager.RESULT_SUCCESS);
        assertThat(mPlaybackDevice.mIsActiveSource).isTrue();
    }

    @Test
    public void oneTouchPlay_addressAllocated() {
        mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
        mTestLooper.dispatchAll();
        assertThat(mHdmiControlService.isAddressAllocated()).isTrue();
        mHdmiControlService.oneTouchPlay(new IHdmiControlCallback.Stub() {
            @Override
            public void onComplete(int result) {
                mResult = result;
            }
        });
        assertEquals(mResult, HdmiControlManager.RESULT_SUCCESS);
        assertThat(mPlaybackDevice.mIsActiveSource).isTrue();
    }
}