Merge "TIF: Change the isForeground API to isVisible and isMainSession" into sc-dev

This commit is contained in:
Shubang Lu
2021-04-20 20:19:42 +00:00
committed by Android (Google) Code Review
7 changed files with 108 additions and 44 deletions

View File

@@ -19,6 +19,7 @@ package android {
field public static final String ACCESS_SHARED_LIBRARIES = "android.permission.ACCESS_SHARED_LIBRARIES"; field public static final String ACCESS_SHARED_LIBRARIES = "android.permission.ACCESS_SHARED_LIBRARIES";
field public static final String ACCESS_SHORTCUTS = "android.permission.ACCESS_SHORTCUTS"; field public static final String ACCESS_SHORTCUTS = "android.permission.ACCESS_SHORTCUTS";
field public static final String ACCESS_SURFACE_FLINGER = "android.permission.ACCESS_SURFACE_FLINGER"; field public static final String ACCESS_SURFACE_FLINGER = "android.permission.ACCESS_SURFACE_FLINGER";
field public static final String ACCESS_TUNED_INFO = "android.permission.ACCESS_TUNED_INFO";
field public static final String ACCESS_TV_DESCRAMBLER = "android.permission.ACCESS_TV_DESCRAMBLER"; field public static final String ACCESS_TV_DESCRAMBLER = "android.permission.ACCESS_TV_DESCRAMBLER";
field public static final String ACCESS_TV_TUNER = "android.permission.ACCESS_TV_TUNER"; field public static final String ACCESS_TV_TUNER = "android.permission.ACCESS_TV_TUNER";
field public static final String ACCESS_VIBRATOR_STATE = "android.permission.ACCESS_VIBRATOR_STATE"; field public static final String ACCESS_VIBRATOR_STATE = "android.permission.ACCESS_VIBRATOR_STATE";
@@ -5635,8 +5636,9 @@ package android.media.tv {
method public int getAppType(); method public int getAppType();
method @Nullable public android.net.Uri getChannelUri(); method @Nullable public android.net.Uri getChannelUri();
method @NonNull public String getInputId(); method @NonNull public String getInputId();
method public boolean isForeground(); method public boolean isMainSession();
method public boolean isRecordingSession(); method public boolean isRecordingSession();
method public boolean isVisible();
method public void writeToParcel(@NonNull android.os.Parcel, int); method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final int APP_TAG_SELF = 0; // 0x0 field public static final int APP_TAG_SELF = 0; // 0x0
field public static final int APP_TYPE_NON_SYSTEM = 3; // 0x3 field public static final int APP_TYPE_NON_SYSTEM = 3; // 0x3
@@ -5760,7 +5762,7 @@ package android.media.tv {
method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull android.media.tv.TvContentRating); method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull android.media.tv.TvContentRating);
method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig); method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig);
method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String); method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String);
method @NonNull @RequiresPermission("com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS") public java.util.List<android.media.tv.TunedInfo> getCurrentTunedInfos(); method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TUNED_INFO) public java.util.List<android.media.tv.TunedInfo> getCurrentTunedInfos();
method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList(); method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList();
method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList(); method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList();
method @RequiresPermission(android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS) public java.util.List<android.media.tv.TvContentRatingSystemInfo> getTvContentRatingSystemList(); method @RequiresPermission(android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS) public java.util.List<android.media.tv.TvContentRatingSystemInfo> getTvContentRatingSystemList();
@@ -5787,7 +5789,7 @@ package android.media.tv {
} }
public abstract static class TvInputManager.TvInputCallback { public abstract static class TvInputManager.TvInputCallback {
method public void onCurrentTunedInfosUpdated(@NonNull java.util.List<android.media.tv.TunedInfo>); method @RequiresPermission(android.Manifest.permission.ACCESS_TUNED_INFO) public void onCurrentTunedInfosUpdated(@NonNull java.util.List<android.media.tv.TunedInfo>);
} }
public abstract class TvInputService extends android.app.Service { public abstract class TvInputService extends android.app.Service {

View File

@@ -5734,6 +5734,12 @@
<permission android:name="android.permission.SET_CLIP_SOURCE" <permission android:name="android.permission.SET_CLIP_SOURCE"
android:protectionLevel="signature|recents" /> android:protectionLevel="signature|recents" />
<!-- @SystemApi Allows an application to access TV tuned info
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.ACCESS_TUNED_INFO"
android:protectionLevel="signature|privileged|vendorPrivileged" />
<!-- Allows an application to indicate via <!-- Allows an application to indicate via
{@link android.content.pm.PackageInstaller.SessionParams#setRequireUserAction(boolean)} {@link android.content.pm.PackageInstaller.SessionParams#setRequireUserAction(boolean)}
that user action should not be required for an app update. that user action should not be required for an app update.

View File

@@ -458,6 +458,7 @@ applications that come with the platform
<permission name="android.permission.ACCESS_TV_TUNER" /> <permission name="android.permission.ACCESS_TV_TUNER" />
<permission name="android.permission.TUNER_RESOURCE_ACCESS" /> <permission name="android.permission.TUNER_RESOURCE_ACCESS" />
<!-- Permissions required for CTS test - TVInputManagerTest --> <!-- Permissions required for CTS test - TVInputManagerTest -->
<permission name="android.permission.ACCESS_TUNED_INFO" />
<permission name="android.permission.TV_INPUT_HARDWARE" /> <permission name="android.permission.TV_INPUT_HARDWARE" />
<!-- Permission required for CTS test - PrivilegedLocationPermissionTest --> <!-- Permission required for CTS test - PrivilegedLocationPermissionTest -->
<permission name="android.permission.LOCATION_HARDWARE" /> <permission name="android.permission.LOCATION_HARDWARE" />

View File

@@ -25,6 +25,7 @@ import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.Surface;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@@ -92,18 +93,20 @@ public final class TunedInfo implements Parcelable {
private final String mInputId; private final String mInputId;
@Nullable private final Uri mChannelUri; @Nullable private final Uri mChannelUri;
private final boolean mIsRecordingSession; private final boolean mIsRecordingSession;
private final boolean mIsForeground; private final boolean mIsVisible;
private final boolean mIsMainSession;
@AppType private final int mAppType; @AppType private final int mAppType;
private final int mAppTag; private final int mAppTag;
/** @hide */ /** @hide */
public TunedInfo( public TunedInfo(
String inputId, @Nullable Uri channelUri, boolean isRecordingSession, String inputId, @Nullable Uri channelUri, boolean isRecordingSession,
boolean isForeground, @AppType int appType, int appTag) { boolean isVisible, boolean isMainSession, @AppType int appType, int appTag) {
mInputId = inputId; mInputId = inputId;
mChannelUri = channelUri; mChannelUri = channelUri;
mIsRecordingSession = isRecordingSession; mIsRecordingSession = isRecordingSession;
mIsForeground = isForeground; mIsVisible = isVisible;
mIsMainSession = isMainSession;
mAppType = appType; mAppType = appType;
mAppTag = appTag; mAppTag = appTag;
} }
@@ -114,7 +117,8 @@ public final class TunedInfo implements Parcelable {
String uriString = source.readString(); String uriString = source.readString();
mChannelUri = uriString == null ? null : Uri.parse(uriString); mChannelUri = uriString == null ? null : Uri.parse(uriString);
mIsRecordingSession = (source.readInt() == 1); mIsRecordingSession = (source.readInt() == 1);
mIsForeground = (source.readInt() == 1); mIsVisible = (source.readInt() == 1);
mIsMainSession = (source.readInt() == 1);
mAppType = source.readInt(); mAppType = source.readInt();
mAppTag = source.readInt(); mAppTag = source.readInt();
} }
@@ -145,11 +149,23 @@ public final class TunedInfo implements Parcelable {
} }
/** /**
* Returns {@code true} if the application is a foreground application. * Returns {@code true} if the corresponding session is visible.
* @see android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND * <p>The system checks whether the {@link Surface} of the session is {@code null} or not. When
* it becomes invisible, the surface is destroyed and set to null.
* @see TvInputService.Session#onSetSurface(Surface)
* @see android.view.SurfaceView#notifySurfaceDestroyed
*/ */
public boolean isForeground() { public boolean isVisible() {
return mIsForeground; return mIsVisible;
}
/**
* Returns {@code true} if the corresponding session is set as main session.
* @see TvView#setMain
* @see TvInputService.Session#onSetMain
*/
public boolean isMainSession() {
return mIsMainSession;
} }
/** /**
@@ -180,7 +196,8 @@ public final class TunedInfo implements Parcelable {
String uriString = mChannelUri == null ? null : mChannelUri.toString(); String uriString = mChannelUri == null ? null : mChannelUri.toString();
dest.writeString(uriString); dest.writeString(uriString);
dest.writeInt(mIsRecordingSession ? 1 : 0); dest.writeInt(mIsRecordingSession ? 1 : 0);
dest.writeInt(mIsForeground ? 1 : 0); dest.writeInt(mIsVisible ? 1 : 0);
dest.writeInt(mIsMainSession ? 1 : 0);
dest.writeInt(mAppType); dest.writeInt(mAppType);
dest.writeInt(mAppTag); dest.writeInt(mAppTag);
} }
@@ -190,7 +207,8 @@ public final class TunedInfo implements Parcelable {
return "inputID=" + mInputId return "inputID=" + mInputId
+ ";channelUri=" + mChannelUri + ";channelUri=" + mChannelUri
+ ";isRecording=" + mIsRecordingSession + ";isRecording=" + mIsRecordingSession
+ ";isForeground=" + mIsForeground + ";isVisible=" + mIsVisible
+ ";isMainSession=" + mIsMainSession
+ ";appType=" + mAppType + ";appType=" + mAppType
+ ";appTag=" + mAppTag; + ";appTag=" + mAppTag;
} }
@@ -206,7 +224,8 @@ public final class TunedInfo implements Parcelable {
return TextUtils.equals(mInputId, other.getInputId()) return TextUtils.equals(mInputId, other.getInputId())
&& Objects.equals(mChannelUri, other.mChannelUri) && Objects.equals(mChannelUri, other.mChannelUri)
&& mIsRecordingSession == other.mIsRecordingSession && mIsRecordingSession == other.mIsRecordingSession
&& mIsForeground == other.mIsForeground && mIsVisible == other.mIsVisible
&& mIsMainSession == other.mIsMainSession
&& mAppType == other.mAppType && mAppType == other.mAppType
&& mAppTag == other.mAppTag; && mAppTag == other.mAppTag;
} }
@@ -214,6 +233,7 @@ public final class TunedInfo implements Parcelable {
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash( return Objects.hash(
mInputId, mChannelUri, mIsRecordingSession, mIsForeground, mAppType, mAppTag); mInputId, mChannelUri, mIsRecordingSession, mIsVisible, mIsMainSession, mAppType,
mAppTag);
} }
} }

View File

@@ -907,6 +907,7 @@ public final class TvInputManager {
* @hide * @hide
*/ */
@SystemApi @SystemApi
@RequiresPermission(android.Manifest.permission.ACCESS_TUNED_INFO)
public void onCurrentTunedInfosUpdated(@NonNull List<TunedInfo> tunedInfos) { public void onCurrentTunedInfosUpdated(@NonNull List<TunedInfo> tunedInfos) {
} }
} }
@@ -1989,7 +1990,7 @@ public final class TvInputManager {
* @hide * @hide
*/ */
@SystemApi @SystemApi
@RequiresPermission("com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS") @RequiresPermission(android.Manifest.permission.ACCESS_TUNED_INFO)
@NonNull @NonNull
public List<TunedInfo> getCurrentTunedInfos() { public List<TunedInfo> getCurrentTunedInfos() {
try { try {

View File

@@ -429,6 +429,7 @@
<uses-permission android:name="android.permission.ACCESS_SHARED_LIBRARIES" /> <uses-permission android:name="android.permission.ACCESS_SHARED_LIBRARIES" />
<!-- Permissions required for CTS test - TVInputManagerTest --> <!-- Permissions required for CTS test - TVInputManagerTest -->
<uses-permission android:name="android.permission.ACCESS_TUNED_INFO" />
<uses-permission android:name="android.permission.TV_INPUT_HARDWARE" /> <uses-permission android:name="android.permission.TV_INPUT_HARDWARE" />
<!-- Permission needed for CTS test - PrivilegedLocationPermissionTest --> <!-- Permission needed for CTS test - PrivilegedLocationPermissionTest -->

View File

@@ -24,7 +24,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.ContentResolver; import android.content.ContentResolver;
@@ -109,6 +108,7 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@@ -511,11 +511,21 @@ public final class TvInputManagerService extends SystemService {
sessionStatesToRelease.add(sessionState); sessionStatesToRelease.add(sessionState);
} }
} }
boolean notifyInfoUpdated = false;
for (SessionState sessionState : sessionStatesToRelease) { for (SessionState sessionState : sessionStatesToRelease) {
try { try {
sessionState.session.release(); sessionState.session.release();
sessionState.currentChannel = null;
if (sessionState.isCurrent) {
sessionState.isCurrent = false;
notifyInfoUpdated = true;
}
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "error in release", e); Slog.e(TAG, "error in release", e);
} finally {
if (notifyInfoUpdated) {
notifyCurrentChannelInfosUpdatedLocked(userState);
}
} }
clearSessionAndNotifyClientLocked(sessionState); clearSessionAndNotifyClientLocked(sessionState);
} }
@@ -576,12 +586,22 @@ public final class TvInputManagerService extends SystemService {
return; return;
} }
// Release all created sessions. // Release all created sessions.
boolean notifyInfoUpdated = false;
for (SessionState state : userState.sessionStateMap.values()) { for (SessionState state : userState.sessionStateMap.values()) {
if (state.session != null) { if (state.session != null) {
try { try {
state.session.release(); state.session.release();
state.currentChannel = null;
if (state.isCurrent) {
state.isCurrent = false;
notifyInfoUpdated = true;
}
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "error in release", e); Slog.e(TAG, "error in release", e);
} finally {
if (notifyInfoUpdated) {
notifyCurrentChannelInfosUpdatedLocked(userState);
}
} }
} }
} }
@@ -826,9 +846,11 @@ public final class TvInputManagerService extends SystemService {
sessionState.session.asBinder().unlinkToDeath(sessionState, 0); sessionState.session.asBinder().unlinkToDeath(sessionState, 0);
sessionState.session.release(); sessionState.session.release();
} }
sessionState.isCurrent = false;
sessionState.currentChannel = null; sessionState.currentChannel = null;
notifyCurrentChannelInfosUpdatedLocked(userState); if (sessionState.isCurrent) {
sessionState.isCurrent = false;
notifyCurrentChannelInfosUpdatedLocked(userState);
}
} catch (RemoteException | SessionNotFoundException e) { } catch (RemoteException | SessionNotFoundException e) {
Slog.e(TAG, "error in releaseSession", e); Slog.e(TAG, "error in releaseSession", e);
} finally { } finally {
@@ -898,6 +920,11 @@ public final class TvInputManagerService extends SystemService {
} }
ITvInputSession session = getSessionLocked(sessionState); ITvInputSession session = getSessionLocked(sessionState);
session.setMain(isMain); session.setMain(isMain);
if (sessionState.isMainSession != isMain) {
UserState userState = getUserStateLocked(userId);
sessionState.isMainSession = isMain;
notifyCurrentChannelInfosUpdatedLocked(userState);
}
} catch (RemoteException | SessionNotFoundException e) { } catch (RemoteException | SessionNotFoundException e) {
Slog.e(TAG, "error in setMain", e); Slog.e(TAG, "error in setMain", e);
} }
@@ -987,6 +1014,10 @@ public final class TvInputManagerService extends SystemService {
try { try {
ITvInputManagerCallback callback = userState.mCallbacks.getBroadcastItem(i); ITvInputManagerCallback callback = userState.mCallbacks.getBroadcastItem(i);
Pair<Integer, Integer> pidUid = userState.callbackPidUidMap.get(callback); Pair<Integer, Integer> pidUid = userState.callbackPidUidMap.get(callback);
if (mContext.checkPermission(android.Manifest.permission.ACCESS_TUNED_INFO,
pidUid.first, pidUid.second) != PackageManager.PERMISSION_GRANTED) {
continue;
}
List<TunedInfo> infos = getCurrentTunedInfosInternalLocked( List<TunedInfo> infos = getCurrentTunedInfosInternalLocked(
userState, pidUid.first, pidUid.second); userState, pidUid.first, pidUid.second);
callback.onCurrentTunedInfosUpdated(infos); callback.onCurrentTunedInfosUpdated(infos);
@@ -1517,6 +1548,11 @@ public final class TvInputManagerService extends SystemService {
getSessionLocked(sessionState.hardwareSessionToken, getSessionLocked(sessionState.hardwareSessionToken,
Process.SYSTEM_UID, resolvedUserId).setSurface(surface); Process.SYSTEM_UID, resolvedUserId).setSurface(surface);
} }
boolean isVisible = (surface == null);
if (sessionState.isVisible != isVisible) {
sessionState.isVisible = isVisible;
notifyCurrentChannelInfosUpdatedLocked(userState);
}
} catch (RemoteException | SessionNotFoundException e) { } catch (RemoteException | SessionNotFoundException e) {
Slog.e(TAG, "error in setSurface", e); Slog.e(TAG, "error in setSurface", e);
} }
@@ -1609,9 +1645,12 @@ public final class TvInputManagerService extends SystemService {
UserState userState = getOrCreateUserStateLocked(resolvedUserId); UserState userState = getOrCreateUserStateLocked(resolvedUserId);
SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
userState); userState);
sessionState.isCurrent = true; if (!sessionState.isCurrent
sessionState.currentChannel = channelUri; || !Objects.equals(sessionState.currentChannel, channelUri)) {
notifyCurrentChannelInfosUpdatedLocked(userState); sessionState.isCurrent = true;
sessionState.currentChannel = channelUri;
notifyCurrentChannelInfosUpdatedLocked(userState);
}
if (TvContract.isChannelUriForPassthroughInput(channelUri)) { if (TvContract.isChannelUriForPassthroughInput(channelUri)) {
// Do not log the watch history for passthrough inputs. // Do not log the watch history for passthrough inputs.
return; return;
@@ -2309,6 +2348,11 @@ public final class TvInputManagerService extends SystemService {
@Override @Override
public List<TunedInfo> getCurrentTunedInfos(@UserIdInt int userId) { public List<TunedInfo> getCurrentTunedInfos(@UserIdInt int userId) {
if (mContext.checkCallingPermission(android.Manifest.permission.ACCESS_TUNED_INFO)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(
"The caller does not have access tuned info permission");
}
int callingPid = Binder.getCallingPid(); int callingPid = Binder.getCallingPid();
int callingUid = Binder.getCallingUid(); int callingUid = Binder.getCallingUid();
final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId, final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
@@ -2524,7 +2568,8 @@ public final class TvInputManagerService extends SystemService {
state.inputId, state.inputId,
watchedProgramsAccess ? state.currentChannel : null, watchedProgramsAccess ? state.currentChannel : null,
state.isRecordingSession, state.isRecordingSession,
isForeground(state.callingPid), state.isVisible,
state.isMainSession,
appType, appType,
appTag)); appTag));
} }
@@ -2532,23 +2577,6 @@ public final class TvInputManagerService extends SystemService {
return channelInfos; return channelInfos;
} }
private boolean isForeground(int pid) {
if (mActivityManager == null) {
return false;
}
List<RunningAppProcessInfo> appProcesses = mActivityManager.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.pid == pid
&& appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
return true;
}
}
return false;
}
private boolean hasAccessWatchedProgramsPermission(int callingPid, int callingUid) { private boolean hasAccessWatchedProgramsPermission(int callingPid, int callingUid) {
return mContext.checkPermission(PERMISSION_ACCESS_WATCHED_PROGRAMS, callingPid, callingUid) return mContext.checkPermission(PERMISSION_ACCESS_WATCHED_PROGRAMS, callingPid, callingUid)
== PackageManager.PERMISSION_GRANTED; == PackageManager.PERMISSION_GRANTED;
@@ -2788,6 +2816,8 @@ public final class TvInputManagerService extends SystemService {
private boolean isCurrent = false; private boolean isCurrent = false;
private Uri currentChannel = null; private Uri currentChannel = null;
private boolean isVisible = false;
private boolean isMainSession = false;
private SessionState(IBinder sessionToken, String inputId, ComponentName componentName, private SessionState(IBinder sessionToken, String inputId, ComponentName componentName,
boolean isRecordingSession, ITvInputClient client, int seq, int callingUid, boolean isRecordingSession, ITvInputClient client, int seq, int callingUid,
@@ -3039,16 +3069,19 @@ public final class TvInputManagerService extends SystemService {
if (mSessionState.session == null || mSessionState.client == null) { if (mSessionState.session == null || mSessionState.client == null) {
return; return;
} }
mSessionState.isCurrent = true;
mSessionState.currentChannel = channelUri;
UserState userState = getOrCreateUserStateLocked(mSessionState.userId);
notifyCurrentChannelInfosUpdatedLocked(userState);
try { try {
// TODO: Consider adding this channel change in the watch log. When we do // TODO: Consider adding this channel change in the watch log. When we do
// that, how we can protect the watch log from malicious tv inputs should // that, how we can protect the watch log from malicious tv inputs should
// be addressed. e.g. add a field which represents where the channel change // be addressed. e.g. add a field which represents where the channel change
// originated from. // originated from.
mSessionState.client.onChannelRetuned(channelUri, mSessionState.seq); mSessionState.client.onChannelRetuned(channelUri, mSessionState.seq);
if (!mSessionState.isCurrent
|| !Objects.equals(mSessionState.currentChannel, channelUri)) {
UserState userState = getOrCreateUserStateLocked(mSessionState.userId);
mSessionState.isCurrent = true;
mSessionState.currentChannel = channelUri;
notifyCurrentChannelInfosUpdatedLocked(userState);
}
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "error in onChannelRetuned", e); Slog.e(TAG, "error in onChannelRetuned", e);
} }