blob: 9f8a6217c5f4dea8017b7d769d36741952bfd591 [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 */
85 public static final String EXTRA_ACTIVITY_TOKEN =
86 "android.service.autofill.extra.ACTIVITY_TOKEN";
87
88 // Handler messages.
89 private static final int MSG_CONNECT = 1;
90 private static final int MSG_DISCONNECT = 2;
91 private static final int MSG_ON_FILL_REQUEST = 3;
92 private static final int MSG_ON_SAVE_REQUEST = 4;
93
Felipe Leme2ac463e2017-03-13 14:06:25 -070094 private static final int UNUSED_ARG = -1;
95
Felipe Leme640f30a2017-03-06 15:44:06 -080096 private final IAutoFillService mInterface = new IAutoFillService.Stub() {
97 @Override
98 public void onInit(IAutoFillServiceConnection connection) {
99 if (connection != null) {
100 mHandlerCaller.obtainMessageO(MSG_CONNECT, connection).sendToTarget();
101 } else {
102 mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget();
103 }
104 }
105
106 @Override
107 public void onFillRequest(AssistStructure structure, Bundle extras,
Felipe Leme2ac463e2017-03-13 14:06:25 -0700108 IFillCallback callback, int flags) {
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 }
Felipe Leme2ac463e2017-03-13 14:06:25 -0700115 mHandlerCaller.obtainMessageIIOOOO(MSG_ON_FILL_REQUEST, flags, UNUSED_ARG, structure,
Felipe Leme640f30a2017-03-06 15:44:06 -0800116 CancellationSignal.fromTransport(transport), extras, callback)
117 .sendToTarget();
118 }
119
120 @Override
121 public void onSaveRequest(AssistStructure structure, Bundle extras,
122 ISaveCallback callback) {
123 mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure,
124 extras, callback).sendToTarget();
125 }
126 };
127
128 private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
129 switch (msg.what) {
130 case MSG_CONNECT: {
131 mConnection = (IAutoFillServiceConnection) msg.obj;
132 onConnected();
133 break;
134 } case MSG_ON_FILL_REQUEST: {
135 final SomeArgs args = (SomeArgs) msg.obj;
136 final AssistStructure structure = (AssistStructure) args.arg1;
137 final CancellationSignal cancellation = (CancellationSignal) args.arg2;
138 final Bundle extras = (Bundle) args.arg3;
139 final IFillCallback callback = (IFillCallback) args.arg4;
140 final FillCallback fillCallback = new FillCallback(callback);
Felipe Leme2ac463e2017-03-13 14:06:25 -0700141 final int flags = msg.arg1;
Felipe Leme640f30a2017-03-06 15:44:06 -0800142 args.recycle();
Felipe Leme2ac463e2017-03-13 14:06:25 -0700143 onFillRequest(structure, extras, flags, cancellation, fillCallback);
Felipe Leme640f30a2017-03-06 15:44:06 -0800144 break;
145 } case MSG_ON_SAVE_REQUEST: {
146 final SomeArgs args = (SomeArgs) msg.obj;
147 final AssistStructure structure = (AssistStructure) args.arg1;
148 final Bundle extras = (Bundle) args.arg2;
149 final ISaveCallback callback = (ISaveCallback) args.arg3;
150 final SaveCallback saveCallback = new SaveCallback(callback);
151 args.recycle();
152 onSaveRequest(structure, extras, saveCallback);
153 break;
154 } case MSG_DISCONNECT: {
155 onDisconnected();
156 mConnection = null;
157 break;
158 } default: {
159 Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
160 }
161 }
162 };
163
164 private HandlerCaller mHandlerCaller;
165
166 private IAutoFillServiceConnection mConnection;
167
168 /**
169 * {@inheritDoc}
170 *
171 * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}.
172 */
173 @Override
174 public void onCreate() {
175 super.onCreate();
176 mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
177 }
178
179 @Override
180 public final IBinder onBind(Intent intent) {
181 if (SERVICE_INTERFACE.equals(intent.getAction())
182 || OLD_SERVICE_INTERFACE.equals(intent.getAction())) {
183 return mInterface.asBinder();
184 }
185 Log.w(TAG, "Tried to bind to wrong intent: " + intent);
186 return null;
187 }
188
189 /**
190 * Called when the Android system connects to service.
191 *
192 * <p>You should generally do initialization here rather than in {@link #onCreate}.
193 */
194 public void onConnected() {
Felipe Leme640f30a2017-03-06 15:44:06 -0800195 }
196
197 /**
198 * Called by the Android system do decide if an {@link Activity} can be autofilled by the
199 * service.
200 *
201 * <p>Service must call one of the {@link FillCallback} methods (like
202 * {@link FillCallback#onSuccess(FillResponse)}
203 * or {@link FillCallback#onFailure(CharSequence)})
204 * to notify the result of the request.
205 *
206 * @param structure {@link Activity}'s view structure.
207 * @param data bundle containing data passed by the service on previous calls to fill.
208 * This bundle allows your service to keep state between fill and save requests
209 * as well as when filling different sections of the UI as the system will try to
210 * aggressively unbind from the service to conserve resources. See {@link
211 * FillResponse} Javadoc for examples of multiple-sections requests.
Felipe Leme2ac463e2017-03-13 14:06:25 -0700212 * @param flags either {@code 0} or {@link AutofillManager#FLAG_MANUAL_REQUEST}.
Felipe Leme640f30a2017-03-06 15:44:06 -0800213 * @param cancellationSignal signal for observing cancellation requests. The system will use
214 * this to notify you that the fill result is no longer needed and you should stop
215 * handling this fill request in order to save resources.
216 * @param callback object used to notify the result of the request.
217 */
Felipe Leme2ac463e2017-03-13 14:06:25 -0700218 public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data, int flags,
219 @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) {
220 //TODO(b/33197203): make non-abstract once older method is removed
221 onFillRequest(structure, data, cancellationSignal, callback);
222 }
223
224 /**
225 * @hide
226 * @deprecated - use {@link #onFillRequest(AssistStructure, Bundle, int,
227 * CancellationSignal, FillCallback)} instead
228 */
229 //TODO(b/33197203): remove once clients are not using anymore
230 @Deprecated
Felipe Leme24d58932017-03-21 14:13:58 -0700231 public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
232 @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) {
233 // Should never be called because it was abstract before.
234 throw new UnsupportedOperationException("deprecated");
235 }
Felipe Leme640f30a2017-03-06 15:44:06 -0800236
237 /**
238 * Called when user requests service to save the fields of an {@link Activity}.
239 *
240 * <p>Service must call one of the {@link SaveCallback} methods (like
241 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
242 * to notify the result of the request.
243 *
244 * @param structure {@link Activity}'s view structure.
245 * @param data bundle containing data passed by the service on previous calls to fill.
246 * This bundle allows your service to keep state between fill and save requests
247 * as well as when filling different sections of the UI as the system will try to
248 * aggressively unbind from the service to conserve resources. See {@link
249 * FillResponse} Javadoc for examples of multiple-sections requests.
250 * @param callback object used to notify the result of the request.
251 */
252 public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
253 @NonNull SaveCallback callback);
254
255 /**
256 * Called when the Android system disconnects from the service.
257 *
258 * <p> At this point this service may no longer be an active {@link AutofillService}.
259 */
260 public void onDisconnected() {
Felipe Leme640f30a2017-03-06 15:44:06 -0800261 }
262
263 /**
264 * Disables the service. After calling this method, the service will
265 * be disabled and settings will show that it is turned off.
266 *
267 * <p>You should call this method only after a call to {@link #onConnected()}
268 * and before the corresponding call to {@link #onDisconnected()}. In other words
269 * you can disable your service only while the system is connected to it.</p>
270 */
271 public final void disableSelf() {
272 if (mConnection != null) {
273 try {
274 mConnection.disableSelf();
275 } catch (RemoteException re) {
276 throw re.rethrowFromSystemServer();
277 }
278 }
279 }
280}