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

Commit eab62baa authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

Restore session on new window after app kill

Also:
- Give the session an integer ID as the activityToken is not stable over
  restarts of the activity
- Verify that session is only accessed by one UID
- stabilize AccessibilityViewIds over activity lifecycle at least for
  the IDs we can do that. This required to split the ID namespace in
  "per-app" and "per-activity" views. Only the later ones can be
  restored.
- Do not end session when app is killed (as it can be restarted)

Bug: 35484143
Fixes: 36392498
Test: cts-tradefed run cts-dev -m CtsAutoFillServiceTestCases --test=android.autofillservice.cts.SessionLifecycleTest
      cts-tradefed run cts-dev -m CtsAutoFillServiceTestCases
Change-Id: I229acc1b3ce35fb57262da7d7466b5d4328b49d4
parent ca24a97a
Loading
Loading
Loading
Loading
+68 −11
Original line number Original line Diff line number Diff line
@@ -724,8 +724,9 @@ public class Activity extends ContextThemeWrapper
    public static final int FINISH_TASK_WITH_ACTIVITY = 2;
    public static final int FINISH_TASK_WITH_ACTIVITY = 2;


    static final String FRAGMENTS_TAG = "android:fragments";
    static final String FRAGMENTS_TAG = "android:fragments";
    static final String AUTOFILL_RESET_NEEDED_TAG = "android:autofillResetNeeded";
    private static final String LAST_ACCESSIBILITY_ID = "android:lastAccessibilityId";


    private static final String AUTOFILL_RESET_NEEDED = "@android:autofillResetNeeded";
    private static final String WINDOW_HIERARCHY_TAG = "android:viewHierarchyState";
    private static final String WINDOW_HIERARCHY_TAG = "android:viewHierarchyState";
    private static final String SAVED_DIALOG_IDS_KEY = "android:savedDialogIds";
    private static final String SAVED_DIALOG_IDS_KEY = "android:savedDialogIds";
    private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";
    private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";
