From 9ca5f902ca95b24ff34c60d7dc9439afad023ec0 Mon Sep 17 00:00:00 2001 From: Charles Chen Date: Mon, 28 Dec 2020 15:16:13 +0800 Subject: [PATCH] Limit UI context verification to UI related APIs This CL relaxed the UI context checks to only apply on UI related APIs in WallpaperManager. Test: build & run Bug: 176958992 Change-Id: I390e865e31fde48bad6bbddb4203e4c997a1400a --- core/java/android/app/ContextImpl.java | 3 +-- core/java/android/app/WallpaperManager.java | 16 ++++++++++++ core/java/android/os/StrictMode.java | 27 +++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 700d8ff364463..93c63e6248634 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1996,8 +1996,7 @@ class ContextImpl extends Context { } private static boolean isUiComponent(String name) { - return WINDOW_SERVICE.equals(name) || LAYOUT_INFLATER_SERVICE.equals(name) - || WALLPAPER_SERVICE.equals(name); + return WINDOW_SERVICE.equals(name) || LAYOUT_INFLATER_SERVICE.equals(name); } @Override diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index ab0901da632f1..76ef040a67ccb 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -63,6 +63,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import android.os.StrictMode; import android.os.SystemProperties; import android.text.TextUtils; import android.util.Log; @@ -606,6 +607,7 @@ public class WallpaperManager { * is not able to access the wallpaper. */ public Drawable getDrawable() { + assertUiContext("getDrawable"); final ColorManagementProxy cmProxy = getColorManagementProxy(); Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, cmProxy); if (bm != null) { @@ -673,6 +675,7 @@ public class WallpaperManager { */ public Drawable getBuiltInDrawable(int outWidth, int outHeight, boolean scaleToFit, float horizontalAlignment, float verticalAlignment, @SetWallpaperFlags int which) { + assertUiContext("getBuiltInDrawable"); if (sGlobals.mService == null) { Log.w(TAG, "WallpaperService not running"); throw new RuntimeException(new DeadSystemException()); @@ -838,6 +841,7 @@ public class WallpaperManager { * null pointer if these is none. */ public Drawable peekDrawable() { + assertUiContext("peekDrawable"); final ColorManagementProxy cmProxy = getColorManagementProxy(); Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, cmProxy); if (bm != null) { @@ -880,6 +884,7 @@ public class WallpaperManager { */ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public Drawable peekFastDrawable() { + assertUiContext("peekFastDrawable"); final ColorManagementProxy cmProxy = getColorManagementProxy(); Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, cmProxy); if (bm != null) { @@ -1046,6 +1051,7 @@ public class WallpaperManager { */ @UnsupportedAppUsage public @Nullable WallpaperColors getWallpaperColors(int which, int userId) { + assertUiContext("getWallpaperColors"); return sGlobals.getWallpaperColors(which, userId, mContext.getDisplayId()); } @@ -1261,6 +1267,7 @@ public class WallpaperManager { @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setResource(@RawRes int resid, @SetWallpaperFlags int which) throws IOException { + assertUiContext("setResource"); if (sGlobals.mService == null) { Log.w(TAG, "WallpaperService not running"); throw new RuntimeException(new DeadSystemException()); @@ -1581,6 +1588,7 @@ public class WallpaperManager { * @see #getDesiredMinimumHeight() */ public int getDesiredMinimumWidth() { + assertUiContext("getDesiredMinimumWidth"); if (sGlobals.mService == null) { Log.w(TAG, "WallpaperService not running"); throw new RuntimeException(new DeadSystemException()); @@ -1609,6 +1617,7 @@ public class WallpaperManager { * @see #getDesiredMinimumWidth() */ public int getDesiredMinimumHeight() { + assertUiContext("getDesiredMinimumHeight"); if (sGlobals.mService == null) { Log.w(TAG, "WallpaperService not running"); throw new RuntimeException(new DeadSystemException()); @@ -1639,6 +1648,7 @@ public class WallpaperManager { * @param minimumHeight Desired minimum height */ public void suggestDesiredDimensions(int minimumWidth, int minimumHeight) { + assertUiContext("suggestDesiredDimensions"); try { /** * The framework makes no attempt to limit the window size @@ -1694,6 +1704,7 @@ public class WallpaperManager { */ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_HINTS) public void setDisplayPadding(Rect padding) { + assertUiContext("setDisplayPadding"); try { if (sGlobals.mService == null) { Log.w(TAG, "WallpaperService not running"); @@ -1946,6 +1957,7 @@ public class WallpaperManager { */ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public void clear() throws IOException { + assertUiContext("clear"); setStream(openDefaultWallpaper(mContext, FLAG_SYSTEM), null, false); } @@ -2094,6 +2106,10 @@ public class WallpaperManager { return mCmProxy; } + private void assertUiContext(final String methodName) { + StrictMode.assertUiContext(mContext, methodName); + } + /** * A hidden class to help {@link Globals#getCurrentWallpaperLocked} handle color management. * @hide diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 086180e7ead4e..b13be9f4a91a3 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -2194,6 +2194,33 @@ public final class StrictMode { onVmPolicyViolation(new IncorrectContextUseViolation(message, originStack)); } + /** + * A helper method to verify if the {@code context} is a UI context and throw + * {@link IncorrectContextUseViolation} if the {@code context} is not a UI context. + * + * @param context The context to verify if it is a UI context + * @param methodName The asserted method name + * + * @see Context#isUiContext() + * @see IncorrectContextUseViolation + * + * @hide + */ + public static void assertUiContext(@NonNull Context context, @NonNull String methodName) { + if (vmIncorrectContextUseEnabled() && !context.isUiContext()) { + final String errorMessage = "Tried to access UI related API" + methodName + + " from a non-UI Context:" + context; + final String message = "UI-related services, such as WindowManager, WallpaperService " + + "or LayoutInflater should be accessed from Activity or other UI " + + "Contexts. 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); + } + } + /** Assume locked until we hear otherwise */ private static volatile boolean sUserKeyUnlocked = false;