OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 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.content.browser.androidoverlay; | |
6 | |
7 import android.content.Context; | |
8 import android.os.Handler; | |
9 import android.os.HandlerThread; | |
10 import android.os.IBinder; | |
11 | |
12 import org.chromium.base.ContextUtils; | |
13 import org.chromium.base.annotations.CalledByNative; | |
14 import org.chromium.media.IAndroidOverlay; | |
15 import org.chromium.media.IAndroidOverlayCallback; | |
16 import org.chromium.media.IAndroidOverlayProvider; | |
17 | |
18 /** | |
19 * Singleton class to create and manage AndroidOverlay. Normally, you won't nee d | |
20 * to access this directly. Instead, see the native wrappers in | |
21 * dialog_surface_manager.cc for usage. | |
22 * | |
23 * The wrappers do roughly the following on the gpu side: | |
24 * - Create an IAndroidOverlayCallback. For native, AndroidOverlayCallback hid es | |
25 * the threading issues and provides the java peer. | |
26 * - Get an IAndroidOverlayManager from the browser via ChildProcessCallback . | |
27 * - dialogSurface = IAndroidOverlayManager.createOverlay(callback) | |
28 * This calls into the browser, and returns an IAndroidOverlay IBinder. | |
29 * - Wrap the AndroidOverlay in a AndroidOverlayWrapper. This provides the JNI | |
30 * bindings for native. | |
31 * - Expect callbacks on the callback to let you know when the underlying | |
32 * android surface state changes. | |
33 * - Use the surface. | |
34 * - Call IAndroidOverlay::release() to destroy the surface when done. | |
35 */ | |
36 public class AndroidOverlayProviderImpl extends IAndroidOverlayProvider.Stub { | |
37 private static final String TAG = "AOProviderImpl"; | |
38 private static AndroidOverlayProviderImpl sInstance; | |
39 private static final Object sLock = new Object(); | |
40 | |
41 private final Context mContext; | |
42 | |
43 // We maintain a thread with a Looper for the AndroidOverlays to use, | |
44 // since Dialog requires one. We don't want this to be the native thread | |
45 // that's used to create them, because it probably also has a native message | |
46 // loop. Including a looper on it is not a good idea. We don't want to use | |
47 // the UI thread, since it will process synchronous callbacks from Android. | |
48 private final Object mLock = new Object(); | |
49 private HandlerThread mThread; | |
50 private Handler mHandler; | |
51 | |
52 // Number of AndroidOverlays that have been created but not released. | |
53 private int mNumOverlays; | |
54 | |
55 // Maximum number of concurrent surfaces we allow. | |
56 private static final int MAX_SURFACES = 1; | |
57 | |
58 private AndroidOverlayProviderImpl() { | |
59 mContext = ContextUtils.getApplicationContext(); | |
60 mNumOverlays = 0; | |
61 } | |
62 | |
63 // Return the singleton instance, as a convenience. | |
64 public static IBinder getInstance() { | |
65 synchronized (sLock) { | |
66 if (sInstance == null) sInstance = new AndroidOverlayProviderImpl(); | |
67 | |
68 return sInstance.asBinder(); | |
69 } | |
70 } | |
71 | |
72 @Override | |
73 @CalledByNative | |
boliu
2017/02/08 00:01:58
not needed, this doesn't generate jni headers
| |
74 public IAndroidOverlay createOverlay(int rendererPid, int renderFrameId, | |
75 IAndroidOverlayCallback callback, int x, int y, int width, int heigh t) { | |
76 // Note that we may be called on any random binder thread, so lock. | |
77 synchronized (mLock) { | |
78 // Limit the number of concurrent surfaces. | |
79 if (mNumOverlays >= MAX_SURFACES) return null; | |
80 | |
81 startThreadIfNeededLocked(); | |
82 | |
83 mNumOverlays++; | |
84 } | |
85 | |
86 return new DialogAndroidOverlay(rendererPid, renderFrameId, mContext, th is, mHandler, | |
87 callback, x, y, width, height); | |
88 } | |
89 | |
90 /** | |
91 * Called by AndroidOverlays when they no longer need the thread. | |
92 * Called on some random thread. | |
93 */ | |
94 public void notifyReleased() { | |
95 synchronized (mLock) { | |
96 assert mNumOverlays > 0; | |
97 mNumOverlays--; | |
98 | |
99 // We don't stop the looper thread here, else android can get mad wh en | |
100 // it tries to send a message from the dialog on this thread. | |
101 // AndroidOverlay might have to notify us separately to tell us | |
102 // when it's done with the thread, if we don't want to wait until th en | |
103 // to start creating a new SV. | |
104 // Instead, we just avoid shutting down the thread at all for now. | |
105 } | |
106 } | |
107 | |
108 /** | |
109 * Make sure that mThread and mHandler are ready for use. Do nothing if | |
110 * they already are. | |
111 */ | |
112 private void startThreadIfNeededLocked() { | |
113 // Called with mLock held only. | |
boliu
2017/02/08 00:01:58
synhronized blocks are re-entrant safe, so rather
| |
114 if (mThread != null) return; | |
115 | |
116 mThread = new HandlerThread("AndroidOverlayThread"); | |
117 mThread.start(); | |
118 mHandler = new Handler(mThread.getLooper()); | |
119 } | |
120 } | |
OLD | NEW |