AutofillService.java revision 85d1c2d2905362b984563d9b5e8332010c272fc5
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.service.autofill;
17
18import android.annotation.NonNull;
19import android.annotation.Nullable;
20import android.os.RemoteException;
21import com.android.internal.os.HandlerCaller;
22import android.annotation.SdkConstant;
23import android.app.Activity;
24import android.app.Service;
25import android.app.assist.AssistStructure;
26import android.content.Intent;
27import android.os.Bundle;
28import android.os.CancellationSignal;
29import android.os.IBinder;
30import android.os.ICancellationSignal;
31import android.os.Looper;
32import android.util.Log;
33import android.view.autofill.AutofillManager;
34
35import com.android.internal.os.SomeArgs;
36
37import java.util.List;
38
39/**
40 * Top-level service of the current autofill service for a given user.
41 *
42 * <p>Apps providing autofill capabilities must extend this service.
43 */
44public abstract class AutofillService extends Service {
45    private static final String TAG = "AutofillService";
46
47    /**
48     * The {@link Intent} that must be declared as handled by the service.
49     * To be supported, the service must also require the
50     * {@link android.Manifest.permission#BIND_AUTOFILL} permission so
51     * that other applications can not abuse it.
52     */
53    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
54    public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
55
56    /**
57     * Name under which a AutoFillService component publishes information about itself.
58     * This meta-data should reference an XML resource containing a
59     * <code>&lt;{@link
60     * android.R.styleable#AutofillService autofill-service}&gt;</code> tag.
61     * This is a a sample XML file configuring an AutoFillService:
62     * <pre> &lt;autofill-service
63     *     android:settingsActivity="foo.bar.SettingsActivity"
64     *     . . .
65     * /&gt;</pre>
66     */
67    public static final String SERVICE_META_DATA = "android.autofill";
68
69    // Internal extras
70    /** @hide */
71    public static final String EXTRA_SESSION_ID = "android.service.autofill.extra.SESSION_ID";
72
73    // Handler messages.
74    private static final int MSG_CONNECT = 1;
75    private static final int MSG_DISCONNECT = 2;
76    private static final int MSG_ON_FILL_REQUEST = 3;
77    private static final int MSG_ON_SAVE_REQUEST = 4;
78
79    private final IAutoFillService mInterface = new IAutoFillService.Stub() {
80        @Override
81        public void onConnectedStateChanged(boolean connected) {
82            if (connected) {
83                mHandlerCaller.obtainMessage(MSG_CONNECT).sendToTarget();
84            } else {
85                mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget();
86            }
87        }
88
89        @Override
90        public void onFillRequest(FillRequest request, IFillCallback callback) {
91            ICancellationSignal transport = CancellationSignal.createTransport();
92            try {
93                callback.onCancellable(transport);
94            } catch (RemoteException e) {
95                e.rethrowFromSystemServer();
96            }
97            mHandlerCaller.obtainMessageOOO(MSG_ON_FILL_REQUEST, request,
98                    CancellationSignal.fromTransport(transport), callback)
99                    .sendToTarget();
100        }
101
102        @Override
103        public void onSaveRequest(SaveRequest request, ISaveCallback callback) {
104            mHandlerCaller.obtainMessageOO(MSG_ON_SAVE_REQUEST, request,
105                    callback).sendToTarget();
106        }
107    };
108
109    private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
110        switch (msg.what) {
111            case MSG_CONNECT: {
112                onConnected();
113                break;
114            } case MSG_ON_FILL_REQUEST: {
115                final SomeArgs args = (SomeArgs) msg.obj;
116                final FillRequest request = (FillRequest) args.arg1;
117                final CancellationSignal cancellation = (CancellationSignal) args.arg2;
118                final IFillCallback callback = (IFillCallback) args.arg3;
119                final FillCallback fillCallback = new FillCallback(callback, request.getId());
120                args.recycle();
121                onFillRequest(request, cancellation, fillCallback);
122                break;
123            } case MSG_ON_SAVE_REQUEST: {
124                final SomeArgs args = (SomeArgs) msg.obj;
125                final SaveRequest request = (SaveRequest) args.arg1;
126                final ISaveCallback callback = (ISaveCallback) args.arg2;
127                final SaveCallback saveCallback = new SaveCallback(callback);
128                args.recycle();
129                onSaveRequest(request, saveCallback);
130                break;
131            } case MSG_DISCONNECT: {
132                onDisconnected();
133                break;
134            } default: {
135                Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
136            }
137        }
138    };
139
140    private HandlerCaller mHandlerCaller;
141
142    /**
143     * {@inheritDoc}
144     *
145     * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}.
146     */
147    @Override
148    public void onCreate() {
149        super.onCreate();
150        mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
151    }
152
153    @Override
154    public final IBinder onBind(Intent intent) {
155        if (SERVICE_INTERFACE.equals(intent.getAction())) {
156            return mInterface.asBinder();
157        }
158        Log.w(TAG, "Tried to bind to wrong intent: " + intent);
159        return null;
160    }
161
162    /**
163     * Called when the Android system connects to service.
164     *
165     * <p>You should generally do initialization here rather than in {@link #onCreate}.
166     */
167    public void onConnected() {
168    }
169
170    /**
171     * Called by the Android system do decide if an {@link Activity} can be autofilled by the
172     * service.
173     *
174     * <p>Service must call one of the {@link FillCallback} methods (like
175     * {@link FillCallback#onSuccess(FillResponse)}
176     * or {@link FillCallback#onFailure(CharSequence)})
177     * to notify the result of the request.
178     *
179     * @param request the {@link FillRequest request} to handle.
180     *        See {@link FillResponse} for examples of multiple-sections requests.
181     * @param cancellationSignal signal for observing cancellation requests. The system will use
182     *     this to notify you that the fill result is no longer needed and you should stop
183     *     handling this fill request in order to save resources.
184     * @param callback object used to notify the result of the request.
185     */
186    public void onFillRequest(@NonNull FillRequest request,
187            @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) {
188        onFillRequest(request.getStructure(), request.getClientState(), request.getFlags(),
189                cancellationSignal, callback);
190    }
191
192    /**
193     * Called by the Android system do decide if an {@link Activity} can be autofilled by the
194     * service.
195     *
196     * <p>Service must call one of the {@link FillCallback} methods (like
197     * {@link FillCallback#onSuccess(FillResponse)}
198     * or {@link FillCallback#onFailure(CharSequence)})
199     * to notify the result of the request.
200     *
201     * @param structure {@link Activity}'s view structure.
202     * @param data bundle containing data passed by the service in a last call to
203     *        {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
204     *        service to keep state between fill and save requests as well as when filling different
205     *        sections of the UI as the system will try to aggressively unbind from the service to
206     *        conserve resources.
207     *        See {@link FillResponse} for examples of multiple-sections requests.
208     * @param flags either {@code 0} or {@link AutofillManager#FLAG_MANUAL_REQUEST}.
209     * @param cancellationSignal signal for observing cancellation requests. The system will use
210     *     this to notify you that the fill result is no longer needed and you should stop
211     *     handling this fill request in order to save resources.
212     * @param callback object used to notify the result of the request.
213     */
214    @Deprecated
215    public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
216            int flags, @NonNull CancellationSignal cancellationSignal,
217            @NonNull FillCallback callback);
218
219    /**
220     * Called when user requests service to save the fields of an {@link Activity}.
221     *
222     * <p>Service must call one of the {@link SaveCallback} methods (like
223     * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
224     * to notify the result of the request.
225     *
226     * @param request the {@link SaveRequest request} to handle.
227     *        See {@link FillResponse} for examples of multiple-sections requests.
228     * @param callback object used to notify the result of the request.
229     */
230    public void onSaveRequest(@NonNull SaveRequest request, @NonNull SaveCallback callback) {
231        final List<FillContext> contexts = request.getFillContexts();
232        onSaveRequest(contexts.get(contexts.size() - 1).getStructure(),
233                request.getClientState(), callback);
234    }
235
236    /**
237     * Called when user requests service to save the fields of an {@link Activity}.
238     *
239     * <p>Service must call one of the {@link SaveCallback} methods (like
240     * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
241     * to notify the result of the request.
242     *
243     * @param structure {@link Activity}'s view structure.
244     * @param data bundle containing data passed by the service in a last call to
245     *        {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
246     *        service to keep state between fill and save requests as well as when filling different
247     *        sections of the UI as the system will try to aggressively unbind from the service to
248     *        conserve resources.
249     *        See {@link FillResponse} for examples of multiple-sections requests.
250     * @param callback object used to notify the result of the request.
251     */
252    @Deprecated
253    public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
254            @NonNull SaveCallback callback);
255
256    /**
257     * Called when the Android system disconnects from the service.
258     *
259     * <p> At this point this service may no longer be an active {@link AutofillService}.
260     */
261    public void onDisconnected() {
262    }
263
264    @Deprecated
265    public final void disableSelf() {
266        getSystemService(AutofillManager.class).disableOwnedAutofillServices();
267    }
268
269    /**
270     * Returns the {@link FillEventHistory.Event events} since the last {@link FillResponse} was
271     * returned.
272     *
273     * <p>The history is not persisted over reboots.
274     *
275     * @return The history or {@code null} if there are not events.
276     */
277    @Nullable public final FillEventHistory getFillEventHistory() {
278        AutofillManager afm = getSystemService(AutofillManager.class);
279
280        if (afm == null) {
281            return null;
282        } else {
283            return afm.getFillEventHistory();
284        }
285    }
286}
287