Revert "Revert "Add physical TV input handling to TvInputManagerService""

This reverts commit 1940e197a8de186df5edf0b78e0907ae539bd215.

Bug: 14118245, Bug: 15197740
Change-Id: Ia308f16d2ed8ec55112a4d21c180ccb97e8d7c6a
diff --git a/core/java/android/tv/ITvInputHardware.aidl b/core/java/android/tv/ITvInputHardware.aidl
new file mode 100644
index 0000000..7250453
--- /dev/null
+++ b/core/java/android/tv/ITvInputHardware.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.tv;
+
+import android.tv.TvStreamConfig;
+import android.view.KeyEvent;
+import android.view.Surface;
+
+/**
+ * TvInputService representing a physical port should connect to HAL through this interface.
+ * Framework will take care of communication among system services including TvInputManagerService,
+ * HdmiControlService, AudioService, etc.
+ *
+ * @hide
+ */
+interface ITvInputHardware {
+    /**
+     * Make the input render on the surface according to the config. In case of HDMI, this will
+     * trigger CEC commands for adjusting active HDMI source. Returns true on success.
+     */
+    boolean setSurface(in Surface surface, in TvStreamConfig config);
+    /**
+     * Set volume for this stream via AudioGain. (TBD)
+     */
+    void setVolume(float volume);
+
+    /**
+     * Dispatch key event to HDMI service. The events would be automatically converted to
+     * HDMI CEC commands. If the hardware is not representing an HDMI port, this method will fail.
+     */
+    boolean dispatchKeyEventToHdmi(in KeyEvent event);
+}
diff --git a/core/java/android/tv/ITvInputHardwareCallback.aidl b/core/java/android/tv/ITvInputHardwareCallback.aidl
new file mode 100644
index 0000000..83041be
--- /dev/null
+++ b/core/java/android/tv/ITvInputHardwareCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.tv;
+
+import android.tv.TvStreamConfig;
+
+/**
+ * @hide
+ */
+oneway interface ITvInputHardwareCallback {
+    void onReleased();
+    void onStreamConfigChanged(in TvStreamConfig[] configs);
+}
diff --git a/core/java/android/tv/ITvInputManager.aidl b/core/java/android/tv/ITvInputManager.aidl
index b756aba..c6f8d79 100644
--- a/core/java/android/tv/ITvInputManager.aidl
+++ b/core/java/android/tv/ITvInputManager.aidl
@@ -19,7 +19,10 @@
 import android.content.ComponentName;
 import android.graphics.Rect;
 import android.net.Uri;
+import android.tv.ITvInputHardware;
+import android.tv.ITvInputHardwareCallback;
 import android.tv.ITvInputClient;
+import android.tv.TvInputHardwareInfo;
 import android.tv.TvInputInfo;
 import android.view.Surface;
 
@@ -46,4 +49,10 @@
             int userId);
     void relayoutOverlayView(in IBinder sessionToken, in Rect frame, int userId);
     void removeOverlayView(in IBinder sessionToken, int userId);
+
+    // For TV input hardware binding
+    List<TvInputHardwareInfo> getHardwareList();
+    ITvInputHardware acquireTvInputHardware(int deviceId, in ITvInputHardwareCallback callback,
+            int userId);
+    void releaseTvInputHardware(int deviceId, in ITvInputHardware hardware, int userId);
 }
