am 9de91850: am 2c315fef: am 1becc968: TIF: Call setMain(false) when session is released.
* commit '9de91850dc48e4a65749bda2c9f511e0876a56b0': TIF: Call setMain(false) when session is released.
This commit is contained in:
@@ -29,7 +29,7 @@ import android.view.Surface;
|
||||
oneway interface ITvInputSession {
|
||||
void release();
|
||||
|
||||
void setMainSession(boolean isMainSession);
|
||||
void setMain(boolean isMain);
|
||||
void setSurface(in Surface surface);
|
||||
void dispatchSurfaceChanged(int format, int width, int height);
|
||||
// TODO: Remove this once it becomes irrelevant for applications to handle audio focus. The plan
|
||||
|
||||
@@ -42,7 +42,7 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
|
||||
private static final String TAG = "TvInputSessionWrapper";
|
||||
|
||||
private static final int DO_RELEASE = 1;
|
||||
private static final int DO_SET_MAIN_SESSION = 2;
|
||||
private static final int DO_SET_MAIN = 2;
|
||||
private static final int DO_SET_SURFACE = 3;
|
||||
private static final int DO_DISPATCH_SURFACE_CHANGED = 4;
|
||||
private static final int DO_SET_STREAM_VOLUME = 5;
|
||||
@@ -91,8 +91,8 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
|
||||
}
|
||||
return;
|
||||
}
|
||||
case DO_SET_MAIN_SESSION: {
|
||||
mTvInputSessionImpl.setMainSession((Boolean) msg.obj);
|
||||
case DO_SET_MAIN: {
|
||||
mTvInputSessionImpl.setMain((Boolean) msg.obj);
|
||||
return;
|
||||
}
|
||||
case DO_SET_SURFACE: {
|
||||
@@ -162,8 +162,8 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMainSession(boolean isMain) {
|
||||
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_MAIN_SESSION, isMain));
|
||||
public void setMain(boolean isMain) {
|
||||
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_MAIN, isMain));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1023,10 +1023,12 @@ public final class TvInputManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this as main session. See {@link TvView#setMainTvView} for about meaning of "main".
|
||||
* @hide
|
||||
* Sets this as the main session. The main session is a session whose corresponding TV
|
||||
* input determines the HDMI-CEC active source device.
|
||||
*
|
||||
* @see TvView#setMain
|
||||
*/
|
||||
public void setMainSession() {
|
||||
void setMain() {
|
||||
if (mToken == null) {
|
||||
Log.w(TAG, "The session has been already released");
|
||||
return;
|
||||
|
||||
@@ -551,29 +551,30 @@ public abstract class TvInputService extends Service {
|
||||
public abstract void onRelease();
|
||||
|
||||
/**
|
||||
* Set the current session as the "main" session. See {@link TvView#setMainTvView} for the
|
||||
* meaning of "main".
|
||||
* Sets the current session as the main session. The main session is a session whose
|
||||
* corresponding TV input determines the HDMI-CEC active source device.
|
||||
* <p>
|
||||
* This is primarily for HDMI-CEC active source management. TV input service that manages
|
||||
* HDMI-CEC logical device should make sure not only to select the corresponding HDMI
|
||||
* logical device as source device on {@code onSetMainSession(true)}, but also to select
|
||||
* internal device on {@code onSetMainSession(false)}. Also, if surface is set to non-main
|
||||
* session, it needs to select internal device after temporarily selecting corresponding
|
||||
* HDMI logical device for set up.
|
||||
* TV input service that manages HDMI-CEC logical device should implement {@link
|
||||
* #onSetMain} to (1) select the corresponding HDMI logical device as the source device
|
||||
* when {@code isMain} is {@code true}, and to (2) select the internal device (= TV itself)
|
||||
* as the source device when {@code isMain} is {@code false} and the session is still main.
|
||||
* Also, if a surface is passed to a non-main session and active source is changed to
|
||||
* initiate the surface, the active source should be returned to the main session.
|
||||
* </p><p>
|
||||
* It is guaranteed that {@code onSetMainSession(true)} for new session is called first,
|
||||
* and {@code onSetMainSession(false)} for old session is called afterwards. This allows
|
||||
* {@code onSetMainSession(false)} to be no-op when TV input service knows that the next
|
||||
* main session corresponds to another HDMI logical device. Practically, this implies that
|
||||
* one TV input service should handle all HDMI port and HDMI-CEC logical devices for smooth
|
||||
* active source transition.
|
||||
* {@link TvView} guarantees that, when tuning involves a session transition, {@code
|
||||
* onSetMain(true)} for new session is called first, {@code onSetMain(false)} for old
|
||||
* session is called afterwards. This allows {@code onSetMain(false)} to be no-op when TV
|
||||
* input service knows that the next main session corresponds to another HDMI logical
|
||||
* device. Practically, this implies that one TV input service should handle all HDMI port
|
||||
* and HDMI-CEC logical devices for smooth active source transition.
|
||||
* </p>
|
||||
*
|
||||
* @param isMainSession If true, session is main.
|
||||
* @param isMain If true, session should become main.
|
||||
* @see TvView#setMain
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public void onSetMainSession(boolean isMainSession) {
|
||||
public void onSetMain(boolean isMain) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -841,10 +842,10 @@ public abstract class TvInputService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link #onSetMainSession}.
|
||||
* Calls {@link #onSetMain}.
|
||||
*/
|
||||
void setMainSession(boolean isMainSession) {
|
||||
onSetMainSession(isMainSession);
|
||||
void setMain(boolean isMain) {
|
||||
onSetMain(isMain);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -116,8 +116,10 @@ public class TvView extends ViewGroup {
|
||||
private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
Log.d(TAG, "surfaceChanged(holder=" + holder + ", format=" + format + ", width=" + width
|
||||
+ ", height=" + height + ")");
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "surfaceChanged(holder=" + holder + ", format=" + format + ", width="
|
||||
+ width + ", height=" + height + ")");
|
||||
}
|
||||
mSurfaceFormat = format;
|
||||
mSurfaceWidth = width;
|
||||
mSurfaceHeight = height;
|
||||
@@ -188,24 +190,27 @@ public class TvView extends ViewGroup {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this as main TvView.
|
||||
* Sets this as the main {@link TvView}.
|
||||
* <p>
|
||||
* Main TvView is the TvView which user is watching and interacting mainly. It is used for
|
||||
* determining internal behavior of hardware TV input devices. For example, this influences
|
||||
* how HDMI-CEC active source will be managed.
|
||||
* The main {@link TvView} is a {@link TvView} whose corresponding TV input determines the
|
||||
* HDMI-CEC active source device. For an HDMI port input, one of source devices that is
|
||||
* connected to that HDMI port becomes the active source. For an HDMI-CEC logical device input,
|
||||
* the corresponding HDMI-CEC logical device becomes the active source. For any non-HDMI input
|
||||
* (including the tuner, composite, S-Video, etc.), the internal device (= TV itself) becomes
|
||||
* the active source.
|
||||
* </p><p>
|
||||
* First tuned TvView becomes main automatically, and keeps to be main until setMainTvView() is
|
||||
* called for other TvView. Note that main TvView won't be reset even when current main TvView
|
||||
* is removed from view hierarchy.
|
||||
* First tuned {@link TvView} becomes main automatically, and keeps to be main until {@link
|
||||
* #setMain} is called for other {@link TvView}. Note that main {@link TvView} won't be reset
|
||||
* even when current main {@link TvView} is removed from view hierarchy.
|
||||
* </p>
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public void setMainTvView() {
|
||||
public void setMain() {
|
||||
synchronized (sMainTvViewLock) {
|
||||
sMainTvView = this;
|
||||
if (hasWindowFocus() && mSession != null) {
|
||||
mSession.setMainSession();
|
||||
mSession.setMain();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,6 +332,7 @@ public class TvView extends ViewGroup {
|
||||
* This method is primarily used to un-tune the current TvView.
|
||||
*/
|
||||
public void reset() {
|
||||
if (DEBUG) Log.d(TAG, "reset()");
|
||||
if (mSession != null) {
|
||||
release();
|
||||
resetSurfaceView();
|
||||
@@ -538,7 +544,7 @@ public class TvView extends ViewGroup {
|
||||
// Set main again to regain main session.
|
||||
synchronized (sMainTvViewLock) {
|
||||
if (hasFocus && this == sMainTvView && mSession != null) {
|
||||
mSession.setMainSession();
|
||||
mSession.setMain();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -596,6 +602,7 @@ public class TvView extends ViewGroup {
|
||||
mSurfaceView.getHolder().removeCallback(mSurfaceHolderCallback);
|
||||
removeView(mSurfaceView);
|
||||
}
|
||||
mSurface = null;
|
||||
mSurfaceView = new SurfaceView(getContext(), mAttrs, mDefStyleAttr) {
|
||||
@Override
|
||||
protected void updateWindow(boolean force, boolean redrawNeeded) {
|
||||
@@ -821,11 +828,14 @@ public class TvView extends ViewGroup {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onSessionCreated()");
|
||||
}
|
||||
mSession = session;
|
||||
if (session != null) {
|
||||
synchronized (sMainTvViewLock) {
|
||||
if (hasWindowFocus() && TvView.this == sMainTvView) {
|
||||
mSession.setMainSession();
|
||||
mSession.setMain();
|
||||
}
|
||||
}
|
||||
// mSurface may not be ready yet as soon as starting an application.
|
||||
|
||||
@@ -691,6 +691,10 @@ public final class TvInputManagerService extends SystemService {
|
||||
private void releaseSessionLocked(IBinder sessionToken, int callingUid, int userId) {
|
||||
SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
|
||||
if (sessionState.mSession != null) {
|
||||
UserState userState = getUserStateLocked(userId);
|
||||
if (sessionToken == userState.mainSessionToken) {
|
||||
setMainLocked(sessionToken, false, callingUid, userId);
|
||||
}
|
||||
try {
|
||||
sessionState.mSession.release();
|
||||
} catch (RemoteException e) {
|
||||
@@ -704,6 +708,9 @@ public final class TvInputManagerService extends SystemService {
|
||||
private void removeSessionStateLocked(IBinder sessionToken, int userId) {
|
||||
UserState userState = getUserStateLocked(userId);
|
||||
if (sessionToken == userState.mainSessionToken) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "mainSessionToken=null");
|
||||
}
|
||||
userState.mainSessionToken = null;
|
||||
}
|
||||
|
||||
@@ -740,6 +747,25 @@ public final class TvInputManagerService extends SystemService {
|
||||
mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_LOG_WATCH_END, args).sendToTarget();
|
||||
}
|
||||
|
||||
private void setMainLocked(IBinder sessionToken, boolean isMain, int callingUid, int userId) {
|
||||
SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userId);
|
||||
if (sessionState.mHardwareSessionToken != null) {
|
||||
sessionState = getSessionStateLocked(sessionState.mHardwareSessionToken,
|
||||
Process.SYSTEM_UID, userId);
|
||||
}
|
||||
ServiceState serviceState = getServiceStateLocked(sessionState.mInfo.getComponent(),
|
||||
userId);
|
||||
if (!serviceState.mIsHardware) {
|
||||
return;
|
||||
}
|
||||
ITvInputSession session = getSessionLocked(sessionState);
|
||||
try {
|
||||
session.setMain(isMain);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "error in setMain", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyInputAddedLocked(UserState userState, String inputId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "notifyInputAdded: inputId = " + inputId);
|
||||
@@ -1050,6 +1076,9 @@ public final class TvInputManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void releaseSession(IBinder sessionToken, int userId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "releaseSession(): " + sessionToken);
|
||||
}
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
|
||||
userId, "releaseSession");
|
||||
@@ -1065,6 +1094,9 @@ public final class TvInputManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void setMainSession(IBinder sessionToken, int userId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "setMainSession(): " + sessionToken);
|
||||
}
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
|
||||
userId, "setMainSession");
|
||||
@@ -1075,50 +1107,19 @@ public final class TvInputManagerService extends SystemService {
|
||||
if (userState.mainSessionToken == sessionToken) {
|
||||
return;
|
||||
}
|
||||
|
||||
SessionState newMainSessionState = getSessionStateLocked(
|
||||
sessionToken, callingUid, resolvedUserId);
|
||||
if (newMainSessionState.mHardwareSessionToken != null) {
|
||||
newMainSessionState = getSessionStateLocked(
|
||||
newMainSessionState.mHardwareSessionToken,
|
||||
Process.SYSTEM_UID, resolvedUserId);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "mainSessionToken=" + sessionToken);
|
||||
}
|
||||
ServiceState newMainServiceState = getServiceStateLocked(
|
||||
newMainSessionState.mInfo.getComponent(), resolvedUserId);
|
||||
ITvInputSession newMainSession = getSessionLocked(newMainSessionState);
|
||||
|
||||
ServiceState oldMainServiceState = null;
|
||||
ITvInputSession oldMainSession = null;
|
||||
if (userState.mainSessionToken != null) {
|
||||
SessionState oldMainSessionState = getSessionStateLocked(
|
||||
userState.mainSessionToken, Process.SYSTEM_UID, resolvedUserId);
|
||||
if (oldMainSessionState.mHardwareSessionToken != null) {
|
||||
oldMainSessionState = getSessionStateLocked(
|
||||
oldMainSessionState.mHardwareSessionToken,
|
||||
Process.SYSTEM_UID, resolvedUserId);
|
||||
}
|
||||
oldMainServiceState = getServiceStateLocked(
|
||||
oldMainSessionState.mInfo.getComponent(), resolvedUserId);
|
||||
oldMainSession = getSessionLocked(oldMainSessionState);
|
||||
}
|
||||
|
||||
IBinder oldMainSessionToken = userState.mainSessionToken;
|
||||
userState.mainSessionToken = sessionToken;
|
||||
|
||||
// Inform the new main session first.
|
||||
// See {@link TvInputService#onSetMainSession}.
|
||||
if (newMainServiceState.mIsHardware) {
|
||||
try {
|
||||
newMainSession.setMainSession(true);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "error in setMainSession", e);
|
||||
}
|
||||
// See {@link TvInputService.Session#onSetMain}.
|
||||
if (sessionToken != null) {
|
||||
setMainLocked(sessionToken, true, callingUid, userId);
|
||||
}
|
||||
if (oldMainSession != null && oldMainServiceState.mIsHardware) {
|
||||
try {
|
||||
oldMainSession.setMainSession(false);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "error in setMainSession", e);
|
||||
}
|
||||
if (oldMainSessionToken != null) {
|
||||
setMainLocked(oldMainSessionToken, false, Process.SYSTEM_UID, userId);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user