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

Commit 9444cdd8 authored by Amy's avatar Amy
Browse files

Unhide APIs of Android HDMI Framework for Q.

Test: manual
Bug: 110094868
Change-Id: I4f8d992a1dc7be7e52710153d5d093ca2b82abd6
parent b17eb4a7
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -1810,9 +1810,15 @@ package android.hardware.hdmi {
  public final class HdmiControlManager {
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void addHotplugEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
    method @Nullable public android.hardware.hdmi.HdmiClient getClient(int);
    method @Nullable public java.util.List<android.hardware.hdmi.HdmiDeviceInfo> getConnectedDevicesList();
    method public int getPhysicalAddress();
    method @Nullable public android.hardware.hdmi.HdmiPlaybackClient getPlaybackClient();
    method @Nullable public android.hardware.hdmi.HdmiSwitchClient getSwitchClient();
    method @Nullable public android.hardware.hdmi.HdmiTvClient getTvClient();
    method public boolean isRemoteDeviceConnected(android.hardware.hdmi.HdmiDeviceInfo);
    method public void powerOffRemoteDevice(android.hardware.hdmi.HdmiDeviceInfo);
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void removeHotplugEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
    method public void requestRemoteDeviceToBecomeActiveSource(android.hardware.hdmi.HdmiDeviceInfo);
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setStandbyMode(boolean);
    field public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE";
    field public static final int AVR_VOLUME_MUTED = 101; // 0x65
@@ -1902,6 +1908,9 @@ package android.hardware.hdmi {
    field public static final int TIMER_STATUS_PROGRAMMED_INFO_NO_MEDIA_INFO = 10; // 0xa
  }
  @IntDef({android.hardware.hdmi.HdmiControlManager.RESULT_SUCCESS, android.hardware.hdmi.HdmiControlManager.RESULT_TIMEOUT, android.hardware.hdmi.HdmiControlManager.RESULT_SOURCE_NOT_AVAILABLE, android.hardware.hdmi.HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE, android.hardware.hdmi.HdmiControlManager.RESULT_ALREADY_IN_PROGRESS, android.hardware.hdmi.HdmiControlManager.RESULT_EXCEPTION, android.hardware.hdmi.HdmiControlManager.RESULT_INCORRECT_MODE, android.hardware.hdmi.HdmiControlManager.RESULT_COMMUNICATION_FAILED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public static @interface HdmiControlManager.ControlCallbackResult {
  }
  public static interface HdmiControlManager.HotplugEventListener {
    method public void onReceived(android.hardware.hdmi.HdmiHotplugEvent);
  }
@@ -2028,6 +2037,16 @@ package android.hardware.hdmi {
  public abstract static class HdmiRecordSources.RecordSource {
  }
  public class HdmiSwitchClient extends android.hardware.hdmi.HdmiClient {
    method public int getDeviceType();
    method public void selectPort(int, @NonNull android.hardware.hdmi.HdmiSwitchClient.OnSelectListener);
    method public void selectPort(int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.hdmi.HdmiSwitchClient.OnSelectListener);
  }
  public static interface HdmiSwitchClient.OnSelectListener {
    method public void onSelect(@android.hardware.hdmi.HdmiControlManager.ControlCallbackResult int);
  }
  public class HdmiTimerRecordSources {
    method public static boolean checkTimerRecordSource(int, byte[]);
    method public static android.hardware.hdmi.HdmiTimerRecordSources.Duration durationOf(int, int);
+58 −21
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.hardware.hdmi;

import static com.android.internal.os.RoSystemProperties.PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
@@ -33,6 +34,8 @@ import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.Log;

import com.android.internal.util.Preconditions;

import java.util.List;

/**
@@ -106,9 +109,24 @@ public final class HdmiControlManager {
    public static final int POWER_STATUS_TRANSIENT_TO_ON = 2;
    public static final int POWER_STATUS_TRANSIENT_TO_STANDBY = 3;

    @IntDef ({
        RESULT_SUCCESS,
        RESULT_TIMEOUT,
        RESULT_SOURCE_NOT_AVAILABLE,
        RESULT_TARGET_NOT_AVAILABLE,
        RESULT_ALREADY_IN_PROGRESS,
        RESULT_EXCEPTION,
        RESULT_INCORRECT_MODE,
        RESULT_COMMUNICATION_FAILED,
    })
    public @interface ControlCallbackResult {}

    /** Control operation is successfully handled by the framework. */
    public static final int RESULT_SUCCESS = 0;
    public static final int RESULT_TIMEOUT = 1;
    /** Source device that the application is using is not available. */
    public static final int RESULT_SOURCE_NOT_AVAILABLE = 2;
    /** Target device that the application is controlling is not available. */
    public static final int RESULT_TARGET_NOT_AVAILABLE = 3;

    @Deprecated public static final int RESULT_ALREADY_IN_PROGRESS = 4;
@@ -394,16 +412,15 @@ public final class HdmiControlManager {
    /**
     * Gets an object that represents an HDMI-CEC logical device of type switch on the system.
     *
     * <p>Used to send HDMI control messages to other devices like TV through HDMI bus. It is also
     * possible to communicate with other logical devices hosted in the same system if the system is
     * configured to host more than one type of HDMI-CEC logical devices.
     * <p>Used to send HDMI control messages to other devices (e.g. TVs) through HDMI bus.
     * It is also possible to communicate with other logical devices hosted in the same
     * system if the system is configured to host more than one type of HDMI-CEC logical device.
     *
     * @return {@link HdmiSwitchClient} instance. {@code null} on failure.
     *
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    @Nullable
    @SystemApi
    @SuppressLint("Doclava125")
    public HdmiSwitchClient getSwitchClient() {
        return (HdmiSwitchClient) getClient(HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH);
@@ -412,11 +429,15 @@ public final class HdmiControlManager {
    /**
     * Get a snapshot of the real-time status of the remote devices.
     *
     * @return a list of {@link HdmiDeviceInfo} of the devices connected to the current device.
     * <p>This only applies to devices with multiple HDMI inputs.
     *
     * @return a list of {@link HdmiDeviceInfo} of the connected CEC devices. An empty
     * list will be returned if there is none.
     *
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    @SystemApi
    @Nullable
    public List<HdmiDeviceInfo> getConnectedDevicesList() {
        try {
            return mService.getDeviceList();
@@ -426,14 +447,17 @@ public final class HdmiControlManager {
    }

    /**
     * Power off the target device.
     * Power off the target device by sending CEC commands.
     *
     * @param deviceInfo HdmiDeviceInfo of the device to be powered off
     * <p>The target device info can be obtained by calling {@link #getConnectedDevicesList()}.
     *
     * @param deviceInfo {@link HdmiDeviceInfo} of the device to be powered off.
     *
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    @SystemApi
    public void powerOffRemoteDevice(HdmiDeviceInfo deviceInfo) {
        Preconditions.checkNotNull(deviceInfo);
        try {
            mService.powerOffRemoteDevice(
                    deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
@@ -443,14 +467,16 @@ public final class HdmiControlManager {
    }

    /**
     * Power on the target device.
     * Power on the target device by sending CEC commands.
     *
     * @param deviceInfo HdmiDeviceInfo of the device to be powered on
     * <p>The target device info can be obtained by calling {@link #getConnectedDevicesList()}.
     *
     * @param deviceInfo {@link HdmiDeviceInfo} of the device to be powered on.
     *
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public void powerOnRemoteDevice(HdmiDeviceInfo deviceInfo) {
        Preconditions.checkNotNull(deviceInfo);
        try {
            mService.powerOnRemoteDevice(
                    deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
@@ -460,14 +486,17 @@ public final class HdmiControlManager {
    }

    /**
     * Ask the target device to be the new Active Source.
     * Request the target device to be the new Active Source by sending CEC commands.
     *
     * <p>The target device info can be obtained by calling {@link #getConnectedDevicesList()}.
     *
     * @param deviceInfo HdmiDeviceInfo of the target device
     *
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public void askRemoteDeviceToBecomeActiveSource(HdmiDeviceInfo deviceInfo) {
    @SystemApi
    public void requestRemoteDeviceToBecomeActiveSource(HdmiDeviceInfo deviceInfo) {
        Preconditions.checkNotNull(deviceInfo);
        try {
            mService.askRemoteDeviceToBecomeActiveSource(deviceInfo.getPhysicalAddress());
        } catch (RemoteException e) {
@@ -506,8 +535,13 @@ public final class HdmiControlManager {
    /**
     * Get the physical address of the device.
     *
     * <p>Physical address needs to be automatically adjusted when devices are phyiscally or
     * electrically added or removed from the device tree. Please see HDMI Specification Version
     * 1.4b 8.7 Physical Address for more details on the address discovery proccess.
     *
     * @hide
     */
    @SystemApi
    public int getPhysicalAddress() {
        if (mPhysicalAddress != INVALID_PHYSICAL_ADDRESS) {
            return mPhysicalAddress;
@@ -521,16 +555,19 @@ public final class HdmiControlManager {
    }

    /**
     * Check if the target device is connected to the current device. The
     * API also returns true if the current device is the target.
     * Check if the target remote device is connected to the current device.
     *
     * <p>The API also returns true if the current device is the target.
     *
     * @param targetDevice {@link HdmiDeviceInfo} of the target device.
     * @return true if {@code device} is directly or indirectly connected to the
     * @return true if {@code targetDevice} is directly or indirectly
     * connected to the current device.
     *
     * TODO(b/110094868): unhide for Q
     * @hide
     */
    public boolean isTargetDeviceConnected(HdmiDeviceInfo targetDevice) {
    @SystemApi
    public boolean isRemoteDeviceConnected(HdmiDeviceInfo targetDevice) {
        Preconditions.checkNotNull(targetDevice);
        mPhysicalAddress = getPhysicalAddress();
        if (mPhysicalAddress == INVALID_PHYSICAL_ADDRESS) {
            return false;
+96 −32
Original line number Diff line number Diff line
@@ -15,24 +15,30 @@
 */
package android.hardware.hdmi;

import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.hardware.hdmi.HdmiControlManager.ControlCallbackResult;
import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.util.Preconditions;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * HdmiSwitchClient represents HDMI-CEC logical device of type Switch in the Android system which
 * acts as switch.
 * An {@code HdmiSwitchClient} represents a HDMI-CEC switch device.
 *
 * <p>HdmiSwitchClient has a CEC device type of HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH,
 * but it is used by all Android TV devices that have multiple HDMI inputs,
 * even if it is not a "pure" swicth and has another device type like TV or Player.
 * <p>HdmiSwitchClient has a CEC device type of HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH, but it is
 * used by all Android devices that have multiple HDMI inputs, even if it is not a "pure" swicth
 * and has another device type like TV or Player.
 *
 * @hide
 * TODO(b/110094868): unhide and add @SystemApi for Q
 */
@SystemApi
public class HdmiSwitchClient extends HdmiClient {

    private static final String TAG = "HdmiSwitchClient";
@@ -41,17 +47,15 @@ public class HdmiSwitchClient extends HdmiClient {
        super(service);
    }

    private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) {
    private static IHdmiControlCallback getCallbackWrapper(final OnSelectListener listener) {
        return new IHdmiControlCallback.Stub() {
            @Override
            public void onComplete(int result) {
                callback.onComplete(result);
                listener.onSelect(result);
            }
        };
    }

    /** @hide */
    // TODO(b/110094868): unhide for Q
    @Override
    public int getDeviceType() {
        return HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH;
@@ -61,20 +65,17 @@ public class HdmiSwitchClient extends HdmiClient {
     * Selects a CEC logical device to be a new active source.
     *
     * @param logicalAddress logical address of the device to select
     * @param callback callback to get the result with
     * @throws {@link IllegalArgumentException} if the {@code callback} is null
     * @param listener listener to get the result with
     *
     * @hide
     * TODO(b/110094868): unhide and add @SystemApi for Q
     */
    public void deviceSelect(int logicalAddress, @NonNull SelectCallback callback) {
        if (callback == null) {
            throw new IllegalArgumentException("callback must not be null.");
        }
    public void selectDevice(int logicalAddress, @NonNull OnSelectListener listener) {
        Preconditions.checkNotNull(listener);
        try {
            mService.deviceSelect(logicalAddress, getCallbackWrapper(callback));
            mService.deviceSelect(logicalAddress, getCallbackWrapper(listener));
        } catch (RemoteException e) {
            Log.e(TAG, "failed to select device: ", e);
            throw e.rethrowFromSystemServer();
        }
    }

@@ -82,20 +83,83 @@ public class HdmiSwitchClient extends HdmiClient {
     * Selects a HDMI port to be a new route path.
     *
     * @param portId HDMI port to select
     * @param callback callback to get the result with
     * @throws {@link IllegalArgumentException} if the {@code callback} is null
     * @see {@link android.media.tv.TvInputHardwareInfo#getHdmiPortId()}
     *     to get portId of a specific TV Input.
     * @param listener listener to get the result with
     *
     * @hide
     * TODO(b/110094868): unhide and add @SystemApi for Q
     */
    public void portSelect(int portId, @NonNull SelectCallback callback) {
        if (callback == null) {
            throw new IllegalArgumentException("Callback must not be null");
    @SystemApi
    public void selectPort(int portId, @NonNull OnSelectListener listener) {
        Preconditions.checkNotNull(listener);
        try {
            mService.portSelect(portId, getCallbackWrapper(listener));
        } catch (RemoteException e) {
            Log.e(TAG, "failed to select port: ", e);
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Selects a CEC logical device to be a new active source.
     *
     * @param logicalAddress logical address of the device to select
     * @param executor executor to allow the develper to specify the thread upon which the listeners
     *     will be invoked
     * @param listener listener to get the result with
     *
     * @hide
     */
    public void selectDevice(
            int logicalAddress,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnSelectListener listener) {
        Preconditions.checkNotNull(listener);
        try {
            mService.portSelect(portId, getCallbackWrapper(callback));
            mService.deviceSelect(logicalAddress,
                    new IHdmiControlCallback.Stub() {
                            @Override
                            public void onComplete(int result) {
                                Binder.withCleanCallingIdentity(
                                        () -> executor.execute(() -> listener.onSelect(result)));
                            }
                    }
            );
        } catch (RemoteException e) {
            Log.e(TAG, "failed to select device: ", e);
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Selects a HDMI port to be a new route path.
     *
     * @param portId HDMI port to select
     * @param executor executor to allow the develper to specify the thread upon which the listeners
     *     will be invoked
     * @param listener listener to get the result with
     *
     * @hide
     */
    @SystemApi
    public void selectPort(
            int portId,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnSelectListener listener) {
        Preconditions.checkNotNull(listener);
        try {
            mService.portSelect(portId,
                    new IHdmiControlCallback.Stub() {
                            @Override
                            public void onComplete(int result) {
                                Binder.withCleanCallingIdentity(
                                        () -> executor.execute(() -> listener.onSelect(result)));
                            }
                    }
            );
        } catch (RemoteException e) {
            Log.e(TAG, "failed to select port: ", e);
            throw e.rethrowFromSystemServer();
        }
    }

@@ -108,7 +172,6 @@ public class HdmiSwitchClient extends HdmiClient {
     *     there is none.
     *
     * @hide
     * TODO(b/110094868): unhide and add @SystemApi for Q
     */
    public List<HdmiDeviceInfo> getDeviceList() {
        try {
@@ -120,18 +183,19 @@ public class HdmiSwitchClient extends HdmiClient {
    }

    /**
     * Callback interface used to get the result of {@link #deviceSelect} or {@link #portSelect}.
     * Listener interface used to get the result of {@link #deviceSelect} or {@link #portSelect}.
     *
     * @hide
     * TODO(b/110094868): unhide and add @SystemApi for Q
     */
    public interface SelectCallback {
    @SystemApi
    public interface OnSelectListener {

        /**
         * Called when the operation is finished.
         *
         * @param result the result value of {@link #deviceSelect} or {@link #portSelect}.
         * @param result callback result.
         * @see {@link ControlCallbackResult}
         */
        void onComplete(int result);
        void onSelect(@ControlCallbackResult int result);
    }
}