blob: 394bd0ac70f7c1ab0d290367a03b83bfd41005d5 [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
Svet Ganovecfa58a2017-05-05 19:38:45 -070018import android.annotation.CallSuper;
Felipe Leme640f30a2017-03-06 15:44:06 -080019import 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;
Felipe Leme640f30a2017-03-06 15:44:06 -080026import android.content.Intent;
Felipe Leme640f30a2017-03-06 15:44:06 -080027import android.os.CancellationSignal;
28import android.os.IBinder;
29import android.os.ICancellationSignal;
30import android.os.Looper;
31import android.util.Log;
Felipe Leme2ac463e2017-03-13 14:06:25 -070032import android.view.autofill.AutofillManager;
Felipe Leme640f30a2017-03-06 15:44:06 -080033
34import com.android.internal.os.SomeArgs;
35
Felipe Leme640f30a2017-03-06 15:44:06 -080036/**
37 * Top-level service of the current autofill service for a given user.
38 *
39 * <p>Apps providing autofill capabilities must extend this service.
40 */
41public abstract class AutofillService extends Service {
42 private static final String TAG = "AutofillService";
43
44 /**
45 * The {@link Intent} that must be declared as handled by the service.
46 * To be supported, the service must also require the
Felipe Lemedecd8872017-04-26 17:42:38 -070047 * {@link android.Manifest.permission#BIND_AUTOFILL_SERVICE} permission so
Felipe Leme640f30a2017-03-06 15:44:06 -080048 * that other applications can not abuse it.
49 */
50 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
51 public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
52
53 /**
54 * Name under which a AutoFillService component publishes information about itself.
55 * This meta-data should reference an XML resource containing a
56 * <code>&lt;{@link
Felipe Lemef78e9522017-04-04 15:07:13 -070057 * android.R.styleable#AutofillService autofill-service}&gt;</code> tag.
Felipe Leme640f30a2017-03-06 15:44:06 -080058 * This is a a sample XML file configuring an AutoFillService:
59 * <pre> &lt;autofill-service
60 * android:settingsActivity="foo.bar.SettingsActivity"
61 * . . .
62 * /&gt;</pre>
63 */
64 public static final String SERVICE_META_DATA = "android.autofill";
65
Felipe Leme640f30a2017-03-06 15:44:06 -080066 // Handler messages.
67 private static final int MSG_CONNECT = 1;
68 private static final int MSG_DISCONNECT = 2;
69 private static final int MSG_ON_FILL_REQUEST = 3;
70 private static final int MSG_ON_SAVE_REQUEST = 4;
71
72 private final IAutoFillService mInterface = new IAutoFillService.Stub() {
73 @Override
Svet Ganovf20a0372017-04-10 17:08:05 -070074 public void onConnectedStateChanged(boolean connected) {
75 if (connected) {
76 mHandlerCaller.obtainMessage(MSG_CONNECT).sendToTarget();
Felipe Leme640f30a2017-03-06 15:44:06 -080077 } else {
78 mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget();
79 }
80 }
81
82 @Override
Svet Ganov013efe12017-04-13 21:56:16 -070083 public void onFillRequest(FillRequest request, IFillCallback callback) {
Felipe Leme640f30a2017-03-06 15:44:06 -080084 ICancellationSignal transport = CancellationSignal.createTransport();
85 try {
86 callback.onCancellable(transport);
87 } catch (RemoteException e) {
88 e.rethrowFromSystemServer();
89 }
Svet Ganov013efe12017-04-13 21:56:16 -070090 mHandlerCaller.obtainMessageOOO(MSG_ON_FILL_REQUEST, request,
91 CancellationSignal.fromTransport(transport), callback)
Felipe Leme640f30a2017-03-06 15:44:06 -080092 .sendToTarget();
93 }
94
95 @Override
Svet Ganov013efe12017-04-13 21:56:16 -070096 public void onSaveRequest(SaveRequest request, ISaveCallback callback) {
97 mHandlerCaller.obtainMessageOO(MSG_ON_SAVE_REQUEST, request,
98 callback).sendToTarget();
Felipe Leme640f30a2017-03-06 15:44:06 -080099 }
100 };
101
102 private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
103 switch (msg.what) {
104 case MSG_CONNECT: {
Felipe Leme640f30a2017-03-06 15:44:06 -0800105 onConnected();
106 break;
107 } case MSG_ON_FILL_REQUEST: {
108 final SomeArgs args = (SomeArgs) msg.obj;
Svet Ganov013efe12017-04-13 21:56:16 -0700109 final FillRequest request = (FillRequest) args.arg1;
Felipe Leme640f30a2017-03-06 15:44:06 -0800110 final CancellationSignal cancellation = (CancellationSignal) args.arg2;
Svet Ganov013efe12017-04-13 21:56:16 -0700111 final IFillCallback callback = (IFillCallback) args.arg3;
112 final FillCallback fillCallback = new FillCallback(callback, request.getId());
Felipe Leme640f30a2017-03-06 15:44:06 -0800113 args.recycle();
Felipe Leme73fedac2017-05-12 09:52:07 -0700114 onFillRequest(request, cancellation, fillCallback);
Felipe Leme640f30a2017-03-06 15:44:06 -0800115 break;
116 } case MSG_ON_SAVE_REQUEST: {
117 final SomeArgs args = (SomeArgs) msg.obj;
Svet Ganov013efe12017-04-13 21:56:16 -0700118 final SaveRequest request = (SaveRequest) args.arg1;
119 final ISaveCallback callback = (ISaveCallback) args.arg2;
Felipe Leme640f30a2017-03-06 15:44:06 -0800120 final SaveCallback saveCallback = new SaveCallback(callback);
121 args.recycle();
Felipe Leme73fedac2017-05-12 09:52:07 -0700122 onSaveRequest(request, saveCallback);
Felipe Leme640f30a2017-03-06 15:44:06 -0800123 break;
124 } case MSG_DISCONNECT: {
125 onDisconnected();
Felipe Leme640f30a2017-03-06 15:44:06 -0800126 break;
127 } default: {
128 Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
129 }
130 }
131 };
132
133 private HandlerCaller mHandlerCaller;
134
Felipe Leme640f30a2017-03-06 15:44:06 -0800135 /**
136 * {@inheritDoc}
137 *
138 * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}.
139 */
Svet Ganovecfa58a2017-05-05 19:38:45 -0700140 @CallSuper
Felipe Leme640f30a2017-03-06 15:44:06 -0800141 @Override
142 public void onCreate() {
143 super.onCreate();
144 mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
145 }
146
147 @Override
148 public final IBinder onBind(Intent intent) {
Felipe Leme85d1c2d2017-04-21 08:56:04 -0700149 if (SERVICE_INTERFACE.equals(intent.getAction())) {
Felipe Leme640f30a2017-03-06 15:44:06 -0800150 return mInterface.asBinder();
151 }
152 Log.w(TAG, "Tried to bind to wrong intent: " + intent);
153 return null;
154 }
155
156 /**
157 * Called when the Android system connects to service.
158 *
159 * <p>You should generally do initialization here rather than in {@link #onCreate}.
160 */
161 public void onConnected() {
Felipe Leme640f30a2017-03-06 15:44:06 -0800162 }
163
164 /**
165 * Called by the Android system do decide if an {@link Activity} can be autofilled by the
166 * service.
167 *
168 * <p>Service must call one of the {@link FillCallback} methods (like
169 * {@link FillCallback#onSuccess(FillResponse)}
170 * or {@link FillCallback#onFailure(CharSequence)})
171 * to notify the result of the request.
172 *
Svet Ganov013efe12017-04-13 21:56:16 -0700173 * @param request the {@link FillRequest request} to handle.
174 * See {@link FillResponse} for examples of multiple-sections requests.
175 * @param cancellationSignal signal for observing cancellation requests. The system will use
176 * this to notify you that the fill result is no longer needed and you should stop
177 * handling this fill request in order to save resources.
178 * @param callback object used to notify the result of the request.
179 */
Felipe Leme6a778492017-04-25 09:19:49 -0700180 public abstract void onFillRequest(@NonNull FillRequest request,
181 @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback);
Svet Ganov013efe12017-04-13 21:56:16 -0700182
183 /**
Felipe Leme640f30a2017-03-06 15:44:06 -0800184 * Called when user requests service to save the fields of an {@link Activity}.
185 *
186 * <p>Service must call one of the {@link SaveCallback} methods (like
187 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
188 * to notify the result of the request.
189 *
Felipe Leme26675232017-06-19 09:45:48 -0700190 * <p><b>NOTE: </b>to retrieve the actual value of the field, the service should call
191 * {@link android.app.assist.AssistStructure.ViewNode#getAutofillValue()}; if it calls
192 * {@link android.app.assist.AssistStructure.ViewNode#getText()} or other methods, there is no
193 * guarantee such method will return the most recent value of the field.
194 *
Svet Ganov013efe12017-04-13 21:56:16 -0700195 * @param request the {@link SaveRequest request} to handle.
196 * See {@link FillResponse} for examples of multiple-sections requests.
197 * @param callback object used to notify the result of the request.
198 */
Felipe Leme6a778492017-04-25 09:19:49 -0700199 public abstract void onSaveRequest(@NonNull SaveRequest request,
200 @NonNull SaveCallback callback);
Svet Ganov013efe12017-04-13 21:56:16 -0700201
202 /**
Felipe Leme640f30a2017-03-06 15:44:06 -0800203 * Called when the Android system disconnects from the service.
204 *
205 * <p> At this point this service may no longer be an active {@link AutofillService}.
206 */
207 public void onDisconnected() {
Felipe Leme640f30a2017-03-06 15:44:06 -0800208 }
209
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700210 /**
Felipe Leme2e30c6f2017-06-20 10:55:01 -0700211 * Gets the events that happened after the last
212 * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
213 * call.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700214 *
Felipe Leme2e30c6f2017-06-20 10:55:01 -0700215 * <p>This method is typically used to keep track of previous user actions to optimize further
216 * requests. For example, the service might return email addresses in alphabetical order by
217 * default, but change that order based on the address the user picked on previous requests.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700218 *
Felipe Leme2e30c6f2017-06-20 10:55:01 -0700219 * <p>The history is not persisted over reboots, and it's cleared every time the service
220 * replies to a {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} by calling
221 * {@link FillCallback#onSuccess(FillResponse)} or {@link FillCallback#onFailure(CharSequence)}
222 * (if the service doesn't call any of these methods, the history will clear out after some
223 * pre-defined time). Hence, the service should call {@link #getFillEventHistory()} before
224 * finishing the {@link FillCallback}.
225 *
226 * @return The history or {@code null} if there are no events.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700227 */
228 @Nullable public final FillEventHistory getFillEventHistory() {
229 AutofillManager afm = getSystemService(AutofillManager.class);
230
231 if (afm == null) {
232 return null;
233 } else {
234 return afm.getFillEventHistory();
235 }
236 }
Felipe Leme640f30a2017-03-06 15:44:06 -0800237}