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

Commit 0e7175db authored by Madhava Srinivasan's avatar Madhava Srinivasan Committed by android-build-merger
Browse files

Merge "Honor HDMI_CONTROL_ENABLED setting in AudioService" am: 4efb0c51

am: a40f432a

Change-Id: Ia4c92888f5ddc2e01a8b9025bdec0b00afb8c539
parents 63522e8f a40f432a
Loading
Loading
Loading
Loading
+91 −0
Original line number Diff line number Diff line
@@ -684,6 +684,28 @@ public final class HdmiControlManager {
    private final ArrayMap<HotplugEventListener, IHdmiHotplugEventListener>
            mHotplugEventListeners = new ArrayMap<>();

    /**
     * Listener used to get HDMI Control (CEC) status (enabled/disabled) and the connected display
     * status.
     * @hide
     */
    public interface HdmiControlStatusChangeListener {
        /**
         * Called when HDMI Control (CEC) is enabled/disabled.
         *
         * @param isCecEnabled status of HDMI Control
         * {@link android.provider.Settings.Global#HDMI_CONTROL_ENABLED}: {@code true} if enabled.
         * @param isCecAvailable status of CEC support of the connected display (the TV).
         * {@code true} if supported.
         *
         * Note: Value of isCecAvailable is only valid when isCecEnabled is true.
         **/
        void onStatusChange(boolean isCecEnabled, boolean isCecAvailable);
    }

    private final ArrayMap<HdmiControlStatusChangeListener, IHdmiControlStatusChangeListener>
            mHdmiControlStatusChangeListeners = new ArrayMap<>();

    /**
     * Listener used to get vendor-specific commands.
     */
@@ -777,4 +799,73 @@ public final class HdmiControlManager {
            }
        };
    }

    /**
     * Adds a listener to get informed of {@link HdmiControlStatusChange}.
     *
     * <p>To stop getting the notification,
     * use {@link #removeHdmiControlStatusChangeListener(HdmiControlStatusChangeListener)}.
     *
     * @param listener {@link HdmiControlStatusChangeListener} instance
     * @see HdmiControlManager#removeHdmiControlStatusChangeListener(
     * HdmiControlStatusChangeListener)
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
    public void addHdmiControlStatusChangeListener(HdmiControlStatusChangeListener listener) {
        if (mService == null) {
            Log.e(TAG, "HdmiControlService is not available");
            return;
        }
        if (mHdmiControlStatusChangeListeners.containsKey(listener)) {
            Log.e(TAG, "listener is already registered");
            return;
        }
        IHdmiControlStatusChangeListener wrappedListener =
                getHdmiControlStatusChangeListenerWrapper(listener);
        mHdmiControlStatusChangeListeners.put(listener, wrappedListener);
        try {
            mService.addHdmiControlStatusChangeListener(wrappedListener);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Removes a listener to stop getting informed of {@link HdmiControlStatusChange}.
     *
     * @param listener {@link HdmiControlStatusChangeListener} instance to be removed
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
    public void removeHdmiControlStatusChangeListener(HdmiControlStatusChangeListener listener) {
        if (mService == null) {
            Log.e(TAG, "HdmiControlService is not available");
            return;
        }
        IHdmiControlStatusChangeListener wrappedListener =
                mHdmiControlStatusChangeListeners.remove(listener);
        if (wrappedListener == null) {
            Log.e(TAG, "tried to remove not-registered listener");
            return;
        }
        try {
            mService.removeHdmiControlStatusChangeListener(wrappedListener);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private IHdmiControlStatusChangeListener getHdmiControlStatusChangeListenerWrapper(
            final HdmiControlStatusChangeListener listener) {
        return new IHdmiControlStatusChangeListener.Stub() {
            @Override
            public void onStatusChange(boolean isCecEnabled, boolean isCecAvailable) {
                listener.onStatusChange(isCecEnabled, isCecAvailable);
            }
        };
    }

}
+3 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.hardware.hdmi;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.hdmi.IHdmiControlStatusChangeListener;
import android.hardware.hdmi.IHdmiDeviceEventListener;
import android.hardware.hdmi.IHdmiHotplugEventListener;
import android.hardware.hdmi.IHdmiInputChangeListener;
@@ -41,6 +42,8 @@ interface IHdmiControlService {
    HdmiDeviceInfo getActiveSource();
    void oneTouchPlay(IHdmiControlCallback callback);
    void queryDisplayStatus(IHdmiControlCallback callback);
    void addHdmiControlStatusChangeListener(IHdmiControlStatusChangeListener listener);
    void removeHdmiControlStatusChangeListener(IHdmiControlStatusChangeListener listener);
    void addHotplugEventListener(IHdmiHotplugEventListener listener);
    void removeHotplugEventListener(IHdmiHotplugEventListener listener);
    void addDeviceEventListener(IHdmiDeviceEventListener listener);
+40 −0
Original line number 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 android.hardware.hdmi;

import android.hardware.hdmi.HdmiDeviceInfo;

/**
 * Callback interface definition for HDMI client to get informed of
 * the CEC availability change event.
 *
 * @hide
 */
