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. + * + *
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. + * + *
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. + * + *
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. + * + *
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. + * + *
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. + * + *
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. + * + *
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 6cd02581ee673..d858ae41cee89 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;
@@ -1727,6 +1728,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