diff options
author | Dongwon Kang <dwkang@google.com> | 2014-10-29 14:39:27 +0900 |
---|---|---|
committer | Dongwon Kang <dwkang@google.com> | 2014-10-30 09:34:56 +0900 |
commit | 3eefa59e37291abc72edd1c30b5469a21993dbbb (patch) | |
tree | e41393ca4b91c95573b2e0ea778bc0845e296ec4 /media | |
parent | 05b2fedcb8057f31ed078a59a8cffce131449df0 (diff) | |
download | frameworks_base-3eefa59e37291abc72edd1c30b5469a21993dbbb.zip frameworks_base-3eefa59e37291abc72edd1c30b5469a21993dbbb.tar.gz frameworks_base-3eefa59e37291abc72edd1c30b5469a21993dbbb.tar.bz2 |
TIF: Handle notifyXXX() calls requested before the session initialization
Previously, we relied on a handler by posting runnables when the
session is not initialized yet. However, this trick was broken when we
separated the creation procedure into DO_CREATE_SESSION and
DO_NOTIFY_SESSION_CREATED.
Bug: 17909798
Change-Id: I46f610cb9673f8162266525ac0e343b61c6db9ec
Diffstat (limited to 'media')
-rw-r--r-- | media/java/android/media/tv/TvInputService.java | 89 |
1 files changed, 59 insertions, 30 deletions
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index 5d5ea02..2c97db0 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -48,6 +48,7 @@ import android.view.accessibility.CaptioningManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -250,7 +251,12 @@ public abstract class TvInputService extends Service { private boolean mOverlayViewEnabled; private IBinder mWindowToken; private Rect mOverlayFrame; + + private Object mLock = new Object(); + // @GuardedBy("mLock") private ITvInputSessionCallback mSessionCallback; + // @GuardedBy("mLock") + private List<Runnable> mPendingActions = new ArrayList<>(); /** * Creates a new Session. @@ -295,11 +301,12 @@ public abstract class TvInputService extends Service { * @param eventArgs Optional arguments of the event. * @hide */ + @SystemApi public void notifySessionEvent(final String eventType, final Bundle eventArgs) { if (eventType == null) { throw new IllegalArgumentException("eventType should not be null."); } - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -318,7 +325,7 @@ public abstract class TvInputService extends Service { * @param channelUri The URI of a channel. */ public void notifyChannelRetuned(final Uri channelUri) { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -355,7 +362,7 @@ public abstract class TvInputService extends Service { trackIdSet.clear(); // TODO: Validate the track list. - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -383,7 +390,7 @@ public abstract class TvInputService extends Service { * @see #onSelectTrack */ public void notifyTrackSelected(final int type, final String trackId) { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -404,7 +411,7 @@ public abstract class TvInputService extends Service { * @see #notifyVideoUnavailable */ public void notifyVideoAvailable() { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -436,7 +443,7 @@ public abstract class TvInputService extends Service { || reason > TvInputManager.VIDEO_UNAVAILABLE_REASON_END) { throw new IllegalArgumentException("Unknown reason: " + reason); } - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -475,7 +482,7 @@ public abstract class TvInputService extends Service { * @see TvInputManager */ public void notifyContentAllowed() { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -515,7 +522,7 @@ public abstract class TvInputService extends Service { * @see TvInputManager */ public void notifyContentBlocked(final TvContentRating rating) { - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -544,7 +551,7 @@ public abstract class TvInputService extends Service { if (left > right || top > bottm) { throw new IllegalArgumentException("Invalid parameter"); } - runOnMainThread(new Runnable() { + executeOrPostRunnable(new Runnable() { @Override public void run() { try { @@ -852,6 +859,10 @@ public abstract class TvInputService extends Service { mSurface.release(); mSurface = null; } + synchronized(mLock) { + mSessionCallback = null; + mPendingActions.clear(); + } } /** @@ -1059,17 +1070,29 @@ public abstract class TvInputService extends Service { } } - private void setSessionCallback(ITvInputSessionCallback callback) { - mSessionCallback = callback; + private void initialize(ITvInputSessionCallback callback) { + synchronized(mLock) { + mSessionCallback = callback; + for (Runnable runnable : mPendingActions) { + runnable.run(); + } + mPendingActions.clear(); + } } - private final void runOnMainThread(Runnable action) { - if (mHandler.getLooper().isCurrentThread() && mSessionCallback != null) { - action.run(); - } else { - // Posts the runnable if this is not called from the main thread or the session - // is not initialized yet. - mHandler.post(action); + private final void executeOrPostRunnable(Runnable action) { + synchronized(mLock) { + if (mSessionCallback == null) { + // The session is not initialized yet. + mPendingActions.add(action); + } else { + if (mHandler.getLooper().isCurrentThread()) { + action.run(); + } else { + // Posts the runnable if this is not called from the main thread + mHandler.post(action); + } + } } } } @@ -1125,13 +1148,15 @@ public abstract class TvInputService extends Service { mHardwareSession = session; SomeArgs args = SomeArgs.obtain(); if (session != null) { - args.arg1 = mProxySession; - args.arg2 = mProxySessionCallback; - args.arg3 = session.getToken(); + args.arg1 = HardwareSession.this; + args.arg2 = mProxySession; + args.arg3 = mProxySessionCallback; + args.arg4 = session.getToken(); } else { args.arg1 = null; - args.arg2 = mProxySessionCallback; - args.arg3 = null; + args.arg2 = null; + args.arg3 = mProxySessionCallback; + args.arg4 = null; onRelease(); } mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_SESSION_CREATED, args) @@ -1269,7 +1294,6 @@ public abstract class TvInputService extends Service { } return; } - sessionImpl.setSessionCallback(cb); ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this, sessionImpl, channel); if (sessionImpl instanceof HardwareSession) { @@ -1300,9 +1324,10 @@ public abstract class TvInputService extends Service { proxySession.mHardwareSessionCallback, mServiceHandler); } else { SomeArgs someArgs = SomeArgs.obtain(); - someArgs.arg1 = stub; - someArgs.arg2 = cb; - someArgs.arg3 = null; + someArgs.arg1 = sessionImpl; + someArgs.arg2 = stub; + someArgs.arg3 = cb; + someArgs.arg4 = null; mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_SESSION_CREATED, someArgs).sendToTarget(); } @@ -1310,14 +1335,18 @@ public abstract class TvInputService extends Service { } case DO_NOTIFY_SESSION_CREATED: { SomeArgs args = (SomeArgs) msg.obj; - ITvInputSession stub = (ITvInputSession) args.arg1; - ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg2; - IBinder hardwareSessionToken = (IBinder) args.arg3; + Session sessionImpl = (Session) args.arg1; + ITvInputSession stub = (ITvInputSession) args.arg2; + ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg3; + IBinder hardwareSessionToken = (IBinder) args.arg4; try { cb.onSessionCreated(stub, hardwareSessionToken); } catch (RemoteException e) { Log.e(TAG, "error in onSessionCreated"); } + if (sessionImpl != null) { + sessionImpl.initialize(cb); + } args.recycle(); return; } |