From 911d0827ca67d61c141ab91e75816da94b3f414e Mon Sep 17 00:00:00 2001 From: Dongwon Kang Date: Mon, 18 Aug 2014 16:05:17 -0700 Subject: [PATCH 1/5] TIF: verify the hardware input ID from getHardwareInputId(). This will prevent an input from displaying other tuner inputs. Change-Id: I77a6b99599eac4a9048a12e2928bc16b34d94343 --- .../java/android/media/tv/TvInputService.java | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index c93b2616b5db6..f34f6955b4bb9 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -94,6 +94,8 @@ public abstract class TvInputService extends Service { private final RemoteCallbackList mCallbacks = new RemoteCallbackList(); + private TvInputManager mTvInputManager; + @Override public final IBinder onBind(Intent intent) { return new ITvInputService.Stub() { @@ -225,6 +227,17 @@ public abstract class TvInputService extends Service { return null; } + private boolean isPassthroughInput(String inputId) { + if (mTvInputManager == null) { + mTvInputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE); + } + TvInputInfo info = mTvInputManager.getTvInputInfo(inputId); + if (info != null && info.isPassthroughInput()) { + return true; + } + return false; + } + /** * Base class for derived classes to implement to provide a TV input session. */ @@ -1229,9 +1242,14 @@ public abstract class TvInputService extends Service { HardwareSession proxySession = ((HardwareSession) sessionImpl); String harewareInputId = proxySession.getHardwareInputId(); - if (TextUtils.isEmpty(harewareInputId)) { + if (TextUtils.isEmpty(harewareInputId) || + !isPassthroughInput(harewareInputId)) { + if (TextUtils.isEmpty(harewareInputId)) { + Log.w(TAG, "Hardware input id is not setup yet."); + } else { + Log.w(TAG, "Invalid hardware input id : " + harewareInputId); + } sessionImpl.onRelease(); - Log.w(TAG, "Hardware input id is not setup yet."); try { cb.onSessionCreated(null, null); } catch (RemoteException e) { @@ -1239,7 +1257,6 @@ public abstract class TvInputService extends Service { } return; } - // TODO: check if the given ID is really hardware TV input. proxySession.mProxySession = stub; proxySession.mProxySessionCallback = cb; proxySession.mServiceHandler = mServiceHandler; From a42be3c95021c5fb7e4ac0a8fbfc542f841f44dd Mon Sep 17 00:00:00 2001 From: Jaewan Kim Date: Tue, 19 Aug 2014 11:55:07 +0900 Subject: [PATCH 2/5] Fix NPE when passing null TvContentRating Change-Id: I80b0ca60b1623356fd39015521b50ae9f1eaef07 --- media/java/android/media/tv/TvInputManager.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index f76c78b66044a..815ba5208cc00 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -1339,6 +1339,9 @@ public final class TvInputManager { Log.w(TAG, "The session has been already released"); return; } + if (unblockedRating == null) { + throw new IllegalArgumentException("unblockedRating cannot be null"); + } try { mService.requestUnblockContent(mToken, unblockedRating.flattenToString(), mUserId); } catch (RemoteException e) { From ed0864557b3340ab7db00e2dc95b29c4b8bb485d Mon Sep 17 00:00:00 2001 From: Jinsuk Kim Date: Mon, 18 Aug 2014 15:01:53 +0900 Subject: [PATCH 3/5] CEC: Invoke events listener upon MHL device state change With this change, mobile devices state changes are propagated through TIF to UI, hence the input pickers shows the mobile devices as expected. Bug: 16986744 Change-Id: Id633207acf4f814f57d43cc1de5f8cb88ac23ad6 --- .../android/hardware/hdmi/HdmiDeviceInfo.java | 2 +- .../server/hdmi/HdmiCecLocalDeviceTv.java | 6 +- .../server/hdmi/HdmiControlService.java | 58 ++++++++++++++++--- .../com/android/server/hdmi/HdmiUtils.java | 16 +++++ 4 files changed, 68 insertions(+), 14 deletions(-) diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java index 97da3a2f16b09..d8da80e667326 100644 --- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java +++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java @@ -230,7 +230,7 @@ public class HdmiDeviceInfo implements Parcelable { mDeviceType = DEVICE_RESERVED; mVendorId = 0; mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN; - mDisplayName = "MHL"; + mDisplayName = "Mobile"; mDeviceId = adopterId; mAdopterId = deviceId; diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 809fef42875c8..126a56d5915af 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -1007,10 +1007,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { /** * Return external input devices. */ - List getSafeExternalInputs() { - synchronized (mLock) { - return mSafeExternalInputs; - } + List getSafeExternalInputsLocked() { + return mSafeExternalInputs; } @ServiceThreadOnly diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 14c066ebc305c..0b2cf8a74332e 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -16,6 +16,8 @@ package com.android.server.hdmi; +import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_ADD_DEVICE; +import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE; import static com.android.server.hdmi.Constants.DISABLED; import static com.android.server.hdmi.Constants.ENABLED; import static com.android.server.hdmi.Constants.OPTION_CEC_AUTO_WAKEUP; @@ -202,6 +204,9 @@ public final class HdmiControlService extends SystemService { @GuardedBy("mLock") private boolean mMhlInputChangeEnabled; + @GuardedBy("mLock") + private List mMhlDevices; + // List of listeners registered by callers that want to get notified of // system audio mode changes. private final ArrayList @@ -293,6 +298,7 @@ public final class HdmiControlService extends SystemService { Slog.i(TAG, "Device does not support MHL-control."); } initPortInfo(); + mMhlDevices = Collections.emptyList(); mMessageValidator = new HdmiCecMessageValidator(this); publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService()); @@ -684,16 +690,16 @@ public final class HdmiControlService extends SystemService { /** * Called when a new hotplug event is issued. * - * @param portNo hdmi port number where hot plug event issued. + * @param portId hdmi port number where hot plug event issued. * @param connected whether to be plugged in or not */ @ServiceThreadOnly - void onHotplug(int portNo, boolean connected) { + void onHotplug(int portId, boolean connected) { assertRunOnServiceThread(); for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) { - device.onHotplug(portNo, connected); + device.onHotplug(portId, connected); } - announceHotplugEvent(portNo, connected); + announceHotplugEvent(portId, connected); } /** @@ -794,10 +800,15 @@ public final class HdmiControlService extends SystemService { HdmiMhlLocalDevice device = mMhlController.removeLocalDevice(portId); if (device != null) { device.onDeviceRemoved(); + // There is no explicit event for device removal unlike capability register event + // used for device addition . Hence we remove the device on hotplug event. + invokeDeviceEventListeners(device.getInfo(), DEVICE_EVENT_REMOVE_DEVICE); + updateSafeMhlInput(); } else { Slog.w(TAG, "No device to remove:[portId=" + portId); } } + announceHotplugEvent(portId, connected); } @ServiceThreadOnly @@ -824,18 +835,45 @@ public final class HdmiControlService extends SystemService { } @ServiceThreadOnly - void handleCapabilityRegisterChanged(int portId, int adopterId, int deviceId) { + void handleMhlCapabilityRegisterChanged(int portId, int adopterId, int deviceId) { assertRunOnServiceThread(); HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId); - // Hot plug event should be called before capability register change event. + + // Hotplug event should already have been called before capability register change event. if (device != null) { device.setCapabilityRegister(adopterId, deviceId); + invokeDeviceEventListeners(device.getInfo(), DEVICE_EVENT_ADD_DEVICE); + updateSafeMhlInput(); } else { Slog.w(TAG, "No mhl device exists for capability register change event[portId:" + portId + ", adopterId:" + adopterId + ", deviceId:" + deviceId + "]"); } } + @ServiceThreadOnly + private void updateSafeMhlInput() { + assertRunOnServiceThread(); + List inputs = Collections.emptyList(); + SparseArray devices = mMhlController.getAllLocalDevices(); + for (int i = 0; i < devices.size(); ++i) { + HdmiMhlLocalDevice device = devices.valueAt(i); + HdmiDeviceInfo info = device.getInfo(); + if (info != null) { + if (inputs.isEmpty()) { + inputs = new ArrayList<>(); + } + inputs.add(device.getInfo()); + } + } + synchronized (mLock) { + mMhlDevices = inputs; + } + } + + private List getMhlDevicesLocked() { + return mMhlDevices; + } + // Record class that monitors the event of the caller of being killed. Used to clean up // the listener list and record list accordingly. private final class HotplugEventListenerRecord implements IBinder.DeathRecipient { @@ -1139,10 +1177,12 @@ public final class HdmiControlService extends SystemService { // No need to hold the lock for obtaining TV device as the local device instance // is preserved while the HDMI control is enabled. HdmiCecLocalDeviceTv tv = tv(); - if (tv == null) { - return Collections.emptyList(); + synchronized (mLock) { + List cecDevices = (tv == null) + ? Collections.emptyList() + : tv.getSafeExternalInputsLocked(); + return HdmiUtils.mergeToUnmodifiableList(cecDevices, getMhlDevicesLocked()); } - return tv.getSafeExternalInputs(); } @Override diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java index 23f19ff5944b1..22a519bdd067a 100644 --- a/services/core/java/com/android/server/hdmi/HdmiUtils.java +++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java @@ -206,6 +206,22 @@ final class HdmiUtils { return list; } + static List mergeToUnmodifiableList(List a, List b) { + if (a.isEmpty() && b.isEmpty()) { + return Collections.emptyList(); + } + if (a.isEmpty()) { + return Collections.unmodifiableList(b); + } + if (b.isEmpty()) { + return Collections.unmodifiableList(a); + } + List newList = new ArrayList<>(); + newList.addAll(a); + newList.addAll(b); + return Collections.unmodifiableList(newList); + } + /** * See if the new path is affecting the active path. * From 15c56aac985bc8d75f38fb4ecb92dda12d2ca06c Mon Sep 17 00:00:00 2001 From: Ji-Hwan Lee Date: Mon, 18 Aug 2014 22:01:55 +0900 Subject: [PATCH 4/5] TIF: Call setMain(false) when session is released. Also, rename setMainTvView() and setMainSession() to setMain(), except ITvInputManager. Change-Id: I586e3fd42720f07a75d6f31b1ee955ce5c29dd68 --- .../android/media/tv/ITvInputSession.aidl | 2 +- .../media/tv/ITvInputSessionWrapper.java | 10 +-- .../java/android/media/tv/TvInputManager.java | 8 +- .../java/android/media/tv/TvInputService.java | 39 ++++----- media/java/android/media/tv/TvView.java | 36 ++++++--- .../server/tv/TvInputManagerService.java | 79 ++++++++++--------- 6 files changed, 94 insertions(+), 80 deletions(-) diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl index 99fb91147707b..1aad2fabc03be 100644 --- a/media/java/android/media/tv/ITvInputSession.aidl +++ b/media/java/android/media/tv/ITvInputSession.aidl @@ -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 diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java index 5022cc128b353..58e46f0d27588 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -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 diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 815ba5208cc00..45aa6d6916fb4 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -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; diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index f34f6955b4bb9..e3292b6719160 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -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. *

- * 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. *

- * 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. *

* - * @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); } /** diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java index 591f5430fbd91..445194e2037fc 100644 --- a/media/java/android/media/tv/TvView.java +++ b/media/java/android/media/tv/TvView.java @@ -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}. *

- * 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. *

- * 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. *

* @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. diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 0a73a34bfc986..a084cab8edec4 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -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 { From 350e68d0b80c22e6ec37dd683134f46079619803 Mon Sep 17 00:00:00 2001 From: Jungshik Jang Date: Tue, 19 Aug 2014 18:56:21 +0900 Subject: [PATCH 5/5] Clean up MHL local devices when HdmiControlService turns into disabled state Bug: 17122583 Change-Id: Id8f17faf9891952c762f86b46a89732f1497c5fc --- .../server/hdmi/HdmiControlService.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 32d97bad493bf..667ec07a28610 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -356,7 +356,7 @@ public final class HdmiControlService extends SystemService { break; case Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED: tv().setAutoWakeup(enabled); - setOption(OPTION_CEC_AUTO_WAKEUP, toInt(enabled)); + setCecOption(OPTION_CEC_AUTO_WAKEUP, toInt(enabled)); break; case Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED: tv().setAutoDeviceOff(enabled); @@ -1683,11 +1683,17 @@ public final class HdmiControlService extends SystemService { } private void disableDevices(PendingActionClearedCallback callback) { - for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) { - device.disableDevice(mStandbyMessageReceived, callback); + if (mCecController != null) { + for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) { + device.disableDevice(mStandbyMessageReceived, callback); + } + if (isTvDevice()) { + unregisterSettingsObserver(); + } } - if (isTvDevice()) { - unregisterSettingsObserver(); + + if (mMhlController != null) { + mMhlController.clearAllLocalDevices(); } } @@ -1759,7 +1765,7 @@ public final class HdmiControlService extends SystemService { } @ServiceThreadOnly - void setOption(int key, int value) { + void setCecOption(int key, int value) { assertRunOnServiceThread(); mCecController.setOption(key, value); }