blob: 5e49b8f0553fc734c5de489dee18b5db0bb726e2 [file] [log] [blame]
Felipe Leme640f30a2017-03-06 15:44:06 -08001/*
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;
Felipe Leme2ac463e2017-03-13 14:06:25 -070033import android.view.autofill.AutofillManager;
Felipe Leme640f30a2017-03-06 15:44:06 -080034
35import com.android.internal.os.SomeArgs;
36
Svet Ganov013efe12017-04-13 21:56:16 -070037import java.util.List;
38
Felipe Leme640f30a2017-03-06 15:44:06 -080039//TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the
40//life-cycle (and how state could be maintained on server-side) is well documented.
41
42/**
43 * Top-level service of the current autofill service for a given user.
44 *
45 * <p>Apps providing autofill capabilities must extend this service.
46 */
47public abstract class AutofillService extends Service {
48 private static final String TAG = "AutofillService";
49
50 /**
51 * The {@link Intent} that must be declared as handled by the service.
52 * To be supported, the service must also require the
53 * {@link android.Manifest.permission#BIND_AUTO_FILL} permission so
54 * that other applications can not abuse it.
55 *
56 * @hide
57 * @deprecated TODO(b/35956626): remove once clients use AutofillService
58 */
59 @Deprecated
60 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
61 public static final String OLD_SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
62
63 /**
64 * The {@link Intent} that must be declared as handled by the service.
65 * To be supported, the service must also require the
66 * {@link android.Manifest.permission#BIND_AUTOFILL} permission so
67 * that other applications can not abuse it.
68 */
69 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
70 public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
71
72 /**
73 * Name under which a AutoFillService component publishes information about itself.
74 * This meta-data should reference an XML resource containing a
75 * <code>&lt;{@link
Felipe Lemef78e9522017-04-04 15:07:13 -070076 * android.R.styleable#AutofillService autofill-service}&gt;</code> tag.
Felipe Leme640f30a2017-03-06 15:44:06 -080077 * This is a a sample XML file configuring an AutoFillService:
78 * <pre> &lt;autofill-service
79 * android:settingsActivity="foo.bar.SettingsActivity"
80 * . . .
81 * /&gt;</pre>
82 */
83 public static final String SERVICE_META_DATA = "android.autofill";
84
85 // Internal extras
86 /** @hide */
Philip P. Moltmanneab62ba2017-03-20 10:55:43 -070087 public static final String EXTRA_SESSION_ID = "android.service.autofill.extra.SESSION_ID";
Felipe Leme640f30a2017-03-06 15:44:06 -080088
89 // Handler messages.
90 private static final int MSG_CONNECT = 1;
91 private static final int MSG_DISCONNECT = 2;
92 private static final int MSG_ON_FILL_REQUEST = 3;
93 private static final int MSG_ON_SAVE_REQUEST = 4;
94
Felipe Leme2ac463e2017-03-13 14:06:25 -070095 private static final int UNUSED_ARG = -1;
96
Felipe Leme640f30a2017-03-06 15:44:06 -080097 private final IAutoFillService mInterface = new IAutoFillService.Stub() {
98 @Override
Svet Ganovf20a0372017-04-10 17:08:05 -070099 public void onConnectedStateChanged(boolean connected) {
100 if (connected) {
101 mHandlerCaller.obtainMessage(MSG_CONNECT).sendToTarget();
Felipe Leme640f30a2017-03-06 15:44:06 -0800102 } else {
103 mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget();
104 }
105 }
106
107 @Override
Svet Ganov013efe12017-04-13 21:56:16 -0700108 public void onFillRequest(FillRequest request, IFillCallback callback) {
Felipe Leme640f30a2017-03-06 15:44:06 -0800109 ICancellationSignal transport = CancellationSignal.createTransport();
110 try {
111 callback.onCancellable(transport);
112 } catch (RemoteException e) {
113 e.rethrowFromSystemServer();
114 }
Svet Ganov013efe12017-04-13 21:56:16 -0700115 mHandlerCaller.obtainMessageOOO(MSG_ON_FILL_REQUEST, request,
116 CancellationSignal.fromTransport(transport), callback)
Felipe Leme640f30a2017-03-06 15:44:06 -0800117 .sendToTarget();
118 }
119
120 @Override
Svet Ganov013efe12017-04-13 21:56:16 -0700121 public void onSaveRequest(SaveRequest request, ISaveCallback callback) {
122 mHandlerCaller.obtainMessageOO(MSG_ON_SAVE_REQUEST, request,
123 callback).sendToTarget();
Felipe Leme640f30a2017-03-06 15:44:06 -0800124 }
125 };
126
127 private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
128 switch (msg.what) {
129 case MSG_CONNECT: {
Felipe Leme640f30a2017-03-06 15:44:06 -0800130 onConnected();
131 break;
132 } case MSG_ON_FILL_REQUEST: {
133 final SomeArgs args = (SomeArgs) msg.obj;
Svet Ganov013efe12017-04-13 21:56:16 -0700134 final FillRequest request = (FillRequest) args.arg1;
Felipe Leme640f30a2017-03-06 15:44:06 -0800135 final CancellationSignal cancellation = (CancellationSignal) args.arg2;
Svet Ganov013efe12017-04-13 21:56:16 -0700136 final IFillCallback callback = (IFillCallback) args.arg3;
137 final FillCallback fillCallback = new FillCallback(callback, request.getId());
Felipe Leme640f30a2017-03-06 15:44:06 -0800138 args.recycle();
Svet Ganov013efe12017-04-13 21:56:16 -0700139 onFillRequest(request, cancellation, fillCallback);
Felipe Leme640f30a2017-03-06 15:44:06 -0800140 break;
141 } case MSG_ON_SAVE_REQUEST: {
142 final SomeArgs args = (SomeArgs) msg.obj;
Svet Ganov013efe12017-04-13 21:56:16 -0700143 final SaveRequest request = (SaveRequest) args.arg1;
144 final ISaveCallback callback = (ISaveCallback) args.arg2;
Felipe Leme640f30a2017-03-06 15:44:06 -0800145 final SaveCallback saveCallback = new SaveCallback(callback);
146 args.recycle();
Svet Ganov013efe12017-04-13 21:56:16 -0700147 onSaveRequest(request, saveCallback);
Felipe Leme640f30a2017-03-06 15:44:06 -0800148 break;
149 } case MSG_DISCONNECT: {
150 onDisconnected();
Felipe Leme640f30a2017-03-06 15:44:06 -0800151 break;
152 } default: {
153 Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
154 }
155 }
156 };
157
158 private HandlerCaller mHandlerCaller;
159
Felipe Leme640f30a2017-03-06 15:44:06 -0800160 /**
161 * {@inheritDoc}
162 *
163 * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}.
164 */
165 @Override
166 public void onCreate() {
167 super.onCreate();
168 mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
169 }
170
171 @Override
172 public final IBinder onBind(Intent intent) {
173 if (SERVICE_INTERFACE.equals(intent.getAction())
174 || OLD_SERVICE_INTERFACE.equals(intent.getAction())) {
175 return mInterface.asBinder();
176 }
177 Log.w(TAG, "Tried to bind to wrong intent: " + intent);
178 return null;
179 }
180
181 /**
182 * Called when the Android system connects to service.
183 *
184 * <p>You should generally do initialization here rather than in {@link #onCreate}.
185 */
186 public void onConnected() {
Felipe Leme640f30a2017-03-06 15:44:06 -0800187 }
188
189 /**
190 * Called by the Android system do decide if an {@link Activity} can be autofilled by the
191 * service.
192 *
193 * <p>Service must call one of the {@link FillCallback} methods (like
194 * {@link FillCallback#onSuccess(FillResponse)}
195 * or {@link FillCallback#onFailure(CharSequence)})
196 * to notify the result of the request.
197 *
Svet Ganov013efe12017-04-13 21:56:16 -0700198 * @param request the {@link FillRequest request} to handle.
199 * See {@link FillResponse} for examples of multiple-sections requests.
200 * @param cancellationSignal signal for observing cancellation requests. The system will use
201 * this to notify you that the fill result is no longer needed and you should stop
202 * handling this fill request in order to save resources.
203 * @param callback object used to notify the result of the request.
204 */
205 public void onFillRequest(@NonNull FillRequest request,
206 @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) {
207 onFillRequest(request.getStructure(), request.getClientState(), request.getFlags(),
208 cancellationSignal, callback);
209 }
210
211 /**
212 * Called by the Android system do decide if an {@link Activity} can be autofilled by the
213 * service.
214 *
215 * <p>Service must call one of the {@link FillCallback} methods (like
216 * {@link FillCallback#onSuccess(FillResponse)}
217 * or {@link FillCallback#onFailure(CharSequence)})
218 * to notify the result of the request.
219 *
Felipe Leme640f30a2017-03-06 15:44:06 -0800220 * @param structure {@link Activity}'s view structure.
Felipe Leme52d5d3d2017-04-04 13:10:58 -0700221 * @param data bundle containing data passed by the service in a last call to
222 * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
223 * service to keep state between fill and save requests as well as when filling different
224 * sections of the UI as the system will try to aggressively unbind from the service to
225 * conserve resources.
226 * See {@link FillResponse} for examples of multiple-sections requests.
Felipe Leme2ac463e2017-03-13 14:06:25 -0700227 * @param flags either {@code 0} or {@link AutofillManager#FLAG_MANUAL_REQUEST}.
Felipe Leme640f30a2017-03-06 15:44:06 -0800228 * @param cancellationSignal signal for observing cancellation requests. The system will use
229 * this to notify you that the fill result is no longer needed and you should stop
230 * handling this fill request in order to save resources.
231 * @param callback object used to notify the result of the request.
232 */
Svet Ganov013efe12017-04-13 21:56:16 -0700233 @Deprecated
Felipe Lemea86aee62017-04-04 18:27:49 -0700234 public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
235 int flags, @NonNull CancellationSignal cancellationSignal,
236 @NonNull FillCallback callback);
Felipe Leme640f30a2017-03-06 15:44:06 -0800237
238 /**
239 * Called when user requests service to save the fields of an {@link Activity}.
240 *
241 * <p>Service must call one of the {@link SaveCallback} methods (like
242 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
243 * to notify the result of the request.
244 *
Svet Ganov013efe12017-04-13 21:56:16 -0700245 * @param request the {@link SaveRequest request} to handle.
246 * See {@link FillResponse} for examples of multiple-sections requests.
247 * @param callback object used to notify the result of the request.
248 */
249 public void onSaveRequest(@NonNull SaveRequest request, @NonNull SaveCallback callback) {
250 List<FillContext> contexts = request.getFillContexts();
251 onSaveRequest(contexts.get(contexts.size() - 1).getStructure(),
252 request.getClientState(), callback);
253 }
254
255 /**
256 * Called when user requests service to save the fields of an {@link Activity}.
257 *
258 * <p>Service must call one of the {@link SaveCallback} methods (like
259 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
260 * to notify the result of the request.
261 *
Felipe Leme640f30a2017-03-06 15:44:06 -0800262 * @param structure {@link Activity}'s view structure.
Felipe Leme52d5d3d2017-04-04 13:10:58 -0700263 * @param data bundle containing data passed by the service in a last call to
264 * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
265 * service to keep state between fill and save requests as well as when filling different
266 * sections of the UI as the system will try to aggressively unbind from the service to
267 * conserve resources.
268 * See {@link FillResponse} for examples of multiple-sections requests.
Felipe Leme640f30a2017-03-06 15:44:06 -0800269 * @param callback object used to notify the result of the request.
270 */
Svet Ganov013efe12017-04-13 21:56:16 -0700271 @Deprecated
Felipe Leme640f30a2017-03-06 15:44:06 -0800272 public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
273 @NonNull SaveCallback callback);
274
275 /**
276 * Called when the Android system disconnects from the service.
277 *
278 * <p> At this point this service may no longer be an active {@link AutofillService}.
279 */
280 public void onDisconnected() {
Felipe Leme640f30a2017-03-06 15:44:06 -0800281 }
282
Svet Ganovfc4a3002017-04-11 11:40:14 -0700283 @Deprecated
Felipe Leme640f30a2017-03-06 15:44:06 -0800284 public final void disableSelf() {
Svet Ganovf20a0372017-04-10 17:08:05 -0700285 // TODO(b/33197203): Remove when GCore has migrated off this API
286 getSystemService(AutofillManager.class).disableOwnedAutofillServices();
Felipe Leme640f30a2017-03-06 15:44:06 -0800287 }
288}