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

Commit f9b26828 authored by Yan Han's avatar Yan Han Committed by Automerger Merge Worker
Browse files

Merge changes from topics "presubmit-am-7ed5c317d7b347f1a59eb332f20e8522",...

Merge changes from topics "presubmit-am-7ed5c317d7b347f1a59eb332f20e8522", "presubmit-am-86ce18b053454a4db98a349f8b39985e", "presubmit-am-94d3142a4e1c418fadfd6eca6208920a", "presubmit-am-a466ed1382304d549cb550a5cae804e6" into tm-dev am: a62f3275 am: 0c089a72

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17140464



Change-Id: If4bad0b00ed13f8361c0c7efdebe467675ed4c7a
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 8f8e9baf 0c089a72
Loading
Loading
Loading
Loading
+103 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 * Copyright (C) 2022 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.
@@ -16,97 +16,88 @@

package com.android.server.hdmi;

import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.tv.cec.V1_0.SendMessageResult;

import com.android.server.hdmi.HdmiControlService.SendMessageCallback;

import java.util.List;

/**
 * Action to update audio status (volume or mute) of audio amplifier
 * Action to query and track the audio status of the System Audio device when enabling or using
 * Absolute Volume Control. Must be removed when AVC is disabled. Performs two main functions:
 * 1. When enabling AVC: queries the starting audio status of the System Audio device and
 *    enables the feature upon receiving a response.
 * 2. While AVC is enabled: monitors <Report Audio Status> messages from the System Audio device and
 *    notifies AudioService if the audio status changes.
 */
final class SystemAudioStatusAction extends HdmiCecFeatureAction {
    private static final String TAG = "SystemAudioStatusAction";
final class AbsoluteVolumeAudioStatusAction extends HdmiCecFeatureAction {
    private static final String TAG = "AbsoluteVolumeAudioStatusAction";

    // State that waits for <ReportAudioStatus>.
    private static final int STATE_WAIT_FOR_REPORT_AUDIO_STATUS = 1;
    private int mInitialAudioStatusRetriesLeft = 2;

    private final int mAvrAddress;
    private static final int STATE_WAIT_FOR_INITIAL_AUDIO_STATUS = 1;
    private static final int STATE_MONITOR_AUDIO_STATUS = 2;

    SystemAudioStatusAction(
            HdmiCecLocalDevice source, int avrAddress, List<IHdmiControlCallback> callbacks) {
        super(source, callbacks);
        mAvrAddress = avrAddress;
    }
    private final int mTargetAddress;

