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

Commit 4f512fb4 authored by Jinsuk Kim's avatar Jinsuk Kim
Browse files

Add HDMI-CEC service

This CL adds a system service handling HDMI-CEC protocol. The service
is equipped with the capability sending/receiving HDMI-CEC messages

Not all the messages are in place. Currently it has messages to support
a few features only, as follows:

- One touch play
- System information
- Routing control (partially - active source status maintenance only)
- Device OSD transfer
- Power status

It will be extended to cover the wider usages in the follow up CLs.

The CEC standard version referenced in the implementation is 1.3a.

Change-Id: Ifed0b02f52ebf098eddb3bd0987efbf353b7e8fe
parent fd6b9975
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -130,6 +130,8 @@ LOCAL_SRC_FILES += \
	core/java/android/hardware/ISerialManager.aidl \
	core/java/android/hardware/display/IDisplayManager.aidl \
	core/java/android/hardware/display/IDisplayManagerCallback.aidl \
	core/java/android/hardware/hdmi/IHdmiCecListener.aidl \
	core/java/android/hardware/hdmi/IHdmiCecService.aidl \
	core/java/android/hardware/input/IInputManager.aidl \
	core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
	core/java/android/hardware/location/IFusedLocationHardware.aidl \
+48 −0
Original line number Diff line number Diff line
@@ -10898,6 +10898,54 @@ package android.hardware.display {
}
package android.hardware.hdmi {
  public final class HdmiCec {
    method public static java.lang.String getDefaultDeviceName(int);
    method public static int getTypeFromAddress(int);
    method public static boolean isValidAddress(int);
    method public static boolean isValidType(int);
    field public static final int ADDR_AUDIO_SYSTEM = 5; // 0x5
    field public static final int ADDR_BROADCAST = 15; // 0xf
    field public static final int ADDR_FREE_USE = 14; // 0xe
    field public static final int ADDR_INVALID = -1; // 0xffffffff
    field public static final int ADDR_PLAYBACK_1 = 4; // 0x4
    field public static final int ADDR_PLAYBACK_2 = 8; // 0x8
    field public static final int ADDR_PLAYBACK_3 = 11; // 0xb
    field public static final int ADDR_RECORDER_1 = 1; // 0x1
    field public static final int ADDR_RECORDER_2 = 2; // 0x2
    field public static final int ADDR_RECORDER_3 = 9; // 0x9
    field public static final int ADDR_RESERVED_1 = 12; // 0xc
    field public static final int ADDR_RESERVED_2 = 13; // 0xd
    field public static final int ADDR_TUNER_1 = 3; // 0x3
    field public static final int ADDR_TUNER_2 = 6; // 0x6
    field public static final int ADDR_TUNER_3 = 7; // 0x7
    field public static final int ADDR_TUNER_4 = 10; // 0xa
    field public static final int ADDR_TV = 0; // 0x0
    field public static final int ADDR_UNREGISTERED = 15; // 0xf
    field public static final int DEVICE_AUDIO_SYSTEM = 5; // 0x5
    field public static final int DEVICE_INACTIVE = -1; // 0xffffffff
    field public static final int DEVICE_PLAYBACK = 4; // 0x4
    field public static final int DEVICE_RECORDER = 1; // 0x1
    field public static final int DEVICE_RESERVED = 2; // 0x2
    field public static final int DEVICE_TUNER = 3; // 0x3
    field public static final int DEVICE_TV = 0; // 0x0
    field public static final int MESSAGE_ACTIVE_SOURCE = 157; // 0x9d
  }
  public final class HdmiCecMessage implements android.os.Parcelable {
    ctor public HdmiCecMessage(int, int, int, byte[]);
    method public int describeContents();
    method public int getDestination();
    method public int getOpcode();
    method public byte[] getParams();
    method public int getSource();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator CREATOR;
  }
}
package android.hardware.input {
  public final class InputManager {
+190 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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;

/**
 * Defines constants and utility methods related to HDMI-CEC protocol.
 */
public final class HdmiCec {

    /** TV device type. */
    public static final int DEVICE_TV = 0;

    /** Recording device type. */
    public static final int DEVICE_RECORDER = 1;

    /** Device type reserved for future usage. */
    public static final int DEVICE_RESERVED = 2;

    /** Tuner device type. */
    public static final int DEVICE_TUNER = 3;

    /** Playback device type. */
    public static final int DEVICE_PLAYBACK = 4;

    /** Audio system device type. */
    public static final int DEVICE_AUDIO_SYSTEM = 5;

    // Value indicating the device is not an active source.
    public static final int DEVICE_INACTIVE = -1;

    /** Logical address for TV */
    public static final int ADDR_TV = 0;

    /** Logical address for recorder 1 */
    public static final int ADDR_RECORDER_1 = 1;

    /** Logical address for recorder 2 */
    public static final int ADDR_RECORDER_2 = 2;

    /** Logical address for tuner 1 */
    public static final int ADDR_TUNER_1 = 3;

    /** Logical address for playback 1 */
    public static final int ADDR_PLAYBACK_1 = 4;

    /** Logical address for audio system */
    public static final int ADDR_AUDIO_SYSTEM = 5;

    /** Logical address for tuner 2 */
    public static final int ADDR_TUNER_2 = 6;

    /** Logical address for tuner 3 */
    public static final int ADDR_TUNER_3 = 7;

    /** Logical address for playback 2 */
    public static final int ADDR_PLAYBACK_2 = 8;

    /** Logical address for recorder 3 */
    public static final int ADDR_RECORDER_3 = 9;

    /** Logical address for tuner 4 */
    public static final int ADDR_TUNER_4 = 10;

    /** Logical address for playback 3 */
    public static final int ADDR_PLAYBACK_3 = 11;

    /** Logical address reserved for future usage */
    public static final int ADDR_RESERVED_1 = 12;

    /** Logical address reserved for future usage */
    public static final int ADDR_RESERVED_2 = 13;

    /** Logical address for TV other than the one assigned with {@link #ADDR_TV} */
    public static final int ADDR_FREE_USE = 14;

    /** Logical address for devices to which address cannot be allocated */
    public static final int ADDR_UNREGISTERED = 15;

    /** Logical address used in the destination address field for broadcast messages */
    public static final int ADDR_BROADCAST = 15;

    /** Logical address used to indicate it is not initialized or invalid. */
    public static final int ADDR_INVALID = -1;

    // TODO: Complete the list of CEC messages definition.
    public static final int MESSAGE_ACTIVE_SOURCE = 0x9D;

    private static final int[] ADDRESS_TO_TYPE = {
        DEVICE_TV,  // ADDR_TV
        DEVICE_RECORDER,  // ADDR_RECORDER_1
        DEVICE_RECORDER,  // ADDR_RECORDER_2
        DEVICE_TUNER,  // ADDR_TUNER_1
        DEVICE_PLAYBACK,  // ADDR_PLAYBACK_1
        DEVICE_AUDIO_SYSTEM,  // ADDR_AUDIO_SYSTEM
        DEVICE_TUNER,  // ADDR_TUNER_2
        DEVICE_TUNER,  // ADDR_TUNER_3
        DEVICE_PLAYBACK,  // ADDR_PLAYBACK_2
        DEVICE_RECORDER,  // ADDR_RECORDER_3
        DEVICE_TUNER,  // ADDR_TUNER_4
        DEVICE_PLAYBACK,  // ADDR_PLAYBACK_3
    };

    private static final String[] DEFAULT_NAMES = {
        "TV",
        "Recorder_1",
        "Recorder_2",
        "Tuner_1",
        "Playback_1",
        "AudioSystem",
        "Tuner_2",
        "Tuner_3",
        "Playback_2",
        "Recorder_3",
        "Tuner_4",
        "Playback_3",
    };

    private HdmiCec() { }  // Prevents instantiation.

    /**
     * Check if the given type is valid. A valid type is one of the actual
     * logical device types defined in the standard ({@link #DEVICE_TV},
     * {@link #DEVICE_PLAYBACK}, {@link #DEVICE_TUNER}, {@link #DEVICE_RECORDER},
     * and {@link #DEVICE_AUDIO_SYSTEM}).
     *
     * @param type device type
     * @return true if the given type is valid
     */
    public static boolean isValidType(int type) {
        return (DEVICE_TV <= type && type <= DEVICE_AUDIO_SYSTEM)
                && type != DEVICE_RESERVED;
    }

    /**
     * Check if the given logical address is valid. A logical address is valid
     * if it is one allocated for an actual device which allows communication
     * with other logical devices.
     *
     * @param address logical address
     * @return true if the given address is valid
     */
    public static boolean isValidAddress(int address) {
        // TODO: We leave out the address 'free use(14)' for now. Check this later
        //       again to make sure it is a valid address for communication.
        return (ADDR_TV <= address && address <= ADDR_PLAYBACK_3);
    }

    /**
     * Return the device type for the given logical address.
     *
     * @param address logical address
     * @return device type for the given logical address; DEVICE_INACTIVE
     *         if the address is not valid.
     */
    public static int getTypeFromAddress(int address) {
        if (isValidAddress(address)) {
            return ADDRESS_TO_TYPE[address];
        }
        return DEVICE_INACTIVE;
    }

    /**
     * Return the default device name for a logical address. This is the name
     * by which the logical device is known to others until a name is
     * set explicitly using HdmiCecService.setOsdName.
     *
     * @param address logical address
     * @return default device name; empty string if the address is not valid
     */
    public static String getDefaultDeviceName(int address) {
        if (isValidAddress(address)) {
            return DEFAULT_NAMES[address];
        }
        return "";
    }
}
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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;

parcelable HdmiCecMessage;
+145 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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.os.Parcel;
import android.os.Parcelable;

import java.util.Arrays;

/**
 * A class to encapsulate HDMI-CEC message used for the devices connected via
 * HDMI cable to communicate with one another. A message is defined by its
 * source and destination address, command (or opcode), and optional parameters.
 */
public final class HdmiCecMessage implements Parcelable {

    private static final int MAX_MESSAGE_LENGTH = 16;

    private final int mSource;
    private final int mDestination;

    private final int mOpcode;
    private final byte[] mParams;

    /**
     * Constructor.
     */
    public HdmiCecMessage(int source, int destination, int opcode, byte[] params) {
        mSource = source;
        mDestination = destination;
        mOpcode = opcode;
        mParams = Arrays.copyOf(params, params.length);
    }

    /**
     * Return the source address field of the message. It is the logical address
     * of the device which generated the message.
     *
     * @return source address
     */
    public int getSource() {
        return mSource;
    }

    /**
     * Return the destination address field of the message. It is the logical address
     * of the device to which the message is sent.
     *
     * @return destination address
     */
    public int getDestination() {
        return mDestination;
    }

    /**
     * Return the opcode field of the message. It is the type of the message that
     * tells the destination device what to do.
     *
     * @return opcode
     */
    public int getOpcode() {
        return mOpcode;
    }

    /**
     * Return the parameter field of the message. The contents of parameter varies
     * from opcode to opcode, and is used together with opcode to describe
     * the action for the destination device to take.
     *
     * @return parameter
     */
    public byte[] getParams() {
        return mParams;
    }

    /**
     * Describe the kinds of special objects contained in this Parcelable's
     * marshalled representation.
     */
    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * Flatten this object in to a Parcel.
     *
     * @param dest The Parcel in which the object should be written.
     * @param flags Additional flags about how the object should be written.
     *        May be 0 or {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE}.
     */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mSource);
        dest.writeInt(mDestination);
        dest.writeInt(mOpcode);
        dest.writeInt(mParams.length);
        dest.writeByteArray(mParams);
    }

    public static final Parcelable.Creator<HdmiCecMessage> CREATOR
            = new Parcelable.Creator<HdmiCecMessage>() {
        /**
         * Rebuild a HdmiCecMessage previously stored with writeToParcel().
         * @param p HdmiCecMessage object to read the Rating from
         * @return a new HdmiCecMessage created from the data in the parcel
         */
        public HdmiCecMessage createFromParcel(Parcel p) {
            int source = p.readInt();
            int destination = p.readInt();
            int opcode = p.readInt();
            byte[] params = new byte[p.readInt()];
            p.readByteArray(params);
            return new HdmiCecMessage(source, destination, opcode, params);
        }
        public HdmiCecMessage[] newArray(int size) {
            return new HdmiCecMessage[size];
        }
    };

    @Override
    public String toString() {
        StringBuffer s = new StringBuffer();
        s.append(String.format("src: %d dst: %d op: %2X params: ", mSource, mDestination, mOpcode));
        for (byte data : mParams) {
            s.append(String.format("%02X ", data));
        }
        return s.toString();
    }
}
Loading