ViewState.java revision 9f9ee25515591ef33281708c0ab911962f4364a6
16fa8a07143d1984ff42750079cf596a868644663Felipe Leme/*
26fa8a07143d1984ff42750079cf596a868644663Felipe Leme * Copyright (C) 2017 The Android Open Source Project
36fa8a07143d1984ff42750079cf596a868644663Felipe Leme *
46fa8a07143d1984ff42750079cf596a868644663Felipe Leme * Licensed under the Apache License, Version 2.0 (the "License");
56fa8a07143d1984ff42750079cf596a868644663Felipe Leme * you may not use this file except in compliance with the License.
66fa8a07143d1984ff42750079cf596a868644663Felipe Leme * You may obtain a copy of the License at
76fa8a07143d1984ff42750079cf596a868644663Felipe Leme *
86fa8a07143d1984ff42750079cf596a868644663Felipe Leme *      http://www.apache.org/licenses/LICENSE-2.0
96fa8a07143d1984ff42750079cf596a868644663Felipe Leme *
106fa8a07143d1984ff42750079cf596a868644663Felipe Leme * Unless required by applicable law or agreed to in writing, software
116fa8a07143d1984ff42750079cf596a868644663Felipe Leme * distributed under the License is distributed on an "AS IS" BASIS,
126fa8a07143d1984ff42750079cf596a868644663Felipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136fa8a07143d1984ff42750079cf596a868644663Felipe Leme * See the License for the specific language governing permissions and
146fa8a07143d1984ff42750079cf596a868644663Felipe Leme * limitations under the License.
156fa8a07143d1984ff42750079cf596a868644663Felipe Leme */
166fa8a07143d1984ff42750079cf596a868644663Felipe Leme
176fa8a07143d1984ff42750079cf596a868644663Felipe Lemepackage com.android.server.autofill;
186fa8a07143d1984ff42750079cf596a868644663Felipe Leme
199f9ee25515591ef33281708c0ab911962f4364a6Felipe Lemeimport static com.android.server.autofill.Helper.sDebug;
20f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme
216fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport android.annotation.Nullable;
226fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport android.graphics.Rect;
236fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport android.service.autofill.FillResponse;
240f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Lemeimport android.util.DebugUtils;
25f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Lemeimport android.util.Slog;
266fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport android.view.autofill.AutofillId;
276fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport android.view.autofill.AutofillValue;
286fa8a07143d1984ff42750079cf596a868644663Felipe Leme
296fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport java.io.PrintWriter;
306fa8a07143d1984ff42750079cf596a868644663Felipe Leme
316fa8a07143d1984ff42750079cf596a868644663Felipe Leme/**
326fa8a07143d1984ff42750079cf596a868644663Felipe Leme * State for a given view with a AutofillId.
336fa8a07143d1984ff42750079cf596a868644663Felipe Leme *
346fa8a07143d1984ff42750079cf596a868644663Felipe Leme * <p>This class holds state about a view and calls its listener when the fill UI is ready to
356fa8a07143d1984ff42750079cf596a868644663Felipe Leme * be displayed for the view.
366fa8a07143d1984ff42750079cf596a868644663Felipe Leme */
376fa8a07143d1984ff42750079cf596a868644663Felipe Lemefinal class ViewState {
386fa8a07143d1984ff42750079cf596a868644663Felipe Leme    interface Listener {
396fa8a07143d1984ff42750079cf596a868644663Felipe Leme        /**
406fa8a07143d1984ff42750079cf596a868644663Felipe Leme         * Called when the fill UI is ready to be shown for this view.
416fa8a07143d1984ff42750079cf596a868644663Felipe Leme         */
426fa8a07143d1984ff42750079cf596a868644663Felipe Leme        void onFillReady(FillResponse fillResponse, AutofillId focusedId,
436fa8a07143d1984ff42750079cf596a868644663Felipe Leme                @Nullable AutofillValue value);
446fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
456fa8a07143d1984ff42750079cf596a868644663Felipe Leme
46f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    private static final String TAG = "ViewState";
47f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme
480f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    // NOTE: state constants must be public because of flagstoString().
490f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    public static final int STATE_UNKNOWN = 0x00;
500f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    /** Initial state. */
510f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    public static final int STATE_INITIAL = 0x01;
520f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    /** View id is present in a dataset returned by the service. */
530f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    public static final int STATE_FILLABLE = 0x02;
540f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    /** View was autofilled after user selected a dataset. */
550f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    public static final int STATE_AUTOFILLED = 0x04;
560f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    /** View value was changed, but not by the service. */
570f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    public static final int STATE_CHANGED = 0x08;
5878696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    /** Set only in the View that started a session. */
590f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    public static final int STATE_STARTED_SESSION = 0x10;
60f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    /** View that started a new partition when focused on. */
61f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    public static final int STATE_STARTED_PARTITION = 0x20;
62f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    /** User select a dataset in this view, but service must authenticate first. */
63f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    public static final int STATE_WAITING_DATASET_AUTH = 0x40;
6485d1c2d2905362b984563d9b5e8332010c272fc5Felipe Leme    // TODO(b/37424539): temporary workaround until partitioning supports auth
65abe54cbf0c09f40f9a8f95d8063326bf9b83da19Felipe Leme    public static final int STATE_WAITING_RESPONSE_AUTH = 0x80;
660f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
670f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    public final AutofillId id;
680aa4c5065d1495ec0b2c6fe15324569f31dcbdb1Felipe Leme
696fa8a07143d1984ff42750079cf596a868644663Felipe Leme    private final Listener mListener;
706fa8a07143d1984ff42750079cf596a868644663Felipe Leme    private final Session mSession;
716fa8a07143d1984ff42750079cf596a868644663Felipe Leme
720aa4c5065d1495ec0b2c6fe15324569f31dcbdb1Felipe Leme    private FillResponse mResponse;
73cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme    private AutofillValue mInitialValue;
740f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    private AutofillValue mCurrentValue;
7578696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    private AutofillValue mAutofilledValue;
760f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    private Rect mVirtualBounds;
770f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    private int mState;
786fa8a07143d1984ff42750079cf596a868644663Felipe Leme
79cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme    ViewState(Session session, AutofillId id, AutofillValue value, Listener listener, int state) {
806fa8a07143d1984ff42750079cf596a868644663Felipe Leme        mSession = session;
810f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        this.id = id;
82cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme        mInitialValue = value;
836fa8a07143d1984ff42750079cf596a868644663Felipe Leme        mListener = listener;
840f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        mState = state;
856fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
866fa8a07143d1984ff42750079cf596a868644663Felipe Leme
876fa8a07143d1984ff42750079cf596a868644663Felipe Leme    /**
880f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme     * Gets the boundaries of the virtual view, or {@code null} if the the view is not virtual.
896fa8a07143d1984ff42750079cf596a868644663Felipe Leme     */
900f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    @Nullable
910f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    Rect getVirtualBounds() {
920f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        return mVirtualBounds;
936fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
946fa8a07143d1984ff42750079cf596a868644663Felipe Leme
956fa8a07143d1984ff42750079cf596a868644663Felipe Leme    /**
960f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme     * Gets the current value of the view.
976fa8a07143d1984ff42750079cf596a868644663Felipe Leme     */
980f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    @Nullable
990f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    AutofillValue getCurrentValue() {
1000f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        return mCurrentValue;
1010f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1020f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
10378696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    void setCurrentValue(AutofillValue value) {
10478696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        mCurrentValue = value;
10578696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    }
10678696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme
10778696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    @Nullable
10878696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    AutofillValue getAutofilledValue() {
10978696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        return mAutofilledValue;
1100f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1110f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
11278696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    void setAutofilledValue(AutofillValue value) {
11378696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        mAutofilledValue = value;
11478696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    }
11578696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme
11678696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    @Nullable
117cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme    AutofillValue getInitialValue() {
118cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme        return mInitialValue;
119cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme    }
120cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme
121cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme    @Nullable
1220f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    FillResponse getResponse() {
1230f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        return mResponse;
1246fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
1256fa8a07143d1984ff42750079cf596a868644663Felipe Leme
12678696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    void setResponse(FillResponse response) {
12778696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        mResponse = response;
1286fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
1296fa8a07143d1984ff42750079cf596a868644663Felipe Leme
13078696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    CharSequence getServiceName() {
13178696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        return mSession.getServiceName();
1320f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1330f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
1340f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    int getState() {
1350f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        return mState;
1360f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1370f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
1380f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    String getStateAsString() {
1390f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        return DebugUtils.flagsToString(ViewState.class, "STATE_", mState);
1400f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1410f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
1420f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    void setState(int state) {
143f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        if (mState == STATE_INITIAL) {
144f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme            mState = state;
145f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        } else {
146f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme            mState |= state;
147f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        }
148f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    }
149f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme
150f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    void resetState(int state) {
151f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        mState &= ~state;
1520f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1530f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
15485d1c2d2905362b984563d9b5e8332010c272fc5Felipe Leme    // TODO: refactor / rename / document this method (and maybeCallOnFillReady) to make it clear
15585d1c2d2905362b984563d9b5e8332010c272fc5Felipe Leme    // that it can change the value and update the UI; similarly, should replace code that
15685d1c2d2905362b984563d9b5e8332010c272fc5Felipe Leme    // directly sets mAutofillValue to use encapsulation.
1576fa8a07143d1984ff42750079cf596a868644663Felipe Leme    void update(@Nullable AutofillValue autofillValue, @Nullable Rect virtualBounds) {
1586fa8a07143d1984ff42750079cf596a868644663Felipe Leme        if (autofillValue != null) {
1590f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme            mCurrentValue = autofillValue;
1606fa8a07143d1984ff42750079cf596a868644663Felipe Leme        }
1616fa8a07143d1984ff42750079cf596a868644663Felipe Leme        if (virtualBounds != null) {
1626fa8a07143d1984ff42750079cf596a868644663Felipe Leme            mVirtualBounds = virtualBounds;
1636fa8a07143d1984ff42750079cf596a868644663Felipe Leme        }
1646fa8a07143d1984ff42750079cf596a868644663Felipe Leme
1656fa8a07143d1984ff42750079cf596a868644663Felipe Leme        maybeCallOnFillReady();
1666fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
1676fa8a07143d1984ff42750079cf596a868644663Felipe Leme
1686fa8a07143d1984ff42750079cf596a868644663Felipe Leme    /**
1696fa8a07143d1984ff42750079cf596a868644663Felipe Leme     * Calls {@link
1706fa8a07143d1984ff42750079cf596a868644663Felipe Leme     * Listener#onFillReady(FillResponse, AutofillId, AutofillValue)} if the
1716fa8a07143d1984ff42750079cf596a868644663Felipe Leme     * fill UI is ready to be displayed (i.e. when response and bounds are set).
1726fa8a07143d1984ff42750079cf596a868644663Felipe Leme     */
1736fa8a07143d1984ff42750079cf596a868644663Felipe Leme    void maybeCallOnFillReady() {
174f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        if ((mState & (STATE_AUTOFILLED | STATE_WAITING_DATASET_AUTH)) != 0) {
1759f9ee25515591ef33281708c0ab911962f4364a6Felipe Leme            if (sDebug) Slog.d(TAG, "Ignoring UI for " + id + " on " + getStateAsString());
176f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme            return;
177f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        }
1780f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        // First try the current response associated with this View.
1790f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        if (mResponse != null) {
1800f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme            if (mResponse.getDatasets() != null) {
1810f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme                mListener.onFillReady(mResponse, this.id, mCurrentValue);
1820f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme            }
1830f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme            return;
1840f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        }
1850f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        // Then checks if the session has a response waiting authentication; if so, uses it instead.
186f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        final FillResponse responseWaitingAuth = mSession.getResponseWaitingAuth();
187f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        if (responseWaitingAuth != null) {
188f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme            mListener.onFillReady(responseWaitingAuth, this.id, mCurrentValue);
1896fa8a07143d1984ff42750079cf596a868644663Felipe Leme        }
1906fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
1916fa8a07143d1984ff42750079cf596a868644663Felipe Leme
1926fa8a07143d1984ff42750079cf596a868644663Felipe Leme    @Override
1936fa8a07143d1984ff42750079cf596a868644663Felipe Leme    public String toString() {
194cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme        return "ViewState: [id=" + id + ", initialValue=" + mInitialValue
195cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme                + ", currentValue=" + mCurrentValue + ", autofilledValue=" + mAutofilledValue
196cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme                + ", bounds=" + mVirtualBounds + ", state=" + getStateAsString() + "]";
1976fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
1986fa8a07143d1984ff42750079cf596a868644663Felipe Leme
1996fa8a07143d1984ff42750079cf596a868644663Felipe Leme    void dump(String prefix, PrintWriter pw) {
2000f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        pw.print(prefix); pw.print("id:" ); pw.println(this.id);
2010f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        pw.print(prefix); pw.print("state:" ); pw.println(getStateAsString());
2020f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        pw.print(prefix); pw.print("has response:" ); pw.println(mResponse != null);
203cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme        pw.print(prefix); pw.print("initialValue:" ); pw.println(mInitialValue);
2040f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        pw.print(prefix); pw.print("currentValue:" ); pw.println(mCurrentValue);
20578696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        pw.print(prefix); pw.print("autofilledValue:" ); pw.println(mAutofilledValue);
2066fa8a07143d1984ff42750079cf596a868644663Felipe Leme        pw.print(prefix); pw.print("virtualBounds:" ); pw.println(mVirtualBounds);
2076fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
2086fa8a07143d1984ff42750079cf596a868644663Felipe Leme}