Merge "Use pid and uid for getCurrentTvChannelInfo"
This commit is contained in:
committed by
Android (Google) Code Review
commit
e1505c7959
@@ -22,19 +22,44 @@ import android.annotation.Nullable;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
/**
|
||||
* This class is used to specify information of a TV channel.
|
||||
* @hide
|
||||
*/
|
||||
public final class TvChannelInfo implements Parcelable {
|
||||
static final String TAG = "TvChannelInfo";
|
||||
|
||||
/**
|
||||
* App tag for {@link #getAppTag()}: the corresponding application of the channel is the same as
|
||||
* the caller.
|
||||
* <p>{@link #getAppType()} returns {@link #APP_TYPE_SELF} if and only if the app tag is
|
||||
* {@link #APP_TAG_SELF}.
|
||||
*/
|
||||
public static final int APP_TAG_SELF = 0;
|
||||
/**
|
||||
* App tag for {@link #getAppType()}: the corresponding application of the channel is the same
|
||||
* as the caller.
|
||||
* <p>{@link #getAppType()} returns {@link #APP_TYPE_SELF} if and only if the app tag is
|
||||
* {@link #APP_TAG_SELF}.
|
||||
*/
|
||||
public static final int APP_TYPE_SELF = 1;
|
||||
/**
|
||||
* App tag for {@link #getAppType()}: the corresponding app of the channel is a system
|
||||
* application.
|
||||
*/
|
||||
public static final int APP_TYPE_SYSTEM = 2;
|
||||
/**
|
||||
* App tag for {@link #getAppType()}: the corresponding app of the channel is not a system
|
||||
* application.
|
||||
*/
|
||||
public static final int APP_TYPE_NON_SYSTEM = 3;
|
||||
|
||||
/** @hide */
|
||||
@@ -68,6 +93,7 @@ public final class TvChannelInfo implements Parcelable {
|
||||
@AppType private final int mAppType;
|
||||
private final int mAppTag;
|
||||
|
||||
/** @hide */
|
||||
public TvChannelInfo(
|
||||
String inputId, @Nullable Uri channelUri, boolean isRecordingSession,
|
||||
boolean isForeground, @AppType int appType, int appTag) {
|
||||
@@ -90,24 +116,41 @@ public final class TvChannelInfo implements Parcelable {
|
||||
mAppTag = source.readInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TV input ID of the channel.
|
||||
*/
|
||||
@NonNull
|
||||
public String getInputId() {
|
||||
return mInputId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the channel URI of the channel.
|
||||
* <p>Returns {@code null} if it's a passthrough input or the permission is not granted.
|
||||
*/
|
||||
@Nullable
|
||||
public Uri getChannelUri() {
|
||||
return mChannelUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the channel session is a recording session.
|
||||
* @see TvInputService.RecordingSession
|
||||
*/
|
||||
public boolean isRecordingSession() {
|
||||
return mIsRecordingSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the application is a foreground application.
|
||||
* @see android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
|
||||
*/
|
||||
public boolean isForeground() {
|
||||
return mIsForeground;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets app tag.
|
||||
* Returns the app tag.
|
||||
* <p>App tag is used to differentiate one app from another.
|
||||
* {@link #APP_TAG_SELF} is for current app.
|
||||
*/
|
||||
@@ -115,6 +158,9 @@ public final class TvChannelInfo implements Parcelable {
|
||||
return mAppTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the app type.
|
||||
*/
|
||||
@AppType
|
||||
public int getAppType() {
|
||||
return mAppType;
|
||||
@@ -126,7 +172,7 @@ public final class TvChannelInfo implements Parcelable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeString(mInputId);
|
||||
String uriString = mChannelUri == null ? null : mChannelUri.toString();
|
||||
dest.writeString(uriString);
|
||||
@@ -145,4 +191,26 @@ public final class TvChannelInfo implements Parcelable {
|
||||
+ ";appType=" + mAppType
|
||||
+ ";appTag=" + mAppTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof TvChannelInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TvChannelInfo other = (TvChannelInfo) o;
|
||||
|
||||
return TextUtils.equals(mInputId, other.getInputId())
|
||||
&& Objects.equals(mChannelUri, other.mChannelUri)
|
||||
&& mIsRecordingSession == other.mIsRecordingSession
|
||||
&& mIsForeground == other.mIsForeground
|
||||
&& mAppType == other.mAppType
|
||||
&& mAppTag == other.mAppTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(
|
||||
mInputId, mChannelUri, mIsRecordingSession, mIsForeground, mAppType, mAppTag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,8 +900,13 @@ public final class TvInputManager {
|
||||
public void onTvInputInfoUpdated(TvInputInfo inputInfo) {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void onCurrentTvChannelInfosUpdated(List<TvChannelInfo> tvChannelInfos) {
|
||||
/**
|
||||
* This is called when the information about current TV channels has been updated.
|
||||
*
|
||||
* @param tvChannelInfos a list of {@link TvChannelInfo} objects of new current channels.
|
||||
* @hide
|
||||
*/
|
||||
public void onCurrentTvChannelInfosUpdated(@NonNull List<TvChannelInfo> tvChannelInfos) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1976,8 +1981,15 @@ public final class TvInputManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of TV channel information for {@link TvInputService.Session} that are
|
||||
* currently in use.
|
||||
* <p> Permission com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS is required to get
|
||||
* the channel URIs. If the permission is not granted, {@link TvChannelInfo#getChannelUri()}
|
||||
* returns {@code null}.
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission("com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS")
|
||||
@NonNull
|
||||
public List<TvChannelInfo> getCurrentTvChannelInfos() {
|
||||
try {
|
||||
return mService.getCurrentTvChannelInfos(mUserId);
|
||||
|
||||
@@ -77,6 +77,7 @@ import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.view.InputChannel;
|
||||
@@ -709,8 +710,7 @@ public final class TvInputManagerService extends SystemService {
|
||||
}
|
||||
sessionState.isCurrent = false;
|
||||
sessionState.currentChannel = null;
|
||||
notifyCurrentChannelInfosUpdatedLocked(
|
||||
userState, getCurrentTvChannelInfosInternalLocked(userState));
|
||||
notifyCurrentChannelInfosUpdatedLocked(userState);
|
||||
} catch (RemoteException | SessionNotFoundException e) {
|
||||
Slog.e(TAG, "error in releaseSession", e);
|
||||
} finally {
|
||||
@@ -851,15 +851,18 @@ public final class TvInputManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyCurrentChannelInfosUpdatedLocked(
|
||||
UserState userState, List<TvChannelInfo> infos) {
|
||||
private void notifyCurrentChannelInfosUpdatedLocked(UserState userState) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "notifyCurrentChannelInfosUpdatedLocked");
|
||||
}
|
||||
int n = userState.mCallbacks.beginBroadcast();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
try {
|
||||
userState.mCallbacks.getBroadcastItem(i).onCurrentTvChannelInfosUpdated(infos);
|
||||
ITvInputManagerCallback callback = userState.mCallbacks.getBroadcastItem(i);
|
||||
Pair<Integer, Integer> pidUid = userState.callbackPidUidMap.get(callback);
|
||||
List<TvChannelInfo> infos = getCurrentTvChannelInfosInternalLocked(
|
||||
userState, pidUid.first, pidUid.second);
|
||||
callback.onCurrentTvChannelInfosUpdated(infos);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "failed to report updated current channel infos to callback", e);
|
||||
}
|
||||
@@ -1063,14 +1066,19 @@ public final class TvInputManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void registerCallback(final ITvInputManagerCallback callback, int userId) {
|
||||
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
|
||||
Binder.getCallingUid(), userId, "registerCallback");
|
||||
int callingPid = Binder.getCallingPid();
|
||||
int callingUid = Binder.getCallingUid();
|
||||
final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
|
||||
"registerCallback");
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
final UserState userState = getOrCreateUserStateLocked(resolvedUserId);
|
||||
if (!userState.mCallbacks.register(callback)) {
|
||||
Slog.e(TAG, "client process has already died");
|
||||
} else {
|
||||
userState.callbackPidUidMap.put(
|
||||
callback, Pair.create(callingPid, callingUid));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@@ -1087,6 +1095,7 @@ public final class TvInputManagerService extends SystemService {
|
||||
synchronized (mLock) {
|
||||
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
|
||||
userState.mCallbacks.unregister(callback);
|
||||
userState.callbackPidUidMap.remove(callback);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
@@ -1419,8 +1428,8 @@ public final class TvInputManagerService extends SystemService {
|
||||
@Override
|
||||
public void tune(IBinder sessionToken, final Uri channelUri, Bundle params, int userId) {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
|
||||
userId, "tune");
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId, "tune");
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
@@ -1432,8 +1441,7 @@ public final class TvInputManagerService extends SystemService {
|
||||
if (sessionState != null) {
|
||||
sessionState.isCurrent = true;
|
||||
sessionState.currentChannel = channelUri;
|
||||
notifyCurrentChannelInfosUpdatedLocked(
|
||||
userState, getCurrentTvChannelInfosInternalLocked(userState));
|
||||
notifyCurrentChannelInfosUpdatedLocked(userState);
|
||||
}
|
||||
if (TvContract.isChannelUriForPassthroughInput(channelUri)) {
|
||||
// Do not log the watch history for passthrough inputs.
|
||||
@@ -2090,16 +2098,13 @@ public final class TvInputManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public List<TvChannelInfo> getCurrentTvChannelInfos(@UserIdInt int userId) {
|
||||
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
|
||||
Binder.getCallingUid(), userId, "getTvCurrentChannelInfos");
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
|
||||
return getCurrentTvChannelInfosInternalLocked(userState);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
int callingPid = Binder.getCallingPid();
|
||||
int callingUid = Binder.getCallingUid();
|
||||
final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
|
||||
"getTvCurrentChannelInfos");
|
||||
synchronized (mLock) {
|
||||
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
|
||||
return getCurrentTvChannelInfosInternalLocked(userState, callingPid, callingUid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2273,14 +2278,15 @@ public final class TvInputManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private List<TvChannelInfo> getCurrentTvChannelInfosInternalLocked(UserState userState) {
|
||||
private List<TvChannelInfo> getCurrentTvChannelInfosInternalLocked(
|
||||
UserState userState, int callingPid, int callingUid) {
|
||||
List<TvChannelInfo> channelInfos = new ArrayList<>();
|
||||
boolean watchedProgramsAccess = hasAccessWatchedProgramsPermission();
|
||||
boolean watchedProgramsAccess = hasAccessWatchedProgramsPermission(callingPid, callingUid);
|
||||
for (SessionState state : userState.sessionStateMap.values()) {
|
||||
if (state.isCurrent) {
|
||||
Integer appTag;
|
||||
int appType;
|
||||
if (state.callingUid == Binder.getCallingUid()) {
|
||||
if (state.callingUid == callingUid) {
|
||||
appTag = APP_TAG_SELF;
|
||||
appType = TvChannelInfo.APP_TYPE_SELF;
|
||||
} else {
|
||||
@@ -2322,8 +2328,8 @@ public final class TvInputManagerService extends SystemService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasAccessWatchedProgramsPermission() {
|
||||
return mContext.checkCallingPermission(PERMISSION_ACCESS_WATCHED_PROGRAMS)
|
||||
private boolean hasAccessWatchedProgramsPermission(int callingPid, int callingUid) {
|
||||
return mContext.checkPermission(PERMISSION_ACCESS_WATCHED_PROGRAMS, callingPid, callingUid)
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
@@ -2360,6 +2366,9 @@ public final class TvInputManagerService extends SystemService {
|
||||
private final RemoteCallbackList<ITvInputManagerCallback> mCallbacks =
|
||||
new RemoteCallbackList<ITvInputManagerCallback>();
|
||||
|
||||
private final Map<ITvInputManagerCallback, Pair<Integer, Integer>> callbackPidUidMap =
|
||||
new HashMap<>();
|
||||
|
||||
// The token of a "main" TV input session.
|
||||
private IBinder mainSessionToken = null;
|
||||
|
||||
@@ -2712,8 +2721,7 @@ public final class TvInputManagerService extends SystemService {
|
||||
mSessionState.isCurrent = true;
|
||||
mSessionState.currentChannel = channelUri;
|
||||
UserState userState = getOrCreateUserStateLocked(mSessionState.userId);
|
||||
notifyCurrentChannelInfosUpdatedLocked(
|
||||
userState, getCurrentTvChannelInfosInternalLocked(userState));
|
||||
notifyCurrentChannelInfosUpdatedLocked(userState);
|
||||
try {
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user