@@ -773,6 +774,9 @@ public class Activity extends ContextThemeWrapper
    private SearchManager mSearchManager;
    private SearchManager mSearchManager;
    private MenuInflater mMenuInflater;
    private MenuInflater mMenuInflater;


    /** The autofill manager. Always access via {@link #getAutofillManager()}. */
    @Nullable private AutofillManager mAutofillManager;

    static final class NonConfigurationInstances {
    static final class NonConfigurationInstances {
        Object activity;
        Object activity;
        HashMap<String, Object> children;
        HashMap<String, Object> children;
@@ -853,6 +857,9 @@ public class Activity extends ContextThemeWrapper


    private boolean mAutoFillResetNeeded;
    private boolean mAutoFillResetNeeded;


    /** The last accessibility id that was returned from {@link #getNextAccessibilityId()} */
    private int mLastAccessibilityId = View.LAST_APP_ACCESSIBILITY_ID;

    private AutofillPopupWindow mAutofillPopupWindow;
    private AutofillPopupWindow mAutofillPopupWindow;


    private static native String getDlWarning();
    private static native String getDlWarning();
@@ -929,6 +936,19 @@ public class Activity extends ContextThemeWrapper
        return mWindow != null ? mWindow.getCurrentFocus() : null;
        return mWindow != null ? mWindow.getCurrentFocus() : null;
    }
    }


    /**
     * (Create and) return the autofill manager
     *
     * @return The autofill manager
     */
    @NonNull private AutofillManager getAutofillManager() {
        if (mAutofillManager == null) {
            mAutofillManager = getSystemService(AutofillManager.class);
        }

        return mAutofillManager;
    }

    /**
    /**
     * Called when the activity is starting.  This is where most initialization
     * Called when the activity is starting.  This is where most initialization
     * should go: calling {@link #setContentView(int)} to inflate the
     * should go: calling {@link #setContentView(int)} to inflate the
@@ -970,6 +990,13 @@ public class Activity extends ContextThemeWrapper
            }
            }
        }
        }
        if (savedInstanceState != null) {
        if (savedInstanceState != null) {
            mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
            mLastAccessibilityId = savedInstanceState.getInt(LAST_ACCESSIBILITY_ID, View.NO_ID);

            if (mAutoFillResetNeeded) {
                getAutofillManager().onCreate(savedInstanceState);
            }

            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
            mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
                    ? mLastNonConfigurationInstances.fragments : null);
                    ? mLastNonConfigurationInstances.fragments : null);
@@ -1058,12 +1085,6 @@ public class Activity extends ContextThemeWrapper
     * @see #onSaveInstanceState
     * @see #onSaveInstanceState
     */
     */
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED_TAG, false);

        if (mAutoFillResetNeeded) {
            getSystemService(AutofillManager.class).onRestoreInstanceState(savedInstanceState);
        }

        if (mWindow != null) {
        if (mWindow != null) {
            Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
            Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
            if (windowState != null) {
            if (windowState != null) {
@@ -1311,6 +1332,27 @@ public class Activity extends ContextThemeWrapper
        }
        }
    }
    }


    /**
     * Gets the next accessibility ID.
     *
     * <p>All IDs will be bigger than {@link View#LAST_APP_ACCESSIBILITY_ID}. All IDs returned
     * will be unique.
     *
     * @return A ID that is unique in the activity
     *
     * {@hide}
     */
    @Override
    public int getNextAccessibilityId() {
        if (mLastAccessibilityId == Integer.MAX_VALUE - 1) {
            mLastAccessibilityId = View.LAST_APP_ACCESSIBILITY_ID;
        }

        mLastAccessibilityId++;

        return mLastAccessibilityId;
    }

    /**
    /**
     * Check whether this activity is running as part of a voice interaction with the user.
     * Check whether this activity is running as part of a voice interaction with the user.
     * If true, it should perform its interaction with the user through the
     * If true, it should perform its interaction with the user through the
@@ -1505,13 +1547,15 @@ public class Activity extends ContextThemeWrapper
     */
     */
    protected void onSaveInstanceState(Bundle outState) {
    protected void onSaveInstanceState(Bundle outState) {
        outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
        outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());

        outState.putInt(LAST_ACCESSIBILITY_ID, mLastAccessibilityId);
        Parcelable p = mFragments.saveAllState();
        Parcelable p = mFragments.saveAllState();
        if (p != null) {
        if (p != null) {
            outState.putParcelable(FRAGMENTS_TAG, p);
            outState.putParcelable(FRAGMENTS_TAG, p);
        }
        }
        if (mAutoFillResetNeeded) {
        if (mAutoFillResetNeeded) {
            outState.putBoolean(AUTOFILL_RESET_NEEDED_TAG, mAutoFillResetNeeded);
            outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
            getSystemService(AutofillManager.class).onSaveInstanceState(outState);
            getAutofillManager().onSaveInstanceState(outState);
        }
        }
        getApplication().dispatchActivitySaveInstanceState(this, outState);
        getApplication().dispatchActivitySaveInstanceState(this, outState);
    }
    }
@@ -1802,7 +1846,7 @@ public class Activity extends ContextThemeWrapper
        mTranslucentCallback = null;
        mTranslucentCallback = null;
        mCalled = true;
        mCalled = true;
        if (isFinishing() && mAutoFillResetNeeded) {
        if (isFinishing() && mAutoFillResetNeeded) {
            getSystemService(AutofillManager.class).commit();
            getAutofillManager().commit();
        }
        }
    }
    }