    SystemAudioStatusAction(HdmiCecLocalDevice source, int avrAddress,
            IHdmiControlCallback callback) {
        super(source, callback);
        mAvrAddress = avrAddress;
    private AudioStatus mLastAudioStatus;

    AbsoluteVolumeAudioStatusAction(HdmiCecLocalDevice source, int targetAddress) {
        super(source);
        mTargetAddress = targetAddress;
    }

    @Override
    boolean start() {
        mState = STATE_WAIT_FOR_REPORT_AUDIO_STATUS;
        addTimer(mState, HdmiConfig.TIMEOUT_MS);
        mState = STATE_WAIT_FOR_INITIAL_AUDIO_STATUS;
        sendGiveAudioStatus();
        return true;
    }

    private void sendGiveAudioStatus() {
        sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus(getSourceAddress(), mAvrAddress),
                new SendMessageCallback() {
            @Override
            public void onSendCompleted(int error) {
                if (error != SendMessageResult.SUCCESS) {
                    handleSendGiveAudioStatusFailure();
                }
    void updateVolume(int volumeIndex) {
        mLastAudioStatus = new AudioStatus(volumeIndex, mLastAudioStatus.getMute());
    }
        });
    }

    private void handleSendGiveAudioStatusFailure() {

        // Still return SUCCESS to callback.
        finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
    private void sendGiveAudioStatus() {
        addTimer(mState, HdmiConfig.TIMEOUT_MS);
        sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus(getSourceAddress(), mTargetAddress));
    }

    @Override
    boolean processCommand(HdmiCecMessage cmd) {
        if (mState != STATE_WAIT_FOR_REPORT_AUDIO_STATUS || mAvrAddress != cmd.getSource()) {
            return false;
        }

        switch (cmd.getOpcode()) {
            case Constants.MESSAGE_REPORT_AUDIO_STATUS:
                handleReportAudioStatus(cmd);
                return true;
                return handleReportAudioStatus(cmd);
        }

        return false;
    }

    private void handleReportAudioStatus(HdmiCecMessage cmd) {
        byte[] params = cmd.getParams();
    private boolean handleReportAudioStatus(HdmiCecMessage cmd) {
        if (mTargetAddress != cmd.getSource() || cmd.getParams().length == 0) {
            return false;
        }

        boolean mute = HdmiUtils.isAudioStatusMute(cmd);
        int volume = HdmiUtils.getAudioStatusVolume(cmd);
        tv().setAudioStatus(mute, volume);

        if (!(tv().isSystemAudioActivated() ^ mute)) {
            // Toggle AVR's mute status to match with the system audio status.
            sendUserControlPressedAndReleased(mAvrAddress, HdmiCecKeycode.CEC_KEYCODE_MUTE);
        AudioStatus audioStatus = new AudioStatus(volume, mute);
        if (mState == STATE_WAIT_FOR_INITIAL_AUDIO_STATUS) {
            localDevice().getService().enableAbsoluteVolumeControl(audioStatus);
            mState = STATE_MONITOR_AUDIO_STATUS;
        } else if (mState == STATE_MONITOR_AUDIO_STATUS) {
            if (audioStatus.getVolume() != mLastAudioStatus.getVolume()) {
                localDevice().getService().notifyAvcVolumeChange(audioStatus.getVolume());
            }
        finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
            if (audioStatus.getMute() != mLastAudioStatus.getMute()) {
                localDevice().getService().notifyAvcMuteChange(audioStatus.getMute());
            }
        }
        mLastAudioStatus = audioStatus;

        return true;
    }

    @Override
    void handleTimerEvent(int state) {
        if (mState != state) {
            return;
        } else if (mInitialAudioStatusRetriesLeft > 0) {
            mInitialAudioStatusRetriesLeft--;
            sendGiveAudioStatus();
        }

        handleSendGiveAudioStatusFailure();
    }
}
+67 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.content.Context;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceVolumeManager;
import android.media.VolumeInfo;

import java.util.concurrent.Executor;

/**
 * Wrapper for {@link AudioDeviceVolumeManager}. Creates an instance of the class and directly
 * passes method calls to that instance.
 */
public class AudioDeviceVolumeManagerWrapper
        implements AudioDeviceVolumeManagerWrapperInterface {

    private static final String TAG = "AudioDeviceVolumeManagerWrapper";

    private final AudioDeviceVolumeManager mAudioDeviceVolumeManager;

    public AudioDeviceVolumeManagerWrapper(Context context) {
        mAudioDeviceVolumeManager = new AudioDeviceVolumeManager(context);
    }

    @Override
    public void addOnDeviceVolumeBehaviorChangedListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener)
            throws SecurityException {
        mAudioDeviceVolumeManager.addOnDeviceVolumeBehaviorChangedListener(executor, listener);
    }

    @Override
    public void removeOnDeviceVolumeBehaviorChangedListener(
            @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener) {
        mAudioDeviceVolumeManager.removeOnDeviceVolumeBehaviorChangedListener(listener);
    }

    @Override
    public void setDeviceAbsoluteVolumeBehavior(
            @NonNull AudioDeviceAttributes device,
            @NonNull VolumeInfo volume,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener vclistener,
            boolean handlesVolumeAdjustment) {
        mAudioDeviceVolumeManager.setDeviceAbsoluteVolumeBehavior(device, volume, executor,
                vclistener, handlesVolumeAdjustment);
    }
}
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.media.AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener;
import static android.media.AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener;

import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceVolumeManager;
import android.media.VolumeInfo;

import java.util.concurrent.Executor;

/**
 * Interface with the methods from {@link AudioDeviceVolumeManager} used by the HDMI framework.
 * Allows the class to be faked for tests.
 */
public interface AudioDeviceVolumeManagerWrapperInterface {

    /**
     * Wrapper for {@link AudioDeviceVolumeManager#addOnDeviceVolumeBehaviorChangedListener(
     * Executor, OnDeviceVolumeBehaviorChangedListener)}
     */
    void addOnDeviceVolumeBehaviorChangedListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener);

    /**
     * Wrapper for {@link AudioDeviceVolumeManager#removeOnDeviceVolumeBehaviorChangedListener(
     * OnDeviceVolumeBehaviorChangedListener)}
     */
    void removeOnDeviceVolumeBehaviorChangedListener(
            @NonNull AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener listener);

    /**
     * Wrapper for {@link AudioDeviceVolumeManager#setDeviceAbsoluteVolumeBehavior(
     * AudioDeviceAttributes, VolumeInfo, Executor, OnAudioDeviceVolumeChangedListener, boolean)}
     */
    void setDeviceAbsoluteVolumeBehavior(
            @NonNull AudioDeviceAttributes device,
            @NonNull VolumeInfo volume,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener vclistener,
            boolean handlesVolumeAdjustment);
}
+67 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.annotation.Nullable;

import java.util.Objects;

/**
 * Immutable representation of the information in the [Audio Status] operand:
 * volume status (0 <= N <= 100) and mute status (muted or unmuted).
 */
public class AudioStatus {
    public static final int MAX_VOLUME = 100;
    public static final int MIN_VOLUME = 0;

