diff options
-rw-r--r-- | core/api/current.txt | 9 | ||||
-rw-r--r-- | core/res/res/values/attrs.xml | 5 | ||||
-rw-r--r-- | core/res/res/values/public.xml | 1 | ||||
-rw-r--r-- | media/java/android/media/tv/ITvInputManager.aidl | 2 | ||||
-rw-r--r-- | media/java/android/media/tv/ITvInputSession.aidl | 2 | ||||
-rw-r--r-- | media/java/android/media/tv/ITvInputSessionWrapper.java | 20 | ||||
-rw-r--r-- | media/java/android/media/tv/TvInputInfo.java | 40 | ||||
-rw-r--r-- | media/java/android/media/tv/TvInputManager.java | 34 | ||||
-rwxr-xr-x | media/java/android/media/tv/TvInputService.java | 38 | ||||
-rw-r--r-- | media/java/android/media/tv/TvRecordingClient.java | 135 | ||||
-rwxr-xr-x | services/core/java/com/android/server/tv/TvInputManagerService.java | 41 |
11 files changed, 319 insertions, 8 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 252c33c4efda..f14f99989869 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -385,6 +385,7 @@ package android { field public static final int calendarViewShown = 16843596; // 0x101034c field public static final int calendarViewStyle = 16843613; // 0x101035d field public static final int canControlMagnification = 16844039; // 0x1010507 + field public static final int canPauseRecording = 16844311; // 0x1010617 field public static final int canPerformGestures = 16844045; // 0x101050d field public static final int canRecord = 16844060; // 0x101051c field @Deprecated public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8 @@ -24265,6 +24266,7 @@ package android.media.tv { } public final class TvInputInfo implements android.os.Parcelable { + method public boolean canPauseRecording(); method public boolean canRecord(); method @Deprecated public android.content.Intent createSettingsIntent(); method public android.content.Intent createSetupIntent(); @@ -24298,6 +24300,7 @@ package android.media.tv { public static final class TvInputInfo.Builder { ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName); method public android.media.tv.TvInputInfo build(); + method @NonNull public android.media.tv.TvInputInfo.Builder setCanPauseRecording(boolean); method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean); method public android.media.tv.TvInputInfo.Builder setExtras(android.os.Bundle); method public android.media.tv.TvInputInfo.Builder setTunerCount(int); @@ -24389,7 +24392,9 @@ package android.media.tv { method public void notifyRecordingStopped(android.net.Uri); method public void notifyTuned(android.net.Uri); method public void onAppPrivateCommand(@NonNull String, android.os.Bundle); + method public void onPauseRecording(@NonNull android.os.Bundle); method public abstract void onRelease(); + method public void onResumeRecording(@NonNull android.os.Bundle); method public abstract void onStartRecording(@Nullable android.net.Uri); method public void onStartRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle); method public abstract void onStopRecording(); @@ -24439,7 +24444,11 @@ package android.media.tv { public class TvRecordingClient { ctor public TvRecordingClient(android.content.Context, String, @NonNull android.media.tv.TvRecordingClient.RecordingCallback, android.os.Handler); + method public void pauseRecording(); + method public void pauseRecording(@NonNull android.os.Bundle); method public void release(); + method public void resumeRecording(); + method public void resumeRecording(@NonNull android.os.Bundle); method public void sendAppPrivateCommand(@NonNull String, android.os.Bundle); method public void startRecording(@Nullable android.net.Uri); method public void startRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle); diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 2f1bcdc76afb..4b3d82a04b8b 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -8968,6 +8968,11 @@ changed at runtime by calling {@link android.media.tv.TvInputManager#updateTvInputInfo(android.media.tv.TvInputInfo)}. --> <attr name="tunerCount" format="integer" /> + <!-- Attribute whether the TV input service can pause recording programs. + This value can be changed at runtime by calling + {@link android.media.tv.TvInputManager#updateTvInputInfo(android.media.tv.TvInputInfo)} + . --> + <attr name="canPauseRecording" format="boolean" /> </declare-styleable> <!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index e00aff1af37b..a0be0681bd38 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3043,6 +3043,7 @@ =============================================================== --> <public-group type="attr" first-id="0x01010617"> + <public name="canPauseRecording" /> <!-- attribute definitions go here --> </public-group> diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl index 1fbb67260895..5d7fdff70f5c 100644 --- a/media/java/android/media/tv/ITvInputManager.aidl +++ b/media/java/android/media/tv/ITvInputManager.aidl @@ -91,6 +91,8 @@ interface ITvInputManager { // For the recording session void startRecording(in IBinder sessionToken, in Uri programUri, in Bundle params, int userId); void stopRecording(in IBinder sessionToken, int userId); + void pauseRecording(in IBinder sessionToken, in Bundle params, int userId); + void resumeRecording(in IBinder sessionToken, in Bundle params, int userId); // For TV input hardware binding List<TvInputHardwareInfo> getHardwareList(); diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl index 24b87d50b33e..158cf211d9f0 100644 --- a/media/java/android/media/tv/ITvInputSession.aidl +++ b/media/java/android/media/tv/ITvInputSession.aidl @@ -58,4 +58,6 @@ oneway interface ITvInputSession { // For the recording session void startRecording(in Uri programUri, in Bundle params); void stopRecording(); + void pauseRecording(in Bundle params); + void resumeRecording(in Bundle params); } diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java index e89d33d70d5c..abccf8da9cfc 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -68,6 +68,8 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand private static final int DO_TIME_SHIFT_ENABLE_POSITION_TRACKING = 19; private static final int DO_START_RECORDING = 20; private static final int DO_STOP_RECORDING = 21; + private static final int DO_PAUSE_RECORDING = 22; + private static final int DO_RESUME_RECORDING = 23; private final boolean mIsRecordingSession; private final HandlerCaller mCaller; @@ -224,6 +226,14 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand mTvInputRecordingSessionImpl.stopRecording(); break; } + case DO_PAUSE_RECORDING: { + mTvInputRecordingSessionImpl.pauseRecording((Bundle) msg.obj); + break; + } + case DO_RESUME_RECORDING: { + mTvInputRecordingSessionImpl.resumeRecording((Bundle) msg.obj); + break; + } default: { Log.w(TAG, "Unhandled message code: " + msg.what); break; @@ -363,6 +373,16 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_STOP_RECORDING)); } + @Override + public void pauseRecording(@Nullable Bundle params) { + mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_PAUSE_RECORDING, params)); + } + + @Override + public void resumeRecording(@Nullable Bundle params) { + mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_RESUME_RECORDING, params)); + } + private final class TvInputEventReceiver extends InputEventReceiver { public TvInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java index 195ad5bc10f9..54cb2bff5566 100644 --- a/media/java/android/media/tv/TvInputInfo.java +++ b/media/java/android/media/tv/TvInputInfo.java @@ -143,6 +143,7 @@ public final class TvInputInfo implements Parcelable { // Attributes from XML meta data. private final String mSetupActivity; private final boolean mCanRecord; + private final boolean mCanPauseRecording; private final int mTunerCount; // Attributes specific to HDMI @@ -264,8 +265,8 @@ public final class TvInputInfo implements Parcelable { private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput, CharSequence label, int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected, - String setupActivity, boolean canRecord, int tunerCount, HdmiDeviceInfo hdmiDeviceInfo, - boolean isConnectedToHdmiSwitch, + String setupActivity, boolean canRecord, boolean canPauseRecording, int tunerCount, + HdmiDeviceInfo hdmiDeviceInfo, boolean isConnectedToHdmiSwitch, @HdmiAddressRelativePosition int hdmiConnectionRelativePosition, String parentId, Bundle extras) { mService = service; @@ -279,6 +280,7 @@ public final class TvInputInfo implements Parcelable { mIconDisconnected = iconDisconnected; mSetupActivity = setupActivity; mCanRecord = canRecord; + mCanPauseRecording = canPauseRecording; mTunerCount = tunerCount; mHdmiDeviceInfo = hdmiDeviceInfo; mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch; @@ -386,6 +388,14 @@ public final class TvInputInfo implements Parcelable { } /** + * Returns {@code true} if this TV input can pause recording TV programs, + * {@code false} otherwise. + */ + public boolean canPauseRecording() { + return mCanPauseRecording; + } + + /** * Returns domain-specific extras associated with this TV input. */ public Bundle getExtras() { @@ -571,6 +581,7 @@ public final class TvInputInfo implements Parcelable { && Objects.equals(mIconDisconnected, obj.mIconDisconnected) && TextUtils.equals(mSetupActivity, obj.mSetupActivity) && mCanRecord == obj.mCanRecord + && mCanPauseRecording == obj.mCanPauseRecording && mTunerCount == obj.mTunerCount && Objects.equals(mHdmiDeviceInfo, obj.mHdmiDeviceInfo) && mIsConnectedToHdmiSwitch == obj.mIsConnectedToHdmiSwitch @@ -606,6 +617,7 @@ public final class TvInputInfo implements Parcelable { dest.writeParcelable(mIconDisconnected, flags); dest.writeString(mSetupActivity); dest.writeByte(mCanRecord ? (byte) 1 : 0); + dest.writeByte(mCanPauseRecording ? (byte) 1 : 0); dest.writeInt(mTunerCount); dest.writeParcelable(mHdmiDeviceInfo, flags); dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0); @@ -648,6 +660,7 @@ public final class TvInputInfo implements Parcelable { mIconDisconnected = in.readParcelable(null); mSetupActivity = in.readString(); mCanRecord = in.readByte() == 1; + mCanPauseRecording = in.readByte() == 1; mTunerCount = in.readInt(); mHdmiDeviceInfo = in.readParcelable(null); mIsConnectedToHdmiSwitch = in.readByte() == 1; @@ -695,6 +708,7 @@ public final class TvInputInfo implements Parcelable { private Icon mIconDisconnected; private String mSetupActivity; private Boolean mCanRecord; + private Boolean mCanPauseRecording; private Integer mTunerCount; private TvInputHardwareInfo mTvInputHardwareInfo; private HdmiDeviceInfo mHdmiDeviceInfo; @@ -879,6 +893,18 @@ public final class TvInputInfo implements Parcelable { } /** + * Sets whether this TV input can pause recording TV programs or not. + * + * @param canPauseRecording Whether this TV input can pause recording TV programs. + * @return This Builder object to allow for chaining of calls to builder methods. + */ + @NonNull + public Builder setCanPauseRecording(boolean canPauseRecording) { + this.mCanPauseRecording = canPauseRecording; + return this; + } + + /** * Sets domain-specific extras associated with this TV input. * * @param extras Domain-specific extras associated with this TV input. Keys <em>must</em> be @@ -927,7 +953,9 @@ public final class TvInputInfo implements Parcelable { parseServiceMetadata(type); return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabel, mLabelResId, mIcon, mIconStandby, mIconDisconnected, mSetupActivity, - mCanRecord == null ? false : mCanRecord, mTunerCount == null ? 0 : mTunerCount, + mCanRecord == null ? false : mCanRecord, + mCanPauseRecording == null ? false : mCanPauseRecording, + mTunerCount == null ? 0 : mTunerCount, mHdmiDeviceInfo, isConnectedToHdmiSwitch, hdmiConnectionRelativePosition, mParentId, mExtras); } @@ -997,6 +1025,12 @@ public final class TvInputInfo implements Parcelable { mTunerCount = sa.getInt( com.android.internal.R.styleable.TvInputService_tunerCount, 1); } + if (mCanPauseRecording == null) { + mCanPauseRecording = sa.getBoolean( + com.android.internal.R.styleable.TvInputService_canPauseRecording, + false); + } + sa.recycle(); } catch (IOException | XmlPullParserException e) { throw new IllegalStateException("Failed reading meta-data for " + si.packageName, e); diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 98a01a4cb449..6341dc263efd 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -2476,6 +2476,40 @@ public final class TvInputManager { } /** + * Pauses TV program recording in the current recording session. + * + * @param params A set of extra parameters which might be handled with this event. + */ + void pauseRecording(@NonNull Bundle params) { + if (mToken == null) { + Log.w(TAG, "The session has been already released"); + return; + } + try { + mService.pauseRecording(mToken, params, mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Resumes TV program recording in the current recording session. + * + * @param params A set of extra parameters which might be handled with this event. + */ + void resumeRecording(@NonNull Bundle params) { + if (mToken == null) { + Log.w(TAG, "The session has been already released"); + return; + } + try { + mService.resumeRecording(mToken, params, mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle) * TvInputService.Session.appPrivateCommand()} on the current TvView. * diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index abbf4780bcc1..0fe9d504b951 100755 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -1852,6 +1852,28 @@ public abstract class TvInputService extends Service { /** + * Called when the application requests to pause TV program recording. Recording must pause + * immediately when this method is called. + * + * If the pause request cannot be fulfilled, the session must call + * {@link #notifyError(int)}. + * + * @param params Domain-specific data for recording request. + */ + public void onPauseRecording(@NonNull Bundle params) { } + + /** + * Called when the application requests to resume TV program recording. Recording must + * resume immediately when this method is called. + * + * If the resume request cannot be fulfilled, the session must call + * {@link #notifyError(int)}. + * + * @param params Domain-specific data for recording request. + */ + public void onResumeRecording(@NonNull Bundle params) { } + + /** * Called when the application requests to release all the resources held by this recording * session. */ @@ -1903,6 +1925,22 @@ public abstract class TvInputService extends Service { } /** + * Calls {@link #onPauseRecording(Bundle)}. + * + */ + void pauseRecording(@NonNull Bundle params) { + onPauseRecording(params); + } + + /** + * Calls {@link #onResumeRecording(Bundle)}. + * + */ + void resumeRecording(@NonNull Bundle params) { + onResumeRecording(params); + } + + /** * Calls {@link #onAppPrivateCommand(String, Bundle)}. */ void appPrivateCommand(String action, Bundle data) { diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java index 23fadac8a72b..180e2bd6845b 100644 --- a/media/java/android/media/tv/TvRecordingClient.java +++ b/media/java/android/media/tv/TvRecordingClient.java @@ -30,6 +30,7 @@ import android.util.Log; import android.util.Pair; import java.util.ArrayDeque; +import java.util.Objects; import java.util.Queue; /** @@ -49,6 +50,8 @@ public class TvRecordingClient { private boolean mIsRecordingStarted; private boolean mIsTuned; + private boolean mIsPaused; + private boolean mIsRecordingStopping; private final Queue<Pair<String, Bundle>> mPendingAppPrivateCommands = new ArrayDeque<>(); /** @@ -113,17 +116,22 @@ public class TvRecordingClient { if (TextUtils.isEmpty(inputId)) { throw new IllegalArgumentException("inputId cannot be null or an empty string"); } - if (mIsRecordingStarted) { + if (mIsRecordingStarted && !mIsPaused) { throw new IllegalStateException("tune failed - recording already started"); } if (mSessionCallback != null && TextUtils.equals(mSessionCallback.mInputId, inputId)) { if (mSession != null) { + mSessionCallback.mChannelUri = channelUri; mSession.tune(channelUri, params); } else { mSessionCallback.mChannelUri = channelUri; mSessionCallback.mConnectionParams = params; } + mIsTuned = false; } else { + if (mIsPaused) { + throw new IllegalStateException("tune failed - inputId is changed during pause"); + } resetInternal(); mSessionCallback = new MySessionCallback(inputId, channelUri, params); if (mTvInputManager != null) { @@ -148,6 +156,8 @@ public class TvRecordingClient { mSession.release(); mIsTuned = false; mIsRecordingStarted = false; + mIsPaused = false; + mIsRecordingStopping = false; mSession = null; } } @@ -169,7 +179,8 @@ public class TvRecordingClient { * * @param programUri The URI for the TV program to record, built by * {@link TvContract#buildProgramUri(long)}. Can be {@code null}. - * @throws IllegalStateException If {@link #tune} request hasn't been handled yet. + * @throws IllegalStateException If {@link #tune} request hasn't been handled yet or during + * pause. */ public void startRecording(@Nullable Uri programUri) { startRecording(programUri, Bundle.EMPTY); @@ -195,11 +206,16 @@ public class TvRecordingClient { * @param params Domain-specific data for this request. Keys <em>must</em> be a scoped * name, i.e. prefixed with a package name you own, so that different developers will * not create conflicting keys. - * @throws IllegalStateException If {@link #tune} request hasn't been handled yet. + * @throws IllegalStateException If {@link #tune} request hasn't been handled yet or during + * pause. */ public void startRecording(@Nullable Uri programUri, @NonNull Bundle params) { - if (!mIsTuned) { - throw new IllegalStateException("startRecording failed - not yet tuned"); + if (mIsRecordingStopping || !mIsTuned || mIsPaused) { + throw new IllegalStateException("startRecording failed -" + + "recording not yet stopped or not yet tuned or paused"); + } + if (mIsRecordingStarted) { + Log.w(TAG, "startRecording failed - recording already started"); } if (mSession != null) { mSession.startRecording(programUri, params); @@ -225,6 +241,103 @@ public class TvRecordingClient { } if (mSession != null) { mSession.stopRecording(); + if (mIsRecordingStarted) { + mIsRecordingStopping = true; + } + } + } + + /** + * Pause TV program recording in the current recording session. Recording is expected to pause + * immediately when this method is called. If recording has not yet started in the current + * recording session, this method does nothing. + * + * <p>In pause status, the application can tune during recording. To continue recording, + * please call {@link TvRecordingClient#resumeRecording()} to resume instead of + * {@link TvRecordingClient#startRecording(Uri)}. Application can stop + * the recording with {@link TvRecordingClient#stopRecording()} in recording pause status. + * + * <p>If the pause request cannot be fulfilled, the recording session will respond by calling + * {@link RecordingCallback#onError(int)}. + */ + public void pauseRecording() { + pauseRecording(Bundle.EMPTY); + } + + /** + * Pause TV program recording in the current recording session. Recording is expected to pause + * immediately when this method is called. If recording has not yet started in the current + * recording session, this method does nothing. + * + * <p>In pause status, the application can tune during recording. To continue recording, + * please call {@link TvRecordingClient#resumeRecording()} to resume instead of + * {@link TvRecordingClient#startRecording(Uri)}. Application can stop + * the recording with {@link TvRecordingClient#stopRecording()} in recording pause status. + * + * <p>If the pause request cannot be fulfilled, the recording session will respond by calling + * {@link RecordingCallback#onError(int)}. + * + * @param params Domain-specific data for this request. + */ + public void pauseRecording(@NonNull Bundle params) { + if (!mIsRecordingStarted || mIsRecordingStopping) { + throw new IllegalStateException( + "pauseRecording failed - recording not yet started or stopping"); + } + TvInputInfo info = mTvInputManager.getTvInputInfo(mSessionCallback.mInputId); + if (info == null || !info.canPauseRecording()) { + throw new UnsupportedOperationException( + "pauseRecording failed - operation not supported"); + } + if (mIsPaused) { + Log.w(TAG, "pauseRecording failed - recording already paused"); + } + if (mSession != null) { + mSession.pauseRecording(params); + mIsPaused = true; + } + } + + /** + * Resume TV program recording only in recording pause status in the current recording session. + * Recording is expected to resume immediately when this method is called. If recording has not + * yet paused in the current recording session, this method does nothing. + * + * <p>When record is resumed, the recording is continue and can not re-tune. Application can + * stop the recording with {@link TvRecordingClient#stopRecording()} after record resumed. + * + * <p>If the pause request cannot be fulfilled, the recording session will respond by calling + * {@link RecordingCallback#onError(int)}. + */ + public void resumeRecording() { + resumeRecording(Bundle.EMPTY); + } + + /** + * Resume TV program recording only in recording pause status in the current recording session. + * Recording is expected to resume immediately when this method is called. If recording has not + * yet paused in the current recording session, this method does nothing. + * + * <p>When record is resumed, the recording is continues and can not re-tune. Application can + * stop the recording with {@link TvRecordingClient#stopRecording()} after record resumed. + * + * <p>If the resume request cannot be fulfilled, the recording session will respond by calling + * {@link RecordingCallback#onError(int)}. + * + * @param params Domain-specific data for this request. + */ + public void resumeRecording(@NonNull Bundle params) { + if (!mIsRecordingStarted || mIsRecordingStopping || !mIsTuned) { + throw new IllegalStateException( + "resumeRecording failed - recording not yet started or stopping or " + + "not yet tuned"); + } + if (!mIsPaused) { + Log.w(TAG, "resumeRecording failed - recording not yet paused"); + } + if (mSession != null) { + mSession.resumeRecording(params); + mIsPaused = false; } } @@ -367,6 +480,10 @@ public class TvRecordingClient { Log.w(TAG, "onTuned - session not created"); return; } + if (mIsTuned || !Objects.equals(mChannelUri, channelUri)) { + Log.w(TAG, "onTuned - already tuned or not yet tuned to last channel"); + return; + } mIsTuned = true; mCallback.onTuned(channelUri); } @@ -382,6 +499,8 @@ public class TvRecordingClient { } mIsTuned = false; mIsRecordingStarted = false; + mIsPaused = false; + mIsRecordingStopping = false; mSessionCallback = null; mSession = null; if (mCallback != null) { @@ -398,7 +517,13 @@ public class TvRecordingClient { Log.w(TAG, "onRecordingStopped - session not created"); return; } + if (!mIsRecordingStarted) { + Log.w(TAG, "onRecordingStopped - recording not yet started"); + return; + } mIsRecordingStarted = false; + mIsPaused = false; + mIsRecordingStopping = false; mCallback.onRecordingStopped(recordedProgramUri); } diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 6cd02581ee67..d858ae41cee8 100755 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -20,6 +20,7 @@ import static android.media.AudioManager.DEVICE_NONE; import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED; import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.content.BroadcastReceiver; @@ -1728,6 +1729,46 @@ public final class TvInputManagerService extends SystemService { } @Override + public void pauseRecording(IBinder sessionToken, @NonNull Bundle params, int userId) { + final int callingUid = Binder.getCallingUid(); + final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, + userId, "pauseRecording"); + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + try { + getSessionLocked(sessionToken, callingUid, resolvedUserId) + .pauseRecording(params); + } catch (RemoteException | SessionNotFoundException e) { + Slog.e(TAG, "error in pauseRecording", e); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void resumeRecording(IBinder sessionToken, @NonNull Bundle params, int userId) { + final int callingUid = Binder.getCallingUid(); + final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, + userId, "resumeRecording"); + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + try { + getSessionLocked(sessionToken, callingUid, resolvedUserId) + .resumeRecording(params); + } catch (RemoteException | SessionNotFoundException e) { + Slog.e(TAG, "error in resumeRecording", e); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override public List<TvInputHardwareInfo> getHardwareList() throws RemoteException { if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE) != PackageManager.PERMISSION_GRANTED) { |