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

Commit 990957db authored by shubang's avatar shubang
Browse files

Implement callback for current channel infos

Test: mmm
Change-Id: Ia808cddfaab1a506ed106a31b698e406d732646c
parent 47a260f8
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ interface ITvInputManager {
    void timeShiftSetPlaybackParams(in IBinder sessionToken, in PlaybackParams params, int userId);
    void timeShiftEnablePositionTracking(in IBinder sessionToken, boolean enable, int userId);

    List<TvChannelInfo> getTvCurrentChannelInfos(int userId);
    List<TvChannelInfo> getCurrentTvChannelInfos(int userId);

    // For the recording session
    void startRecording(in IBinder sessionToken, in Uri programUri, in Bundle params, int userId);
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.media.tv;

import android.media.tv.TvChannelInfo;
import android.media.tv.TvInputInfo;

/**
@@ -28,4 +29,5 @@ oneway interface ITvInputManagerCallback {
    void onInputUpdated(in String inputId);
    void onInputStateChanged(in String inputId, int state);
    void onTvInputInfoUpdated(in TvInputInfo TvInputInfo);
    void onCurrentTvChannelInfosUpdated(in List<TvChannelInfo> currentTvChannelInfos);
}
+25 −4
Original line number Diff line number Diff line
@@ -899,6 +899,10 @@ public final class TvInputManager {
         */
        public void onTvInputInfoUpdated(TvInputInfo inputInfo) {
        }

        /** @hide */
        public void onCurrentTvChannelInfosUpdated(List<TvChannelInfo> tvChannelInfos) {
        }
    }

    private static final class TvInputCallbackRecord {
@@ -958,6 +962,16 @@ public final class TvInputManager {
                }
            });
        }

        public void postCurrentTvChannelInfosUpdated(
                final List<TvChannelInfo> currentTvChannelInfos) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mCallback.onCurrentTvChannelInfosUpdated(currentTvChannelInfos);
                }
            });
        }
    }

    /**
@@ -1262,6 +1276,15 @@ public final class TvInputManager {
                    }
                }
            }

            @Override
            public void onCurrentTvChannelInfosUpdated(List<TvChannelInfo> currentTvChannelInfos) {
                synchronized (mLock) {
                    for (TvInputCallbackRecord record : mCallbackRecords) {
                        record.postCurrentTvChannelInfosUpdated(currentTvChannelInfos);
                    }
                }
            }
        };
        try {
            if (mService != null) {
@@ -1955,11 +1978,9 @@ public final class TvInputManager {
    /**
     * @hide
     */
    public List<TvChannelInfo> getTvCurrentChannelInfos() {
        // TODO: handle retuned() cases and add a method to TvInputCallback
        // TODO: unhide
    public List<TvChannelInfo> getCurrentTvChannelInfos() {
        try {
            return mService.getTvCurrentChannelInfos(mUserId);
            return mService.getCurrentTvChannelInfos(mUserId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+91 −62
Original line number Diff line number Diff line
@@ -699,8 +699,8 @@ public final class TvInputManagerService extends SystemService {
        SessionState sessionState = null;
        try {
            sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
            if (sessionState.session != null) {
            UserState userState = getOrCreateUserStateLocked(userId);
            if (sessionState.session != null) {
                if (sessionToken == userState.mainSessionToken) {
                    setMainLocked(sessionToken, false, callingUid, userId);
                }
@@ -709,6 +709,8 @@ public final class TvInputManagerService extends SystemService {
            }
            sessionState.isCurrent = false;
            sessionState.currentChannel = null;
            notifyCurrentChannelInfosUpdatedLocked(
                    userState, getCurrentTvChannelInfosInternalLocked(userState));
        } catch (RemoteException | SessionNotFoundException e) {
            Slog.e(TAG, "error in releaseSession", e);
        } finally {
@@ -849,6 +851,22 @@ public final class TvInputManagerService extends SystemService {
        }
    }

    private void notifyCurrentChannelInfosUpdatedLocked(
            UserState userState, List<TvChannelInfo> infos) {
        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);
            } catch (RemoteException e) {
                Slog.e(TAG, "failed to report updated current channel infos to callback", e);
            }
        }
        userState.mCallbacks.finishBroadcast();
    }

    private void updateTvInputInfoLocked(UserState userState, TvInputInfo inputInfo) {
        if (DEBUG) {
            Slog.d(TAG, "updateTvInputInfoLocked(inputInfo=" + inputInfo + ")");
@@ -1414,6 +1432,8 @@ public final class TvInputManagerService extends SystemService {
                        if (sessionState != null) {
                            sessionState.isCurrent = true;
                            sessionState.currentChannel = channelUri;
                            notifyCurrentChannelInfosUpdatedLocked(
                                    userState, getCurrentTvChannelInfosInternalLocked(userState));
                        }
                        if (TvContract.isChannelUriForPassthroughInput(channelUri)) {
                            // Do not log the watch history for passthrough inputs.
@@ -2069,79 +2089,20 @@ public final class TvInputManagerService extends SystemService {
        }

        @Override
        public List<TvChannelInfo> getTvCurrentChannelInfos(@UserIdInt int userId) {
        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);
                    List<TvChannelInfo> channelInfos = new ArrayList<>();
                    boolean watchedProgramsAccess = hasAccessWatchedProgramsPermission();
                    for (SessionState state : userState.sessionStateMap.values()) {
                        if (state.isCurrent) {
                            Integer appTag;
                            int appType;
                            if (state.callingUid == Binder.getCallingUid()) {
                                appTag = APP_TAG_SELF;
                                appType = TvChannelInfo.APP_TYPE_SELF;
                            } else {
                                appTag = userState.mAppTagMap.get(state.callingUid);
                                if (appTag == null) {
                                    appTag = userState.mNextAppTag++;
                                    userState.mAppTagMap.put(state.callingUid, appTag);
                                }
                                appType = isSystemApp(state.componentName.getPackageName())
                                        ? TvChannelInfo.APP_TYPE_SYSTEM
                                        : TvChannelInfo.APP_TYPE_NON_SYSTEM;
                            }
                            channelInfos.add(new TvChannelInfo(
                                    state.inputId,
                                    watchedProgramsAccess ? state.currentChannel : null,
                                    state.isRecordingSession,
                                    isForeground(state.callingPid),
                                    appType,
                                    appTag));
                        }
                    }
                    return channelInfos;
                    return getCurrentTvChannelInfosInternalLocked(userState);
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }

        protected 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() {
            return mContext.checkCallingPermission(PERMISSION_ACCESS_WATCHED_PROGRAMS)
                    == PackageManager.PERMISSION_GRANTED;
        }

        private boolean isSystemApp(String pkg) {
            try {
                return (mContext.getPackageManager().getApplicationInfo(pkg, 0).flags
                        & ApplicationInfo.FLAG_SYSTEM) != 0;
            } catch (NameNotFoundException e) {
                return false;
            }
        }

        /**
         * Add a hardware device in the TvInputHardwareManager for CTS testing
         * purpose.
@@ -2312,6 +2273,69 @@ public final class TvInputManagerService extends SystemService {
        }
    }

    private List<TvChannelInfo> getCurrentTvChannelInfosInternalLocked(UserState userState) {
        List<TvChannelInfo> channelInfos = new ArrayList<>();
        boolean watchedProgramsAccess = hasAccessWatchedProgramsPermission();
        for (SessionState state : userState.sessionStateMap.values()) {
            if (state.isCurrent) {
                Integer appTag;
                int appType;
                if (state.callingUid == Binder.getCallingUid()) {
                    appTag = APP_TAG_SELF;
                    appType = TvChannelInfo.APP_TYPE_SELF;
                } else {
                    appTag = userState.mAppTagMap.get(state.callingUid);
                    if (appTag == null) {
                        appTag = userState.mNextAppTag++;
                        userState.mAppTagMap.put(state.callingUid, appTag);
                    }
                    appType = isSystemApp(state.componentName.getPackageName())
                            ? TvChannelInfo.APP_TYPE_SYSTEM
                            : TvChannelInfo.APP_TYPE_NON_SYSTEM;
                }
                channelInfos.add(new TvChannelInfo(
                        state.inputId,
                        watchedProgramsAccess ? state.currentChannel : null,
                        state.isRecordingSession,
                        isForeground(state.callingPid),
                        appType,
                        appTag));
            }
        }
        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() {
        return mContext.checkCallingPermission(PERMISSION_ACCESS_WATCHED_PROGRAMS)
                == PackageManager.PERMISSION_GRANTED;
    }

    private boolean isSystemApp(String pkg) {
        try {
            return (mContext.getPackageManager().getApplicationInfo(pkg, 0).flags
                    & ApplicationInfo.FLAG_SYSTEM) != 0;
        } catch (NameNotFoundException e) {
            return false;
        }
    }

    private static final class UserState {
        // A mapping from the TV input id to its TvInputState.
        private Map<String, TvInputState> inputMap = new HashMap<>();
@@ -2685,6 +2709,11 @@ public final class TvInputManagerService extends SystemService {
                if (mSessionState.session == null || mSessionState.client == null) {
                    return;
                }
                mSessionState.isCurrent = true;
                mSessionState.currentChannel = channelUri;
                UserState userState = getOrCreateUserStateLocked(mSessionState.userId);
                notifyCurrentChannelInfosUpdatedLocked(
                        userState, getCurrentTvChannelInfosInternalLocked(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