blob: d86dd5b42bb9dc5fb3c05c4977f6c4c542c27cf0 [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
37//TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the
38//life-cycle (and how state could be maintained on server-side) is well documented.
39
40/**
41 * Top-level service of the current autofill service for a given user.
42 *
43 * <p>Apps providing autofill capabilities must extend this service.
44 */
45public abstract class AutofillService extends Service {
46 private static final String TAG = "AutofillService";
47
48 /**
49 * The {@link Intent} that must be declared as handled by the service.
50 * To be supported, the service must also require the
51 * {@link android.Manifest.permission#BIND_AUTO_FILL} permission so
52 * that other applications can not abuse it.
53 *
54 * @hide
55 * @deprecated TODO(b/35956626): remove once clients use AutofillService
56 */
57 @Deprecated
58 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
59 public static final String OLD_SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
60
61 /**
62 * The {@link Intent} that must be declared as handled by the service.
63 * To be supported, the service must also require the
64 * {@link android.Manifest.permission#BIND_AUTOFILL} permission so
65 * that other applications can not abuse it.
66 */
67 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
68 public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
69
70 /**
71 * Name under which a AutoFillService component publishes information about itself.
72 * This meta-data should reference an XML resource containing a
73 * <code>&lt;{@link
Felipe Lemef78e9522017-04-04 15:07:13 -070074 * android.R.styleable#AutofillService autofill-service}&gt;</code> tag.
Felipe Leme640f30a2017-03-06 15:44:06 -080075 * This is a a sample XML file configuring an AutoFillService:
76 * <pre> &lt;autofill-service
77 * android:settingsActivity="foo.bar.SettingsActivity"
78 * . . .
79 * /&gt;</pre>
80 */
81 public static final String SERVICE_META_DATA = "android.autofill";
82
83 // Internal extras
84 /** @hide */
Philip P. Moltmanneab62ba2017-03-20 10:55:43 -070085 public static final String EXTRA_SESSION_ID = "android.service.autofill.extra.SESSION_ID";
Felipe Leme640f30a2017-03-06 15:44:06 -080086
87 // Handler messages.
88 private static final int MSG_CONNECT = 1;
89 private static final int MSG_DISCONNECT = 2;
90 private static final int MSG_ON_FILL_REQUEST = 3;
91 private static final int MSG_ON_SAVE_REQUEST = 4;
92
Felipe Leme2ac463e2017-03-13 14:06:25 -070093 private static final int UNUSED_ARG = -1;
94
Felipe Leme640f30a2017-03-06 15:44:06 -080095 private final IAutoFillService mInterface = new IAutoFillService.Stub() {
96 @Override
Svet Ganovf20a0372017-04-10 17:08:05 -070097 public void onConnectedStateChanged(boolean connected) {
98 if (connected) {
99 mHandlerCaller.obtainMessage(MSG_CONNECT).sendToTarget();
Felipe Leme640f30a2017-03-06 15:44:06 -0800100 } else {
101 mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget();
102 }
103 }
104
105 @Override
106 public void onFillRequest(AssistStructure structure, Bundle extras,
Felipe Leme2ac463e2017-03-13 14:06:25 -0700107 IFillCallback callback, int flags) {
Felipe Leme640f30a2017-03-06 15:44:06 -0800108 ICancellationSignal transport = CancellationSignal.createTransport();
109 try {
110 callback.onCancellable(transport);
111 } catch (RemoteException e) {
112 e.rethrowFromSystemServer();
113 }
Felipe Leme2ac463e2017-03-13 14:06:25 -0700114 mHandlerCaller.obtainMessageIIOOOO(MSG_ON_FILL_REQUEST, flags, UNUSED_ARG, structure,
Felipe Leme640f30a2017-03-06 15:44:06 -0800115 CancellationSignal.fromTransport(transport), extras, callback)
116 .sendToTarget();
117 }
118
119 @Override
120 public void onSaveRequest(AssistStructure structure, Bundle extras,
121 ISaveCallback callback) {
122 mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure,
123 extras, callback).sendToTarget();
124 }
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;
134 final AssistStructure structure = (AssistStructure) args.arg1;
135 final CancellationSignal cancellation = (CancellationSignal) args.arg2;
136 final Bundle extras = (Bundle) args.arg3;
137 final IFillCallback callback = (IFillCallback) args.arg4;
138 final FillCallback fillCallback = new FillCallback(callback);
Felipe Leme2ac463e2017-03-13 14:06:25 -0700139 final int flags = msg.arg1;
Felipe Leme640f30a2017-03-06 15:44:06 -0800140 args.recycle();
Felipe Leme2ac463e2017-03-13 14:06:25 -0700141 onFillRequest(structure, extras, flags, cancellation, fillCallback);
Felipe Leme640f30a2017-03-06 15:44:06 -0800142 break;
143 } case MSG_ON_SAVE_REQUEST: {
144 final SomeArgs args = (SomeArgs) msg.obj;
145 final AssistStructure structure = (AssistStructure) args.arg1;
146 final Bundle extras = (Bundle) args.arg2;
147 final ISaveCallback callback = (ISaveCallback) args.arg3;
148 final SaveCallback saveCallback = new SaveCallback(callback);
149 args.recycle();
150 onSaveRequest(structure, extras, saveCallback);
151 break;
152 } case MSG_DISCONNECT: {
153 onDisconnected();
Felipe Leme640f30a2017-03-06 15:44:06 -0800154 break;
155 } default: {
156 Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
157 }
158 }
159 };
160
161 private HandlerCaller mHandlerCaller;
162
Felipe Leme640f30a2017-03-06 15:44:06 -0800163 /**
164 * {@inheritDoc}
165 *
166 * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}.
167 */
168 @Override
169 public void onCreate() {
170 super.onCreate();
171 mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
172 }
173
174 @Override
175 public final IBinder onBind(Intent intent) {
176 if (SERVICE_INTERFACE.equals(intent.getAction())
177 || OLD_SERVICE_INTERFACE.equals(intent.getAction())) {
178 return mInterface.asBinder();
179 }
180 Log.w(TAG, "Tried to bind to wrong intent: " + intent);
181 return null;
182 }
183
184 /**
185 * Called when the Android system connects to service.
186 *
187 * <p>You should generally do initialization here rather than in {@link #onCreate}.
188 */
189 public void onConnected() {
Felipe Leme640f30a2017-03-06 15:44:06 -0800190 }
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.
Felipe Leme52d5d3d2017-04-04 13:10:58 -0700202 * @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.
Felipe Leme2ac463e2017-03-13 14:06:25 -0700208 * @param flags either {@code 0} or {@link AutofillManager#FLAG_MANUAL_REQUEST}.
Felipe Leme640f30a2017-03-06 15:44:06 -0800209 * @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 */
Felipe Lemea86aee62017-04-04 18:27:49 -0700214 public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
215 int flags, @NonNull CancellationSignal cancellationSignal,
216 @NonNull FillCallback callback);
Felipe Leme640f30a2017-03-06 15:44:06 -0800217
218 /**
219 * Called when user requests service to save the fields of an {@link Activity}.
220 *
221 * <p>Service must call one of the {@link SaveCallback} methods (like
222 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
223 * to notify the result of the request.
224 *
225 * @param structure {@link Activity}'s view structure.
Felipe Leme52d5d3d2017-04-04 13:10:58 -0700226 * @param data bundle containing data passed by the service in a last call to
227 * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
228 * service to keep state between fill and save requests as well as when filling different
229 * sections of the UI as the system will try to aggressively unbind from the service to
230 * conserve resources.
231 * See {@link FillResponse} for examples of multiple-sections requests.
Felipe Leme640f30a2017-03-06 15:44:06 -0800232 * @param callback object used to notify the result of the request.
233 */
234 public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
235 @NonNull SaveCallback callback);
236
237 /**
238 * Called when the Android system disconnects from the service.
239 *
240 * <p> At this point this service may no longer be an active {@link AutofillService}.
241 */
242 public void onDisconnected() {
Felipe Leme640f30a2017-03-06 15:44:06 -0800243 }
244
Svet Ganovf20a0372017-04-10 17:08:05 -0700245 /** @hide */
Felipe Leme640f30a2017-03-06 15:44:06 -0800246 public final void disableSelf() {
Svet Ganovf20a0372017-04-10 17:08:05 -0700247 // TODO(b/33197203): Remove when GCore has migrated off this API
248 getSystemService(AutofillManager.class).disableOwnedAutofillServices();
Felipe Leme640f30a2017-03-06 15:44:06 -0800249 }
250}