Loading core/res/AndroidManifest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -1095,6 +1095,13 @@ <permission android:name="android.permission.TV_INPUT_HARDWARE" android:protectionLevel="signatureOrSystem" /> <!-- @SystemApi Allows to capture a frame of TV input hardware such as built-in tuners and HDMI-in's. @hide <p>Not for use by third-party applications. --> <permission android:name="android.permission.CAPTURE_TV_INPUT" android:protectionLevel="signatureOrSystem" /> <!-- @hide Allows enabling/disabling OEM unlock <p>Not for use by third-party applications. --> <permission android:name="android.permission.OEM_UNLOCK_STATE" Loading media/java/android/media/tv/ITvInputManager.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.media.tv.ITvInputHardwareCallback; import android.media.tv.ITvInputManagerCallback; import android.media.tv.TvInputHardwareInfo; import android.media.tv.TvInputInfo; import android.media.tv.TvStreamConfig; import android.media.tv.TvTrackInfo; import android.net.Uri; import android.os.Bundle; Loading Loading @@ -67,4 +68,9 @@ interface ITvInputManager { ITvInputHardware acquireTvInputHardware(int deviceId, in ITvInputHardwareCallback callback, in TvInputInfo info, int userId); void releaseTvInputHardware(int deviceId, in ITvInputHardware hardware, int userId); // For TV input capturing List<TvStreamConfig> getAvailableTvStreamConfigList(in String inputId, int userId); boolean captureFrame(in String inputId, in Surface surface, in TvStreamConfig config, int userId); } media/java/android/media/tv/TvInputManager.java +35 −0 Original line number Diff line number Diff line Loading @@ -682,6 +682,41 @@ public final class TvInputManager { } } /** * Returns the TvStreamConfig list of the given TV input. * * @param inputId the id of the TV input. * @return List of {@link TvStreamConfig} which is available for capturing * of the given TV input. * @hide */ @SystemApi public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId) { try { return mService.getAvailableTvStreamConfigList(inputId, mUserId); } catch (RemoteException e) { throw new RuntimeException(e); } } /** * Take a snapshot of the given TV input into the provided Surface. * * @param inputId the id of the TV input. * @param surface the {@link Surface} to which the snapshot is captured. * @param config the {@link TvStreamConfig} which is used for capturing. * @return true when the {@link Surface} is ready to be captured. * @hide */ @SystemApi public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config) { try { return mService.captureFrame(inputId, surface, config, mUserId); } catch (RemoteException e) { throw new RuntimeException(e); } } /** * The Session provides the per-session functionality of TV inputs. * @hide Loading services/core/java/com/android/server/tv/TvInputHal.java +14 −1 Original line number Diff line number Diff line Loading @@ -40,16 +40,17 @@ final class TvInputHal implements Handler.Callback { public final static int ERROR_STALE_CONFIG = -2; public final static int ERROR_UNKNOWN = -3; // Below should be in sync with hardware/libhardware/include/hardware/tv_input.h public static final int EVENT_DEVICE_AVAILABLE = 1; public static final int EVENT_DEVICE_UNAVAILABLE = 2; public static final int EVENT_STREAM_CONFIGURATION_CHANGED = 3; public static final int EVENT_FIRST_FRAME_CAPTURED = 4; public interface Callback { public void onDeviceAvailable( TvInputHardwareInfo info, TvStreamConfig[] configs); public void onDeviceUnavailable(int deviceId); public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs); public void onFirstFrameCaptured(int deviceId, int streamId); } private native long nativeOpen(); Loading Loading @@ -131,6 +132,11 @@ final class TvInputHal implements Handler.Callback { mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, 0).sendToTarget(); } private void firstFrameCapturedFromNative(int deviceId, int streamId) { mHandler.sendMessage( mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, streamId)); } // Handler.Callback implementation private Queue<Message> mPendingMessageQueue = new LinkedList<Message>(); Loading Loading @@ -167,6 +173,13 @@ final class TvInputHal implements Handler.Callback { break; } case EVENT_FIRST_FRAME_CAPTURED: { int deviceId = msg.arg1; int streamId = msg.arg2; mCallback.onFirstFrameCaptured(deviceId, streamId); break; } default: Slog.e(TAG, "Unknown event: " + msg); return false; Loading services/core/java/com/android/server/tv/TvInputHardwareManager.java +130 −0 Original line number Diff line number Diff line Loading @@ -172,6 +172,23 @@ class TvInputHardwareManager implements TvInputHal.Callback { } } @Override public void onFirstFrameCaptured(int deviceId, int streamId) { synchronized (mLock) { Connection connection = mConnections.get(deviceId); if (connection == null) { Slog.e(TAG, "FirstFrameCaptured: Cannot find a connection with " + deviceId); return; } Runnable runnable = connection.getOnFirstFrameCapturedLocked(); if (runnable != null) { runnable.run(); connection.setOnFirstFrameCapturedLocked(null); } } } public List<TvInputHardwareInfo> getHardwareList() { synchronized (mLock) { return mInfoList; Loading Loading @@ -337,6 +354,74 @@ class TvInputHardwareManager implements TvInputHal.Callback { return null; } private int findDeviceIdForInputIdLocked(String inputId) { for (int i = 0; i < mConnections.size(); ++i) { Connection connection = mConnections.get(i); if (connection.getInfoLocked().getId().equals(inputId)) { return i; } } return -1; } /** * Get the list of TvStreamConfig which is buffered mode. */ public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int callingUid, int resolvedUserId) { List<TvStreamConfig> configsList = new ArrayList<TvStreamConfig>(); synchronized (mLock) { int deviceId = findDeviceIdForInputIdLocked(inputId); if (deviceId < 0) { Slog.e(TAG, "Invalid inputId : " + inputId); return configsList; } Connection connection = mConnections.get(deviceId); for (TvStreamConfig config : connection.getConfigsLocked()) { if (config.getType() == TvStreamConfig.STREAM_TYPE_BUFFER_PRODUCER) { configsList.add(config); } } } return configsList; } /** * Take a snapshot of the given TV input into the provided Surface. */ public boolean captureFrame(String inputId, Surface surface, final TvStreamConfig config, int callingUid, int resolvedUserId) { synchronized (mLock) { int deviceId = findDeviceIdForInputIdLocked(inputId); if (deviceId < 0) { Slog.e(TAG, "Invalid inputId : " + inputId); return false; } Connection connection = mConnections.get(deviceId); final TvInputHardwareImpl hardwareImpl = connection.getHardwareImplLocked(); if (hardwareImpl != null) { // Stop previous capture. Runnable runnable = connection.getOnFirstFrameCapturedLocked(); if (runnable != null) { runnable.run(); connection.setOnFirstFrameCapturedLocked(null); } boolean result = hardwareImpl.startCapture(surface, config); if (result) { connection.setOnFirstFrameCapturedLocked(new Runnable() { @Override public void run() { hardwareImpl.stopCapture(config); } }); } return result; } } return false; } private class Connection implements IBinder.DeathRecipient { private final TvInputHardwareInfo mHardwareInfo; private TvInputInfo mInfo; Loading @@ -345,6 +430,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { private TvStreamConfig[] mConfigs = null; private Integer mCallingUid = null; private Integer mResolvedUserId = null; private Runnable mOnFirstFrameCaptured; public Connection(TvInputHardwareInfo hardwareInfo) { mHardwareInfo = hardwareInfo; Loading @@ -367,6 +453,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { mInfo = info; mCallingUid = callingUid; mResolvedUserId = resolvedUserId; mOnFirstFrameCaptured = null; if (mHardware != null && mCallback != null) { try { Loading @@ -393,6 +480,10 @@ class TvInputHardwareManager implements TvInputHal.Callback { return mHardware; } public TvInputHardwareImpl getHardwareImplLocked() { return mHardware; } public ITvInputHardwareCallback getCallbackLocked() { return mCallback; } Loading @@ -409,6 +500,14 @@ class TvInputHardwareManager implements TvInputHal.Callback { return mResolvedUserId; } public void setOnFirstFrameCapturedLocked(Runnable runnable) { mOnFirstFrameCaptured = runnable; } public Runnable getOnFirstFrameCapturedLocked() { return mOnFirstFrameCaptured; } @Override public void binderDied() { synchronized (mLock) { Loading Loading @@ -559,6 +658,37 @@ class TvInputHardwareManager implements TvInputHal.Callback { // TODO(hdmi): mHdmiClient.sendKeyEvent(event); return false; } private boolean startCapture(Surface surface, TvStreamConfig config) { synchronized (mImplLock) { if (mReleased) { return false; } if (surface == null || config == null) { return false; } if (config.getType() != TvStreamConfig.STREAM_TYPE_BUFFER_PRODUCER) { return false; } int result = mHal.addStream(mInfo.getDeviceId(), surface, config); return result == TvInputHal.SUCCESS; } } private boolean stopCapture(TvStreamConfig config) { synchronized (mImplLock) { if (mReleased) { return false; } if (config == null) { return false; } int result = mHal.removeStream(mInfo.getDeviceId(), config); return result == TvInputHal.SUCCESS; } } } interface Listener { Loading Loading
core/res/AndroidManifest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -1095,6 +1095,13 @@ <permission android:name="android.permission.TV_INPUT_HARDWARE" android:protectionLevel="signatureOrSystem" /> <!-- @SystemApi Allows to capture a frame of TV input hardware such as built-in tuners and HDMI-in's. @hide <p>Not for use by third-party applications. --> <permission android:name="android.permission.CAPTURE_TV_INPUT" android:protectionLevel="signatureOrSystem" /> <!-- @hide Allows enabling/disabling OEM unlock <p>Not for use by third-party applications. --> <permission android:name="android.permission.OEM_UNLOCK_STATE" Loading
media/java/android/media/tv/ITvInputManager.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.media.tv.ITvInputHardwareCallback; import android.media.tv.ITvInputManagerCallback; import android.media.tv.TvInputHardwareInfo; import android.media.tv.TvInputInfo; import android.media.tv.TvStreamConfig; import android.media.tv.TvTrackInfo; import android.net.Uri; import android.os.Bundle; Loading Loading @@ -67,4 +68,9 @@ interface ITvInputManager { ITvInputHardware acquireTvInputHardware(int deviceId, in ITvInputHardwareCallback callback, in TvInputInfo info, int userId); void releaseTvInputHardware(int deviceId, in ITvInputHardware hardware, int userId); // For TV input capturing List<TvStreamConfig> getAvailableTvStreamConfigList(in String inputId, int userId); boolean captureFrame(in String inputId, in Surface surface, in TvStreamConfig config, int userId); }
media/java/android/media/tv/TvInputManager.java +35 −0 Original line number Diff line number Diff line Loading @@ -682,6 +682,41 @@ public final class TvInputManager { } } /** * Returns the TvStreamConfig list of the given TV input. * * @param inputId the id of the TV input. * @return List of {@link TvStreamConfig} which is available for capturing * of the given TV input. * @hide */ @SystemApi public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId) { try { return mService.getAvailableTvStreamConfigList(inputId, mUserId); } catch (RemoteException e) { throw new RuntimeException(e); } } /** * Take a snapshot of the given TV input into the provided Surface. * * @param inputId the id of the TV input. * @param surface the {@link Surface} to which the snapshot is captured. * @param config the {@link TvStreamConfig} which is used for capturing. * @return true when the {@link Surface} is ready to be captured. * @hide */ @SystemApi public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config) { try { return mService.captureFrame(inputId, surface, config, mUserId); } catch (RemoteException e) { throw new RuntimeException(e); } } /** * The Session provides the per-session functionality of TV inputs. * @hide Loading
services/core/java/com/android/server/tv/TvInputHal.java +14 −1 Original line number Diff line number Diff line Loading @@ -40,16 +40,17 @@ final class TvInputHal implements Handler.Callback { public final static int ERROR_STALE_CONFIG = -2; public final static int ERROR_UNKNOWN = -3; // Below should be in sync with hardware/libhardware/include/hardware/tv_input.h public static final int EVENT_DEVICE_AVAILABLE = 1; public static final int EVENT_DEVICE_UNAVAILABLE = 2; public static final int EVENT_STREAM_CONFIGURATION_CHANGED = 3; public static final int EVENT_FIRST_FRAME_CAPTURED = 4; public interface Callback { public void onDeviceAvailable( TvInputHardwareInfo info, TvStreamConfig[] configs); public void onDeviceUnavailable(int deviceId); public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs); public void onFirstFrameCaptured(int deviceId, int streamId); } private native long nativeOpen(); Loading Loading @@ -131,6 +132,11 @@ final class TvInputHal implements Handler.Callback { mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, 0).sendToTarget(); } private void firstFrameCapturedFromNative(int deviceId, int streamId) { mHandler.sendMessage( mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, streamId)); } // Handler.Callback implementation private Queue<Message> mPendingMessageQueue = new LinkedList<Message>(); Loading Loading @@ -167,6 +173,13 @@ final class TvInputHal implements Handler.Callback { break; } case EVENT_FIRST_FRAME_CAPTURED: { int deviceId = msg.arg1; int streamId = msg.arg2; mCallback.onFirstFrameCaptured(deviceId, streamId); break; } default: Slog.e(TAG, "Unknown event: " + msg); return false; Loading
services/core/java/com/android/server/tv/TvInputHardwareManager.java +130 −0 Original line number Diff line number Diff line Loading @@ -172,6 +172,23 @@ class TvInputHardwareManager implements TvInputHal.Callback { } } @Override public void onFirstFrameCaptured(int deviceId, int streamId) { synchronized (mLock) { Connection connection = mConnections.get(deviceId); if (connection == null) { Slog.e(TAG, "FirstFrameCaptured: Cannot find a connection with " + deviceId); return; } Runnable runnable = connection.getOnFirstFrameCapturedLocked(); if (runnable != null) { runnable.run(); connection.setOnFirstFrameCapturedLocked(null); } } } public List<TvInputHardwareInfo> getHardwareList() { synchronized (mLock) { return mInfoList; Loading Loading @@ -337,6 +354,74 @@ class TvInputHardwareManager implements TvInputHal.Callback { return null; } private int findDeviceIdForInputIdLocked(String inputId) { for (int i = 0; i < mConnections.size(); ++i) { Connection connection = mConnections.get(i); if (connection.getInfoLocked().getId().equals(inputId)) { return i; } } return -1; } /** * Get the list of TvStreamConfig which is buffered mode. */ public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int callingUid, int resolvedUserId) { List<TvStreamConfig> configsList = new ArrayList<TvStreamConfig>(); synchronized (mLock) { int deviceId = findDeviceIdForInputIdLocked(inputId); if (deviceId < 0) { Slog.e(TAG, "Invalid inputId : " + inputId); return configsList; } Connection connection = mConnections.get(deviceId); for (TvStreamConfig config : connection.getConfigsLocked()) { if (config.getType() == TvStreamConfig.STREAM_TYPE_BUFFER_PRODUCER) { configsList.add(config); } } } return configsList; } /** * Take a snapshot of the given TV input into the provided Surface. */ public boolean captureFrame(String inputId, Surface surface, final TvStreamConfig config, int callingUid, int resolvedUserId) { synchronized (mLock) { int deviceId = findDeviceIdForInputIdLocked(inputId); if (deviceId < 0) { Slog.e(TAG, "Invalid inputId : " + inputId); return false; } Connection connection = mConnections.get(deviceId); final TvInputHardwareImpl hardwareImpl = connection.getHardwareImplLocked(); if (hardwareImpl != null) { // Stop previous capture. Runnable runnable = connection.getOnFirstFrameCapturedLocked(); if (runnable != null) { runnable.run(); connection.setOnFirstFrameCapturedLocked(null); } boolean result = hardwareImpl.startCapture(surface, config); if (result) { connection.setOnFirstFrameCapturedLocked(new Runnable() { @Override public void run() { hardwareImpl.stopCapture(config); } }); } return result; } } return false; } private class Connection implements IBinder.DeathRecipient { private final TvInputHardwareInfo mHardwareInfo; private TvInputInfo mInfo; Loading @@ -345,6 +430,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { private TvStreamConfig[] mConfigs = null; private Integer mCallingUid = null; private Integer mResolvedUserId = null; private Runnable mOnFirstFrameCaptured; public Connection(TvInputHardwareInfo hardwareInfo) { mHardwareInfo = hardwareInfo; Loading @@ -367,6 +453,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { mInfo = info; mCallingUid = callingUid; mResolvedUserId = resolvedUserId; mOnFirstFrameCaptured = null; if (mHardware != null && mCallback != null) { try { Loading @@ -393,6 +480,10 @@ class TvInputHardwareManager implements TvInputHal.Callback { return mHardware; } public TvInputHardwareImpl getHardwareImplLocked() { return mHardware; } public ITvInputHardwareCallback getCallbackLocked() { return mCallback; } Loading @@ -409,6 +500,14 @@ class TvInputHardwareManager implements TvInputHal.Callback { return mResolvedUserId; } public void setOnFirstFrameCapturedLocked(Runnable runnable) { mOnFirstFrameCaptured = runnable; } public Runnable getOnFirstFrameCapturedLocked() { return mOnFirstFrameCaptured; } @Override public void binderDied() { synchronized (mLock) { Loading Loading @@ -559,6 +658,37 @@ class TvInputHardwareManager implements TvInputHal.Callback { // TODO(hdmi): mHdmiClient.sendKeyEvent(event); return false; } private boolean startCapture(Surface surface, TvStreamConfig config) { synchronized (mImplLock) { if (mReleased) { return false; } if (surface == null || config == null) { return false; } if (config.getType() != TvStreamConfig.STREAM_TYPE_BUFFER_PRODUCER) { return false; } int result = mHal.addStream(mInfo.getDeviceId(), surface, config); return result == TvInputHal.SUCCESS; } } private boolean stopCapture(TvStreamConfig config) { synchronized (mImplLock) { if (mReleased) { return false; } if (config == null) { return false; } int result = mHal.removeStream(mInfo.getDeviceId(), config); return result == TvInputHal.SUCCESS; } } } interface Listener { Loading