Commit 4c75e385 authored by boliu's avatar boliu Committed by Commit bot

Make ActivityWindowAndroid per-activity

This is to solve the general perf problem of per-webview
ActivityWindowAndroid when there are a lot of webviews in an activity.
It is kept in a WeakHashMap, and ActivityWindowAndroid only weakly holds
the Activity, to ensure Activity can still be gc-ed.
ActivityWindowAndroid.destroy is called by CleanupReference.

Also make WindowAndroid global and leaking. This is ok since it only uses
the Application.

BUG=487487

Review URL: https://codereview.chromium.org/1138113004

Cr-Commit-Position: refs/heads/master@{#330087}
parent c67128f7
......@@ -77,6 +77,7 @@ import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
/**
......@@ -207,7 +208,7 @@ public class AwContents implements SmartClipProvider,
private final Context mContext;
private final int mAppTargetSdkVersion;
private ContentViewCore mContentViewCore;
private WindowAndroid mWindowAndroid;
private WindowAndroidWrapper mWindowAndroid;
private WebContents mWebContents;
private NavigationController mNavigationController;
private final AwContentsClient mContentsClient;
......@@ -287,16 +288,13 @@ public class AwContents implements SmartClipProvider,
private static final class DestroyRunnable implements Runnable {
private final long mNativeAwContents;
private final WindowAndroid mWindowAndroid;
private DestroyRunnable(long nativeAwContents, WindowAndroid windowAndroid) {
private DestroyRunnable(long nativeAwContents) {
mNativeAwContents = nativeAwContents;
mWindowAndroid = windowAndroid;
}
@Override
public void run() {
nativeDestroy(mNativeAwContents);
mWindowAndroid.destroy();
}
}
......@@ -848,6 +846,60 @@ public class AwContents implements SmartClipProvider,
mContainerView.requestLayout();
}
// This class destroys the WindowAndroid when after it is gc-ed.
private static class WindowAndroidWrapper {
private final WindowAndroid mWindowAndroid;
private final CleanupReference mCleanupReference;
private static final class DestroyRunnable implements Runnable {
private final WindowAndroid mWindowAndroid;
private DestroyRunnable(WindowAndroid windowAndroid) {
mWindowAndroid = windowAndroid;
}
@Override
public void run() {
mWindowAndroid.destroy();
}
}
public WindowAndroidWrapper(WindowAndroid windowAndroid) {
mWindowAndroid = windowAndroid;
mCleanupReference =
new CleanupReference(this, new DestroyRunnable(windowAndroid));
}
public WindowAndroid getWindowAndroid() {
return mWindowAndroid;
}
}
private static WindowAndroidWrapper sCachedWindowAndroid;
private static WeakHashMap<Activity, WindowAndroidWrapper> sActivityWindowMap;
// getWindowAndroid is only called on UI thread, so there are no threading issues with lazy
// initialization.
@SuppressFBWarnings("LI_LAZY_INIT_STATIC")
private static WindowAndroidWrapper getWindowAndroid(Context context) {
// TODO(boliu): WebView does not currently initialize ApplicationStatus, crbug.com/470582.
Activity activity = ContentViewCore.activityFromContext(context);
if (activity == null) {
if (sCachedWindowAndroid == null) {
sCachedWindowAndroid = new WindowAndroidWrapper(
new WindowAndroid(context.getApplicationContext()));
}
return sCachedWindowAndroid;
}
if (sActivityWindowMap == null) sActivityWindowMap = new WeakHashMap<>();
WindowAndroidWrapper activityWindowAndroid = sActivityWindowMap.get(activity);
if (activityWindowAndroid == null) {
final boolean listenToActivityState = false;
activityWindowAndroid = new WindowAndroidWrapper(
new ActivityWindowAndroid(activity, listenToActivityState));
sActivityWindowMap.put(activity, activityWindowAndroid);
}
return activityWindowAndroid;
}
/* Common initialization routine for adopting a native AwContents instance into this
* java instance.
*
......@@ -871,15 +923,10 @@ public class AwContents implements SmartClipProvider,
WebContents webContents = nativeGetWebContents(mNativeAwContents);
// WebView does not currently initialize ApplicationStatus, crbug.com/470582.
final boolean listenToActivityState = false;
Activity activity = ContentViewCore.activityFromContext(mContext);
mWindowAndroid = activity != null
? new ActivityWindowAndroid(activity, listenToActivityState)
: new WindowAndroid(mContext.getApplicationContext());
mContentViewCore = createAndInitializeContentViewCore(
mContainerView, mContext, mInternalAccessAdapter, webContents,
new AwGestureStateListener(), mContentViewClient, mZoomControls, mWindowAndroid);
mWindowAndroid = getWindowAndroid(mContext);
mContentViewCore = createAndInitializeContentViewCore(mContainerView, mContext,
mInternalAccessAdapter, webContents, new AwGestureStateListener(),
mContentViewClient, mZoomControls, mWindowAndroid.getWindowAndroid());
nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge,
mIoThreadClient, mInterceptNavigationDelegate);
mWebContents = mContentViewCore.getWebContents();
......@@ -892,7 +939,7 @@ public class AwContents implements SmartClipProvider,
// The native side object has been bound to this java instance, so now is the time to
// bind all the native->java relationships.
mCleanupReference =
new CleanupReference(this, new DestroyRunnable(mNativeAwContents, mWindowAndroid));
new CleanupReference(this, new DestroyRunnable(mNativeAwContents));
}
private void installWebContentsObserver() {
......@@ -2452,7 +2499,7 @@ public class AwContents implements SmartClipProvider,
@CalledByNative
private void postInvalidateOnAnimation() {
if (!mWindowAndroid.isInsideVSync()) {
if (!mWindowAndroid.getWindowAndroid().isInsideVSync()) {
mContainerView.postInvalidateOnAnimation();
} else {
mContainerView.invalidate();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment