summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorCharles Chen <charlesccchen@google.com>2020-04-13 09:44:04 +0000
committerCharles Chen <charlesccchen@google.com>2020-04-27 16:37:46 +0800
commit6661575791ea87bbe990ca1ffc5c20701bffa2e3 (patch)
treecbdec94320a31018d05d6d0d08ef58e1348f1d16 /core/java
parent4bf358fe391c8a1076dd1eed725ffdfd0615a5de (diff)
Fix DecorView error about non-visual context
This error showed because DecorContext uses application context to get WindowManager. This CL changes to use PhoneWindow to obtain WindowManager instance. Also refactor ctr to obtain context from PhoneWindow. Bug: 152806048 Test: manual - enable strict mode and check the error log not shown. Test: atest DecorContextTest Test: atest MemoryTests#testActivityRecreation Change-Id: I1d416b9cdb015c9bc3553571041f3b14bb9da5da
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/view/WindowManagerImpl.java4
-rw-r--r--core/java/com/android/internal/policy/DecorContext.java76
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java2
3 files changed, 43 insertions, 39 deletions
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 2975d5ee8e1c..28a18da37b3e 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -36,6 +36,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.IResultReceiver;
import java.util.List;
@@ -69,7 +70,8 @@ import java.util.List;
public final class WindowManagerImpl implements WindowManager {
@UnsupportedAppUsage
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
- private final Context mContext;
+ @VisibleForTesting
+ public final Context mContext;
private final Window mParentWindow;
private IBinder mDefaultToken;
diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java
index 99b4b5fb7707..01bedb7b0fc6 100644
--- a/core/java/com/android/internal/policy/DecorContext.java
+++ b/core/java/com/android/internal/policy/DecorContext.java
@@ -22,8 +22,6 @@ import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.view.ContextThemeWrapper;
-import android.view.WindowManager;
-import android.view.WindowManagerImpl;
import android.view.contentcapture.ContentCaptureManager;
import com.android.internal.annotations.VisibleForTesting;
@@ -31,8 +29,8 @@ import com.android.internal.annotations.VisibleForTesting;
import java.lang.ref.WeakReference;
/**
- * Context for decor views which can be seeded with pure application context and not depend on the
- * activity, but still provide some of the facilities that Activity has,
+ * Context for decor views which can be seeded with display context and not depend on the activity,
+ * but still provide some of the facilities that Activity has,
* e.g. themes, activity-based resources, etc.
*
* @hide
@@ -40,79 +38,83 @@ import java.lang.ref.WeakReference;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public class DecorContext extends ContextThemeWrapper {
private PhoneWindow mPhoneWindow;
- private WindowManager mWindowManager;
- private Resources mActivityResources;
+ private Resources mResources;
private ContentCaptureManager mContentCaptureManager;
- private WeakReference<Context> mActivityContext;
+ private WeakReference<Context> mContext;
- // TODO(b/149928768): Non-activity context can be passed.
@VisibleForTesting
- public DecorContext(Context context, Context activityContext) {
- super(context.createDisplayContext(activityContext.getDisplayNoVerify()), null);
- mActivityContext = new WeakReference<>(activityContext);
- mActivityResources = activityContext.getResources();
+ public DecorContext(Context baseContext, PhoneWindow phoneWindow) {
+ super(null /* base */, null);
+ setPhoneWindow(phoneWindow);
+ final Context displayContext = baseContext.createDisplayContext(
+ // TODO(b/149790106): Non-activity context can be passed.
+ phoneWindow.getContext().getDisplayNoVerify());
+ attachBaseContext(displayContext);
}
void setPhoneWindow(PhoneWindow phoneWindow) {
mPhoneWindow = phoneWindow;
- mWindowManager = null;
+ final Context context = phoneWindow.getContext();
+ mContext = new WeakReference<>(context);
+ mResources = context.getResources();
}
@Override
public Object getSystemService(String name) {
if (Context.WINDOW_SERVICE.equals(name)) {
- if (mWindowManager == null) {
- WindowManagerImpl wm =
- (WindowManagerImpl) super.getSystemService(Context.WINDOW_SERVICE);
- mWindowManager = wm.createLocalWindowManager(mPhoneWindow);
- }
- return mWindowManager;
+ return mPhoneWindow.getWindowManager();
}
+ final Context context = mContext.get();
if (Context.CONTENT_CAPTURE_MANAGER_SERVICE.equals(name)) {
- if (mContentCaptureManager == null) {
- Context activityContext = mActivityContext.get();
- if (activityContext != null) {
- mContentCaptureManager = (ContentCaptureManager) activityContext
- .getSystemService(name);
- }
+ if (context != null && mContentCaptureManager == null) {
+ mContentCaptureManager = (ContentCaptureManager) context.getSystemService(name);
}
return mContentCaptureManager;
}
- return super.getSystemService(name);
+ // TODO(b/154191411): Try to revisit this issue in S.
+ // We use application to get DisplayManager here because ViewRootImpl holds reference of
+ // DisplayManager and implicitly holds reference of mContext, which makes activity cannot
+ // be GC'd even after destroyed if mContext is an activity object.
+ if (Context.DISPLAY_SERVICE.equals(name)) {
+ return super.getSystemService(name);
+ }
+ // LayoutInflater and WallpaperManagerService should also be obtained from visual context
+ // instead of base context.
+ return (context != null) ? context.getSystemService(name) : super.getSystemService(name);
}
@Override
public Resources getResources() {
- Context activityContext = mActivityContext.get();
+ Context context = mContext.get();
// Attempt to update the local cached Resources from the activity context. If the activity
// is no longer around, return the old cached values.
- if (activityContext != null) {
- mActivityResources = activityContext.getResources();
+ if (context != null) {
+ mResources = context.getResources();
}
- return mActivityResources;
+ return mResources;
}
@Override
public AssetManager getAssets() {
- return mActivityResources.getAssets();
+ return mResources.getAssets();
}
@Override
public AutofillOptions getAutofillOptions() {
- Context activityContext = mActivityContext.get();
- if (activityContext != null) {
- return activityContext.getAutofillOptions();
+ Context context = mContext.get();
+ if (context != null) {
+ return context.getAutofillOptions();
}
return null;
}
@Override
public ContentCaptureOptions getContentCaptureOptions() {
- Context activityContext = mActivityContext.get();
- if (activityContext != null) {
- return activityContext.getContentCaptureOptions();
+ Context context = mContext.get();
+ if (context != null) {
+ return context.getContentCaptureOptions();
}
return null;
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 23ba6530b072..aa75d4010748 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2358,7 +2358,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (applicationContext == null) {
context = getContext();
} else {
- context = new DecorContext(applicationContext, getContext());
+ context = new DecorContext(applicationContext, this);
if (mTheme != -1) {
context.setTheme(mTheme);
}