OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package org.chromium.media; | |
6 | |
7 import android.content.Context; | |
8 import android.os.Handler; | |
9 import android.os.IBinder; | |
10 | |
11 import org.chromium.base.Log; | |
12 | |
13 /** | |
14 * Provide access to Dialog-based Surfaces. It is unlikely that you want to | |
15 * use this class directly. Instead, use the native wrappers for it in | |
16 * dialog_surface_holder.h . If you must use these from Java, then it's likely | |
17 * that you should be using IDialogSurface instead. | |
18 * | |
19 * This class is thread-safe, since it gets calls from random binder threads and | |
20 * callbacks on the UI thread. It interacts with DialogSurfaceCore to do the | |
21 * actual work of managing the DialogSurface. It also hides all the threading | |
22 * by posting messages to a single thread for DialogSurfaceCore. | |
23 */ | |
24 class DialogSurfaceImpl | |
25 extends IDialogSurface.Stub implements DialogSurfaceWindowTokenProvider. Client { | |
26 private static final String TAG = "cr_media"; | |
27 | |
28 private final Handler mHandler; | |
29 | |
30 // Note that we never do any work in response to a binder call with mLock | |
31 // held. We always post elsewhere, which prevents reentrant calls from | |
32 // the client from deadlocking on mLock. | |
boliu
2017/01/04 01:48:44
fwiw, synchronized blocks in java is re-entrant :)
liberato (no reviews please)
2017/01/11 22:17:57
not sure that they'd arrive on the same thread. t
boliu
2017/01/12 20:24:19
Oh you meant re-entrant binder calls.
This commen
| |
33 private final Object mLock = new Object(); | |
34 private DialogSurfaceManagerImpl mOwner; | |
35 private DialogSurfaceCore mDialogCore; | |
36 | |
37 /** | |
38 * Called from a random thread. | |
39 * Note that (pid, frameId) might be replaced by a token. | |
40 * @param rendererPid pid of owning renderer process | |
41 * @param renderFrameId render frame ID owned by Pid | |
42 * @param context Context that we use. | |
43 * @param owner Owning manager that we'll notify on release(). | |
44 * @param handler handler for a thread with a looper. | |
45 * @param callback callback object to notify about state changes. | |
46 * @param x initial x position in chrome compositor (not screen) coords. | |
47 * @param y initial y position in chrome compositor (not screen) coords. | |
48 * @param width initial width. | |
49 * @param height initial height. | |
50 */ | |
51 public DialogSurfaceImpl(int rendererPid, int renderFrameId, final Context c ontext, | |
52 DialogSurfaceManagerImpl owner, Handler handler, final IDialogSurfac eCallback callback, | |
53 final int x, final int y, final int width, final int height) { | |
54 mOwner = owner; | |
55 mHandler = handler; | |
56 | |
57 mDialogCore = new DialogSurfaceCore(); | |
58 | |
59 // Post init to the proper thread. | |
60 final DialogSurfaceCore dialogCore = mDialogCore; | |
61 Runnable r = new Runnable() { | |
62 @Override | |
63 public void run() { | |
64 dialogCore.initialize(context, callback, x, y, width, height); | |
65 } | |
66 }; | |
67 mHandler.post(r); | |
68 | |
69 // Register to get token updates. | |
70 mOwner.getWindowTokenProvider().registerClient(rendererPid, renderFrameI d, this); | |
71 } | |
72 | |
73 // Note that the native wrapper should call release() anyway on destruction. | |
74 protected void finalize() throws Throwable { | |
boliu
2017/01/04 01:48:44
I gave a talk once about never using finalizers..
liberato (no reviews please)
2017/01/11 22:17:57
not sure. the problem is that there's only the ca
boliu
2017/01/12 20:24:19
According to a comment on an internal thread, an a
liberato (no reviews please)
2017/02/03 21:28:32
i'm not sure that i understand how linkToDeath wil
| |
75 if (mDialogCore != null) { | |
76 Log.w(TAG, "Not released before finalization, releasing now"); | |
77 release(); | |
78 } | |
79 super.finalize(); | |
80 } | |
81 | |
82 /** | |
83 * Release the underlying surface, and generally clean up, in response to | |
84 * the client releasing the IDialogSurface. | |
85 */ | |
86 @Override | |
87 public void release() { | |
88 synchronized (mLock) { | |
89 // If we've already been released, then do nothing. | |
90 if (mDialogCore == null) return; | |
91 | |
92 // Unregister for token callbacks. | |
93 mOwner.getWindowTokenProvider().unregisterClient(this); | |
94 | |
95 // Post a release on the proper thread to |mDialogCore|. | |
96 final DialogSurfaceCore dialogCore = mDialogCore; | |
97 Runnable r = new Runnable() { | |
98 @Override | |
99 public void run() { | |
100 dialogCore.release(); | |
101 } | |
102 }; | |
103 mHandler.post(r); | |
104 | |
105 // Notify our owner. We don't bother to wait until the post | |
106 // completes, since it'll get cleaned up shortly anyway. | |
107 mOwner.notifyReleased(); | |
108 mOwner = null; | |
109 | |
110 mDialogCore = null; | |
111 } | |
112 } | |
113 | |
114 @Override | |
115 public void scheduleLayoutSurface(final int x, final int y, final int width, final int height) { | |
116 // Random thread. | |
117 synchronized (mLock) { | |
118 if (mDialogCore == null) return; | |
119 | |
120 final DialogSurfaceCore dialogCore = mDialogCore; | |
121 Runnable r = new Runnable() { | |
boliu
2017/01/04 01:48:44
if this could happen every frame, can consider sav
liberato (no reviews please)
2017/01/11 22:17:57
it can, in principle, if we ever try to use this f
| |
122 @Override | |
123 public void run() { | |
124 dialogCore.layoutSurface(x, y, width, height); | |
125 } | |
126 }; | |
127 | |
128 mHandler.post(r); | |
129 } | |
130 } | |
131 | |
132 @Override | |
133 public void onWindowToken(final IBinder token) { | |
134 synchronized (mLock) { | |
135 // Forward this change. | |
136 // Note that if we don't have a window token, then we could wait | |
137 // until we do, simply by skipping sending null if we haven't sent | |
138 // any non-null token yet. If we're transitioning between windows, | |
139 // that might make the client's job easier, since it wouldn't have | |
140 // to guess when a new token is available. | |
141 final DialogSurfaceCore dialogCore = mDialogCore; | |
142 Runnable r = new Runnable() { | |
143 @Override | |
144 public void run() { | |
145 dialogCore.onWindowToken(token); | |
146 } | |
147 }; | |
148 | |
149 mHandler.post(r); | |
150 } | |
151 } | |
152 } | |
OLD | NEW |