Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e1505c79 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Use pid and uid for getCurrentTvChannelInfo"

parents 1d9fa39b 6f10e974
Loading
Loading
Loading
Loading
+70 −2
Original line number Diff line number Diff line
@@ -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);
    }
}
+14 −2
Original line number Diff line number Diff line
@@ -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);
+36 −28
Original line number Diff line number Diff line
@@ -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 {
            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);
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
                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