    int mVolume;
    boolean mMute;

    public AudioStatus(int volume, boolean mute) {
        mVolume = volume;
        mMute = mute;
    }

    public int getVolume() {
        return mVolume;
    }

    public boolean getMute() {
        return mMute;
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (!(obj instanceof AudioStatus)) {
            return false;
        }

        AudioStatus other = (AudioStatus) obj;
        return mVolume == other.mVolume
                && mMute == other.mMute;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mVolume, mMute);
    }

    @Override
    public String toString() {
        return "AudioStatus mVolume:" + mVolume + " mMute:" + mMute;
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ final class Constants {
            MESSAGE_SYSTEM_AUDIO_MODE_REQUEST,
            MESSAGE_GIVE_AUDIO_STATUS,
            MESSAGE_SET_SYSTEM_AUDIO_MODE,
            MESSAGE_SET_AUDIO_VOLUME_LEVEL,
            MESSAGE_REPORT_AUDIO_STATUS,
            MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS,
            MESSAGE_SYSTEM_AUDIO_MODE_STATUS,
@@ -197,9 +198,9 @@ final class Constants {
    static final int MESSAGE_SYSTEM_AUDIO_MODE_REQUEST = 0x70;
    static final int MESSAGE_GIVE_AUDIO_STATUS = 0x71;
    static final int MESSAGE_SET_SYSTEM_AUDIO_MODE = 0x72;
    static final int MESSAGE_SET_AUDIO_VOLUME_LEVEL = 0x73;
    static final int MESSAGE_REPORT_AUDIO_STATUS = 0x7A;
    static final int MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D;
    static final int MESSAGE_SET_AUDIO_VOLUME_LEVEL = 0x73;
    static final int MESSAGE_SYSTEM_AUDIO_MODE_STATUS = 0x7E;
    static final int MESSAGE_ROUTING_CHANGE = 0x80;
    static final int MESSAGE_ROUTING_INFORMATION = 0x81;
Loading