@@ -3056,6 +3100,19 @@ public class Activity extends ContextThemeWrapper
    public void onWindowFocusChanged(boolean hasFocus) {
    public void onWindowFocusChanged(boolean hasFocus) {
    }
    }


    /**
     * Called before {@link #onAttachedToWindow}.
     *
     * @hide
     */
    @CallSuper
    public void onBeforeAttachedToWindow() {
        if (mAutoFillResetNeeded) {
            getAutofillManager().onAttachedToWindow(
                    getWindow().getDecorView().getRootView().getWindowToken());
        }
    }

    /**
    /**
     * Called when the main window associated with the activity has been
     * Called when the main window associated with the activity has been
     * attached to the window manager.
     * attached to the window manager.
@@ -7125,7 +7182,7 @@ public class Activity extends ContextThemeWrapper
            }
            }
        } else if (who.startsWith(AUTO_FILL_AUTH_WHO_PREFIX)) {
        } else if (who.startsWith(AUTO_FILL_AUTH_WHO_PREFIX)) {
            Intent resultData = (resultCode == Activity.RESULT_OK) ? data : null;
            Intent resultData = (resultCode == Activity.RESULT_OK) ? data : null;
            getSystemService(AutofillManager.class).onAuthenticationResult(resultData);
            getAutofillManager().onAuthenticationResult(resultData);
        } else {
        } else {
            Fragment frag = mFragments.findFragmentByWho(who);
            Fragment frag = mFragments.findFragmentByWho(who);
            if (frag != null) {
            if (frag != null) {
+24 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,7 @@ import android.provider.MediaStore;
import android.util.AttributeSet;
import android.util.AttributeSet;
import android.view.Display;
import android.view.Display;
import android.view.DisplayAdjustments;
import android.view.DisplayAdjustments;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewDebug;
import android.view.WindowManager;
import android.view.WindowManager;
import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassificationManager;
@@ -436,6 +437,29 @@ public abstract class Context {
     */
     */
    public abstract Context getApplicationContext();
    public abstract Context getApplicationContext();


    /** Non-activity related accessibility ids are unique in the app */
    private static int sLastAccessibilityId = View.NO_ID;

    /**
     * Gets the next accessibility ID.
     *
     * <p>All IDs will be smaller or the same as {@link View#LAST_APP_ACCESSIBILITY_ID}. All IDs
     * returned will be unique.
     *
     * @return A ID that is unique in the process
     *
     * {@hide}
     */
    public int getNextAccessibilityId() {
        if (sLastAccessibilityId == View.LAST_APP_ACCESSIBILITY_ID - 1) {
            sLastAccessibilityId = View.NO_ID;
        }

        sLastAccessibilityId++;

        return sLastAccessibilityId;
    }

    /**
    /**
     * Add a new {@link ComponentCallbacks} to the base application of the
     * Add a new {@link ComponentCallbacks} to the base application of the
     * Context, which will be called at the same times as the ComponentCallbacks
     * Context, which will be called at the same times as the ComponentCallbacks
+1 −2
Original line number Original line Diff line number Diff line
@@ -82,8 +82,7 @@ public abstract class AutofillService extends Service {


    // Internal extras
    // Internal extras
    /** @hide */
    /** @hide */
    public static final String EXTRA_ACTIVITY_TOKEN =
    public static final String EXTRA_SESSION_ID = "android.service.autofill.extra.SESSION_ID";
            "android.service.autofill.extra.ACTIVITY_TOKEN";


    // Handler messages.
    // Handler messages.
    private static final int MSG_CONNECT = 1;
    private static final int MSG_CONNECT = 1;
+32 −10
Original line number Original line Diff line number Diff line
@@ -796,6 +796,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
     */
    public static final int NO_ID = -1;
    public static final int NO_ID = -1;
    /**
     * Last ID that is given to Views that are no part of activities.
     *
     * {@hide}
     */
    public static final int LAST_APP_ACCESSIBILITY_ID = Integer.MAX_VALUE / 2;
    /**
    /**
     * Signals that compatibility booleans have been initialized according to
     * Signals that compatibility booleans have been initialized according to
     * target SDK versions.
     * target SDK versions.
@@ -1966,11 +1973,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
     */
    private SparseArray<Object> mKeyedTags;
    private SparseArray<Object> mKeyedTags;
    /**
     * The next available accessibility id.
     */
    private static int sNextAccessibilityViewId;
    /**
    /**
     * The animation currently associated with this view.
     * The animation currently associated with this view.
     * @hide
     * @hide
@@ -2013,10 +2015,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    @ViewDebug.ExportedProperty(resolveId = true)
    @ViewDebug.ExportedProperty(resolveId = true)
    int mID = NO_ID;
    int mID = NO_ID;
    /**
    /** The ID of this view for accessibility and autofill purposes.
     * The stable ID of this view for accessibility purposes.
     * <ul>
     *     <li>== {@link #NO_ID}: ID has not been assigned yet
     *     <li>&le; {@link #LAST_APP_ACCESSIBILITY_ID}: View is not part of a activity. The ID is
     *                                                  unique in the process. This might change
     *                                                  over activity lifecycle events.
     *     <li>&gt; {@link #LAST_APP_ACCESSIBILITY_ID}: View is part of a activity. The ID is
     *                                                  unique in the activity. This stays the same
     *                                                  over activity lifecycle events.
     */
     */
    int mAccessibilityViewId = NO_ID;
    private int mAccessibilityViewId = NO_ID;
    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
