Loading core/java/android/app/ContextImpl.java +20 −8 Original line number Diff line number Diff line Loading @@ -243,6 +243,9 @@ class ContextImpl extends Context { */ private boolean mForceDisplayOverrideInResources; /** @see Context#isConfigurationContext() */ private boolean mIsConfigurationBasedContext; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private final int mFlags; Loading Loading @@ -2002,13 +2005,12 @@ class ContextImpl extends Context { public Object getSystemService(String name) { if (vmIncorrectContextUseEnabled()) { // Check incorrect Context usage. if (isUiComponent(name) && !isUiContext()) { if (WINDOW_SERVICE.equals(name) && !isUiContext()) { final String errorMessage = "Tried to access visual service " + SystemServiceRegistry.getSystemServiceClassName(name) + " from a non-visual Context:" + getOuterContext(); final String message = "Visual services, such as WindowManager " + "or LayoutInflater should be accessed from Activity or another visual " + "Context. Use an Activity or a Context created with " final String message = "WindowManager 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); Loading Loading @@ -2041,6 +2043,12 @@ class ContextImpl extends Context { } } /** @hide */ @Override public boolean isConfigurationContext() { return isUiContext() || mIsConfigurationBasedContext; } /** * Temporary workaround to permit incorrect usages of Context by SystemUI. * TODO(b/147647877): Fix usages and remove. Loading @@ -2053,10 +2061,6 @@ class ContextImpl extends Context { Binder.getCallingUid()) == PERMISSION_GRANTED; } private static boolean isUiComponent(String name) { return WINDOW_SERVICE.equals(name) || LAYOUT_INFLATER_SERVICE.equals(name); } @Override public int checkPermission(String permission, int pid, int uid) { if (permission == null) { Loading Loading @@ -2538,6 +2542,7 @@ class ContextImpl extends Context { mAttributionSource.getAttributionTag(), mAttributionSource.getNext(), mSplitName, mToken, mUser, mFlags, mClassLoader, null); context.mIsConfigurationBasedContext = true; final int displayId = getDisplayId(); final Integer overrideDisplayId = mForceDisplayOverrideInResources Loading Loading @@ -2575,6 +2580,10 @@ class ContextImpl extends Context { // the display that would otherwise be inherited from mToken (or the global configuration if // mToken is null). context.mForceDisplayOverrideInResources = true; // The configuration is overridden by display adjustments' configuration and won't receive // configuration changes. This context won't be regarded as having the proper configuration // anymore. context.mIsConfigurationBasedContext = false; return context; } Loading Loading @@ -2988,6 +2997,7 @@ class ContextImpl extends Context { ContextImpl context = new ContextImpl(null, mainThread, packageInfo, ContextParams.EMPTY, null, null, activityInfo.splitName, activityToken, null, 0, classLoader, null); context.mContextType = CONTEXT_TYPE_ACTIVITY; context.mIsConfigurationBasedContext = true; // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY. displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY; Loading Loading @@ -3058,6 +3068,7 @@ class ContextImpl extends Context { setResources(container.mResources); mDisplay = container.mDisplay; mForceDisplayOverrideInResources = container.mForceDisplayOverrideInResources; mIsConfigurationBasedContext = container.mIsConfigurationBasedContext; mContextType = container.mContextType; } else { mBasePackageName = packageInfo.mPackageName; Loading Loading @@ -3135,6 +3146,7 @@ class ContextImpl extends Context { // WindowContext. if (mOuterContext.isUiContext() && mContextType <= CONTEXT_TYPE_DISPLAY_CONTEXT) { mContextType = CONTEXT_TYPE_WINDOW_CONTEXT; mIsConfigurationBasedContext = true; } } Loading core/java/android/content/Context.java +21 −0 Original line number Diff line number Diff line Loading @@ -6817,4 +6817,25 @@ public abstract class Context { * @hide */ public void destroy() { } /** * Indicates this {@link Context} has the proper {@link Configuration} to obtain * {@link android.view.LayoutInflater}, {@link android.view.ViewConfiguration} and * {@link android.view.GestureDetector}. Generally, all UI contexts, such as * {@link android.app.Activity} or {@link android.app.WindowContext}, are initialized with base * configuration. * <p> * Note that the context created via {@link Context#createConfigurationContext(Configuration)} * is also regarded as a context that is based on a configuration because the * configuration is explicitly provided via the API. * </p> * * @see #isUiContext() * @see #createConfigurationContext(Configuration) * * @hide */ public boolean isConfigurationContext() { throw new RuntimeException("Not implemented. Must override in a subclass."); } } core/java/android/content/ContextWrapper.java +11 −0 Original line number Diff line number Diff line Loading @@ -1250,4 +1250,15 @@ public class ContextWrapper extends Context { } return mBase.isUiContext(); } /** * @hide */ @Override public boolean isConfigurationContext() { if (mBase == null) { return false; } return mBase.isConfigurationContext(); } } core/java/android/os/StrictMode.java +39 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.net.TrafficStats; import android.net.Uri; import android.os.storage.IStorageManager; Loading Loading @@ -2260,6 +2261,44 @@ public final class StrictMode { onVmPolicyViolation(new IncorrectContextUseViolation(message, originStack)); } /** * A helper method to verify if the {@code context} has a proper {@link Configuration} to obtain * {@link android.view.LayoutInflater}, {@link android.view.ViewConfiguration} or * {@link android.view.GestureDetector}. Throw {@link IncorrectContextUseViolation} if the * {@code context} doesn't have a proper configuration. * <p> * Note that the context created via {@link Context#createConfigurationContext(Configuration)} * is also regarded as a context with a proper configuration because the {@link Configuration} * is handled by developers. * </p> * @param context The context to verify if it is a display associative context * @param methodName The asserted method name * * @see Context#isConfigurationContext() * @see Context#createConfigurationContext(Configuration) * @see Context#getSystemService(String) * @see Context#LAYOUT_INFLATER_SERVICE * @see android.view.ViewConfiguration#get(Context) * @see android.view.LayoutInflater#from(Context) * @see IncorrectContextUseViolation * * @hide */ public static void assertConfigurationContext(@NonNull Context context, @NonNull String methodName) { if (vmIncorrectContextUseEnabled() && !context.isConfigurationContext()) { final String errorMessage = "Tried to access the API:" + methodName + " which needs to" + " have proper configuration from a non-UI Context:" + context; final String message = "The API:" + methodName + " needs a proper configuration." + " Use UI contexts such as an activity or a context created" + " via createWindowContext(Display, int, Bundle) or " + " createConfigurationContext(Configuration) with a proper configuration."; final Exception exception = new IllegalAccessException(errorMessage); StrictMode.onIncorrectContextUsed(message, exception); Log.e(TAG, errorMessage + " " + message, exception); } } /** * 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. Loading core/java/android/view/GestureDetector.java +2 −14 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package android.view; import static android.os.StrictMode.vmIncorrectContextUseEnabled; import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS; import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP; import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS; Loading @@ -34,7 +32,6 @@ import android.os.Handler; import android.os.Message; import android.os.StrictMode; import android.os.SystemClock; import android.util.Log; import com.android.internal.util.FrameworkStatsLog; Loading Loading @@ -394,6 +391,7 @@ public class GestureDetector { * * @throws NullPointerException if {@code listener} is null. */ // TODO(b/182007470): Use @ConfigurationContext instead public GestureDetector(@UiContext Context context, OnGestureListener listener) { this(context, listener, null); } Loading Loading @@ -467,17 +465,7 @@ public class GestureDetector { mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity(); mAmbiguousGestureMultiplier = ViewConfiguration.getAmbiguousGestureMultiplier(); } else { if (!context.isUiContext() && vmIncorrectContextUseEnabled()) { final String errorMessage = "Tried to access UI constants from a non-visual Context."; final String message = "GestureDetector must 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 IllegalArgumentException(errorMessage); StrictMode.onIncorrectContextUsed(message, exception); Log.e(TAG, errorMessage + message, exception); } StrictMode.assertConfigurationContext(context, "GestureDetector#init"); final ViewConfiguration configuration = ViewConfiguration.get(context); touchSlop = configuration.getScaledTouchSlop(); doubleTapTouchSlop = configuration.getScaledDoubleTapTouchSlop(); Loading Loading
core/java/android/app/ContextImpl.java +20 −8 Original line number Diff line number Diff line Loading @@ -243,6 +243,9 @@ class ContextImpl extends Context { */ private boolean mForceDisplayOverrideInResources; /** @see Context#isConfigurationContext() */ private boolean mIsConfigurationBasedContext; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private final int mFlags; Loading Loading @@ -2002,13 +2005,12 @@ class ContextImpl extends Context { public Object getSystemService(String name) { if (vmIncorrectContextUseEnabled()) { // Check incorrect Context usage. if (isUiComponent(name) && !isUiContext()) { if (WINDOW_SERVICE.equals(name) && !isUiContext()) { final String errorMessage = "Tried to access visual service " + SystemServiceRegistry.getSystemServiceClassName(name) + " from a non-visual Context:" + getOuterContext(); final String message = "Visual services, such as WindowManager " + "or LayoutInflater should be accessed from Activity or another visual " + "Context. Use an Activity or a Context created with " final String message = "WindowManager 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); Loading Loading @@ -2041,6 +2043,12 @@ class ContextImpl extends Context { } } /** @hide */ @Override public boolean isConfigurationContext() { return isUiContext() || mIsConfigurationBasedContext; } /** * Temporary workaround to permit incorrect usages of Context by SystemUI. * TODO(b/147647877): Fix usages and remove. Loading @@ -2053,10 +2061,6 @@ class ContextImpl extends Context { Binder.getCallingUid()) == PERMISSION_GRANTED; } private static boolean isUiComponent(String name) { return WINDOW_SERVICE.equals(name) || LAYOUT_INFLATER_SERVICE.equals(name); } @Override public int checkPermission(String permission, int pid, int uid) { if (permission == null) { Loading Loading @@ -2538,6 +2542,7 @@ class ContextImpl extends Context { mAttributionSource.getAttributionTag(), mAttributionSource.getNext(), mSplitName, mToken, mUser, mFlags, mClassLoader, null); context.mIsConfigurationBasedContext = true; final int displayId = getDisplayId(); final Integer overrideDisplayId = mForceDisplayOverrideInResources Loading Loading @@ -2575,6 +2580,10 @@ class ContextImpl extends Context { // the display that would otherwise be inherited from mToken (or the global configuration if // mToken is null). context.mForceDisplayOverrideInResources = true; // The configuration is overridden by display adjustments' configuration and won't receive // configuration changes. This context won't be regarded as having the proper configuration // anymore. context.mIsConfigurationBasedContext = false; return context; } Loading Loading @@ -2988,6 +2997,7 @@ class ContextImpl extends Context { ContextImpl context = new ContextImpl(null, mainThread, packageInfo, ContextParams.EMPTY, null, null, activityInfo.splitName, activityToken, null, 0, classLoader, null); context.mContextType = CONTEXT_TYPE_ACTIVITY; context.mIsConfigurationBasedContext = true; // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY. displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY; Loading Loading @@ -3058,6 +3068,7 @@ class ContextImpl extends Context { setResources(container.mResources); mDisplay = container.mDisplay; mForceDisplayOverrideInResources = container.mForceDisplayOverrideInResources; mIsConfigurationBasedContext = container.mIsConfigurationBasedContext; mContextType = container.mContextType; } else { mBasePackageName = packageInfo.mPackageName; Loading Loading @@ -3135,6 +3146,7 @@ class ContextImpl extends Context { // WindowContext. if (mOuterContext.isUiContext() && mContextType <= CONTEXT_TYPE_DISPLAY_CONTEXT) { mContextType = CONTEXT_TYPE_WINDOW_CONTEXT; mIsConfigurationBasedContext = true; } } Loading
core/java/android/content/Context.java +21 −0 Original line number Diff line number Diff line Loading @@ -6817,4 +6817,25 @@ public abstract class Context { * @hide */ public void destroy() { } /** * Indicates this {@link Context} has the proper {@link Configuration} to obtain * {@link android.view.LayoutInflater}, {@link android.view.ViewConfiguration} and * {@link android.view.GestureDetector}. Generally, all UI contexts, such as * {@link android.app.Activity} or {@link android.app.WindowContext}, are initialized with base * configuration. * <p> * Note that the context created via {@link Context#createConfigurationContext(Configuration)} * is also regarded as a context that is based on a configuration because the * configuration is explicitly provided via the API. * </p> * * @see #isUiContext() * @see #createConfigurationContext(Configuration) * * @hide */ public boolean isConfigurationContext() { throw new RuntimeException("Not implemented. Must override in a subclass."); } }
core/java/android/content/ContextWrapper.java +11 −0 Original line number Diff line number Diff line Loading @@ -1250,4 +1250,15 @@ public class ContextWrapper extends Context { } return mBase.isUiContext(); } /** * @hide */ @Override public boolean isConfigurationContext() { if (mBase == null) { return false; } return mBase.isConfigurationContext(); } }
core/java/android/os/StrictMode.java +39 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.net.TrafficStats; import android.net.Uri; import android.os.storage.IStorageManager; Loading Loading @@ -2260,6 +2261,44 @@ public final class StrictMode { onVmPolicyViolation(new IncorrectContextUseViolation(message, originStack)); } /** * A helper method to verify if the {@code context} has a proper {@link Configuration} to obtain * {@link android.view.LayoutInflater}, {@link android.view.ViewConfiguration} or * {@link android.view.GestureDetector}. Throw {@link IncorrectContextUseViolation} if the * {@code context} doesn't have a proper configuration. * <p> * Note that the context created via {@link Context#createConfigurationContext(Configuration)} * is also regarded as a context with a proper configuration because the {@link Configuration} * is handled by developers. * </p> * @param context The context to verify if it is a display associative context * @param methodName The asserted method name * * @see Context#isConfigurationContext() * @see Context#createConfigurationContext(Configuration) * @see Context#getSystemService(String) * @see Context#LAYOUT_INFLATER_SERVICE * @see android.view.ViewConfiguration#get(Context) * @see android.view.LayoutInflater#from(Context) * @see IncorrectContextUseViolation * * @hide */ public static void assertConfigurationContext(@NonNull Context context, @NonNull String methodName) { if (vmIncorrectContextUseEnabled() && !context.isConfigurationContext()) { final String errorMessage = "Tried to access the API:" + methodName + " which needs to" + " have proper configuration from a non-UI Context:" + context; final String message = "The API:" + methodName + " needs a proper configuration." + " Use UI contexts such as an activity or a context created" + " via createWindowContext(Display, int, Bundle) or " + " createConfigurationContext(Configuration) with a proper configuration."; final Exception exception = new IllegalAccessException(errorMessage); StrictMode.onIncorrectContextUsed(message, exception); Log.e(TAG, errorMessage + " " + message, exception); } } /** * 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. Loading
core/java/android/view/GestureDetector.java +2 −14 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package android.view; import static android.os.StrictMode.vmIncorrectContextUseEnabled; import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DEEP_PRESS; import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__DOUBLE_TAP; import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS; Loading @@ -34,7 +32,6 @@ import android.os.Handler; import android.os.Message; import android.os.StrictMode; import android.os.SystemClock; import android.util.Log; import com.android.internal.util.FrameworkStatsLog; Loading Loading @@ -394,6 +391,7 @@ public class GestureDetector { * * @throws NullPointerException if {@code listener} is null. */ // TODO(b/182007470): Use @ConfigurationContext instead public GestureDetector(@UiContext Context context, OnGestureListener listener) { this(context, listener, null); } Loading Loading @@ -467,17 +465,7 @@ public class GestureDetector { mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity(); mAmbiguousGestureMultiplier = ViewConfiguration.getAmbiguousGestureMultiplier(); } else { if (!context.isUiContext() && vmIncorrectContextUseEnabled()) { final String errorMessage = "Tried to access UI constants from a non-visual Context."; final String message = "GestureDetector must 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 IllegalArgumentException(errorMessage); StrictMode.onIncorrectContextUsed(message, exception); Log.e(TAG, errorMessage + message, exception); } StrictMode.assertConfigurationContext(context, "GestureDetector#init"); final ViewConfiguration configuration = ViewConfiguration.get(context); touchSlop = configuration.getScaledTouchSlop(); doubleTapTouchSlop = configuration.getScaledDoubleTapTouchSlop(); Loading