Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c22aff4e authored by Charles Chen's avatar Charles Chen Committed by Android (Google) Code Review
Browse files

Merge "Allow config context to inflate views" into sc-dev

parents 0584a987 d12be752
Loading
Loading
Loading
Loading
+20 −8
Original line number Diff line number Diff line
@@ -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;

@@ -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);
@@ -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.
@@ -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) {
@@ -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
@@ -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;
    }

@@ -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;
@@ -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;
@@ -3135,6 +3146,7 @@ class ContextImpl extends Context {
        //  WindowContext.
        if (mOuterContext.isUiContext() && mContextType <= CONTEXT_TYPE_DISPLAY_CONTEXT) {
            mContextType = CONTEXT_TYPE_WINDOW_CONTEXT;
            mIsConfigurationBasedContext = true;
        }
    }

+21 −0
Original line number Diff line number Diff line
@@ -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.");
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -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();
    }
}
+39 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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.
+2 −14
Original line number Diff line number Diff line
@@ -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;
@@ -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;

@@ -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);
    }
@@ -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