@@ -8144,7 +8153,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
     */
    public int getAccessibilityViewId() {
    public int getAccessibilityViewId() {
        if (mAccessibilityViewId == NO_ID) {
        if (mAccessibilityViewId == NO_ID) {
            mAccessibilityViewId = sNextAccessibilityViewId++;
            mAccessibilityViewId = mContext.getNextAccessibilityId();
        }
        }
        return mAccessibilityViewId;
        return mAccessibilityViewId;
    }
    }
@@ -17159,7 +17168,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    @CallSuper
    @CallSuper
    protected Parcelable onSaveInstanceState() {
    protected Parcelable onSaveInstanceState() {
        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
        if (mStartActivityRequestWho != null || isAutofilled()) {
        if (mStartActivityRequestWho != null || isAutofilled()
                || mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
            if (mStartActivityRequestWho != null) {
            if (mStartActivityRequestWho != null) {
@@ -17170,8 +17180,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
            }
            }
            if (mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
                state.mSavedData |= BaseSavedState.ACCESSIBILITY_ID;
            }
            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
            state.mIsAutofilled = isAutofilled();
            state.mIsAutofilled = isAutofilled();
            state.mAccessibilityViewId = mAccessibilityViewId;
            return state;
            return state;
        }
        }
        return BaseSavedState.EMPTY_STATE;
        return BaseSavedState.EMPTY_STATE;
@@ -17249,6 +17264,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
                setAutofilled(baseState.mIsAutofilled);
                setAutofilled(baseState.mIsAutofilled);
            }
            }
            if ((baseState.mSavedData & BaseSavedState.ACCESSIBILITY_ID) != 0) {
                mAccessibilityViewId = baseState.mAccessibilityViewId;
            }
        }
        }
    }
    }
@@ -24408,11 +24426,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    public static class BaseSavedState extends AbsSavedState {
    public static class BaseSavedState extends AbsSavedState {
        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
        static final int IS_AUTOFILLED = 0b10;
        static final int IS_AUTOFILLED = 0b10;
        static final int ACCESSIBILITY_ID = 0b100;
        // Flags that describe what data in this state is valid
        // Flags that describe what data in this state is valid
        int mSavedData;
        int mSavedData;
        String mStartActivityRequestWhoSaved;
        String mStartActivityRequestWhoSaved;
        boolean mIsAutofilled;
        boolean mIsAutofilled;
        int mAccessibilityViewId;
        /**
        /**
         * Constructor used when reading from a parcel. Reads the state of the superclass.
         * Constructor used when reading from a parcel. Reads the state of the superclass.
@@ -24435,6 +24455,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mSavedData = source.readInt();
            mSavedData = source.readInt();
            mStartActivityRequestWhoSaved = source.readString();
            mStartActivityRequestWhoSaved = source.readString();
            mIsAutofilled = source.readBoolean();
            mIsAutofilled = source.readBoolean();
            mAccessibilityViewId = source.readInt();
        }
        }
        /**
        /**
@@ -24453,6 +24474,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            out.writeInt(mSavedData);
            out.writeInt(mSavedData);
            out.writeString(mStartActivityRequestWhoSaved);
            out.writeString(mStartActivityRequestWhoSaved);
            out.writeBoolean(mIsAutofilled);
            out.writeBoolean(mIsAutofilled);
            out.writeInt(mAccessibilityViewId);
        }
        }
        public static final Parcelable.Creator<BaseSavedState> CREATOR
        public static final Parcelable.Creator<BaseSavedState> CREATOR
+7 −0
Original line number Original line Diff line number Diff line
@@ -479,6 +479,13 @@ public abstract class Window {
         */
         */
        public void onWindowFocusChanged(boolean hasFocus);
        public void onWindowFocusChanged(boolean hasFocus);


        /**
         * @hide
         */
        default void onBeforeAttachedToWindow() {
            // empty
        }

        /**
        /**
         * Called when the window has been attached to the window manager.
         * Called when the window has been attached to the window manager.
         * See {@link View#onAttachedToWindow() View.onAttachedToWindow()}
         * See {@link View#onAttachedToWindow() View.onAttachedToWindow()}
Loading