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.os.Handler; | |
8 import android.os.HandlerThread; | |
9 import android.os.IBinder; | |
10 | |
11 import org.chromium.base.UnguessableToken; | |
12 import org.chromium.base.annotations.CalledByNative; | |
13 import org.chromium.base.annotations.JNINamespace; | |
14 | |
15 /** | |
16 * Singleton class to create and manage DialogSurface. Normally, you won't need | |
17 * to access this directly. Instead, see the native wrappers in | |
18 * dialog_surface_manager.cc for usage. | |
19 * | |
20 * The wrappers do roughly the following on the gpu side: | |
21 * - Create an IDialogSurfaceCallback. For native, DialogSurfaceCallback hides | |
22 * the threading issues and provides the java peer. | |
23 * - Get an IDialogSurfaceManager from the browser via ChildProcessCallback . | |
24 * - dialogSurface = IDialogSurfaceManager.createSurface(callback) | |
25 * This calls into the browser, and returns an IDialogSurface IBinder. | |
26 * - Wrap the DialogSurface in a DialogSurfaceWrapper. This provides the JNI | |
27 * bindings for native. | |
28 * - Expect callbacks on the callback to let you know when the underlying | |
29 * android surface state changes. | |
30 * - Use the surface. | |
31 * - Call IDialogSurface::release() to destroy the surface when done. | |
32 */ | |
33 @JNINamespace("media") | |
34 public class DialogSurfaceManagerImpl extends IDialogSurfaceManager.Stub { | |
35 private static final String TAG = "cr_media"; | |
36 private static DialogSurfaceManagerImpl sInstance; | |
37 private static final Object sLock = new Object(); | |
38 | |
39 // We maintain a thread with a Looper for the DialogSurfaces to use, | |
40 // since Dialog requires one. We don't want this to be the native thread | |
41 // that's used to create them, because it probably also has a native message | |
42 // loop. Including a looper on it is not a good idea. | |
43 private final Object mLock = new Object(); | |
44 private HandlerThread mThread; | |
45 private Handler mHandler; | |
46 private final IDialogSurfaceActivityMapper mMapper; | |
47 | |
48 // Number of DialogSurfaces that have been created but not released. | |
49 private int mNumSurfaces; | |
50 | |
51 // Maximum number of concurrent surfaces we allow. | |
52 private static final int sMaxSurfaces = 1; | |
boliu
2016/11/14 16:39:25
stype: MAX_SURFACES
liberato (no reviews please)
2016/12/20 17:16:38
Done.
| |
53 | |
54 private DialogSurfaceManagerImpl(IDialogSurfaceActivityMapper mapper) { | |
55 mMapper = mapper; | |
56 mNumSurfaces = 0; | |
57 } | |
58 | |
59 // Return the singleton instance, as a convenience. | |
60 public static IBinder instance(IDialogSurfaceActivityMapper mapper) { | |
61 synchronized (sLock) { | |
62 if (sInstance == null) sInstance = new DialogSurfaceManagerImpl(mapp er); | |
63 | |
64 return sInstance.asBinder(); | |
65 } | |
66 } | |
67 | |
68 @Override | |
69 @CalledByNative | |
70 public IDialogSurfaceHolder createSurface(UnguessableToken frameToken, | |
71 IDialogSurfaceCallback callback, int x, int y, int width, int height ) { | |
72 // Note that we may be called on any random binder thread, so lock. | |
73 synchronized (mLock) { | |
74 // Limit the number of concurrent surfaces. | |
75 if (mNumSurfaces >= sMaxSurfaces) return null; | |
76 | |
77 // TODO(liberato): would get the WindowToken / Activity here. | |
78 | |
79 startThreadIfNeededLocked(); | |
80 | |
81 mNumSurfaces++; | |
82 } | |
83 | |
84 // TODO(liberato): would instantiate DialogSurfaceHolder here. | |
85 return null; | |
86 } | |
87 | |
88 /** | |
89 * Called by DialogSurfaces when they no longer need the thread. | |
90 */ | |
91 public void notifyReleased() { | |
92 synchronized (mLock) { | |
93 if (mNumSurfaces > 0) mNumSurfaces--; | |
94 | |
95 // We don't stop the looper thread here, else android can get mad wh en | |
96 // it tries to send a message from the dialog on this thread. | |
97 // DialogSurface might have to notify us separately to tell us | |
98 // when it's done with the thread, if we don't want to wait until th en | |
99 // to start creating a new SV. | |
100 // Instead, we just avoid shutting down the thread at all for now. | |
101 } | |
102 } | |
103 | |
104 /** | |
105 * Make sure that mThread and mHandler are ready for use. Do nothing if | |
106 * they already are. | |
107 */ | |
108 private void startThreadIfNeededLocked() { | |
109 // Called with mLock held only. | |
110 if (mThread != null) return; | |
111 | |
112 // Just to avoid "Unread field" in findbugs. Normally, we wills send | |
113 // mHandler to DialogSurface. | |
114 if (mHandler != null) return; | |
115 | |
116 mThread = new HandlerThread("DialogSurfaceThread"); | |
117 mThread.start(); | |
118 mHandler = new Handler(mThread.getLooper()); | |
119 } | |
120 | |
121 /** | |
122 * Return the activity mapper. | |
123 */ | |
124 public IDialogSurfaceActivityMapper getMapper() { | |
125 return mMapper; | |
126 } | |
127 } | |
OLD | NEW |