blob: 29e207358e708997cae089556b26725659838aa5 [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;
33
34import com.android.internal.os.SomeArgs;
35
36//TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the
37//life-cycle (and how state could be maintained on server-side) is well documented.
38
39/**
40 * Top-level service of the current autofill service for a given user.
41 *
42 * <p>Apps providing autofill capabilities must extend this service.
43 */
44public abstract class AutofillService extends Service {
45 private static final String TAG = "AutofillService";
46
47 /**
48 * The {@link Intent} that must be declared as handled by the service.
49 * To be supported, the service must also require the
50 * {@link android.Manifest.permission#BIND_AUTO_FILL} permission so
51 * that other applications can not abuse it.
52 *
53 * @hide
54 * @deprecated TODO(b/35956626): remove once clients use AutofillService
55 */
56 @Deprecated
57 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
58 public static final String OLD_SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
59
60 /**
61 * The {@link Intent} that must be declared as handled by the service.
62 * To be supported, the service must also require the
63 * {@link android.Manifest.permission#BIND_AUTOFILL} permission so
64 * that other applications can not abuse it.
65 */
66 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
67 public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
68
69 /**
70 * Name under which a AutoFillService component publishes information about itself.
71 * This meta-data should reference an XML resource containing a
72 * <code>&lt;{@link
73 * android.R.styleable#AutoFillService autofill-service}&gt;</code> tag.
74 * This is a a sample XML file configuring an AutoFillService:
75 * <pre> &lt;autofill-service
76 * android:settingsActivity="foo.bar.SettingsActivity"
77 * . . .
78 * /&gt;</pre>
79 */
80 public static final String SERVICE_META_DATA = "android.autofill";
81
82 // Internal extras
83 /** @hide */
84 public static final String EXTRA_ACTIVITY_TOKEN =
85 "android.service.autofill.extra.ACTIVITY_TOKEN";
86
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
93 private final IAutoFillService mInterface = new IAutoFillService.Stub() {
94 @Override
95 public void onInit(IAutoFillServiceConnection connection) {
96 if (connection != null) {
97 mHandlerCaller.obtainMessageO(MSG_CONNECT, connection).sendToTarget();
98 } else {
99 mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget();
100 }
101 }
102
103 @Override
104 public void onFillRequest(AssistStructure structure, Bundle extras,
105 IFillCallback callback) {
106 ICancellationSignal transport = CancellationSignal.createTransport();
107 try {
108 callback.onCancellable(transport);
109 } catch (RemoteException e) {
110 e.rethrowFromSystemServer();
111 }
112 mHandlerCaller.obtainMessageOOOO(MSG_ON_FILL_REQUEST, structure,
113 CancellationSignal.fromTransport(transport), extras, callback)
114 .sendToTarget();
115 }
116
117 @Override
118 public void onSaveRequest(AssistStructure structure, Bundle extras,
119 ISaveCallback callback) {
120 mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure,
121 extras, callback).sendToTarget();
122 }
123 };
124
125 private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
126 switch (msg.what) {
127 case MSG_CONNECT: {
128 mConnection = (IAutoFillServiceConnection) msg.obj;
129 onConnected();
130 break;
131 } case MSG_ON_FILL_REQUEST: {
132 final SomeArgs args = (SomeArgs) msg.obj;
133 final AssistStructure structure = (AssistStructure) args.arg1;
134 final CancellationSignal cancellation = (CancellationSignal) args.arg2;
135 final Bundle extras = (Bundle) args.arg3;
136 final IFillCallback callback = (IFillCallback) args.arg4;
137 final FillCallback fillCallback = new FillCallback(callback);
138 args.recycle();
139 onFillRequest(structure, extras, cancellation, fillCallback);
140 break;
141 } case MSG_ON_SAVE_REQUEST: {
142 final SomeArgs args = (SomeArgs) msg.obj;
143 final AssistStructure structure = (AssistStructure) args.arg1;
144 final Bundle extras = (Bundle) args.arg2;
145 final ISaveCallback callback = (ISaveCallback) args.arg3;
146 final SaveCallback saveCallback = new SaveCallback(callback);
147 args.recycle();
148 onSaveRequest(structure, extras, saveCallback);
149 break;
150 } case MSG_DISCONNECT: {
151 onDisconnected();
152 mConnection = null;
153 break;
154 } default: {
155 Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
156 }
157 }
158 };
159
160 private HandlerCaller mHandlerCaller;
161
162 private IAutoFillServiceConnection mConnection;
163
164 /**
165 * {@inheritDoc}
166 *
167 * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}.
168 */
169 @Override
170 public void onCreate() {
171 super.onCreate();
172 mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
173 }
174
175 @Override
176 public final IBinder onBind(Intent intent) {
177 if (SERVICE_INTERFACE.equals(intent.getAction())
178 || OLD_SERVICE_INTERFACE.equals(intent.getAction())) {
179 return mInterface.asBinder();
180 }
181 Log.w(TAG, "Tried to bind to wrong intent: " + intent);
182 return null;
183 }
184
185 /**
186 * Called when the Android system connects to service.
187 *
188 * <p>You should generally do initialization here rather than in {@link #onCreate}.
189 */
190 public void onConnected() {
191 //TODO(b/33197203): is not called anymore, fix it!
192 }
193
194 /**
195 * Called by the Android system do decide if an {@link Activity} can be autofilled by the
196 * service.
197 *
198 * <p>Service must call one of the {@link FillCallback} methods (like
199 * {@link FillCallback#onSuccess(FillResponse)}
200 * or {@link FillCallback#onFailure(CharSequence)})
201 * to notify the result of the request.
202 *
203 * @param structure {@link Activity}'s view structure.
204 * @param data bundle containing data passed by the service on previous calls to fill.
205 * This bundle allows your service to keep state between fill and save requests
206 * as well as when filling different sections of the UI as the system will try to
207 * aggressively unbind from the service to conserve resources. See {@link
208 * FillResponse} Javadoc for examples of multiple-sections requests.
209 * @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 */
214 public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
215 @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback);
216
217 /**
218 * Called when user requests service to save the fields of an {@link Activity}.
219 *
220 * <p>Service must call one of the {@link SaveCallback} methods (like
221 * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
222 * to notify the result of the request.
223 *
224 * @param structure {@link Activity}'s view structure.
225 * @param data bundle containing data passed by the service on previous calls to fill.
226 * This bundle allows your service to keep state between fill and save requests
227 * as well as when filling different sections of the UI as the system will try to
228 * aggressively unbind from the service to conserve resources. See {@link
229 * FillResponse} Javadoc for examples of multiple-sections requests.
230 * @param callback object used to notify the result of the request.
231 */
232 public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
233 @NonNull SaveCallback callback);
234
235 /**
236 * Called when the Android system disconnects from the service.
237 *
238 * <p> At this point this service may no longer be an active {@link AutofillService}.
239 */
240 public void onDisconnected() {
241 //TODO(b/33197203): is not called anymore, fix it!
242 }
243
244 /**
245 * Disables the service. After calling this method, the service will
246 * be disabled and settings will show that it is turned off.
247 *
248 * <p>You should call this method only after a call to {@link #onConnected()}
249 * and before the corresponding call to {@link #onDisconnected()}. In other words
250 * you can disable your service only while the system is connected to it.</p>
251 */
252 public final void disableSelf() {
253 if (mConnection != null) {
254 try {
255 mConnection.disableSelf();
256 } catch (RemoteException re) {
257 throw re.rethrowFromSystemServer();
258 }
259 }
260 }
261}