oneway interface IHdmiControlStatusChangeListener {

    /**
     * Called when HDMI Control (CEC) is enabled/disabled.
     *
     * @param isCecEnabled status of HDMI Control
     * {@link android.provider.Settings.Global#HDMI_CONTROL_ENABLED}: {@code true} if enabled.
     * @param isCecAvailable status of CEC support of the connected display (the TV).
     * {@code true} if supported.
     *
     * Note: Value of isCecAvailable is only valid when isCecEnabled is true.
     **/
    void onStatusChange(boolean isCecEnabled, boolean isCecAvailable);
}
+10 −0
Original line number Diff line number Diff line
@@ -193,6 +193,16 @@ public class HdmiAudioSystemClientTest {
        public void queryDisplayStatus(final IHdmiControlCallback callback) {
        }

        @Override
        public void addHdmiControlStatusChangeListener(
                final IHdmiControlStatusChangeListener listener) {
        }

        @Override
        public void removeHdmiControlStatusChangeListener(
                final IHdmiControlStatusChangeListener listener) {
        }

        @Override
        public void addHotplugEventListener(final IHdmiHotplugEventListener listener) {
        }
+37 −27
Original line number Diff line number Diff line
@@ -845,7 +845,12 @@ public class AudioService extends IAudioService.Stub

        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
            synchronized (mHdmiClientLock) {
                mHdmiCecSink = false;
                mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
                if (mHdmiManager != null) {
                    mHdmiManager.addHdmiControlStatusChangeListener(
                            mHdmiControlStatusChangeListenerCallback);
                }
                mHdmiTvClient = mHdmiManager.getTvClient();
                if (mHdmiTvClient != null) {
                    mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
@@ -856,7 +861,6 @@ public class AudioService extends IAudioService.Stub
                    mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
                    mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
                }
                mHdmiCecSink = false;
                mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
            }
        }
@@ -1113,8 +1117,7 @@ public class AudioService extends IAudioService.Stub
                checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, caller);
                synchronized (mHdmiClientLock) {
                    if (mHdmiManager != null && mHdmiPlaybackClient != null) {
                        mHdmiCecSink = false;
                        mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
                        updateHdmiCecSinkLocked(mHdmiCecSink | false);
                    }
                }
            }
@@ -1124,7 +1127,7 @@ public class AudioService extends IAudioService.Stub
            if (isPlatformTelevision()) {
                synchronized (mHdmiClientLock) {
                    if (mHdmiManager != null) {
                        mHdmiCecSink = false;
                        updateHdmiCecSinkLocked(mHdmiCecSink | false);
                    }
                }
            }
@@ -5774,12 +5777,9 @@ public class AudioService extends IAudioService.Stub
    //     are transformed into key events for the HDMI playback client.
    //==========================================================================================

    private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
        public void onComplete(int status) {
            synchronized (mHdmiClientLock) {
                if (mHdmiManager != null) {
                    mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
                    // Television devices without CEC service apply software volume on HDMI output
    @GuardedBy("mHdmiClientLock")
    private void updateHdmiCecSinkLocked(boolean hdmiCecSink) {
        mHdmiCecSink = hdmiCecSink;
        if (mHdmiCecSink) {
            if (DEBUG_VOL) {
                Log.d(TAG, "CEC sink: setting HDMI as full vol device");
@@ -5793,12 +5793,20 @@ public class AudioService extends IAudioService.Stub
            // HDMI output
            mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
        }

        checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI,
                "HdmiPlaybackClient.DisplayStatusCallback");
    }

    private class MyHdmiControlStatusChangeListenerCallback
            implements HdmiControlManager.HdmiControlStatusChangeListener {
        public void onStatusChange(boolean isCecEnabled, boolean isCecAvailable) {
            synchronized (mHdmiClientLock) {
                if (mHdmiManager == null) return;
                updateHdmiCecSinkLocked(isCecEnabled ? isCecAvailable : false);
            }
        }
    }
    };

    private final Object mHdmiClientLock = new Object();

@@ -5815,12 +5823,14 @@ public class AudioService extends IAudioService.Stub
    @GuardedBy("mHdmiClientLock")
    private HdmiPlaybackClient mHdmiPlaybackClient;
    // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
    @GuardedBy("mHdmiClientLock")
    private boolean mHdmiCecSink;
    // Set only when device is an audio system.
    @GuardedBy("mHdmiClientLock")
    private HdmiAudioSystemClient mHdmiAudioSystemClient;

    private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
    private MyHdmiControlStatusChangeListenerCallback mHdmiControlStatusChangeListenerCallback =
            new MyHdmiControlStatusChangeListenerCallback();

    @Override
    public int setHdmiSystemAudioSupported(boolean on) {
Loading