blob: 42f12eb23d39b89556bad1f9a882edf84886fef1 [file] [log] [blame]
Wonsik Kimc22dbb62014-05-26 02:26:04 +00001/*
2 * Copyright 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 com.android.server.tv;
18
Shubang39f285d2017-03-21 12:56:08 -070019import android.hardware.tv.input.V1_0.Constants;
Jae Seod5cc4a22014-05-30 16:57:43 -070020import android.media.tv.TvInputHardwareInfo;
21import android.media.tv.TvStreamConfig;
Wonsik Kimc22dbb62014-05-26 02:26:04 +000022import android.os.Handler;
Wonsik Kim9e922ca2014-06-20 17:27:32 +090023import android.os.Message;
Wonsik Kim57b37f62014-12-17 11:18:36 +090024import android.os.MessageQueue;
Wonsik Kim9e922ca2014-06-20 17:27:32 +090025import android.util.Slog;
Wonsik Kim21aa3462014-07-29 16:39:00 +090026import android.util.SparseArray;
27import android.util.SparseIntArray;
Jae Seo5b1caaf2014-08-18 15:03:33 -070028import android.view.Surface;
Wonsik Kim9e922ca2014-06-20 17:27:32 +090029
30import java.util.LinkedList;
31import java.util.Queue;
Wonsik Kimc22dbb62014-05-26 02:26:04 +000032
33/**
34 * Provides access to the low-level TV input hardware abstraction layer.
35 */
Wonsik Kim9e922ca2014-06-20 17:27:32 +090036final class TvInputHal implements Handler.Callback {
Jae Seoee2ec052014-09-14 10:30:05 -070037 private final static boolean DEBUG = false;
Wonsik Kim9e922ca2014-06-20 17:27:32 +090038 private final static String TAG = TvInputHal.class.getSimpleName();
39
Wonsik Kimc22dbb62014-05-26 02:26:04 +000040 public final static int SUCCESS = 0;
41 public final static int ERROR_NO_INIT = -1;
42 public final static int ERROR_STALE_CONFIG = -2;
43 public final static int ERROR_UNKNOWN = -3;
44
Shubang39f285d2017-03-21 12:56:08 -070045 public static final int EVENT_DEVICE_AVAILABLE = Constants.EVENT_DEVICE_AVAILABLE;
46 public static final int EVENT_DEVICE_UNAVAILABLE = Constants.EVENT_DEVICE_UNAVAILABLE;
47 public static final int EVENT_STREAM_CONFIGURATION_CHANGED =
48 Constants.EVENT_STREAM_CONFIGURATIONS_CHANGED;
Terry Heoc086a3d2014-06-18 14:26:44 +090049 public static final int EVENT_FIRST_FRAME_CAPTURED = 4;
Wonsik Kim9e922ca2014-06-20 17:27:32 +090050
Wonsik Kimc22dbb62014-05-26 02:26:04 +000051 public interface Callback {
Jae Seo6e4cbfd2015-06-21 16:40:34 -070052 void onDeviceAvailable(TvInputHardwareInfo info, TvStreamConfig[] configs);
53 void onDeviceUnavailable(int deviceId);
54 void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs);
55 void onFirstFrameCaptured(int deviceId, int streamId);
Wonsik Kimc22dbb62014-05-26 02:26:04 +000056 }
57
Wonsik Kim57b37f62014-12-17 11:18:36 +090058 private native long nativeOpen(MessageQueue queue);
Wonsik Kimc22dbb62014-05-26 02:26:04 +000059
Wonsik Kim8f24a8b2014-10-22 16:27:39 +090060 private static native int nativeAddOrUpdateStream(long ptr, int deviceId, int streamId,
Wonsik Kimc22dbb62014-05-26 02:26:04 +000061 Surface surface);
Wonsik Kim839ae5f2014-07-03 19:06:56 +090062 private static native int nativeRemoveStream(long ptr, int deviceId, int streamId);
Wonsik Kimc22dbb62014-05-26 02:26:04 +000063 private static native TvStreamConfig[] nativeGetStreamConfigs(long ptr, int deviceId,
64 int generation);
65 private static native void nativeClose(long ptr);
66
Jae Seo5b1caaf2014-08-18 15:03:33 -070067 private final Object mLock = new Object();
Wonsik Kim610ccd92014-07-19 18:49:49 +090068 private long mPtr = 0;
Wonsik Kimc22dbb62014-05-26 02:26:04 +000069 private final Callback mCallback;
Wonsik Kimc22dbb62014-05-26 02:26:04 +000070 private final Handler mHandler;
Jae Seo5b1caaf2014-08-18 15:03:33 -070071 private final SparseIntArray mStreamConfigGenerations = new SparseIntArray();
72 private final SparseArray<TvStreamConfig[]> mStreamConfigs = new SparseArray<>();
Wonsik Kimc22dbb62014-05-26 02:26:04 +000073
74 public TvInputHal(Callback callback) {
75 mCallback = callback;
Wonsik Kim610ccd92014-07-19 18:49:49 +090076 mHandler = new Handler(this);
Wonsik Kimc22dbb62014-05-26 02:26:04 +000077 }
78
Wonsik Kim21aa3462014-07-29 16:39:00 +090079 public void init() {
80 synchronized (mLock) {
Wonsik Kim57b37f62014-12-17 11:18:36 +090081 mPtr = nativeOpen(mHandler.getLooper().getQueue());
Wonsik Kim839ae5f2014-07-03 19:06:56 +090082 }
83 }
84
Wonsik Kim8f24a8b2014-10-22 16:27:39 +090085 public int addOrUpdateStream(int deviceId, Surface surface, TvStreamConfig streamConfig) {
Wonsik Kim21aa3462014-07-29 16:39:00 +090086 synchronized (mLock) {
87 if (mPtr == 0) {
88 return ERROR_NO_INIT;
89 }
90 int generation = mStreamConfigGenerations.get(deviceId, 0);
91 if (generation != streamConfig.getGeneration()) {
92 return ERROR_STALE_CONFIG;
93 }
Wonsik Kim8f24a8b2014-10-22 16:27:39 +090094 if (nativeAddOrUpdateStream(mPtr, deviceId, streamConfig.getStreamId(), surface) == 0) {
Wonsik Kim21aa3462014-07-29 16:39:00 +090095 return SUCCESS;
96 } else {
97 return ERROR_UNKNOWN;
98 }
Wonsik Kimc22dbb62014-05-26 02:26:04 +000099 }
100 }
101
Wonsik Kim21aa3462014-07-29 16:39:00 +0900102 public int removeStream(int deviceId, TvStreamConfig streamConfig) {
103 synchronized (mLock) {
104 if (mPtr == 0) {
105 return ERROR_NO_INIT;
106 }
107 int generation = mStreamConfigGenerations.get(deviceId, 0);
108 if (generation != streamConfig.getGeneration()) {
109 return ERROR_STALE_CONFIG;
110 }
111 if (nativeRemoveStream(mPtr, deviceId, streamConfig.getStreamId()) == 0) {
112 return SUCCESS;
113 } else {
114 return ERROR_UNKNOWN;
115 }
Wonsik Kimc22dbb62014-05-26 02:26:04 +0000116 }
117 }
118
Wonsik Kim21aa3462014-07-29 16:39:00 +0900119 public void close() {
120 synchronized (mLock) {
Jae Seo2a2b2992016-01-12 23:13:14 -0800121 if (mPtr != 0L) {
Wonsik Kim21aa3462014-07-29 16:39:00 +0900122 nativeClose(mPtr);
123 }
124 }
125 }
126
127 private void retrieveStreamConfigsLocked(int deviceId) {
128 int generation = mStreamConfigGenerations.get(deviceId, 0) + 1;
129 mStreamConfigs.put(deviceId, nativeGetStreamConfigs(mPtr, deviceId, generation));
130 mStreamConfigGenerations.put(deviceId, generation);
Wonsik Kimc22dbb62014-05-26 02:26:04 +0000131 }
132
133 // Called from native
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900134 private void deviceAvailableFromNative(TvInputHardwareInfo info) {
Wonsik Kim610ccd92014-07-19 18:49:49 +0900135 if (DEBUG) {
136 Slog.d(TAG, "deviceAvailableFromNative: info = " + info);
137 }
138 mHandler.obtainMessage(EVENT_DEVICE_AVAILABLE, info).sendToTarget();
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900139 }
140
141 private void deviceUnavailableFromNative(int deviceId) {
Wonsik Kim610ccd92014-07-19 18:49:49 +0900142 mHandler.obtainMessage(EVENT_DEVICE_UNAVAILABLE, deviceId, 0).sendToTarget();
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900143 }
144
145 private void streamConfigsChangedFromNative(int deviceId) {
Wonsik Kim610ccd92014-07-19 18:49:49 +0900146 mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, 0).sendToTarget();
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900147 }
148
Terry Heoc086a3d2014-06-18 14:26:44 +0900149 private void firstFrameCapturedFromNative(int deviceId, int streamId) {
150 mHandler.sendMessage(
151 mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, streamId));
152 }
153
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900154 // Handler.Callback implementation
155
Jae Seo6e4cbfd2015-06-21 16:40:34 -0700156 private final Queue<Message> mPendingMessageQueue = new LinkedList<>();
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900157
158 @Override
159 public boolean handleMessage(Message msg) {
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900160 switch (msg.what) {
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900161 case EVENT_DEVICE_AVAILABLE: {
Wonsik Kim21aa3462014-07-29 16:39:00 +0900162 TvStreamConfig[] configs;
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900163 TvInputHardwareInfo info = (TvInputHardwareInfo)msg.obj;
Wonsik Kim21aa3462014-07-29 16:39:00 +0900164 synchronized (mLock) {
165 retrieveStreamConfigsLocked(info.getDeviceId());
166 if (DEBUG) {
167 Slog.d(TAG, "EVENT_DEVICE_AVAILABLE: info = " + info);
168 }
169 configs = mStreamConfigs.get(info.getDeviceId());
Wonsik Kim610ccd92014-07-19 18:49:49 +0900170 }
Wonsik Kim21aa3462014-07-29 16:39:00 +0900171 mCallback.onDeviceAvailable(info, configs);
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900172 break;
Wonsik Kimc22dbb62014-05-26 02:26:04 +0000173 }
Wonsik Kimc22dbb62014-05-26 02:26:04 +0000174
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900175 case EVENT_DEVICE_UNAVAILABLE: {
176 int deviceId = msg.arg1;
Wonsik Kim610ccd92014-07-19 18:49:49 +0900177 if (DEBUG) {
178 Slog.d(TAG, "EVENT_DEVICE_UNAVAILABLE: deviceId = " + deviceId);
179 }
Wonsik Kimd7c29182014-05-27 10:38:21 +0900180 mCallback.onDeviceUnavailable(deviceId);
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900181 break;
Wonsik Kimc22dbb62014-05-26 02:26:04 +0000182 }
Wonsik Kimc22dbb62014-05-26 02:26:04 +0000183
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900184 case EVENT_STREAM_CONFIGURATION_CHANGED: {
Wonsik Kim21aa3462014-07-29 16:39:00 +0900185 TvStreamConfig[] configs;
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900186 int deviceId = msg.arg1;
Wonsik Kim21aa3462014-07-29 16:39:00 +0900187 synchronized (mLock) {
188 if (DEBUG) {
189 Slog.d(TAG, "EVENT_STREAM_CONFIGURATION_CHANGED: deviceId = " + deviceId);
190 }
191 retrieveStreamConfigsLocked(deviceId);
192 configs = mStreamConfigs.get(deviceId);
Wonsik Kim610ccd92014-07-19 18:49:49 +0900193 }
Wonsik Kim21aa3462014-07-29 16:39:00 +0900194 mCallback.onStreamConfigurationChanged(deviceId, configs);
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900195 break;
Wonsik Kimc22dbb62014-05-26 02:26:04 +0000196 }
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900197
Terry Heoc086a3d2014-06-18 14:26:44 +0900198 case EVENT_FIRST_FRAME_CAPTURED: {
199 int deviceId = msg.arg1;
200 int streamId = msg.arg2;
201 mCallback.onFirstFrameCaptured(deviceId, streamId);
202 break;
203 }
204
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900205 default:
206 Slog.e(TAG, "Unknown event: " + msg);
Wonsik Kim610ccd92014-07-19 18:49:49 +0900207 return false;
Wonsik Kim9e922ca2014-06-20 17:27:32 +0900208 }
Wonsik Kim610ccd92014-07-19 18:49:49 +0900209
210 return true;
Wonsik Kimc22dbb62014-05-26 02:26:04 +0000211 }
212}