1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.media.tv;
18
19import static java.lang.annotation.RetentionPolicy.SOURCE;
20
21import android.annotation.IntDef;
22import android.annotation.SystemApi;
23import android.hardware.tv.input.V1_0.Constants;
24import android.media.AudioManager;
25import android.os.Parcel;
26import android.os.Parcelable;
27import android.util.Log;
28import java.lang.annotation.Retention;
29
30/**
31 * Simple container for information about TV input hardware.
32 * Not for third-party developers.
33 *
34 * @hide
35 */
36@SystemApi
37public final class TvInputHardwareInfo implements Parcelable {
38    static final String TAG = "TvInputHardwareInfo";
39
40    // Match hardware/libhardware/include/hardware/tv_input.h
41    public static final int TV_INPUT_TYPE_OTHER_HARDWARE = Constants.TV_INPUT_TYPE_OTHER;
42    public static final int TV_INPUT_TYPE_TUNER          = Constants.TV_INPUT_TYPE_TUNER;
43    public static final int TV_INPUT_TYPE_COMPOSITE      = Constants.TV_INPUT_TYPE_COMPOSITE;
44    public static final int TV_INPUT_TYPE_SVIDEO         = Constants.TV_INPUT_TYPE_SVIDEO;
45    public static final int TV_INPUT_TYPE_SCART          = Constants.TV_INPUT_TYPE_SCART;
46    public static final int TV_INPUT_TYPE_COMPONENT      = Constants.TV_INPUT_TYPE_COMPONENT;
47    public static final int TV_INPUT_TYPE_VGA            = Constants.TV_INPUT_TYPE_VGA;
48    public static final int TV_INPUT_TYPE_DVI            = Constants.TV_INPUT_TYPE_DVI;
49    public static final int TV_INPUT_TYPE_HDMI           = Constants.TV_INPUT_TYPE_HDMI;
50    public static final int TV_INPUT_TYPE_DISPLAY_PORT   = Constants.TV_INPUT_TYPE_DISPLAY_PORT;
51
52    /** @hide */
53    @Retention(SOURCE)
54    @IntDef({CABLE_CONNECTION_STATUS_UNKNOWN, CABLE_CONNECTION_STATUS_CONNECTED,
55        CABLE_CONNECTION_STATUS_DISCONNECTED})
56    public @interface CableConnectionStatus {}
57
58    // Match hardware/interfaces/tv/input/1.0/types.hal
59    /**
60     * The hardware is unsure about the connection status or does not support cable detection.
61     */
62    public static final int CABLE_CONNECTION_STATUS_UNKNOWN =
63            Constants.CABLE_CONNECTION_STATUS_UNKNOWN;
64
65    /**
66     * Cable is connected to the hardware.
67     */
68    public static final int CABLE_CONNECTION_STATUS_CONNECTED =
69            Constants.CABLE_CONNECTION_STATUS_CONNECTED;
70
71    /**
72     * Cable is disconnected to the hardware.
73     */
74    public static final int CABLE_CONNECTION_STATUS_DISCONNECTED =
75            Constants.CABLE_CONNECTION_STATUS_DISCONNECTED;
76
77    public static final Parcelable.Creator<TvInputHardwareInfo> CREATOR =
78            new Parcelable.Creator<TvInputHardwareInfo>() {
79        @Override
80        public TvInputHardwareInfo createFromParcel(Parcel source) {
81            try {
82                TvInputHardwareInfo info = new TvInputHardwareInfo();
83                info.readFromParcel(source);
84                return info;
85            } catch (Exception e) {
86                Log.e(TAG, "Exception creating TvInputHardwareInfo from parcel", e);
87                return null;
88            }
89        }
90
91        @Override
92        public TvInputHardwareInfo[] newArray(int size) {
93            return new TvInputHardwareInfo[size];
94        }
95    };
96
97    private int mDeviceId;
98    private int mType;
99    private int mAudioType;
100    private String mAudioAddress;
101    private int mHdmiPortId;
102    @CableConnectionStatus
103    private int mCableConnectionStatus;
104
105    private TvInputHardwareInfo() {
106    }
107
108    public int getDeviceId() {
109        return mDeviceId;
110    }
111
112    public int getType() {
113        return mType;
114    }
115
116    public int getAudioType() {
117        return mAudioType;
118    }
119
120    public String getAudioAddress() {
121        return mAudioAddress;
122    }
123
124    public int getHdmiPortId() {
125        if (mType != TV_INPUT_TYPE_HDMI) {
126            throw new IllegalStateException();
127        }
128        return mHdmiPortId;
129    }
130
131    /**
132     * Gets the cable connection status of the hardware.
133     *
134     * @return {@code CABLE_CONNECTION_STATUS_CONNECTED} if cable is connected.
135     *         {@code CABLE_CONNECTION_STATUS_DISCONNECTED} if cable is disconnected.
136     *         {@code CABLE_CONNECTION_STATUS_UNKNOWN} if the hardware is unsure about the
137     *         connection status or does not support cable detection.
138     */
139    @CableConnectionStatus
140    public int getCableConnectionStatus() {
141        return mCableConnectionStatus;
142    }
143
144    @Override
145    public String toString() {
146        StringBuilder b = new StringBuilder(128);
147        b.append("TvInputHardwareInfo {id=").append(mDeviceId);
148        b.append(", type=").append(mType);
149        b.append(", audio_type=").append(mAudioType);
150        b.append(", audio_addr=").append(mAudioAddress);
151        if (mType == TV_INPUT_TYPE_HDMI) {
152            b.append(", hdmi_port=").append(mHdmiPortId);
153        }
154        b.append(", cable_connection_status=").append(mCableConnectionStatus);
155        b.append("}");
156        return b.toString();
157    }
158
159    // Parcelable
160    @Override
161    public int describeContents() {
162        return 0;
163    }
164
165    @Override
166    public void writeToParcel(Parcel dest, int flags) {
167        dest.writeInt(mDeviceId);
168        dest.writeInt(mType);
169        dest.writeInt(mAudioType);
170        dest.writeString(mAudioAddress);
171        if (mType == TV_INPUT_TYPE_HDMI) {
172            dest.writeInt(mHdmiPortId);
173        }
174        dest.writeInt(mCableConnectionStatus);
175    }
176
177    public void readFromParcel(Parcel source) {
178        mDeviceId = source.readInt();
179        mType = source.readInt();
180        mAudioType = source.readInt();
181        mAudioAddress = source.readString();
182        if (mType == TV_INPUT_TYPE_HDMI) {
183            mHdmiPortId = source.readInt();
184        }
185        mCableConnectionStatus = source.readInt();
186    }
187
188    public static final class Builder {
189        private Integer mDeviceId = null;
190        private Integer mType = null;
191        private int mAudioType = AudioManager.DEVICE_NONE;
192        private String mAudioAddress = "";
193        private Integer mHdmiPortId = null;
194        private Integer mCableConnectionStatus = CABLE_CONNECTION_STATUS_UNKNOWN;
195
196        public Builder() {
197        }
198
199        public Builder deviceId(int deviceId) {
200            mDeviceId = deviceId;
201            return this;
202        }
203
204        public Builder type(int type) {
205            mType = type;
206            return this;
207        }
208
209        public Builder audioType(int audioType) {
210            mAudioType = audioType;
211            return this;
212        }
213
214        public Builder audioAddress(String audioAddress) {
215            mAudioAddress = audioAddress;
216            return this;
217        }
218
219        public Builder hdmiPortId(int hdmiPortId) {
220            mHdmiPortId = hdmiPortId;
221            return this;
222        }
223
224        /**
225         * Sets cable connection status.
226         */
227        public Builder cableConnectionStatus(@CableConnectionStatus int cableConnectionStatus) {
228            mCableConnectionStatus = cableConnectionStatus;
229            return this;
230        }
231
232        public TvInputHardwareInfo build() {
233            if (mDeviceId == null || mType == null) {
234                throw new UnsupportedOperationException();
235            }
236            if ((mType == TV_INPUT_TYPE_HDMI && mHdmiPortId == null) ||
237                    (mType != TV_INPUT_TYPE_HDMI && mHdmiPortId != null)) {
238                throw new UnsupportedOperationException();
239            }
240
241            TvInputHardwareInfo info = new TvInputHardwareInfo();
242            info.mDeviceId = mDeviceId;
243            info.mType = mType;
244            info.mAudioType = mAudioType;
245            if (info.mAudioType != AudioManager.DEVICE_NONE) {
246                info.mAudioAddress = mAudioAddress;
247            }
248            if (mHdmiPortId != null) {
249                info.mHdmiPortId = mHdmiPortId;
250            }
251            info.mCableConnectionStatus = mCableConnectionStatus;
252            return info;
253        }
254    }
255}
256