blob: c82b9ebb6b39a45312ac437d2d817ca2270cce29 [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
97 public void onInit(IAutoFillServiceConnection connection) {
98 if (connection != null) {
99 mHandlerCaller.obtainMessageO(MSG_CONNECT, connection).sendToTarget();
100 } 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: {
130 mConnection = (IAutoFillServiceConnection) msg.obj;
131 onConnected();
132 break;
133 } case MSG_ON_FILL_REQUEST: {
134 final SomeArgs args = (SomeArgs) msg.obj;
135 final AssistStructure structure = (AssistStructure) args.arg1;
136 final CancellationSignal cancellation = (CancellationSignal) args.arg2;
137 final Bundle extras = (Bundle) args.arg3;
138 final IFillCallback callback = (IFillCallback) args.arg4;
139 final FillCallback fillCallback = new FillCallback(callback);
Felipe Leme2ac463e2017-03-13 14:06:25 -0700140 final int flags = msg.arg1;
Felipe Leme640f30a2017-03-06 15:44:06 -0800141 args.recycle();
Felipe Leme2ac463e2017-03-13 14:06:25 -0700142 onFillRequest(structure, extras, flags, cancellation, fillCallback);
Felipe Leme640f30a2017-03-06 15:44:06 -0800143 break;
144 } case MSG_ON_SAVE_REQUEST: {
145 final SomeArgs args = (SomeArgs) msg.obj;
146 final AssistStructure structure = (AssistStructure) args.arg1;
147 final Bundle extras = (Bundle) args.arg2;
148 final ISaveCallback callback = (ISaveCallback) args.arg3;
149 final SaveCallback saveCallback = new SaveCallback(callback);
150 args.recycle();
151 onSaveRequest(structure, extras, saveCallback);
152 break;
153 } case MSG_DISCONNECT: {
154 onDisconnected();
155 mConnection = null;
156 break;
157 } default: {
158 Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
159 }
160 }
161 };
162
163 private HandlerCaller mHandlerCaller;
164
165 private IAutoFillServiceConnection mConnection;
166
167 /**
168 * {@inheritDoc}
169 *
170 * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}.
171 */
172 @Override
173 public void onCreate() {
174 super.onCreate();
175 mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
176 }
177
178 @Override
179 public final IBinder onBind(Intent intent) {
180 if (SERVICE_INTERFACE.equals(intent.getAction())
181 || OLD_SERVICE_INTERFACE.equals(intent.getAction())) {
182 return mInterface.asBinder();
183 }
184 Log.w(TAG, "Tried to bind to wrong intent: " + intent);
185 return null;
186 }
187
188 /**
189 * Called when the Android system connects to service.
190 *
191 * <p>You should generally do initialization here rather than in {@link #onCreate}.
192 */
193 public void onConnected() {
Felipe Leme640f30a2017-03-06 15:44:06 -0800194 }
195
196 /**
197 * Called by the Android system do decide if an {@link Activity} can be autofilled by the
198 * service.
199 *
200 * <p>Service must call one of the {@link FillCallback} methods (like
201 * {@link FillCallback#onSuccess(FillResponse)}
202 * or {@link FillCallback#onFailure(CharSequence)})
203 * to notify the result of the request.
204 *
205 * @param structure {@link Activity}'s view structure.
Felipe Leme52d5d3d2017-04-04 13:10:58 -0700206 * @param data bundle containing data passed by the service in a last call to
207 * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
208 * service to keep state between fill and save requests as well as when filling different
209 * sections of the UI as the system will try to aggressively unbind from the service to
210 * conserve resources.
211 * See {@link FillResponse} 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 Lemea86aee62017-04-04 18:27:49 -0700218 public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
219 int flags, @NonNull CancellationSignal cancellationSignal,
220 @NonNull FillCallback callback);
Felipe Leme640f30a2017-03-06 15:44:06 -0800221
222 /**
223 * Called when user requests service to save the fields of an {@link Activity}.
224 *
225 * <p>Service must call one of the {@link SaveCallback} methods (like
226 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
227 * to notify the result of the request.
228 *
229 * @param structure {@link Activity}'s view structure.
Felipe Leme52d5d3d2017-04-04 13:10:58 -0700230 * @param data bundle containing data passed by the service in a last call to
231 * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
232 * service to keep state between fill and save requests as well as when filling different
233 * sections of the UI as the system will try to aggressively unbind from the service to
234 * conserve resources.
235 * See {@link FillResponse} for examples of multiple-sections requests.
Felipe Leme640f30a2017-03-06 15:44:06 -0800236 * @param callback object used to notify the result of the request.
237 */
238 public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
239 @NonNull SaveCallback callback);
240
241 /**
242 * Called when the Android system disconnects from the service.
243 *
244 * <p> At this point this service may no longer be an active {@link AutofillService}.
245 */
246 public void onDisconnected() {
Felipe Leme640f30a2017-03-06 15:44:06 -0800247 }
248
249 /**
250 * Disables the service. After calling this method, the service will
251 * be disabled and settings will show that it is turned off.
252 *
253 * <p>You should call this method only after a call to {@link #onConnected()}
254 * and before the corresponding call to {@link #onDisconnected()}. In other words
255 * you can disable your service only while the system is connected to it.</p>
256 */
257 public final void disableSelf() {
258 if (mConnection != null) {
259 try {
260 mConnection.disableSelf();
261 } catch (RemoteException re) {
262 throw re.rethrowFromSystemServer();
263 }
264 }
265 }
266}