Merge "Add pause and resume recoding APIs"

This commit is contained in:
Henry Fang
2021-01-15 01:13:46 +00:00
committed by Android (Google) Code Review
11 changed files with 323 additions and 13 deletions

View File

@@ -393,6 +393,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 = 16844314; // 0x101061a
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
@@ -1054,11 +1055,11 @@ package android {
field public static final int parentActivityName = 16843687; // 0x10103a7
field @Deprecated public static final int password = 16843100; // 0x101015c
field public static final int path = 16842794; // 0x101002a
field public static final int pathAdvancedPattern = 16844318; // 0x101061e
field public static final int pathAdvancedPattern = 16844319; // 0x101061f
field public static final int pathData = 16843781; // 0x1010405
field public static final int pathPattern = 16842796; // 0x101002c
field public static final int pathPrefix = 16842795; // 0x101002b
field public static final int pathSuffix = 16844316; // 0x101061c
field public static final int pathSuffix = 16844317; // 0x101061d
field public static final int patternPathData = 16843978; // 0x10104ca
field public static final int permission = 16842758; // 0x1010006
field public static final int permissionFlags = 16843719; // 0x10103c7
@@ -1151,7 +1152,7 @@ package android {
field public static final int reqNavigation = 16843306; // 0x101022a
field public static final int reqTouchScreen = 16843303; // 0x1010227
field public static final int requestLegacyExternalStorage = 16844291; // 0x1010603
field public static final int requireDeviceScreenOn = 16844315; // 0x101061b
field public static final int requireDeviceScreenOn = 16844316; // 0x101061c
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
@@ -1292,10 +1293,10 @@ package android {
field public static final int spotShadowAlpha = 16843967; // 0x10104bf
field public static final int src = 16843033; // 0x1010119
field public static final int ssp = 16843747; // 0x10103e3
field public static final int sspAdvancedPattern = 16844319; // 0x101061f
field public static final int sspAdvancedPattern = 16844320; // 0x1010620
field public static final int sspPattern = 16843749; // 0x10103e5
field public static final int sspPrefix = 16843748; // 0x10103e4
field public static final int sspSuffix = 16844317; // 0x101061d
field public static final int sspSuffix = 16844318; // 0x101061e
field public static final int stackFromBottom = 16843005; // 0x10100fd
field public static final int stackViewStyle = 16843838; // 0x101043e
field public static final int starStyle = 16842882; // 0x1010082
@@ -24751,6 +24752,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();
@@ -24784,6 +24786,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);
@@ -24875,7 +24878,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();
@@ -24925,7 +24930,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);

View File

@@ -9013,6 +9013,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

View File

@@ -3047,6 +3047,7 @@
<public name="rollbackDataPolicy" />
<public name="allowClickWhenDisabled" />
<public name="windowLayoutAffinity" />
<public name="canPauseRecording" />
<!-- @hide -->
<public name="windowBackgroundBlurRadius"/>
<public name="requireDeviceScreenOn" />

View File

@@ -94,6 +94,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();

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;
@@ -385,6 +387,14 @@ public final class TvInputInfo implements Parcelable {
return mCanRecord;
}
/**
* 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.
*/
@@ -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;
@@ -878,6 +892,18 @@ public final class TvInputInfo implements Parcelable {
return this;
}
/**
* 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.
*
@@ -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);

View File

@@ -2522,6 +2522,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.

View File

@@ -1872,6 +1872,28 @@ public abstract class TvInputService extends Service {
public abstract void onStopRecording();
/**
* 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.
@@ -1923,6 +1945,22 @@ public abstract class TvInputService extends Service {
onStopRecording();
}
/**
* 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)}.
*/

View File

@@ -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);
}

View File

@@ -1873,6 +1873,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)