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

Commit e0304428 authored by Tim Yu's avatar Tim Yu
Browse files

Fix Autofill Inflating as User 0

Autofill will inflate views as the current foreground user instead of
the system_server user (0).

Bug: 327137311
Test: local build
Flag: EXEMPT bugfix
Change-Id: I8a2c96259976e61d297dec914d10d86e585a6d6f
parent 67271f5b
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -16,10 +16,13 @@

package com.android.server.autofill;

import static android.Manifest.permission.INTERACT_ACROSS_USERS;

import static com.android.server.autofill.Helper.sDebug;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.assist.AssistStructure;
@@ -29,6 +32,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.metrics.LogMaker;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
@@ -57,7 +61,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;


public final class Helper {

    private static final String TAG = "AutofillHelper";
@@ -69,7 +72,7 @@ public final class Helper {
     * {@code cmd autofill set log_level debug} or through
     * {@link android.provider.Settings.Global#AUTOFILL_LOGGING_LEVEL}.
     */
    public static boolean sDebug = false;
    public static boolean sDebug = true;

    /**
     * Defines a logging flag that can be dynamically changed at runtime using
@@ -103,6 +106,26 @@ public final class Helper {
        return permissionsOk.get();
    }

    /**
     * Creates the context as the foreground user
     *
     * <p>Returns the current context as the current foreground user
     */
    @RequiresPermission(INTERACT_ACROSS_USERS)
    public static Context getUserContext(Context context) {
        int userId = ActivityManager.getCurrentUser();
        Context c = context.createContextAsUser(UserHandle.of(userId), /* flags= */ 0);
        if (sDebug) {
            Slog.d(
                    TAG,
                    "Current User: "
                            + userId
                            + ", context created as: "
                            + c.getContentResolver().getUserId());
        }
        return c;
    }

    /**
     * Checks the URI permissions of the remote view,
     * to see if the current userId is able to access it.
+24 −10
Original line number Diff line number Diff line
@@ -5084,11 +5084,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        // Try to get the custom Icon, if one was passed through FillResponse
        int iconResourceId = response.getIconResourceId();
        if (iconResourceId != 0) {
            serviceIcon = mService.getMaster().getContext().getPackageManager()
            long token = Binder.clearCallingIdentity();
            try {
                serviceIcon =
                        mService.getMaster()
                                .getContext()
                                .getPackageManager()
                                .getDrawable(
                    mService.getServicePackageName(),
                    iconResourceId,
                    null);
                                        mService.getServicePackageName(), iconResourceId, null);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        // Custom icon wasn't fetched, use the default package icon instead
@@ -5114,11 +5120,19 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        // Try to get the custom Service name, if one was passed through FillResponse
        int customServiceNameId = response.getServiceDisplayNameResourceId();
        if (customServiceNameId != 0) {
            serviceLabel = mService.getMaster().getContext().getPackageManager()
            long token = Binder.clearCallingIdentity();
            try {
                serviceLabel =
                        mService.getMaster()
                                .getContext()
                                .getPackageManager()
                                .getText(
                                        mService.getServicePackageName(),
                                        customServiceNameId,
                                        null);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        // Custom label wasn't fetched, use the default package name instead
+7 −3
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ final class DialogFillUi {
    private final ComponentName mComponentName;
    private final int mThemeId;
    private final @NonNull Context mContext;
    private final @NonNull Context mUserContext;
    private final @NonNull UiCallback mCallback;
    private final @NonNull ListView mListView;
    private final @Nullable ItemsAdapter mAdapter;
@@ -104,6 +105,8 @@ final class DialogFillUi {
    private @Nullable AnnounceFilterResult mAnnounceFilterResult;
    private boolean mDestroyed;

    // System has all permissions, see b/228957088
    @SuppressWarnings("AndroidFrameworkRequiresPermission")
    DialogFillUi(@NonNull Context context, @NonNull FillResponse response,
            @NonNull AutofillId focusedViewId, @Nullable String filterText,
            @Nullable Drawable serviceIcon, @Nullable String servicePackageName,
@@ -117,6 +120,7 @@ final class DialogFillUi {
        mComponentName = componentName;

        mContext = new ContextThemeWrapper(context, mThemeId);
        mUserContext = Helper.getUserContext(mContext);
        final LayoutInflater inflater = LayoutInflater.from(mContext);
        final View decor = inflater.inflate(R.layout.autofill_fill_dialog, null);

@@ -224,7 +228,7 @@ final class DialogFillUi {
        };

        final View content = presentation.applyWithTheme(
                mContext, (ViewGroup) decor, interceptionHandler, mThemeId);
                mUserContext, (ViewGroup) decor, interceptionHandler, mThemeId);
        container.addView(content);
        container.setVisibility(View.VISIBLE);
    }
@@ -263,7 +267,7 @@ final class DialogFillUi {
            return true;
        };
        final View content = presentation.applyWithTheme(
                mContext, (ViewGroup) decor, interceptionHandler, mThemeId);
                mUserContext, (ViewGroup) decor, interceptionHandler, mThemeId);
        container.addView(content);
        container.setVisibility(View.VISIBLE);
        container.setFocusable(true);
@@ -305,7 +309,7 @@ final class DialogFillUi {
                try {
                    if (sVerbose) Slog.v(TAG, "setting remote view for " + focusedViewId);
                    view = presentation.applyWithTheme(
                            mContext, null, interceptionHandler, mThemeId);
                            mUserContext, null, interceptionHandler, mThemeId);
                } catch (RuntimeException e) {
                    Slog.e(TAG, "Error inflating remote views", e);
                    continue;
+9 −4
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ final class FillUi {
            new AutofillWindowPresenter();

    private final @NonNull Context mContext;
    private final @NonNull Context mUserContext;

    private final @NonNull AnchoredWindow mWindow;

@@ -141,6 +142,8 @@ final class FillUi {
        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
    }

    // System has all permissions, see b/228957088
    @SuppressWarnings("AndroidFrameworkRequiresPermission")
    FillUi(@NonNull Context context, @NonNull FillResponse response,
            @NonNull AutofillId focusedViewId, @Nullable String filterText,
            @NonNull OverlayControl overlayControl, @NonNull CharSequence serviceLabel,
@@ -153,6 +156,7 @@ final class FillUi {
        mCallback = callback;
        mFullScreen = isFullScreen(context);
        mContext = new ContextThemeWrapper(context, mThemeId);
        mUserContext = Helper.getUserContext(mContext);
        mMaxInputLengthForAutofill = maxInputLengthForAutofill;

        final LayoutInflater inflater = LayoutInflater.from(mContext);
@@ -245,7 +249,7 @@ final class FillUi {
                    throw new RuntimeException("Permission error accessing RemoteView");
                }
                content = response.getPresentation().applyWithTheme(
                        mContext, decor, interceptionHandler, mThemeId);
                        mUserContext, decor, interceptionHandler, mThemeId);
                container.addView(content);
            } catch (RuntimeException e) {
                callback.onCanceled();
@@ -286,7 +290,7 @@ final class FillUi {
            if (headerPresentation != null) {
                interactionBlocker = newInteractionBlocker();
                mHeader = headerPresentation.applyWithTheme(
                        mContext, null, interactionBlocker, mThemeId);
                        mUserContext, null, interactionBlocker, mThemeId);
                final LinearLayout headerContainer =
                        decor.findViewById(R.id.autofill_dataset_header);
                applyCancelAction(mHeader, response.getCancelIds());
@@ -305,7 +309,7 @@ final class FillUi {
                        interactionBlocker = newInteractionBlocker();
                    }
                    mFooter = footerPresentation.applyWithTheme(
                            mContext, null, interactionBlocker, mThemeId);
                            mUserContext, null, interactionBlocker, mThemeId);
                    applyCancelAction(mFooter, response.getCancelIds());
                    // Footer not supported on some platform e.g. TV
                    if (sVerbose) Slog.v(TAG, "adding footer");
@@ -334,7 +338,7 @@ final class FillUi {
                    try {
                        if (sVerbose) Slog.v(TAG, "setting remote view for " + focusedViewId);
                        view = presentation.applyWithTheme(
                                mContext, null, interceptionHandler, mThemeId);
                                mUserContext, null, interceptionHandler, mThemeId);
                    } catch (RuntimeException e) {
                        Slog.e(TAG, "Error inflating remote views", e);
                        continue;
@@ -812,6 +816,7 @@ final class FillUi {
        pw.print(prefix); pw.print("mContentHeight: "); pw.println(mContentHeight);
        pw.print(prefix); pw.print("mDestroyed: "); pw.println(mDestroyed);
        pw.print(prefix); pw.print("mContext: "); pw.println(mContext);
        pw.print(prefix); pw.print("mUserContext: "); pw.println(mUserContext);
        pw.print(prefix); pw.print("theme id: "); pw.print(mThemeId);
        switch (mThemeId) {
            case THEME_ID_DARK:
+4 −1
Original line number Diff line number Diff line
@@ -176,6 +176,8 @@ final class SaveUi {

    private boolean mDestroyed;

    // System has all permissions, see b/228957088
    @SuppressWarnings("AndroidFrameworkRequiresPermission")
    SaveUi(@NonNull Context context, @NonNull PendingUi pendingUi,
           @NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
           @Nullable String servicePackageName, @NonNull ComponentName componentName,
@@ -193,7 +195,7 @@ final class SaveUi {
        mComponentName = componentName;
        mCompatMode = compatMode;

        context = new ContextThemeWrapper(context, mThemeId) {
        context = new ContextThemeWrapper(Helper.getUserContext(context), mThemeId) {
            @Override
            public void startActivity(Intent intent) {
                if (resolveActivity(intent) == null) {
@@ -235,6 +237,7 @@ final class SaveUi {
                return null;
            }
        };

        final LayoutInflater inflater = LayoutInflater.from(context);
        final View view = inflater.inflate(R.layout.autofill_save, null);