diff --git a/core/java/android/tv/TvInputHardwareInfo.aidl b/core/java/android/tv/TvInputHardwareInfo.aidl
new file mode 100644
index 0000000..484ab60
--- /dev/null
+++ b/core/java/android/tv/TvInputHardwareInfo.aidl
@@ -0,0 +1,20 @@
+/*
+ *
+ * Copyright 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.tv;
+
+parcelable TvInputHardwareInfo;
diff --git a/core/java/android/tv/TvInputHardwareInfo.java b/core/java/android/tv/TvInputHardwareInfo.java
new file mode 100644
index 0000000..b0dc58e
--- /dev/null
+++ b/core/java/android/tv/TvInputHardwareInfo.java
@@ -0,0 +1,93 @@
+/*
+ * 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.tv;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Simple container for information about TV input hardware.
+ * Not for third-party developers.
+ *
+ * @hide
+ */
+public final class TvInputHardwareInfo implements Parcelable {
+    static final String TAG = "TvInputHardwareInfo";
+
+    // Match hardware/libhardware/include/hardware/tv_input.h
+    public static final int TV_INPUT_TYPE_HDMI           = 1;
+    public static final int TV_INPUT_TYPE_BUILT_IN_TUNER = 2;
+    public static final int TV_INPUT_TYPE_PASSTHROUGH    = 3;
+
+    public static final Parcelable.Creator<TvInputHardwareInfo> CREATOR =
+            new Parcelable.Creator<TvInputHardwareInfo>() {
+        @Override
+        public TvInputHardwareInfo createFromParcel(Parcel source) {
+            try {
+                TvInputHardwareInfo info = new TvInputHardwareInfo();
+                info.readFromParcel(source);
+                return info;
+            } catch (Exception e) {
+                Log.e(TAG, "Exception creating TvInputHardwareInfo from parcel", e);
+                return null;
+            }
+        }
+
+        @Override
+        public TvInputHardwareInfo[] newArray(int size) {
+            return new TvInputHardwareInfo[size];
+        }
+    };
+
+    private int mDeviceId;
+    private int mType;
+    // TODO: Add audio port & audio address for audio service.
+    // TODO: Add HDMI handle for HDMI service.
+
+    public TvInputHardwareInfo() { }
+
+    public TvInputHardwareInfo(int deviceId, int type) {
+        mDeviceId = deviceId;
+        mType = type;
+    }
+
+    public int getDeviceId() {
+        return mDeviceId;
+    }
+
+    public int getType() {
+        return mType;
+    }
+
+    // Parcelable
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mDeviceId);
+        dest.writeInt(mType);
+    }
+
+    public void readFromParcel(Parcel source) {
+        mDeviceId = source.readInt();
+        mType = source.readInt();
+    }
+}
diff --git a/core/java/android/tv/TvStreamConfig.aidl b/core/java/android/tv/TvStreamConfig.aidl
new file mode 100644
index 0000000..4d0add4
--- /dev/null
+++ b/core/java/android/tv/TvStreamConfig.aidl
@@ -0,0 +1,20 @@
+/*
+ *
+ * Copyright 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.tv;
+
+parcelable TvStreamConfig;
\ No newline at end of file
diff --git a/core/java/android/tv/TvStreamConfig.java b/core/java/android/tv/TvStreamConfig.java
new file mode 100644
index 0000000..03e63b1
--- /dev/null
+++ b/core/java/android/tv/TvStreamConfig.java
@@ -0,0 +1,157 @@
+/*
+ * 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.tv;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class TvStreamConfig implements Parcelable {
+    static final String TAG = TvStreamConfig.class.getSimpleName();
+
+    public final static int STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE = 1;
+    public final static int STREAM_TYPE_BUFFER_PRODUCER = 2;
+
+    private int mStreamId;
+    private int mType;
+    // TODO: Revisit if max widht/height really make sense.
+    private int mMaxWidth;
+    private int mMaxHeight;
+    /**
+     * Generations are incremented once framework receives STREAM_CONFIGURATION_CHANGED event from
+     * HAL module. Framework should throw away outdated configurations and get new configurations
+     * via tv_input_device::get_stream_configurations().
+     */
+    private int mGeneration;
+
+    public static final Parcelable.Creator<TvStreamConfig> CREATOR =
+            new Parcelable.Creator<TvStreamConfig>() {
+        @Override
+        public TvStreamConfig createFromParcel(Parcel source) {
+            try {
+                return new Builder().
+                        streamId(source.readInt()).
+                        type(source.readInt()).
+                        maxWidth(source.readInt()).
+                        maxHeight(source.readInt()).
+                        generation(source.readInt()).build();
+            } catch (Exception e) {
+                Log.e(TAG, "Exception creating TvStreamConfig from parcel", e);
+                return null;
+            }
+        }
+
+        @Override
+        public TvStreamConfig[] newArray(int size) {
+            return new TvStreamConfig[size];
+        }
+    };
+
+    private TvStreamConfig() {}
+
+    public int getStreamId() {
+        return mStreamId;
+    }
+
+    public int getType() {
+        return mType;
+    }
+
+    public int getMaxWidth() {
+        return mMaxWidth;
+    }
+
+    public int getMaxHeight() {
+        return mMaxHeight;
+    }
+
+    public int getGeneration() {
+        return mGeneration;
+    }
+
+    // Parcelable
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mStreamId);
+        dest.writeInt(mType);
+        dest.writeInt(mMaxWidth);
+        dest.writeInt(mMaxHeight);
+        dest.writeInt(mGeneration);
+    }
+
+    /**
+     * A helper class for creating a TvStreamConfig object.
+     */
+    public static final class Builder {
+        private Integer mStreamId;
+        private Integer mType;
+        private Integer mMaxWidth;
+        private Integer mMaxHeight;
+        private Integer mGeneration;
+
+        public Builder() {
+        }
+
+        public Builder streamId(int streamId) {
+            mStreamId = streamId;
+            return this;
+        }
+
+        public Builder type(int type) {
+            mType = type;
+            return this;
+        }
+
+        public Builder maxWidth(int maxWidth) {
+            mMaxWidth = maxWidth;
+            return this;
+        }
+
+        public Builder maxHeight(int maxHeight) {
+            mMaxHeight = maxHeight;
+            return this;
+        }
+
+        public Builder generation(int generation) {
+            mGeneration = generation;
+            return this;
+        }
+
+        public TvStreamConfig build() {
+            if (mStreamId == null || mType == null || mMaxWidth == null || mMaxHeight == null
+                    || mGeneration == null) {
+                throw new UnsupportedOperationException();
+            }
+
+            TvStreamConfig config = new TvStreamConfig();
+            config.mStreamId = mStreamId;
+            config.mType = mType;
+            config.mMaxWidth = mMaxWidth;
+            config.mMaxHeight = mMaxHeight;
+            config.mGeneration = mGeneration;
+            return config;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1874fd8..14141d7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1014,6 +1014,13 @@
         android:description="@string/permdesc_sim_communication"
         android:protectionLevel="dangerous" />
 
+    <!-- Allows TvInputService to access underlying TV input hardware such as
+         built-in tuners and HDMI-in's.
+         @hide This should only be used by OEM's TvInputService's.
+    -->
+    <permission android:name="android.permission.TV_INPUT_HARDWARE"
+        android:protectionLevel="signatureOrSystem" />
+
     <!-- =========================================== -->
     <!-- Permissions associated with audio capture -->
     <!-- =========================================== -->