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

Commit fdce9e54 authored by Dongwon Kang's avatar Dongwon Kang
Browse files

TIF: handle a race condition when a session is crashed

Currently, TIMS has a logic for handling session crash (binderDied).
However, this can be racy if the client calls an operation right before it gets
ITvInputClient.onSessionReleased() callback. This change handles those request
gracefully without causing a crash in the client side.

Bug: 18612616
Change-Id: I37241e05d53f3cca693e0239fc9ad5dce02fc925
parent 130e30fe
Loading
Loading
Loading
Loading
+46 −33
Original line number Diff line number Diff line
@@ -461,7 +461,7 @@ public final class TvInputManagerService extends SystemService {
        UserState userState = getUserStateLocked(userId);
        SessionState sessionState = userState.sessionStateMap.get(sessionToken);
        if (sessionState == null) {
            throw new IllegalArgumentException("Session state not found for token " + sessionToken);
            throw new SessionNotFoundException("Session state not found for token " + sessionToken);
        }
        // Only the application that requested this session or the system can access it.
        if (callingUid != Process.SYSTEM_UID && callingUid != sessionState.callingUid) {
@@ -589,19 +589,23 @@ public final class TvInputManagerService extends SystemService {
    }

    private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) {
        SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
        SessionState sessionState = null;
        try {
            sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
            if (sessionState.session != null) {
                UserState userState = getUserStateLocked(userId);
                if (sessionToken == userState.mainSessionToken) {
                    setMainLocked(sessionToken, false, callingUid, userId);
                }
            try {
                sessionState.session.release();
            } catch (RemoteException e) {
                Slog.e(TAG, "session process has already died", e);
            }
        } catch (RemoteException | SessionNotFoundException e) {
            Slog.e(TAG, "error in releaseSession", e);
        } finally {
            if (sessionState != null) {
                sessionState.session = null;
            }
        }
        removeSessionStateLocked(sessionToken, userId);
    }

@@ -648,6 +652,7 @@ public final class TvInputManagerService extends SystemService {
    }

    private void setMainLocked(IBinder sessionToken, boolean isMain, int callingUid, int userId) {
        try {
            SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
            if (sessionState.hardwareSessionToken != null) {
                sessionState = getSessionStateLocked(sessionState.hardwareSessionToken,
@@ -658,9 +663,8 @@ public final class TvInputManagerService extends SystemService {
                return;
            }
            ITvInputSession session = getSessionLocked(sessionState);
        try {
            session.setMain(isMain);
        } catch (RemoteException e) {
        } catch (RemoteException | SessionNotFoundException e) {
            Slog.e(TAG, "error in setMain", e);
        }
    }
@@ -1085,7 +1089,7 @@ public final class TvInputManagerService extends SystemService {
                            getSessionLocked(sessionState.hardwareSessionToken,
                                    Process.SYSTEM_UID, resolvedUserId).setSurface(surface);
                        }
                    } catch (RemoteException e) {
                    } catch (RemoteException | SessionNotFoundException e) {
                        Slog.e(TAG, "error in setSurface", e);
                    }
                }
@@ -1116,7 +1120,7 @@ public final class TvInputManagerService extends SystemService {
                            getSessionLocked(sessionState.hardwareSessionToken, Process.SYSTEM_UID,
                                    resolvedUserId).dispatchSurfaceChanged(format, width, height);
                        }
                    } catch (RemoteException e) {
                    } catch (RemoteException | SessionNotFoundException e) {
                        Slog.e(TAG, "error in dispatchSurfaceChanged", e);
                    }
                }
@@ -1146,7 +1150,7 @@ public final class TvInputManagerService extends SystemService {
                                    Process.SYSTEM_UID, resolvedUserId).setVolume((volume > 0.0f)
                                            ? REMOTE_VOLUME_ON : REMOTE_VOLUME_OFF);
                        }
                    } catch (RemoteException e) {
                    } catch (RemoteException | SessionNotFoundException e) {
                        Slog.e(TAG, "error in setVolume", e);
                    }
                }
@@ -1183,7 +1187,7 @@ public final class TvInputManagerService extends SystemService {
                        args.arg5 = sessionToken;
                        mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_LOG_WATCH_START, args)
                                .sendToTarget();
                    } catch (RemoteException e) {
                    } catch (RemoteException | SessionNotFoundException e) {
                        Slog.e(TAG, "error in tune", e);
                        return;
                    }
@@ -1205,7 +1209,7 @@ public final class TvInputManagerService extends SystemService {
                    try {
                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
                                .requestUnblockContent(unblockedRating);
                    } catch (RemoteException e) {
                    } catch (RemoteException | SessionNotFoundException e) {
                        Slog.e(TAG, "error in requestUnblockContent", e);
                    }
                }
@@ -1225,7 +1229,7 @@ public final class TvInputManagerService extends SystemService {
                    try {
                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
                                .setCaptionEnabled(enabled);
                    } catch (RemoteException e) {
                    } catch (RemoteException | SessionNotFoundException e) {
                        Slog.e(TAG, "error in setCaptionEnabled", e);
                    }
                }
@@ -1245,7 +1249,7 @@ public final class TvInputManagerService extends SystemService {
                    try {
                        getSessionLocked(sessionToken, callingUid, resolvedUserId).selectTrack(
                                type, trackId);
                    } catch (RemoteException e) {
                    } catch (RemoteException | SessionNotFoundException e) {
                        Slog.e(TAG, "error in selectTrack", e);
                    }
                }
@@ -1266,7 +1270,7 @@ public final class TvInputManagerService extends SystemService {
                    try {
                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
                                .appPrivateCommand(command, data);
                    } catch (RemoteException e) {
                    } catch (RemoteException | SessionNotFoundException e) {
                        Slog.e(TAG, "error in appPrivateCommand", e);
                    }
                }
@@ -1287,7 +1291,7 @@ public final class TvInputManagerService extends SystemService {
                    try {
                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
                                .createOverlayView(windowToken, frame);
                    } catch (RemoteException e) {
                    } catch (RemoteException | SessionNotFoundException e) {
                        Slog.e(TAG, "error in createOverlayView", e);
                    }
                }
@@ -1307,7 +1311,7 @@ public final class TvInputManagerService extends SystemService {
                    try {
                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
                                .relayoutOverlayView(frame);
                    } catch (RemoteException e) {
                    } catch (RemoteException | SessionNotFoundException e) {
                        Slog.e(TAG, "error in relayoutOverlayView", e);
                    }
                }
@@ -1327,7 +1331,7 @@ public final class TvInputManagerService extends SystemService {
                    try {
                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
                                .removeOverlayView();
                    } catch (RemoteException e) {
                    } catch (RemoteException | SessionNotFoundException e) {
                        Slog.e(TAG, "error in removeOverlayView", e);
                    }
                }
@@ -2340,4 +2344,13 @@ public final class TvInputManagerService extends SystemService {
            }
        }
    }

    private static class SessionNotFoundException extends IllegalArgumentException {
        public SessionNotFoundException() {
        }

        public SessionNotFoundException(String name) {
            super(name);
        }
    }
}