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

Commit 0969d6ec authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Unhide APIs of Android HDMI Framework for Q."

parents c8dfe980 9444cdd8
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -1853,9 +1853,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
@@ -1945,6 +1951,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);
  }
@@ -2071,6 +2080,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);
    }
}