Exempt-From-Owner-Approval: Report non-visual Context misuse
Make obtaining a visual service from non-visual Context instance
report a strict mode violation and print the stacktrace.
Make calling getDisplay() throw an exception if called on an instance
that is not associated with a display. For existing usages introduce
a new internal method that does not perform the verification until
the usages are properly fixed.
Bug: 128338354
Test: StrictModeTest#testIncorrectContextUse_GetSystemService
Test: StrictModeTest#testIncorrectContextUse_GetDisplay
Change-Id: Id25d590eca6e10066e55d7ed6436d3bc9e433beb
diff --git a/api/test-current.txt b/api/test-current.txt
index 957794c..57606333 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2529,6 +2529,11 @@
method public void log(android.os.StrictMode.ViolationInfo);
}
+ public static final class StrictMode.VmPolicy.Builder {
+ method @NonNull public android.os.StrictMode.VmPolicy.Builder detectIncorrectContextUse();
+ method @NonNull public android.os.StrictMode.VmPolicy.Builder permitIncorrectContextUse();
+ }
+
public class SystemConfigManager {
method @NonNull @RequiresPermission("android.permission.READ_CARRIER_APP_INFO") public java.util.Set<java.lang.String> getDisabledUntilUsedPreinstalledCarrierApps();
method @NonNull @RequiresPermission("android.permission.READ_CARRIER_APP_INFO") public java.util.Map<java.lang.String,java.util.List<java.lang.String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 6b5bfda..8df26cb 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -16,6 +16,9 @@
package android.app;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.StrictMode.vmIncorrectContextUseEnabled;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -64,6 +67,7 @@
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
+import android.os.StrictMode;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
@@ -247,6 +251,7 @@
private boolean mIsSystemOrSystemUiContext;
private boolean mIsUiContext;
+ private boolean mIsAssociatedWithDisplay;
@GuardedBy("mSync")
private File mDatabasesDir;
@@ -1891,9 +1896,20 @@
@Override
public Object getSystemService(String name) {
- if (isUiComponent(name) && !isUiContext()) {
- Log.w(TAG, name + " should be accessed from Activity or other visual Context");
+ // Check incorrect Context usage.
+ if (isUiComponent(name) && !isUiContext() && vmIncorrectContextUseEnabled()) {
+ final String errorMessage = "Tried to access visual service " + name
+ + " from a non-visual Context.";
+ final String message = "Visual services, such as WindowManager, WallpaperService or "
+ + "LayoutInflater should be accessed from Activity or other visual Context. "
+ + "Use an Activity or a Context created with "
+ + "Context#createWindowContext(int, Bundle), which are adjusted to the "
+ + "configuration and visual bounds of an area on screen.";
+ final Exception exception = new IllegalAccessException(errorMessage);
+ StrictMode.onIncorrectContextUsed(message, exception);
+ Log.e(TAG, errorMessage + message, exception);
}
+
return SystemServiceRegistry.getSystemService(this, name);
}
@@ -1902,8 +1918,17 @@
return SystemServiceRegistry.getSystemServiceName(serviceClass);
}
- boolean isUiContext() {
- return mIsSystemOrSystemUiContext || mIsUiContext;
+ private boolean isUiContext() {
+ return mIsSystemOrSystemUiContext || mIsUiContext || isSystemOrSystemUI();
+ }
+
+ /**
+ * Temporary workaround to permit incorrect usages of Context by SystemUI.
+ * TODO(b/149790106): Fix usages and remove.
+ */
+ private boolean isSystemOrSystemUI() {
+ return ActivityThread.isSystem() || checkPermission("android.permission.STATUS_BAR_SERVICE",
+ Binder.getCallingPid(), Binder.getCallingUid()) == PERMISSION_GRANTED;
}
private static boolean isUiComponent(String name) {
@@ -1925,7 +1950,7 @@
final int appId = UserHandle.getAppId(uid);
if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " holds " + permission);
- return PackageManager.PERMISSION_GRANTED;
+ return PERMISSION_GRANTED;
}
Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
+ permission);
@@ -1989,7 +2014,7 @@
private void enforce(
String permission, int resultOfCheck,
boolean selfToo, int uid, String message) {
- if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
+ if (resultOfCheck != PERMISSION_GRANTED) {
throw new SecurityException(
(message != null ? (message + ": ") : "") +
(selfToo
@@ -2116,15 +2141,15 @@
if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
if (readPermission == null
|| checkPermission(readPermission, pid, uid)
- == PackageManager.PERMISSION_GRANTED) {
- return PackageManager.PERMISSION_GRANTED;
+ == PERMISSION_GRANTED) {
+ return PERMISSION_GRANTED;
}
}
if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
if (writePermission == null
|| checkPermission(writePermission, pid, uid)
- == PackageManager.PERMISSION_GRANTED) {
- return PackageManager.PERMISSION_GRANTED;
+ == PERMISSION_GRANTED) {
+ return PERMISSION_GRANTED;
}
}
return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
@@ -2157,7 +2182,7 @@
private void enforceForUri(
int modeFlags, int resultOfCheck, boolean selfToo,
int uid, Uri uri, String message) {
- if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
+ if (resultOfCheck != PERMISSION_GRANTED) {
throw new SecurityException(
(message != null ? (message + ": ") : "") +
(selfToo
@@ -2373,6 +2398,7 @@
null, getDisplayAdjustments(displayId).getCompatibilityInfo(),
mResources.getLoaders()));
context.mDisplay = display;
+ context.mIsAssociatedWithDisplay = true;
return context;
}
@@ -2390,6 +2416,7 @@
ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
mSplitName, token, mUser, mFlags, mClassLoader, null);
context.mIsUiContext = true;
+ context.mIsAssociatedWithDisplay = true;
return context;
}
@@ -2440,6 +2467,19 @@
@Override
public Display getDisplay() {
+ if (!mIsSystemOrSystemUiContext && !mIsAssociatedWithDisplay && !isSystemOrSystemUI()) {
+ throw new UnsupportedOperationException("Tried to obtain display from a Context not "
+ + "associated with one. Only visual Contexts (such as Activity or one created "
+ + "with Context#createWindowContext) or ones created with "
+ + "Context#createDisplayContext are associated with displays. Other types of "
+ + "Contexts are typically related to background entities and may return an "
+ + "arbitrary display.");
+ }
+ return getDisplayNoVerify();
+ }
+
+ @Override
+ public Display getDisplayNoVerify() {
if (mDisplay == null) {
return mResourcesManager.getAdjustedDisplay(Display.DEFAULT_DISPLAY,
mResources);
@@ -2450,13 +2490,14 @@
@Override
public int getDisplayId() {
- final Display display = getDisplay();
+ final Display display = getDisplayNoVerify();
return display != null ? display.getDisplayId() : Display.DEFAULT_DISPLAY;
}
@Override
public void updateDisplay(int displayId) {
mDisplay = mResourcesManager.getAdjustedDisplay(displayId, mResources);
+ mIsAssociatedWithDisplay = true;
}
@Override
@@ -2630,6 +2671,7 @@
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null,
activityInfo.splitName, activityToken, null, 0, classLoader, null);
context.mIsUiContext = true;
+ context.mIsAssociatedWithDisplay = true;
// Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY.
displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY;
diff --git a/core/java/android/app/TaskEmbedder.java b/core/java/android/app/TaskEmbedder.java
index 761b225..5ebcc46 100644
--- a/core/java/android/app/TaskEmbedder.java
+++ b/core/java/android/app/TaskEmbedder.java
@@ -597,7 +597,7 @@
if (mTmpDisplayMetrics == null) {
mTmpDisplayMetrics = new DisplayMetrics();
}
- mContext.getDisplay().getMetrics(mTmpDisplayMetrics);
+ mContext.getDisplayNoVerify().getRealMetrics(mTmpDisplayMetrics);
return mTmpDisplayMetrics.densityDpi;
}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 5f74d2e..d9405e1 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -2097,7 +2097,7 @@
public ColorManagementProxy(@NonNull Context context) {
// Get a list of supported wide gamut color spaces.
- Display display = context.getDisplay();
+ Display display = context.getDisplayNoVerify();
if (display != null) {
mSupportedColorSpaces.addAll(Arrays.asList(display.getSupportedWideColorGamut()));
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ae12de0..c6e84b7 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3495,13 +3495,23 @@
* <dl>
* <dt> {@link #WINDOW_SERVICE} ("window")
* <dd> The top-level window manager in which you can place custom
- * windows. The returned object is a {@link android.view.WindowManager}.
+ * windows. The returned object is a {@link android.view.WindowManager}. Must only be obtained
+ * from a visual context such as Activity or a Context created with
+ * {@link #createWindowContext(int, Bundle)}, which are adjusted to the configuration and
+ * visual bounds of an area on screen.
* <dt> {@link #LAYOUT_INFLATER_SERVICE} ("layout_inflater")
* <dd> A {@link android.view.LayoutInflater} for inflating layout resources
- * in this context.
+ * in this context. Must only be obtained from a visual context such as Activity or a Context
+ * created with {@link #createWindowContext(int, Bundle)}, which are adjusted to the
+ * configuration and visual bounds of an area on screen.
* <dt> {@link #ACTIVITY_SERVICE} ("activity")
* <dd> A {@link android.app.ActivityManager} for interacting with the
* global activity state of the system.
+ * <dt> {@link #WALLPAPER_SERVICE} ("wallpaper")
+ * <dd> A {@link android.service.wallpaper.WallpaperService} for accessing wallpapers in this
+ * context. Must only be obtained from a visual context such as Activity or a Context created
+ * with {@link #createWindowContext(int, Bundle)}, which are adjusted to the configuration and
+ * visual bounds of an area on screen.
* <dt> {@link #POWER_SERVICE} ("power")
* <dd> A {@link android.os.PowerManager} for controlling power
* management.
@@ -5901,6 +5911,8 @@
* {@link #createDisplayContext(Display)} to get a display object associated with a Context, or
* {@link android.hardware.display.DisplayManager#getDisplay} to get a display object by id.
* @return Returns the {@link Display} object this context is associated with.
+ * @throws UnsupportedOperationException if the method is called on an instance that is not
+ * associated with any display.
*/
@Nullable
public Display getDisplay() {
@@ -5908,6 +5920,17 @@
}
/**
+ * A version of {@link #getDisplay()} that does not perform a Context misuse check to be used by
+ * legacy APIs.
+ * TODO(b/149790106): Fix usages and remove.
+ * @hide
+ */
+ @Nullable
+ public Display getDisplayNoVerify() {
+ throw new RuntimeException("Not implemented. Must override in a subclass.");
+ }
+
+ /**
* Gets the ID of the display this context is associated with.
*
* @return display ID associated with this {@link Context}.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index f6515e8..e5381ea 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1003,6 +1003,12 @@
return mBase.getDisplay();
}
+ /** @hide */
+ @Override
+ public @Nullable Display getDisplayNoVerify() {
+ return mBase.getDisplayNoVerify();
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index be22458..d60820e 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -16,6 +16,8 @@
package android.os;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import static java.nio.charset.StandardCharsets.UTF_8;
import android.annotation.NonNull;
@@ -33,6 +35,7 @@
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.PackageManager;
+import android.hardware.display.DisplayManager;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -614,7 +617,8 @@
// On TV, reboot quiescently if the screen is off
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
- if (context.getDisplay().getState() != Display.STATE_ON) {
+ DisplayManager dm = context.getSystemService(DisplayManager.class);
+ if (dm.getDisplay(DEFAULT_DISPLAY).getState() != Display.STATE_ON) {
reason += ",quiescent";
}
}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 3faaff7..e8af564 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -42,6 +42,7 @@
import android.os.strictmode.ExplicitGcViolation;
import android.os.strictmode.FileUriExposedViolation;
import android.os.strictmode.ImplicitDirectBootViolation;
+import android.os.strictmode.IncorrectContextUseViolation;
import android.os.strictmode.InstanceCountViolation;
import android.os.strictmode.IntentReceiverLeakedViolation;
import android.os.strictmode.LeakedClosableViolation;
@@ -250,6 +251,7 @@
DETECT_VM_UNTAGGED_SOCKET,
DETECT_VM_NON_SDK_API_USAGE,
DETECT_VM_IMPLICIT_DIRECT_BOOT,
+ DETECT_VM_INCORRECT_CONTEXT_USE,
PENALTY_GATHER,
PENALTY_LOG,
PENALTY_DIALOG,
@@ -289,6 +291,8 @@
private static final int DETECT_VM_IMPLICIT_DIRECT_BOOT = 1 << 10;
/** @hide */
private static final int DETECT_VM_CREDENTIAL_PROTECTED_WHILE_LOCKED = 1 << 11;
+ /** @hide */
+ private static final int DETECT_VM_INCORRECT_CONTEXT_USE = 1 << 12;
/** @hide */
private static final int DETECT_VM_ALL = 0x0000ffff;
@@ -871,6 +875,9 @@
if (targetSdk >= Build.VERSION_CODES.Q) {
detectCredentialProtectedWhileLocked();
}
+ if (targetSdk >= Build.VERSION_CODES.R) {
+ detectIncorrectContextUse();
+ }
// TODO: Decide whether to detect non SDK API usage beyond a certain API level.
// TODO: enable detectImplicitDirectBoot() once system is less noisy
@@ -1028,6 +1035,32 @@
}
/**
+ * Detect attempts to invoke a method on a {@link Context} that is not suited for such
+ * operation.
+ * <p>An example of this is trying to obtain an instance of visual service (e.g.
+ * {@link android.view.WindowManager}) from a non-visual {@link Context}. This is not
+ * allowed, since a non-visual {@link Context} is not adjusted to any visual area, and
+ * therefore can report incorrect metrics or resources.
+ * @see Context#getDisplay()
+ * @see Context#getSystemService(String)
+ * @hide
+ */
+ @TestApi
+ public @NonNull Builder detectIncorrectContextUse() {
+ return enable(DETECT_VM_INCORRECT_CONTEXT_USE);
+ }
+
+ /**
+ * Disable detection of incorrect context use.
+ * TODO(b/149790106): Fix usages and remove.
+ * @hide
+ */
+ @TestApi
+ public @NonNull Builder permitIncorrectContextUse() {
+ return disable(DETECT_VM_INCORRECT_CONTEXT_USE);
+ }
+
+ /**
* Crashes the whole process on violation. This penalty runs at the end of all enabled
* penalties so you'll still get your logging or other violations before the process
* dies.
@@ -2057,6 +2090,11 @@
}
/** @hide */
+ public static boolean vmIncorrectContextUseEnabled() {
+ return (sVmPolicy.mask & DETECT_VM_INCORRECT_CONTEXT_USE) != 0;
+ }
+
+ /** @hide */
public static void onSqliteObjectLeaked(String message, Throwable originStack) {
onVmPolicyViolation(new SqliteObjectLeakedViolation(message, originStack));
}
@@ -2130,6 +2168,11 @@
onVmPolicyViolation(new ImplicitDirectBootViolation());
}
+ /** @hide */
+ public static void onIncorrectContextUsed(String message, Throwable originStack) {
+ onVmPolicyViolation(new IncorrectContextUseViolation(message, originStack));
+ }
+
/** Assume locked until we hear otherwise */
private static volatile boolean sUserKeyUnlocked = false;
diff --git a/core/java/android/os/strictmode/IncorrectContextUseViolation.java b/core/java/android/os/strictmode/IncorrectContextUseViolation.java
new file mode 100644
index 0000000..647db17
--- /dev/null
+++ b/core/java/android/os/strictmode/IncorrectContextUseViolation.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.strictmode;
+
+import android.content.Context;
+
+/**
+ * Incorrect usage of {@link Context}, such as obtaining a visual service from non-visual
+ * {@link Context} instance.
+ * @see Context#getSystemService(String)
+ * @see Context#getDisplayNoVerify()
+ * @hide
+ */
+public final class IncorrectContextUseViolation extends Violation {
+
+ /** @hide */
+ public IncorrectContextUseViolation(String message, Throwable originStack) {
+ super(message);
+ initCause(originStack);
+ }
+}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 56683dd..d40f505 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -101,7 +101,7 @@
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
- mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
+ mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow);
mIsViewAdded = true;
mLastView = view;
mLastParams = (WindowManager.LayoutParams) params;
@@ -158,7 +158,7 @@
@Override
public Display getDefaultDisplay() {
- return mContext.getDisplay();
+ return mContext.getDisplayNoVerify();
}
@Override
@@ -240,7 +240,7 @@
private Rect getMaximumBounds() {
// TODO(b/128338354): Current maximum bound is display size, but it should be displayArea
// bound after displayArea feature is finished.
- final Display display = mContext.getDisplay();
+ final Display display = mContext.getDisplayNoVerify();
final Point displaySize = new Point();
display.getRealSize(displaySize);
return new Rect(0, 0, displaySize.x, displaySize.y);
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 69b1609..633d684 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -210,7 +210,7 @@
}
private boolean isContentRectWithinBounds() {
- mContext.getDisplay().getRealSize(mDisplaySize);
+ mContext.getDisplayNoVerify().getRealSize(mDisplaySize);
mScreenRect.set(0, 0, mDisplaySize.x, mDisplaySize.y);
return intersectsClosed(mContentRectOnScreen, mScreenRect)
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index 13425e5..cfb2bf9 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -77,10 +77,7 @@
final Point size = new Point();
final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
try {
- final Display display = context.getDisplay();
- final int displayId = display != null
- ? display.getDisplayId()
- : Display.DEFAULT_DISPLAY;
+ final int displayId = context.getDisplayId();
wm.getInitialDisplaySize(displayId, size);
return size.x < size.y ?
Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;
diff --git a/core/tests/coretests/src/android/content/ContextTest.java b/core/tests/coretests/src/android/content/ContextTest.java
index f074233..f0997a6 100644
--- a/core/tests/coretests/src/android/content/ContextTest.java
+++ b/core/tests/coretests/src/android/content/ContextTest.java
@@ -16,11 +16,13 @@
package android.content;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import static org.junit.Assert.assertEquals;
import android.app.ActivityThread;
+import android.hardware.display.DisplayManager;
import android.os.UserHandle;
-import android.view.WindowManager;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -45,17 +47,16 @@
final Context testContext =
InstrumentationRegistry.getInstrumentation().getTargetContext();
- assertEquals(testContext.getDisplay().getDisplayId(), testContext.getDisplayId());
+ assertEquals(testContext.getDisplayNoVerify().getDisplayId(), testContext.getDisplayId());
}
- // TODO(b/128338354): Re-visit this test after introducing WindowContext
@Test
public void testDisplayIdForDefaultDisplayContext() {
final Context testContext =
InstrumentationRegistry.getInstrumentation().getTargetContext();
- final WindowManager wm = testContext.getSystemService(WindowManager.class);
+ final DisplayManager dm = testContext.getSystemService(DisplayManager.class);
final Context defaultDisplayContext =
- testContext.createDisplayContext(wm.getDefaultDisplay());
+ testContext.createDisplayContext(dm.getDisplay(DEFAULT_DISPLAY));
assertEquals(defaultDisplayContext.getDisplay().getDisplayId(),
defaultDisplayContext.getDisplayId());
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index 7c78bce..7f0e0d2 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -61,7 +61,7 @@
.setName("testSurface")
.build();
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- ViewRootImpl viewRootImpl = new ViewRootImpl(mContext, mContext.getDisplay());
+ ViewRootImpl viewRootImpl = new ViewRootImpl(mContext, mContext.getDisplayNoVerify());
try {
viewRootImpl.setView(new TextView(mContext), new LayoutParams(), null);
} catch (BadTokenException e) {
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 24fe2a0..7737b1a 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -110,7 +110,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
Context context = InstrumentationRegistry.getTargetContext();
// cannot mock ViewRootImpl since it's final.
- mViewRoot = new ViewRootImpl(context, context.getDisplay());
+ mViewRoot = new ViewRootImpl(context, context.getDisplayNoVerify());
try {
mViewRoot.setView(new TextView(context), new LayoutParams(), null);
} catch (BadTokenException e) {
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index 5e9e2f0..754c679 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -77,7 +77,8 @@
instrumentation.runOnMainSync(() -> {
final Context context = instrumentation.getTargetContext();
// cannot mock ViewRootImpl since it's final.
- final ViewRootImpl viewRootImpl = new ViewRootImpl(context, context.getDisplay());
+ final ViewRootImpl viewRootImpl = new ViewRootImpl(context,
+ context.getDisplayNoVerify());
try {
viewRootImpl.setView(new TextView(context), new LayoutParams(), null);
} catch (BadTokenException e) {
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index df6ed8c..e2adbcc 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -61,7 +61,7 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
mViewRootImpl = new ViewRootImplAccessor(
- new ViewRootImpl(mContext, mContext.getDisplay()));
+ new ViewRootImpl(mContext, mContext.getDisplayNoVerify()));
});
}
diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
index cdcf23f..3e40466 100644
--- a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
@@ -53,7 +53,10 @@
@Test
public void testDecorContextWithDefaultDisplay() {
- DecorContext context = new DecorContext(mContext.getApplicationContext(), mContext);
+ Display defaultDisplay = new Display(DisplayManagerGlobal.getInstance(), DEFAULT_DISPLAY,
+ new DisplayInfo(), DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+ DecorContext context = new DecorContext(mContext.getApplicationContext(),
+ mContext.createDisplayContext(defaultDisplay));
assertDecorContextDisplay(DEFAULT_DISPLAY, context);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
index e0ca1ab..a38091d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
@@ -97,7 +97,7 @@
final Resources res = context.getResources();
final DisplayMetrics metrics = new DisplayMetrics();
- context.getDisplay().getRealMetrics(metrics);
+ context.getDisplayNoVerify().getRealMetrics(metrics);
final int currentDensity = metrics.densityDpi;
int currentDensityIndex = -1;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 61caf3b..241f96e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -149,7 +149,7 @@
new WindowlessWindowManager(context.getResources().getConfiguration(),
surfaceControl, input);
mUniversalSmartspaceViewHost = new SurfaceControlViewHost(context,
- context.getDisplay(), windowlessWindowManager);
+ context.getDisplayNoVerify(), windowlessWindowManager);
WindowManager.LayoutParams layoutParams =
new WindowManager.LayoutParams(
surfaceControl.getWidth(),
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
index b6ca8d8e..7231b8a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
@@ -41,8 +41,8 @@
InjectionInflationController inflationController = new InjectionInflationController(
SystemUIFactory.getInstance().getRootComponent());
Context context = getContext();
- KeyguardPresentation keyguardPresentation =
- new KeyguardPresentation(context, context.getDisplay(), inflationController);
+ KeyguardPresentation keyguardPresentation = new KeyguardPresentation(context,
+ context.getDisplayNoVerify(), inflationController);
keyguardPresentation.onCreate(null /*savedInstanceState */);
}
}
diff --git a/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java b/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java
index fcb113e..210fdc6 100644
--- a/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java
+++ b/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java
@@ -163,7 +163,7 @@
private static boolean isHighResolution(Context context) {
DisplayMetrics metrics = new DisplayMetrics();
- context.getDisplay().getMetrics(metrics);
+ context.getDisplayNoVerify().getMetrics(metrics);
return metrics.heightPixels > 2048 || metrics.widthPixels > 2048;
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 7151d2b..a8a2791 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -281,7 +281,7 @@
}
private void computeMaximumWidgetBitmapMemory() {
- Display display = mContext.getDisplay();
+ Display display = mContext.getDisplayNoVerify();
Point size = new Point();
display.getRealSize(size);
// Cap memory usage at 1.5 times the size of the display
diff --git a/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java b/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
index 813fc8d..14bd7d7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
+++ b/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
@@ -75,7 +75,7 @@
final TypedValue typedValue = new TypedValue();
final Point point = new Point();
final Context context = getContext();
- context.getDisplay().getSize(point);
+ context.getDisplayNoVerify().getSize(point);
context.getTheme().resolveAttribute(R.attr.autofillSaveCustomSubtitleMaxHeight,
typedValue, true);
final View child = getChildAt(0);
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 5dc43ef..344b92f 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -165,7 +165,7 @@
// In full screen we only initialize size once assuming screen size never changes
if (mFullScreen) {
final Point outPoint = mTempPoint;
- mContext.getDisplay().getSize(outPoint);
+ mContext.getDisplayNoVerify().getSize(outPoint);
// full with of screen and half height of screen
mContentWidth = LayoutParams.MATCH_PARENT;
mContentHeight = outPoint.y / 2;
@@ -559,7 +559,7 @@
}
private static void resolveMaxWindowSize(Context context, Point outPoint) {
- context.getDisplay().getSize(outPoint);
+ context.getDisplayNoVerify().getSize(outPoint);
final TypedValue typedValue = sTempTypedValue;
context.getTheme().resolveAttribute(R.attr.autofillDatasetPickerMaxWidth,
typedValue, true);
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index 359c448..2c66047 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -834,6 +834,12 @@
/** @hide */
@Override
+ public Display getDisplayNoVerify() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @hide */
+ @Override
public int getDisplayId() {
throw new UnsupportedOperationException();
}