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