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
198697a31d3c32f212cee48b4d0576e8783c6c9d5fFelipe Lemeimport static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
209f9ee25515591ef33281708c0ab911962f4364a6Felipe Lemeimport static com.android.server.autofill.Helper.sDebug;
21c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Lemeimport static com.android.server.autofill.Helper.sVerbose;
22f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme
236fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport android.annotation.Nullable;
246fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport android.graphics.Rect;
256fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport android.service.autofill.FillResponse;
260f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Lemeimport android.util.DebugUtils;
27f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Lemeimport android.util.Slog;
286fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport android.view.autofill.AutofillId;
296fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport android.view.autofill.AutofillValue;
306fa8a07143d1984ff42750079cf596a868644663Felipe Leme
316fa8a07143d1984ff42750079cf596a868644663Felipe Lemeimport java.io.PrintWriter;
326fa8a07143d1984ff42750079cf596a868644663Felipe Leme
336fa8a07143d1984ff42750079cf596a868644663Felipe Leme/**
346fa8a07143d1984ff42750079cf596a868644663Felipe Leme * State for a given view with a AutofillId.
356fa8a07143d1984ff42750079cf596a868644663Felipe Leme *
366fa8a07143d1984ff42750079cf596a868644663Felipe Leme * <p>This class holds state about a view and calls its listener when the fill UI is ready to
376fa8a07143d1984ff42750079cf596a868644663Felipe Leme * be displayed for the view.
386fa8a07143d1984ff42750079cf596a868644663Felipe Leme */
396fa8a07143d1984ff42750079cf596a868644663Felipe Lemefinal class ViewState {
406fa8a07143d1984ff42750079cf596a868644663Felipe Leme    interface Listener {
416fa8a07143d1984ff42750079cf596a868644663Felipe Leme        /**
426fa8a07143d1984ff42750079cf596a868644663Felipe Leme         * Called when the fill UI is ready to be shown for this view.
436fa8a07143d1984ff42750079cf596a868644663Felipe Leme         */
446fa8a07143d1984ff42750079cf596a868644663Felipe Leme        void onFillReady(FillResponse fillResponse, AutofillId focusedId,
456fa8a07143d1984ff42750079cf596a868644663Felipe Leme                @Nullable AutofillValue value);
466fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
476fa8a07143d1984ff42750079cf596a868644663Felipe Leme
48f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    private static final String TAG = "ViewState";
49f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme
500f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    // NOTE: state constants must be public because of flagstoString().
519a2e6058df51e94417dcedd4c7dd2a0cc380dcb1Felipe Leme    public static final int STATE_UNKNOWN = 0x000;
520f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    /** Initial state. */
539a2e6058df51e94417dcedd4c7dd2a0cc380dcb1Felipe Leme    public static final int STATE_INITIAL = 0x001;
540f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    /** View id is present in a dataset returned by the service. */
559a2e6058df51e94417dcedd4c7dd2a0cc380dcb1Felipe Leme    public static final int STATE_FILLABLE = 0x002;
560f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    /** View was autofilled after user selected a dataset. */
579a2e6058df51e94417dcedd4c7dd2a0cc380dcb1Felipe Leme    public static final int STATE_AUTOFILLED = 0x004;
580f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    /** View value was changed, but not by the service. */
599a2e6058df51e94417dcedd4c7dd2a0cc380dcb1Felipe Leme    public static final int STATE_CHANGED = 0x008;
6078696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    /** Set only in the View that started a session. */
619a2e6058df51e94417dcedd4c7dd2a0cc380dcb1Felipe Leme    public static final int STATE_STARTED_SESSION = 0x010;
62f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    /** View that started a new partition when focused on. */
639a2e6058df51e94417dcedd4c7dd2a0cc380dcb1Felipe Leme    public static final int STATE_STARTED_PARTITION = 0x020;
64f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    /** User select a dataset in this view, but service must authenticate first. */
659a2e6058df51e94417dcedd4c7dd2a0cc380dcb1Felipe Leme    public static final int STATE_WAITING_DATASET_AUTH = 0x040;
66c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Leme    /** Service does not care about this view. */
679a2e6058df51e94417dcedd4c7dd2a0cc380dcb1Felipe Leme    public static final int STATE_IGNORED = 0x080;
689a2e6058df51e94417dcedd4c7dd2a0cc380dcb1Felipe Leme    /** User manually request autofill in this view, after it was already autofilled. */
699a2e6058df51e94417dcedd4c7dd2a0cc380dcb1Felipe Leme    public static final int STATE_RESTARTED_SESSION = 0x100;
700f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
710f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    public final AutofillId id;
720aa4c5065d1495ec0b2c6fe15324569f31dcbdb1Felipe Leme
736fa8a07143d1984ff42750079cf596a868644663Felipe Leme    private final Listener mListener;
746fa8a07143d1984ff42750079cf596a868644663Felipe Leme    private final Session mSession;
756fa8a07143d1984ff42750079cf596a868644663Felipe Leme
760aa4c5065d1495ec0b2c6fe15324569f31dcbdb1Felipe Leme    private FillResponse mResponse;
770f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    private AutofillValue mCurrentValue;
7878696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    private AutofillValue mAutofilledValue;
790f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    private Rect mVirtualBounds;
800f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    private int mState;
816fa8a07143d1984ff42750079cf596a868644663Felipe Leme
82e8f68080795374c4c3ee25a068990d602e63320fFelipe Leme    ViewState(Session session, AutofillId id, Listener listener, int state) {
836fa8a07143d1984ff42750079cf596a868644663Felipe Leme        mSession = session;
840f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        this.id = id;
856fa8a07143d1984ff42750079cf596a868644663Felipe Leme        mListener = listener;
860f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        mState = state;
876fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
886fa8a07143d1984ff42750079cf596a868644663Felipe Leme
896fa8a07143d1984ff42750079cf596a868644663Felipe Leme    /**
900f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme     * Gets the boundaries of the virtual view, or {@code null} if the the view is not virtual.
916fa8a07143d1984ff42750079cf596a868644663Felipe Leme     */
920f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    @Nullable
930f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    Rect getVirtualBounds() {
940f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        return mVirtualBounds;
956fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
966fa8a07143d1984ff42750079cf596a868644663Felipe Leme
976fa8a07143d1984ff42750079cf596a868644663Felipe Leme    /**
980f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme     * Gets the current value of the view.
996fa8a07143d1984ff42750079cf596a868644663Felipe Leme     */
1000f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    @Nullable
1010f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    AutofillValue getCurrentValue() {
1020f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        return mCurrentValue;
1030f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1040f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
10578696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    void setCurrentValue(AutofillValue value) {
10678696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        mCurrentValue = value;
10778696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    }
10878696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme
10978696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    @Nullable
11078696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    AutofillValue getAutofilledValue() {
11178696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        return mAutofilledValue;
1120f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1130f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
114a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov    void setAutofilledValue(@Nullable AutofillValue value) {
11578696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        mAutofilledValue = value;
11678696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    }
11778696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme
11878696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    @Nullable
1190f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    FillResponse getResponse() {
1200f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        return mResponse;
1216fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
1226fa8a07143d1984ff42750079cf596a868644663Felipe Leme
12378696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    void setResponse(FillResponse response) {
12478696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        mResponse = response;
1256fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
1266fa8a07143d1984ff42750079cf596a868644663Felipe Leme
12778696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme    CharSequence getServiceName() {
12878696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        return mSession.getServiceName();
1290f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1300f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
1310f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    int getState() {
1320f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        return mState;
1330f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1340f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
1350f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    String getStateAsString() {
1360f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        return DebugUtils.flagsToString(ViewState.class, "STATE_", mState);
1370f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1380f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
1390f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    void setState(int state) {
140f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        if (mState == STATE_INITIAL) {
141f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme            mState = state;
142f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        } else {
143f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme            mState |= state;
144f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        }
145f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    }
146f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme
147f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme    void resetState(int state) {
148f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        mState &= ~state;
1490f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme    }
1500f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme
15185d1c2d2905362b984563d9b5e8332010c272fc5Felipe Leme    // TODO: refactor / rename / document this method (and maybeCallOnFillReady) to make it clear
15285d1c2d2905362b984563d9b5e8332010c272fc5Felipe Leme    // that it can change the value and update the UI; similarly, should replace code that
15385d1c2d2905362b984563d9b5e8332010c272fc5Felipe Leme    // directly sets mAutofillValue to use encapsulation.
1548697a31d3c32f212cee48b4d0576e8783c6c9d5fFelipe Leme    void update(@Nullable AutofillValue autofillValue, @Nullable Rect virtualBounds, int flags) {
1556fa8a07143d1984ff42750079cf596a868644663Felipe Leme        if (autofillValue != null) {
1560f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme            mCurrentValue = autofillValue;
1576fa8a07143d1984ff42750079cf596a868644663Felipe Leme        }
1586fa8a07143d1984ff42750079cf596a868644663Felipe Leme        if (virtualBounds != null) {
1596fa8a07143d1984ff42750079cf596a868644663Felipe Leme            mVirtualBounds = virtualBounds;
1606fa8a07143d1984ff42750079cf596a868644663Felipe Leme        }
1616fa8a07143d1984ff42750079cf596a868644663Felipe Leme
1628697a31d3c32f212cee48b4d0576e8783c6c9d5fFelipe Leme        maybeCallOnFillReady(flags);
1636fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
1646fa8a07143d1984ff42750079cf596a868644663Felipe Leme
1656fa8a07143d1984ff42750079cf596a868644663Felipe Leme    /**
1666fa8a07143d1984ff42750079cf596a868644663Felipe Leme     * Calls {@link
1676fa8a07143d1984ff42750079cf596a868644663Felipe Leme     * Listener#onFillReady(FillResponse, AutofillId, AutofillValue)} if the
1686fa8a07143d1984ff42750079cf596a868644663Felipe Leme     * fill UI is ready to be displayed (i.e. when response and bounds are set).
1696fa8a07143d1984ff42750079cf596a868644663Felipe Leme     */
1708697a31d3c32f212cee48b4d0576e8783c6c9d5fFelipe Leme    void maybeCallOnFillReady(int flags) {
1718697a31d3c32f212cee48b4d0576e8783c6c9d5fFelipe Leme        if ((mState & STATE_AUTOFILLED) != 0 && (flags & FLAG_MANUAL_REQUEST) == 0) {
1729f9ee25515591ef33281708c0ab911962f4364a6Felipe Leme            if (sDebug) Slog.d(TAG, "Ignoring UI for " + id + " on " + getStateAsString());
173f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme            return;
174f43ca7968fed9fe8862d9b7217c94687dbb12e0aFelipe Leme        }
1750f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        // First try the current response associated with this View.
1760f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        if (mResponse != null) {
177a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov            if (mResponse.getDatasets() != null || mResponse.getAuthentication() != null) {
1780f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme                mListener.onFillReady(mResponse, this.id, mCurrentValue);
1790f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme            }
1806fa8a07143d1984ff42750079cf596a868644663Felipe Leme        }
1816fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
1826fa8a07143d1984ff42750079cf596a868644663Felipe Leme
1836fa8a07143d1984ff42750079cf596a868644663Felipe Leme    @Override
1846fa8a07143d1984ff42750079cf596a868644663Felipe Leme    public String toString() {
185e8f68080795374c4c3ee25a068990d602e63320fFelipe Leme        return "ViewState: [id=" + id + ", currentValue=" + mCurrentValue
186e8f68080795374c4c3ee25a068990d602e63320fFelipe Leme                + ", autofilledValue=" + mAutofilledValue
187cde040ae9563600179502f8ce8dd06bc7bb5a1c0Felipe Leme                + ", bounds=" + mVirtualBounds + ", state=" + getStateAsString() + "]";
1886fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
1896fa8a07143d1984ff42750079cf596a868644663Felipe Leme
1906fa8a07143d1984ff42750079cf596a868644663Felipe Leme    void dump(String prefix, PrintWriter pw) {
1910f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        pw.print(prefix); pw.print("id:" ); pw.println(this.id);
1920f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        pw.print(prefix); pw.print("state:" ); pw.println(getStateAsString());
193c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Leme        pw.print(prefix); pw.print("response:");
194c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Leme        if (mResponse == null) {
195c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Leme            pw.println("N/A");
196c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Leme        } else {
197c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Leme            if (sVerbose) {
198c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Leme                pw.println(mResponse);
199c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Leme            } else {
200c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Leme                pw.println(mResponse.getRequestId());
201c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Leme            }
202c2430f3c4d6e3b996917f57c8afb0b00b5bef45bFelipe Leme        }
2030f9464e1729bbc5a018436244c3ad7bfe69eea6aFelipe Leme        pw.print(prefix); pw.print("currentValue:" ); pw.println(mCurrentValue);
20478696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme        pw.print(prefix); pw.print("autofilledValue:" ); pw.println(mAutofilledValue);
2056fa8a07143d1984ff42750079cf596a868644663Felipe Leme        pw.print(prefix); pw.print("virtualBounds:" ); pw.println(mVirtualBounds);
2066fa8a07143d1984ff42750079cf596a868644663Felipe Leme    }
2076fa8a07143d1984ff42750079cf596a868644663Felipe Leme}